gsd-pi 2.82.0 → 3.0.0

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 (555) hide show
  1. package/README.md +51 -32
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -1
  4. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  5. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  6. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  7. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +1 -1
  8. package/dist/resources/extensions/cmux/index.js +5 -0
  9. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  10. package/dist/resources/extensions/gsd/auto/loop.js +19 -6
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  12. package/dist/resources/extensions/gsd/auto/phases.js +90 -31
  13. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  14. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +3 -0
  15. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  16. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  17. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +1 -0
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  19. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  20. package/dist/resources/extensions/gsd/auto-post-unit.js +246 -133
  21. package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
  22. package/dist/resources/extensions/gsd/auto-recovery.js +71 -14
  23. package/dist/resources/extensions/gsd/auto-start.js +87 -14
  24. package/dist/resources/extensions/gsd/auto-verification.js +45 -26
  25. package/dist/resources/extensions/gsd/auto-worktree.js +176 -10
  26. package/dist/resources/extensions/gsd/auto.js +178 -63
  27. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +31 -7
  28. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -9
  29. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
  30. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  31. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +17 -3
  33. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  34. package/dist/resources/extensions/gsd/commands/catalog.js +10 -1
  35. package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -1
  36. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  38. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  39. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +7 -2
  40. package/dist/resources/extensions/gsd/commands-verdict.js +139 -0
  41. package/dist/resources/extensions/gsd/context-store.js +112 -0
  42. package/dist/resources/extensions/gsd/crash-recovery.js +43 -5
  43. package/dist/resources/extensions/gsd/db/milestone-leases.js +24 -0
  44. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  45. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  46. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  47. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  48. package/dist/resources/extensions/gsd/doctor-git-checks.js +87 -7
  49. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  50. package/dist/resources/extensions/gsd/doctor.js +2 -28
  51. package/dist/resources/extensions/gsd/export-html.js +27 -425
  52. package/dist/resources/extensions/gsd/forensics.js +3 -3
  53. package/dist/resources/extensions/gsd/git-service.js +45 -3
  54. package/dist/resources/extensions/gsd/gsd-db.js +21 -6
  55. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -3
  56. package/dist/resources/extensions/gsd/guided-flow.js +101 -116
  57. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  58. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  59. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  60. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  61. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  62. package/dist/resources/extensions/gsd/markdown-renderer.js +16 -9
  63. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  64. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  65. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  66. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  67. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  68. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  69. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  70. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  71. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  72. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  73. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  74. package/dist/resources/extensions/gsd/paths.js +4 -0
  75. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  76. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  77. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  78. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  79. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  80. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  81. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  82. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  83. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  84. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  85. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  86. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  87. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  88. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  89. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  90. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  91. package/dist/resources/extensions/gsd/queue-reorder-ui.js +30 -13
  92. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  93. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  94. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  95. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  96. package/dist/resources/extensions/gsd/state.js +3 -3
  97. package/dist/resources/extensions/gsd/status-guards.js +11 -0
  98. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  99. package/dist/resources/extensions/gsd/templates/plan.md +9 -5
  100. package/dist/resources/extensions/gsd/templates/task-plan.md +10 -2
  101. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  102. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  103. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  104. package/dist/resources/extensions/gsd/tools/plan-slice.js +87 -14
  105. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  106. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  107. package/dist/resources/extensions/gsd/validation.js +23 -1
  108. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  109. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  110. package/dist/resources/extensions/gsd/workflow-mcp.js +17 -1
  111. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  112. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  113. package/dist/resources/extensions/gsd/worktree-manager.js +1 -1
  114. package/dist/resources/extensions/shared/html-shell.js +388 -0
  115. package/dist/resources/extensions/subagent/index.js +448 -78
  116. package/dist/resources/extensions/subagent/launch.js +77 -0
  117. package/dist/resources/extensions/subagent/run-store.js +148 -0
  118. package/dist/resources/extensions/ttsr/ttsr-manager.js +3 -1
  119. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  120. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  121. package/dist/resources/extensions/visual-brief/index.js +5 -0
  122. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  123. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  124. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  125. package/dist/web/standalone/.next/BUILD_ID +1 -1
  126. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  127. package/dist/web/standalone/.next/build-manifest.json +3 -3
  128. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  129. package/dist/web/standalone/.next/react-loadable-manifest.json +5 -5
  130. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  140. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  144. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  145. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  147. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  150. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/index.html +1 -1
  153. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  154. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  156. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  158. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  159. package/dist/web/standalone/.next/server/app/page.js +2 -2
  160. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  163. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  164. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  168. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  169. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  170. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  171. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  172. package/dist/web/standalone/.next/static/chunks/8359.65b24fac92188a6b.js +10 -0
  173. package/dist/web/standalone/.next/static/chunks/9441.ff70bb53f6835771.js +1 -0
  174. package/dist/web/standalone/.next/static/chunks/app/layout-b23b3f6858dc6dc8.js +1 -0
  175. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-855d616060cb6e59.js} +1 -1
  176. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  177. package/package.json +6 -5
  178. package/packages/contracts/dist/rpc.test.js +7 -0
  179. package/packages/contracts/dist/rpc.test.js.map +1 -1
  180. package/packages/contracts/dist/workflow.d.ts +21 -0
  181. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  182. package/packages/contracts/dist/workflow.js +24 -0
  183. package/packages/contracts/dist/workflow.js.map +1 -1
  184. package/packages/contracts/src/rpc.test.ts +8 -0
  185. package/packages/contracts/src/workflow.ts +24 -0
  186. package/packages/daemon/package.json +2 -2
  187. package/packages/mcp-server/README.md +14 -3
  188. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  189. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  190. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  191. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  192. package/packages/mcp-server/package.json +2 -2
  193. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  194. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  195. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  196. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  197. package/packages/native/package.json +1 -1
  198. package/packages/native/tsconfig.json +2 -1
  199. package/packages/native/tsconfig.tsbuildinfo +1 -1
  200. package/packages/pi-agent-core/package.json +1 -1
  201. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  202. package/packages/pi-ai/dist/index.d.ts +2 -2
  203. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  204. package/packages/pi-ai/dist/index.js +1 -1
  205. package/packages/pi-ai/dist/index.js.map +1 -1
  206. package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
  207. package/packages/pi-ai/dist/providers/google-gemini-cli.js +5 -0
  208. package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
  209. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts +2 -0
  210. package/packages/pi-ai/dist/providers/google-gemini-cli.test.d.ts.map +1 -0
  211. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js +41 -0
  212. package/packages/pi-ai/dist/providers/google-gemini-cli.test.js.map +1 -0
  213. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  214. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  215. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  216. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  217. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  218. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  219. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  220. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  221. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  222. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  223. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  224. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  225. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  226. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  227. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  228. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  229. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  230. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  231. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  232. package/packages/pi-ai/package.json +1 -1
  233. package/packages/pi-ai/src/index.ts +7 -2
  234. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +49 -0
  235. package/packages/pi-ai/src/providers/google-gemini-cli.ts +7 -0
  236. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  237. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  238. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  239. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  240. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  241. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  242. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  243. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  244. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  245. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  246. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  247. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -3
  249. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/sdk.js +1 -1
  251. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  253. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +71 -97
  259. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js +25 -1
  261. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-ordering.test.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +24 -10
  265. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  267. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  268. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  269. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  270. package/packages/pi-coding-agent/package.json +1 -1
  271. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  272. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  273. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +53 -3
  274. package/packages/pi-coding-agent/src/core/sdk.ts +1 -1
  275. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  276. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  277. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -102
  278. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +30 -1
  279. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +29 -10
  280. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  281. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  282. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  283. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  284. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  285. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  286. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  287. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  288. package/packages/pi-tui/dist/terminal.js +12 -0
  289. package/packages/pi-tui/dist/terminal.js.map +1 -1
  290. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  291. package/packages/pi-tui/dist/tui.js +5 -0
  292. package/packages/pi-tui/dist/tui.js.map +1 -1
  293. package/packages/pi-tui/package.json +1 -1
  294. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  295. package/packages/pi-tui/src/terminal.ts +11 -0
  296. package/packages/pi-tui/src/tui.ts +6 -0
  297. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  298. package/packages/rpc-client/package.json +1 -1
  299. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  300. package/pkg/package.json +1 -1
  301. package/src/resources/GSD-WORKFLOW.md +10 -1
  302. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  303. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  304. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  305. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1 -1
  306. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  307. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +9 -0
  308. package/src/resources/extensions/cmux/index.ts +6 -0
  309. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  310. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  311. package/src/resources/extensions/gsd/auto/loop.ts +22 -6
  312. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  313. package/src/resources/extensions/gsd/auto/phases.ts +104 -38
  314. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  315. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +5 -1
  316. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  317. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  318. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -0
  319. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -19
  320. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  321. package/src/resources/extensions/gsd/auto-post-unit.ts +279 -144
  322. package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
  323. package/src/resources/extensions/gsd/auto-recovery.ts +74 -11
  324. package/src/resources/extensions/gsd/auto-start.ts +94 -12
  325. package/src/resources/extensions/gsd/auto-verification.ts +58 -36
  326. package/src/resources/extensions/gsd/auto-worktree.ts +193 -10
  327. package/src/resources/extensions/gsd/auto.ts +187 -61
  328. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +42 -7
  329. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -9
  330. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
  331. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  332. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  333. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +20 -4
  334. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  335. package/src/resources/extensions/gsd/commands/catalog.ts +10 -1
  336. package/src/resources/extensions/gsd/commands/handlers/core.ts +42 -1
  337. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  338. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  339. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  340. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +8 -3
  341. package/src/resources/extensions/gsd/commands-verdict.ts +202 -0
  342. package/src/resources/extensions/gsd/context-store.ts +120 -1
  343. package/src/resources/extensions/gsd/crash-recovery.ts +44 -4
  344. package/src/resources/extensions/gsd/db/milestone-leases.ts +26 -0
  345. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  346. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  347. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  348. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  349. package/src/resources/extensions/gsd/doctor-git-checks.ts +89 -7
  350. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  351. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  352. package/src/resources/extensions/gsd/doctor.ts +2 -27
  353. package/src/resources/extensions/gsd/export-html.ts +27 -427
  354. package/src/resources/extensions/gsd/forensics.ts +3 -3
  355. package/src/resources/extensions/gsd/git-service.ts +51 -4
  356. package/src/resources/extensions/gsd/gsd-db.ts +21 -6
  357. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -3
  358. package/src/resources/extensions/gsd/guided-flow.ts +134 -133
  359. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  360. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  361. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  362. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  363. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  364. package/src/resources/extensions/gsd/markdown-renderer.ts +16 -9
  365. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  366. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  367. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  368. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  369. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  370. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  371. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  372. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  373. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  374. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  375. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  376. package/src/resources/extensions/gsd/paths.ts +5 -0
  377. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  378. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  379. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  380. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  381. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  382. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  383. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  384. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  385. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  386. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  387. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  388. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  389. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  390. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  391. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  392. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  393. package/src/resources/extensions/gsd/queue-reorder-ui.ts +31 -13
  394. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  395. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  396. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  397. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  398. package/src/resources/extensions/gsd/state.ts +3 -3
  399. package/src/resources/extensions/gsd/status-guards.ts +13 -0
  400. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  401. package/src/resources/extensions/gsd/templates/plan.md +9 -5
  402. package/src/resources/extensions/gsd/templates/task-plan.md +10 -2
  403. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  404. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  405. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +131 -0
  406. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  407. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +151 -12
  408. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  409. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +18 -6
  410. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +91 -6
  411. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  412. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  413. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  415. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  416. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  417. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  418. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  419. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  420. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  421. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +378 -0
  422. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  423. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  424. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  425. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  426. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +86 -2
  427. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
  428. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  429. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  430. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  431. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  432. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +66 -0
  434. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  435. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  436. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  437. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  438. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  439. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +11 -0
  440. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  441. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +5 -2
  442. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  443. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  444. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  445. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  446. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  447. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  448. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  449. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  450. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  451. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  452. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  453. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +112 -1
  454. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  455. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  456. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  457. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +46 -0
  458. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  459. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  460. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  461. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  462. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  463. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  464. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  465. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  466. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  467. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  468. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  469. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  470. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  471. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  472. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +2 -1
  473. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  474. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  475. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  476. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +251 -2
  477. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  478. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  479. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  480. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  481. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +84 -0
  482. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  483. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +59 -0
  484. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
  485. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  486. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +37 -1
  487. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  488. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +6 -0
  489. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  490. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +89 -2
  491. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +2 -3
  492. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  493. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  494. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  495. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  496. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  497. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  498. package/src/resources/extensions/gsd/tests/status-guards.test.ts +13 -1
  499. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  500. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  501. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +103 -7
  502. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +29 -2
  503. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  504. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  505. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  506. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +19 -1
  507. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  508. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  509. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  510. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  511. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  512. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  513. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  514. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  515. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  516. package/src/resources/extensions/gsd/tools/plan-slice.ts +97 -12
  517. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  518. package/src/resources/extensions/gsd/types.ts +1 -1
  519. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  520. package/src/resources/extensions/gsd/validation.ts +23 -1
  521. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  522. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  523. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  524. package/src/resources/extensions/gsd/workflow-mcp.ts +18 -1
  525. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  526. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  527. package/src/resources/extensions/gsd/worktree-manager.ts +1 -1
  528. package/src/resources/extensions/shared/html-shell.ts +412 -0
  529. package/src/resources/extensions/subagent/index.ts +567 -103
  530. package/src/resources/extensions/subagent/launch.ts +131 -0
  531. package/src/resources/extensions/subagent/run-store.ts +218 -0
  532. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  533. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  534. package/src/resources/extensions/ttsr/ttsr-manager.ts +5 -1
  535. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  536. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  537. package/src/resources/extensions/visual-brief/index.ts +8 -0
  538. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  539. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  540. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  541. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  542. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +0 -10
  544. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  545. package/dist/web/standalone/.next/static/chunks/app/layout-9ecfd95f343793f0.js +0 -1
  546. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  547. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  548. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  549. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  550. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  551. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  552. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  553. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  554. /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_buildManifest.js +0 -0
  555. /package/dist/web/standalone/.next/static/{S44UQTFCUdA44dkjfYt6S → qoMxZh-xuwuvpFW0x0k01}/_ssgManifest.js +0 -0
@@ -0,0 +1,348 @@
1
+ // ADR-013 Phase 6 cutover (Stage 3) — destructive lock-in.
2
+ //
3
+ // After this stage, new decisions written via gsd_save_decision land ONLY in
4
+ // the memories table. The decisions table receives no new rows; its existing
5
+ // rows remain for backwards-compat reads until #5756 drops the table.
6
+ //
7
+ // Tests cover five properties:
8
+ // 1. New saveDecisionToDb call does NOT insert into the decisions table
9
+ // 2. The new decision DOES appear as a memory row with sourceDecisionId
10
+ // 3. The rendered DECISIONS.md projection includes the new decision
11
+ // 4. Pre-existing decisions-table rows are untouched
12
+ // 5. Decision IDs are monotonic across both surfaces (max of either + 1)
13
+
14
+ import test from "node:test";
15
+ import assert from "node:assert/strict";
16
+ import {
17
+ existsSync,
18
+ mkdirSync,
19
+ mkdtempSync,
20
+ readFileSync,
21
+ rmSync,
22
+ } from "node:fs";
23
+ import { join } from "node:path";
24
+ import { tmpdir } from "node:os";
25
+
26
+ import {
27
+ _getAdapter,
28
+ closeDatabase,
29
+ insertDecision,
30
+ openDatabase,
31
+ } from "../gsd-db.ts";
32
+ import { saveDecisionToDb } from "../db-writer.ts";
33
+ import {
34
+ getAllDecisionsFromMemories,
35
+ queryDecisions,
36
+ } from "../context-store.ts";
37
+
38
+ function makeTmpBase(): string {
39
+ const base = mkdtempSync(join(tmpdir(), "gsd-decisions-stage3-"));
40
+ mkdirSync(join(base, ".gsd"), { recursive: true });
41
+ openDatabase(join(base, ".gsd", "gsd.db"));
42
+ return base;
43
+ }
44
+
45
+ function cleanup(base: string): void {
46
+ try {
47
+ closeDatabase();
48
+ } catch {
49
+ /* noop */
50
+ }
51
+ try {
52
+ rmSync(base, { recursive: true, force: true });
53
+ } catch {
54
+ /* noop */
55
+ }
56
+ }
57
+
58
+ function countDecisionRows(): number {
59
+ const adapter = _getAdapter();
60
+ if (!adapter) return 0;
61
+ const row = adapter
62
+ .prepare("SELECT COUNT(*) as n FROM decisions")
63
+ .get() as { n: number };
64
+ return row.n;
65
+ }
66
+
67
+ function seedLegacyDecision(args: {
68
+ id: string;
69
+ when_context: string;
70
+ scope: string;
71
+ decision: string;
72
+ choice: string;
73
+ rationale: string;
74
+ superseded_by?: string | null;
75
+ }): void {
76
+ insertDecision({
77
+ id: args.id,
78
+ when_context: args.when_context,
79
+ scope: args.scope,
80
+ decision: args.decision,
81
+ choice: args.choice,
82
+ rationale: args.rationale,
83
+ revisable: "Yes",
84
+ made_by: "agent",
85
+ superseded_by: args.superseded_by ?? null,
86
+ });
87
+ }
88
+
89
+ // ─── Core invariants ────────────────────────────────────────────────────────
90
+
91
+ test("saveDecisionToDb no longer writes to the decisions table", async () => {
92
+ const base = makeTmpBase();
93
+ try {
94
+ const before = countDecisionRows();
95
+ assert.equal(before, 0);
96
+
97
+ await saveDecisionToDb(
98
+ {
99
+ when_context: "M001 discuss",
100
+ scope: "M001",
101
+ decision: "Stage 3 destructive: memories-only writes",
102
+ choice: "Drop the upsertDecision call",
103
+ rationale: "Cutover step required by ADR-013 Phase 6",
104
+ revisable: "Yes",
105
+ made_by: "agent",
106
+ },
107
+ base,
108
+ );
109
+
110
+ const after = countDecisionRows();
111
+ assert.equal(after, 0, "decisions table must remain empty after Stage 3 save");
112
+ } finally {
113
+ cleanup(base);
114
+ }
115
+ });
116
+
117
+ test("saveDecisionToDb writes the new decision into memories with sourceDecisionId", async () => {
118
+ const base = makeTmpBase();
119
+ try {
120
+ const { id } = await saveDecisionToDb(
121
+ {
122
+ when_context: "M001 discuss",
123
+ scope: "M001",
124
+ decision: "Use atomic file writes",
125
+ choice: "atomicWriteSync",
126
+ rationale: "crash-safe markdown projections",
127
+ revisable: "Yes",
128
+ made_by: "agent",
129
+ },
130
+ base,
131
+ );
132
+
133
+ const fromMemories = getAllDecisionsFromMemories();
134
+ assert.equal(fromMemories.length, 1);
135
+ assert.equal(fromMemories[0]?.id, id);
136
+ assert.equal(fromMemories[0]?.decision, "Use atomic file writes");
137
+ } finally {
138
+ cleanup(base);
139
+ }
140
+ });
141
+
142
+ test("DECISIONS.md projection includes the memory-only decision", async () => {
143
+ const base = makeTmpBase();
144
+ try {
145
+ await saveDecisionToDb(
146
+ {
147
+ when_context: "M001 discuss",
148
+ scope: "M001",
149
+ decision: "Adopt SQLite",
150
+ choice: "better-sqlite3",
151
+ rationale: "synchronous + native",
152
+ revisable: "Yes",
153
+ made_by: "agent",
154
+ },
155
+ base,
156
+ );
157
+
158
+ const md = readFileSync(join(base, ".gsd", "DECISIONS.md"), "utf-8");
159
+ assert.match(md, /\| D001 \|/);
160
+ assert.match(md, /Adopt SQLite/);
161
+ assert.match(md, /# Decisions Register/);
162
+ } finally {
163
+ cleanup(base);
164
+ }
165
+ });
166
+
167
+ // ─── Existing decisions table is preserved ──────────────────────────────────
168
+
169
+ test("pre-existing decisions-table rows are untouched by Stage 3 saves", async () => {
170
+ const base = makeTmpBase();
171
+ try {
172
+ // Seed two legacy decisions directly into the table — simulates a
173
+ // pre-cutover project.
174
+ seedLegacyDecision({
175
+ id: "D001",
176
+ when_context: "M001 historical",
177
+ scope: "M001",
178
+ decision: "Legacy decision one",
179
+ choice: "A",
180
+ rationale: "r1",
181
+ });
182
+ seedLegacyDecision({
183
+ id: "D002",
184
+ when_context: "M001 historical",
185
+ scope: "M001",
186
+ decision: "Legacy decision two",
187
+ choice: "B",
188
+ rationale: "r2",
189
+ });
190
+ assert.equal(countDecisionRows(), 2);
191
+
192
+ // New save via the cutover path.
193
+ await saveDecisionToDb(
194
+ {
195
+ when_context: "M001 today",
196
+ scope: "M001",
197
+ decision: "Post-cutover decision",
198
+ choice: "C",
199
+ rationale: "r3",
200
+ revisable: "Yes",
201
+ made_by: "agent",
202
+ },
203
+ base,
204
+ );
205
+
206
+ // Decisions table unchanged.
207
+ assert.equal(countDecisionRows(), 2);
208
+
209
+ // Legacy reads still see the pre-existing rows.
210
+ const fromLegacy = queryDecisions();
211
+ assert.equal(fromLegacy.length, 2);
212
+ assert.deepEqual(
213
+ fromLegacy.map((d) => d.id).sort(),
214
+ ["D001", "D002"],
215
+ );
216
+ } finally {
217
+ cleanup(base);
218
+ }
219
+ });
220
+
221
+ // ─── Cross-surface ID monotonicity ─────────────────────────────────────────
222
+
223
+ test("decision IDs are monotonic across legacy table + memory surfaces", async () => {
224
+ const base = makeTmpBase();
225
+ try {
226
+ // Pre-cutover project with D001..D005 in the legacy table (no memory
227
+ // backfill yet — simulates an upgrade that hasn't run backfill).
228
+ for (let i = 1; i <= 5; i++) {
229
+ seedLegacyDecision({
230
+ id: `D${String(i).padStart(3, "0")}`,
231
+ when_context: "historical",
232
+ scope: "M001",
233
+ decision: `Decision ${i}`,
234
+ choice: "x",
235
+ rationale: "y",
236
+ });
237
+ }
238
+ assert.equal(countDecisionRows(), 5);
239
+
240
+ // First Stage 3 save: must pick the next-after-table ID.
241
+ const a = await saveDecisionToDb(
242
+ {
243
+ when_context: "M001 today",
244
+ scope: "M001",
245
+ decision: "First post-cutover",
246
+ choice: "A",
247
+ rationale: "r",
248
+ revisable: "Yes",
249
+ made_by: "agent",
250
+ },
251
+ base,
252
+ );
253
+ assert.equal(a.id, "D006", "first cutover save must follow the legacy table max (D005 -> D006)");
254
+
255
+ // Second save: must pick the next-after-memory ID.
256
+ const b = await saveDecisionToDb(
257
+ {
258
+ when_context: "M001 today",
259
+ scope: "M001",
260
+ decision: "Second post-cutover",
261
+ choice: "B",
262
+ rationale: "r",
263
+ revisable: "Yes",
264
+ made_by: "agent",
265
+ },
266
+ base,
267
+ );
268
+ assert.equal(b.id, "D007", "second cutover save must follow memory max (D006 -> D007)");
269
+
270
+ // Decisions table still has only the original five.
271
+ assert.equal(countDecisionRows(), 5);
272
+ } finally {
273
+ cleanup(base);
274
+ }
275
+ });
276
+
277
+ test("next-ID falls back to D001 when both surfaces are empty", async () => {
278
+ const base = makeTmpBase();
279
+ try {
280
+ const { id } = await saveDecisionToDb(
281
+ {
282
+ when_context: "M001",
283
+ scope: "M001",
284
+ decision: "First ever",
285
+ choice: "A",
286
+ rationale: "r",
287
+ revisable: "Yes",
288
+ made_by: "agent",
289
+ },
290
+ base,
291
+ );
292
+ assert.equal(id, "D001");
293
+ } finally {
294
+ cleanup(base);
295
+ }
296
+ });
297
+
298
+ test("next-ID skips beyond memory-only entries when the legacy table is empty", async () => {
299
+ const base = makeTmpBase();
300
+ try {
301
+ // Three memory-only saves on a fresh project.
302
+ const a = await saveDecisionToDb(
303
+ { when_context: "M001", scope: "M001", decision: "A", choice: "1", rationale: "r", revisable: "Yes", made_by: "agent" },
304
+ base,
305
+ );
306
+ const b = await saveDecisionToDb(
307
+ { when_context: "M001", scope: "M001", decision: "B", choice: "2", rationale: "r", revisable: "Yes", made_by: "agent" },
308
+ base,
309
+ );
310
+ const c = await saveDecisionToDb(
311
+ { when_context: "M001", scope: "M001", decision: "C", choice: "3", rationale: "r", revisable: "Yes", made_by: "agent" },
312
+ base,
313
+ );
314
+
315
+ assert.deepEqual([a.id, b.id, c.id], ["D001", "D002", "D003"]);
316
+ assert.equal(countDecisionRows(), 0, "no decisions-table writes despite three saves");
317
+ } finally {
318
+ cleanup(base);
319
+ }
320
+ });
321
+
322
+ // ─── Defensive: malformed structured_fields don't break next-ID ────────────
323
+
324
+ test("malformed structuredFields in memories are silently skipped during next-ID computation", async () => {
325
+ const base = makeTmpBase();
326
+ try {
327
+ // Insert a memory with broken JSON in structured_fields. The next-ID
328
+ // logic must not throw.
329
+ const adapter = _getAdapter();
330
+ assert.ok(adapter);
331
+ adapter
332
+ .prepare(
333
+ "INSERT INTO memories (id, category, content, confidence, created_at, updated_at, structured_fields) VALUES ('mem-broken', 'architecture', 'oops', 0.5, datetime('now'), datetime('now'), '{\"sourceDecisionId\":\"D999\"')",
334
+ )
335
+ .run();
336
+
337
+ const { id } = await saveDecisionToDb(
338
+ { when_context: "M001", scope: "M001", decision: "Survivor", choice: "x", rationale: "y", revisable: "Yes", made_by: "agent" },
339
+ base,
340
+ );
341
+
342
+ // Broken JSON for D999 doesn't parse, so the surfaced max stays at 0.
343
+ // The new save must still produce a valid sequential ID.
344
+ assert.equal(id, "D001");
345
+ } finally {
346
+ cleanup(base);
347
+ }
348
+ });
@@ -1,6 +1,6 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
3
+ import { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { execFileSync } from "node:child_process";
5
5
  import { tmpdir } from "node:os";
6
6
  import { join } from "node:path";
@@ -10,7 +10,7 @@ import { runDispatch, runPreDispatch } from "../auto/phases.ts";
10
10
  import { AutoSession } from "../auto/session.ts";
11
11
  import { resolveUnitSupervisionTimeouts } from "../auto-timers.ts";
12
12
  import { bootstrapAutoSession } from "../auto-start.ts";
13
- import { postUnitPreVerification } from "../auto-post-unit.ts";
13
+ import { postUnitPostVerification, postUnitPreVerification } from "../auto-post-unit.ts";
14
14
  import { resolveDispatch, setResearchProjectPromptBuilderForTest } from "../auto-dispatch.ts";
15
15
  import { resolveExpectedArtifactPath, verifyExpectedArtifact, writeBlockerPlaceholder } from "../auto-recovery.ts";
16
16
  import { finalizeProjectResearchTimeout } from "../project-research-policy.ts";
@@ -272,6 +272,7 @@ test("deep project setup: bootstrap can start auto-mode without an active milest
272
272
  {
273
273
  shouldUseWorktreeIsolation: () => false,
274
274
  registerSigtermHandler: () => {},
275
+ registerAutoWorkerForSession: () => {},
275
276
  lockBase: () => base,
276
277
  buildLifecycle: () => ({
277
278
  adoptSessionRoot: (sessionBase: string, originalBase?: string) => {
@@ -386,6 +387,7 @@ test("deep project setup: bootstrap continues queued M002 without milestone cont
386
387
  {
387
388
  shouldUseWorktreeIsolation: () => false,
388
389
  registerSigtermHandler: () => {},
390
+ registerAutoWorkerForSession: () => {},
389
391
  lockBase: () => base,
390
392
  buildLifecycle: () => ({
391
393
  adoptSessionRoot: (sessionBase: string, originalBase?: string) => {
@@ -1587,6 +1589,61 @@ test("deep project setup: discuss-milestone question failure pauses instead of a
1587
1589
  }
1588
1590
  });
1589
1591
 
1592
+ test("verified task git closeout failure retries and continues auto-mode", async () => {
1593
+ const base = makeBase();
1594
+ try {
1595
+ execFileSync("git", ["init"], { cwd: base, stdio: "ignore" });
1596
+ execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: base, stdio: "ignore" });
1597
+ execFileSync("git", ["config", "user.name", "Test User"], { cwd: base, stdio: "ignore" });
1598
+ const hookPath = join(base, ".git", "hooks", "pre-commit");
1599
+ writeFileSync(
1600
+ hookPath,
1601
+ [
1602
+ "#!/bin/sh",
1603
+ "count_file=.git/pre-commit-count",
1604
+ "count=0",
1605
+ "if [ -f \"$count_file\" ]; then count=$(cat \"$count_file\"); fi",
1606
+ "count=$((count + 1))",
1607
+ "printf \"%s\" \"$count\" > \"$count_file\"",
1608
+ "echo blocked by test hook >&2",
1609
+ "exit 1",
1610
+ ].join("\n"),
1611
+ );
1612
+ chmodSync(hookPath, 0o755);
1613
+ writeFileSync(join(base, "work.txt"), "changed\n");
1614
+
1615
+ const s = new AutoSession();
1616
+ s.active = true;
1617
+ s.basePath = base;
1618
+ s.originalBasePath = base;
1619
+ s.currentUnit = { type: "execute-task", id: "M001/S01/T01", startedAt: Date.now() };
1620
+
1621
+ let pauseCalled = false;
1622
+ const notifications: Array<{ message: string; severity?: string }> = [];
1623
+ const result = await postUnitPostVerification({
1624
+ s,
1625
+ ctx: { ui: { notify: (message: string, severity?: string) => notifications.push({ message, severity }) } } as any,
1626
+ pi: {} as any,
1627
+ buildSnapshotOpts: () => ({}) as any,
1628
+ lockBase: () => base,
1629
+ stopAuto: async () => {},
1630
+ pauseAuto: async () => { pauseCalled = true; },
1631
+ updateProgressWidget: () => {},
1632
+ });
1633
+
1634
+ assert.equal(result, "continue");
1635
+ assert.equal(pauseCalled, false);
1636
+ assert.equal(s.lastGitActionStatus, "failed");
1637
+ assert.equal(readFileSync(join(base, ".git", "pre-commit-count"), "utf-8"), "3");
1638
+ assert.ok(
1639
+ notifications.some((entry) => entry.severity === "warning" && entry.message.includes("Git commit failed")),
1640
+ "verified task git closeout failure should warn instead of stopping auto-mode",
1641
+ );
1642
+ } finally {
1643
+ rmSync(base, { recursive: true, force: true });
1644
+ }
1645
+ });
1646
+
1590
1647
  test("deep project setup: approval wait wins over deterministic write-gate placeholder", async () => {
1591
1648
  const base = makeBase();
1592
1649
  try {
@@ -10,6 +10,7 @@ import assert from "node:assert/strict";
10
10
  import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import { tmpdir } from "node:os";
13
+ import { execFileSync } from "node:child_process";
13
14
 
14
15
  import { DISPATCH_RULES, type DispatchContext } from "../auto-dispatch.ts";
15
16
  import { closeDatabase, insertMilestone, openDatabase } from "../gsd-db.ts";
@@ -23,6 +24,14 @@ function makeBase(): string {
23
24
  return base;
24
25
  }
25
26
 
27
+ function initGitRepo(base: string): void {
28
+ execFileSync("git", ["init"], { cwd: base, stdio: "ignore" });
29
+ execFileSync("git", ["config", "user.email", "test@test.com"], { cwd: base, stdio: "ignore" });
30
+ execFileSync("git", ["config", "user.name", "Test"], { cwd: base, stdio: "ignore" });
31
+ execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
32
+ execFileSync("git", ["commit", "-m", "initial"], { cwd: base, stdio: "ignore" });
33
+ }
34
+
26
35
  function buildDispatchCtx(basePath: string): DispatchContext {
27
36
  return {
28
37
  basePath,
@@ -76,6 +85,24 @@ describe("completing-milestone dispatch guard (#4324)", () => {
76
85
  assert.equal(result?.unitType, "complete-milestone");
77
86
  assert.equal(result?.unitId, "M001");
78
87
  });
88
+
89
+ test("dispatches complete-milestone when only .gsd/ files exist in git history (#5097)", async () => {
90
+ base = makeBase();
91
+ rmSync(join(base, "implementation.txt"), { force: true });
92
+ initGitRepo(base);
93
+ writeFileSync(join(base, ".gsd", "milestones", "M001", "M001-SUMMARY.md"), "# Milestone Summary\n");
94
+ execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
95
+ execFileSync("git", ["commit", "-m", "chore: planning artifacts only"], { cwd: base, stdio: "ignore" });
96
+
97
+ openDatabase(join(base, ".gsd", "gsd.db"));
98
+ insertMilestone({ id: "M001", title: "Milestone One", status: "active" });
99
+
100
+ const result = await rule.match(buildDispatchCtx(base));
101
+
102
+ assert.equal(result?.action, "dispatch");
103
+ assert.equal(result?.unitType, "complete-milestone");
104
+ assert.equal(result?.unitId, "M001");
105
+ });
79
106
  });
80
107
 
81
108
  describe("complete phase dispatch guard (#5683)", () => {
@@ -118,3 +145,42 @@ describe("complete phase dispatch guard (#5683)", () => {
118
145
  assert.equal(result?.reason, "All milestones complete.");
119
146
  });
120
147
  });
148
+
149
+ describe("complete milestone context recovery guard (#5831)", () => {
150
+ let base = "";
151
+ const executionEntryRule = DISPATCH_RULES.find(
152
+ (candidate) => candidate.name === "execution-entry phase (no context) → discuss-milestone",
153
+ );
154
+ const prePlanningRule = DISPATCH_RULES.find(
155
+ (candidate) => candidate.name === "pre-planning (no context) → discuss-milestone",
156
+ );
157
+ assert.ok(executionEntryRule, "execution-entry missing-context rule should exist");
158
+ assert.ok(prePlanningRule, "pre-planning missing-context rule should exist");
159
+
160
+ afterEach(() => {
161
+ if (base) rmSync(base, { recursive: true, force: true });
162
+ base = "";
163
+ });
164
+
165
+ test("does not discuss a complete execution-entry milestone with no CONTEXT file", async () => {
166
+ base = makeBase();
167
+ const ctx = buildDispatchCtx(base);
168
+ ctx.state.registry = [{ id: "M001", title: "Milestone One", status: "complete" }];
169
+ ctx.state.phase = "completing-milestone";
170
+
171
+ const result = await executionEntryRule.match(ctx);
172
+
173
+ assert.equal(result, null);
174
+ });
175
+
176
+ test("does not discuss a complete pre-planning milestone with no CONTEXT file", async () => {
177
+ base = makeBase();
178
+ const ctx = buildDispatchCtx(base);
179
+ ctx.state.registry = [{ id: "M001", title: "Milestone One", status: "complete" }];
180
+ ctx.state.phase = "pre-planning";
181
+
182
+ const result = await prePlanningRule.match(ctx);
183
+
184
+ assert.equal(result, null);
185
+ });
186
+ });
@@ -47,6 +47,33 @@ test("dispatch guard blocks when prior milestone has incomplete slices", (t) =>
47
47
  );
48
48
  });
49
49
 
50
+ test("dispatch guard skips prior DB parked or deferred milestones without marker files", (t) => {
51
+ const repo = setupRepo();
52
+ t.after(() => teardownRepo(repo));
53
+
54
+ mkdirSync(join(repo, ".gsd", "milestones", "M001"), { recursive: true });
55
+ mkdirSync(join(repo, ".gsd", "milestones", "M002"), { recursive: true });
56
+ mkdirSync(join(repo, ".gsd", "milestones", "M003"), { recursive: true });
57
+
58
+ insertMilestone({ id: "M001", title: "Parked", status: "parked" });
59
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Incomplete", status: "pending", depends: [], sequence: 1 });
60
+
61
+ insertMilestone({ id: "M002", title: "Deferred", status: "deferred" });
62
+ insertSlice({ id: "S01", milestoneId: "M002", title: "Incomplete", status: "pending", depends: [], sequence: 1 });
63
+
64
+ insertMilestone({ id: "M003", title: "Current", status: "active" });
65
+ insertSlice({ id: "S01", milestoneId: "M003", title: "First", status: "pending", depends: [], sequence: 1 });
66
+
67
+ writeFileSync(join(repo, ".gsd", "milestones", "M001", "M001-ROADMAP.md"), "# M001\n");
68
+ writeFileSync(join(repo, ".gsd", "milestones", "M002", "M002-ROADMAP.md"), "# M002\n");
69
+ writeFileSync(join(repo, ".gsd", "milestones", "M003", "M003-ROADMAP.md"), "# M003\n");
70
+
71
+ assert.equal(
72
+ getPriorSliceCompletionBlocker(repo, "main", "plan-slice", "M003/S01"),
73
+ null,
74
+ );
75
+ });
76
+
50
77
  test("dispatch guard blocks later slice in same milestone when earlier incomplete", (t) => {
51
78
  const repo = setupRepo();
52
79
  t.after(() => teardownRepo(repo));
@@ -0,0 +1,65 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Regression tests for doctor repair of empty milestone worktrees.
3
+
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { execFileSync } from "node:child_process";
7
+ import { existsSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+
11
+ import { runGSDDoctor } from "../doctor.ts";
12
+ import { createWorktree, worktreePath } from "../worktree-manager.ts";
13
+
14
+ function runGit(args: string[], cwd: string): string {
15
+ return execFileSync("git", args, {
16
+ cwd,
17
+ stdio: ["ignore", "pipe", "pipe"],
18
+ encoding: "utf-8",
19
+ }).trim();
20
+ }
21
+
22
+ function makeRepo(): string {
23
+ const base = mkdtempSync(join(tmpdir(), "gsd-doctor-empty-worktree-"));
24
+ runGit(["init", "-b", "main"], base);
25
+ runGit(["config", "user.name", "Test User"], base);
26
+ runGit(["config", "user.email", "test@example.com"], base);
27
+ writeFileSync(join(base, "package.json"), "{\"scripts\":{}}\n", "utf-8");
28
+ runGit(["add", "."], base);
29
+ runGit(["commit", "-m", "chore: init"], base);
30
+ return base;
31
+ }
32
+
33
+ test("doctor fix recreates an empty registered milestone worktree", async (t) => {
34
+ const base = makeRepo();
35
+ t.after(() => rmSync(base, { recursive: true, force: true }));
36
+
37
+ createWorktree(base, "M001", { branch: "milestone/M001" });
38
+ const wtPath = worktreePath(base, "M001");
39
+ writeFileSync(join(wtPath, "milestone-note.txt"), "worktree branch content\n", "utf-8");
40
+ runGit(["add", "milestone-note.txt"], wtPath);
41
+ runGit(["commit", "-m", "test: add milestone content"], wtPath);
42
+ for (const entry of readdirSync(wtPath)) {
43
+ if (entry === ".git") continue;
44
+ rmSync(join(wtPath, entry), { recursive: true, force: true });
45
+ }
46
+ assert.ok(existsSync(join(wtPath, ".git")), "test setup keeps registered worktree marker");
47
+ assert.equal(existsSync(join(wtPath, "package.json")), false, "test setup removes project content");
48
+
49
+ const report = await runGSDDoctor(base, {
50
+ fix: true,
51
+ fixLevel: "all",
52
+ isolationMode: "worktree",
53
+ });
54
+
55
+ assert.ok(
56
+ report.issues.some((issue) => issue.code === "worktree_empty_with_project_content"),
57
+ "doctor reports the empty worktree",
58
+ );
59
+ assert.ok(
60
+ report.fixesApplied.some((fix) => fix.includes("recreated empty worktree")),
61
+ "doctor applies the repair",
62
+ );
63
+ assert.ok(existsSync(join(wtPath, "package.json")), "worktree content is restored");
64
+ assert.ok(existsSync(join(wtPath, "milestone-note.txt")), "branch content is restored");
65
+ });
@@ -0,0 +1,38 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Tests for verification evidence cross-reference mismatch policy.
3
+
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+
7
+ import { crossReferenceEvidence } from "../safety/evidence-cross-ref.ts";
8
+ import type { EvidenceEntry } from "../safety/evidence-collector.ts";
9
+
10
+ test("claims of passing verification become errors when recorded bash evidence failed", () => {
11
+ const mismatches = crossReferenceEvidence(
12
+ [{ command: "npm test", exitCode: 0, verdict: "passed" }],
13
+ [
14
+ {
15
+ kind: "bash",
16
+ toolCallId: "call-1",
17
+ command: "npm test",
18
+ exitCode: 1,
19
+ outputSnippet: "failed",
20
+ timestamp: Date.now(),
21
+ },
22
+ ] as EvidenceEntry[],
23
+ );
24
+
25
+ assert.equal(mismatches.length, 1);
26
+ assert.equal(mismatches[0].severity, "error");
27
+ assert.match(mismatches[0].reason, /Claimed exitCode=0/);
28
+ });
29
+
30
+ test("missing recorded bash evidence remains a warning", () => {
31
+ const mismatches = crossReferenceEvidence(
32
+ [{ command: "npm test", exitCode: 0, verdict: "passed" }],
33
+ [],
34
+ );
35
+
36
+ assert.equal(mismatches.length, 1);
37
+ assert.equal(mismatches[0].severity, "warning");
38
+ });
@@ -141,6 +141,14 @@ test("Feature 1: executive summary paragraph is rendered", () => {
141
141
  assert.ok(html.includes("$2.50 spent"), "should contain cost");
142
142
  });
143
143
 
144
+ test("report uses the shared GSD HTML shell", () => {
145
+ const html = generateHtmlReport(mockData(), mockOpts());
146
+ assert.ok(html.includes('<span class="logo">GSD</span>'), "should render shared shell logo");
147
+ assert.ok(html.includes('<span class="kind-chip">Report</span>'), "should render report kind chip");
148
+ assert.ok(html.includes('<nav class="toc" aria-label="Report sections">'), "should render shared shell TOC");
149
+ assert.ok(html.includes('<main>'), "should render content inside shared shell main");
150
+ });
151
+
144
152
  test("Feature 1: executive summary includes budget context when set", () => {
145
153
  const data = mockData({ health: { ...mockData().health, budgetCeiling: 10.00 } });
146
154
  const html = generateHtmlReport(data, mockOpts());