gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.cf9433f56

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 (443) hide show
  1. package/README.md +4 -2
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +2 -2
  4. package/dist/resources/extensions/github-sync/templates.js +39 -8
  5. package/dist/resources/extensions/gsd/auto/loop.js +48 -10
  6. package/dist/resources/extensions/gsd/auto/phases.js +66 -45
  7. package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
  8. package/dist/resources/extensions/gsd/auto/run-unit.js +32 -16
  9. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
  12. package/dist/resources/extensions/gsd/auto-prompts.js +124 -2
  13. package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
  14. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  15. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  16. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  17. package/dist/resources/extensions/gsd/auto.js +77 -5
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +36 -3
  19. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +27 -20
  20. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -1
  21. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  22. package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
  23. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  24. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  25. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  26. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  27. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  28. package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
  29. package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
  30. package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
  31. package/dist/resources/extensions/gsd/detection.js +106 -0
  32. package/dist/resources/extensions/gsd/git-service.js +36 -4
  33. package/dist/resources/extensions/gsd/graph.js +9 -3
  34. package/dist/resources/extensions/gsd/gsd-db.js +146 -13
  35. package/dist/resources/extensions/gsd/guided-flow.js +82 -16
  36. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  37. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  38. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  39. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  40. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  41. package/dist/resources/extensions/gsd/pre-execution-checks.js +7 -0
  42. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  43. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
  44. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  46. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  47. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  48. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  49. package/dist/resources/extensions/gsd/quick.js +34 -2
  50. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  51. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  52. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  53. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  54. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  55. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  56. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  57. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  58. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  59. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  60. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  61. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  62. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  63. package/dist/resources/extensions/gsd/worktree-resolver.js +33 -17
  64. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  65. package/dist/web/standalone/.next/BUILD_ID +1 -1
  66. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  67. package/dist/web/standalone/.next/build-manifest.json +3 -3
  68. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  69. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/index.html +1 -1
  88. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  95. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  96. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  99. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  100. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  101. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  102. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  103. package/package.json +12 -8
  104. package/packages/contracts/package.json +1 -1
  105. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  106. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  107. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  108. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  109. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  110. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  111. package/packages/native/tsconfig.tsbuildinfo +1 -1
  112. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  113. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  114. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  115. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  116. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  117. package/packages/pi-ai/dist/models/index.js +8 -0
  118. package/packages/pi-ai/dist/models/index.js.map +1 -1
  119. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  120. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  121. package/packages/pi-ai/dist/providers/fake.js +319 -0
  122. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  123. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  124. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  125. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  126. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  127. package/packages/pi-ai/src/models/index.ts +9 -0
  128. package/packages/pi-ai/src/providers/fake.ts +376 -0
  129. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  130. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  131. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  132. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  133. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  134. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -0
  135. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  136. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
  137. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  139. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  141. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  143. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  144. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  145. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  146. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  147. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  148. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  149. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  150. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  151. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  152. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  153. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  154. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
  155. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/extensions/runner.js +17 -1
  157. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +99 -0
  159. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
  161. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  163. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  164. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  165. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
  167. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  168. package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
  169. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  172. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  173. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  174. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  176. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  178. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  180. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  182. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  183. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  184. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  185. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  188. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  189. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  190. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  191. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  193. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  195. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
  197. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
  202. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  203. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  205. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  206. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  208. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  209. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  216. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  218. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  220. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  222. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  226. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  231. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  233. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  235. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  237. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  238. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  239. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  240. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  241. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  242. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  243. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  244. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  245. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  246. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  247. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  248. package/packages/pi-coding-agent/src/core/agent-session.ts +8 -0
  249. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
  250. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  251. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  252. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  253. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  254. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +110 -0
  255. package/packages/pi-coding-agent/src/core/extensions/runner.ts +19 -1
  256. package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
  257. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  258. package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
  259. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  260. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  261. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  262. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  263. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  264. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  265. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  266. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  267. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  268. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
  269. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
  270. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
  271. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  272. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  273. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
  274. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  275. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  276. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  277. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  278. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  279. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  280. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  281. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  282. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  283. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  284. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  285. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  286. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  287. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  288. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  289. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  290. package/packages/pi-tui/dist/index.d.ts +1 -0
  291. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  292. package/packages/pi-tui/dist/index.js +2 -0
  293. package/packages/pi-tui/dist/index.js.map +1 -1
  294. package/packages/pi-tui/dist/style.d.ts +41 -0
  295. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  296. package/packages/pi-tui/dist/style.js +158 -0
  297. package/packages/pi-tui/dist/style.js.map +1 -0
  298. package/packages/pi-tui/dist/tui.d.ts +0 -1
  299. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  300. package/packages/pi-tui/dist/tui.js +21 -16
  301. package/packages/pi-tui/dist/tui.js.map +1 -1
  302. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  303. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  304. package/packages/pi-tui/src/index.ts +9 -0
  305. package/packages/pi-tui/src/style.ts +225 -0
  306. package/packages/pi-tui/src/tui.ts +23 -16
  307. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  308. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  309. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  310. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  311. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  312. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  313. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  314. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  315. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  316. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  317. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  318. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  319. package/src/resources/GSD-WORKFLOW.md +2 -2
  320. package/src/resources/extensions/github-sync/templates.ts +38 -8
  321. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  322. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  323. package/src/resources/extensions/gsd/auto/loop.ts +67 -18
  324. package/src/resources/extensions/gsd/auto/phases.ts +77 -48
  325. package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
  326. package/src/resources/extensions/gsd/auto/run-unit.ts +42 -15
  327. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  328. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
  329. package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
  330. package/src/resources/extensions/gsd/auto-prompts.ts +133 -2
  331. package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
  332. package/src/resources/extensions/gsd/auto-start.ts +7 -6
  333. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  334. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  335. package/src/resources/extensions/gsd/auto.ts +92 -4
  336. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +37 -2
  337. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +27 -19
  338. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -1
  339. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  340. package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
  341. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  342. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  343. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  344. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  345. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  346. package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
  347. package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
  348. package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
  349. package/src/resources/extensions/gsd/detection.ts +128 -0
  350. package/src/resources/extensions/gsd/git-service.ts +46 -8
  351. package/src/resources/extensions/gsd/graph.ts +12 -5
  352. package/src/resources/extensions/gsd/gsd-db.ts +168 -13
  353. package/src/resources/extensions/gsd/guided-flow.ts +98 -16
  354. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  355. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  356. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  357. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  358. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  359. package/src/resources/extensions/gsd/pre-execution-checks.ts +7 -0
  360. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  361. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  362. package/src/resources/extensions/gsd/prompts/complete-milestone.md +19 -19
  363. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  364. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  365. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  366. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  367. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  368. package/src/resources/extensions/gsd/quick.ts +37 -2
  369. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  370. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  371. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  372. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +155 -5
  373. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  374. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
  375. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
  376. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  377. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  378. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  379. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  380. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  381. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
  382. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  383. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  384. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  385. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  386. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  387. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  388. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  389. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  390. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  391. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  392. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  393. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  394. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  395. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  396. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
  397. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +234 -0
  398. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  399. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  400. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  401. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  402. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  403. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  404. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  405. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +38 -0
  406. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  407. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  408. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  409. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  410. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  411. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  412. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  413. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  414. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  415. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
  416. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  417. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  418. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
  419. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  420. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  421. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  422. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  423. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  424. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  425. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  426. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +63 -1
  427. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  428. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  429. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  430. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  431. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  432. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  433. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  434. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  435. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  436. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  437. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  438. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  439. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  440. package/src/resources/extensions/gsd/worktree-resolver.ts +36 -15
  441. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  442. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → -5nHJWzSdG-WkPMul_khA}/_buildManifest.js +0 -0
  443. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → -5nHJWzSdG-WkPMul_khA}/_ssgManifest.js +0 -0
@@ -25,6 +25,50 @@ import {
25
25
 
26
26
  import type { MigrationPreview } from "./writer.js";
27
27
  import { homedir } from "node:os";
28
+ import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
29
+ import { clearEngineHierarchy, transaction } from "../gsd-db.js";
30
+ import { migrateFromMarkdown } from "../md-importer.js";
31
+ import { invalidateStateCache } from "../state.js";
32
+
33
+ export type MigrationImportCounts = ReturnType<typeof migrateFromMarkdown>;
34
+
35
+ function assertMigrationImportMatchesPreview(imported: MigrationImportCounts, preview: MigrationPreview): void {
36
+ const mismatches: string[] = [];
37
+ if (imported.hierarchy.milestones !== preview.milestoneCount) {
38
+ mismatches.push(`milestones ${imported.hierarchy.milestones}/${preview.milestoneCount}`);
39
+ }
40
+ if (imported.hierarchy.slices !== preview.totalSlices) {
41
+ mismatches.push(`slices ${imported.hierarchy.slices}/${preview.totalSlices}`);
42
+ }
43
+ if (imported.hierarchy.tasks !== preview.totalTasks) {
44
+ mismatches.push(`tasks ${imported.hierarchy.tasks}/${preview.totalTasks}`);
45
+ }
46
+ if (imported.requirements !== preview.requirements.total) {
47
+ mismatches.push(`requirements ${imported.requirements}/${preview.requirements.total}`);
48
+ }
49
+ if (mismatches.length > 0) {
50
+ throw new Error(`migration DB import verification failed: ${mismatches.join(", ")}`);
51
+ }
52
+ }
53
+
54
+ export async function importWrittenMigrationToDb(
55
+ basePath: string,
56
+ preview?: MigrationPreview,
57
+ ): Promise<MigrationImportCounts> {
58
+ const opened = await ensureDbOpen(basePath);
59
+ if (!opened) {
60
+ throw new Error(`failed to open or create the GSD database at ${basePath}`);
61
+ }
62
+
63
+ const counts = transaction(() => {
64
+ clearEngineHierarchy();
65
+ const imported = migrateFromMarkdown(basePath);
66
+ if (preview) assertMigrationImportMatchesPreview(imported, preview);
67
+ return imported;
68
+ });
69
+ invalidateStateCache();
70
+ return counts;
71
+ }
28
72
 
29
73
  /** Format preview stats for embedding in the review prompt. */
30
74
  function formatPreviewStats(preview: MigrationPreview): string {
@@ -182,9 +226,10 @@ export async function handleMigrate(
182
226
 
183
227
  const result = await writeGSDDirectory(project, process.cwd());
184
228
  const gsdPath = gsdRoot(process.cwd());
229
+ const imported = await importWrittenMigrationToDb(process.cwd(), preview);
185
230
 
186
231
  ctx.ui.notify(
187
- `✓ Migration complete — ${result.paths.length} file(s) written to .gsd/`,
232
+ `✓ Migration complete — ${result.paths.length} file(s) written to .gsd/ and ${imported.hierarchy.milestones}M/${imported.hierarchy.slices}S/${imported.hierarchy.tasks}T imported to the database`,
188
233
  "info",
189
234
  );
190
235
 
@@ -193,6 +238,7 @@ export async function handleMigrate(
193
238
  title: "Migration written",
194
239
  summary: [
195
240
  `${result.paths.length} files written to .gsd/`,
241
+ `${imported.hierarchy.milestones} milestone(s), ${imported.hierarchy.slices} slice(s), and ${imported.hierarchy.tasks} task(s) imported to gsd.db`,
196
242
  "",
197
243
  "The agent can now review the migrated output against GSD-2 standards —",
198
244
  "checking structure, content quality, deriveState() round-trip, and",
@@ -0,0 +1,129 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+
3
+ import { ensureDbOpen } from "./bootstrap/dynamic-tools.js";
4
+ import {
5
+ clearEngineHierarchy,
6
+ getAllMilestones,
7
+ getMilestoneSlices,
8
+ getSliceTasks,
9
+ isDbAvailable,
10
+ transaction,
11
+ } from "./gsd-db.js";
12
+ import { migrateHierarchyToDb } from "./md-importer.js";
13
+ import { parsePlan, parseRoadmap } from "./parsers-legacy.js";
14
+ import {
15
+ milestonesDir,
16
+ resolveMilestoneFile,
17
+ resolveSliceFile,
18
+ } from "./paths.js";
19
+ import { invalidateStateCache } from "./state.js";
20
+
21
+ export interface HierarchyCounts {
22
+ milestones: number;
23
+ slices: number;
24
+ tasks: number;
25
+ }
26
+
27
+ export interface MigrationAutoCheckResult {
28
+ action: "none" | "imported";
29
+ reason: "no-markdown" | "in-sync" | "db-empty" | "count-mismatch";
30
+ markdown: HierarchyCounts;
31
+ beforeDb: HierarchyCounts;
32
+ afterDb: HierarchyCounts;
33
+ }
34
+
35
+ function zeroCounts(): HierarchyCounts {
36
+ return { milestones: 0, slices: 0, tasks: 0 };
37
+ }
38
+
39
+ function sameCounts(a: HierarchyCounts, b: HierarchyCounts): boolean {
40
+ return a.milestones === b.milestones && a.slices === b.slices && a.tasks === b.tasks;
41
+ }
42
+
43
+ export function countMarkdownHierarchy(basePath: string): HierarchyCounts {
44
+ const root = milestonesDir(basePath);
45
+ if (!existsSync(root)) return zeroCounts();
46
+
47
+ const counts = zeroCounts();
48
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
49
+ if (!entry.isDirectory() || !/^M\d+/.test(entry.name)) continue;
50
+ counts.milestones++;
51
+
52
+ const roadmapPath = resolveMilestoneFile(basePath, entry.name, "ROADMAP");
53
+ if (!roadmapPath || !existsSync(roadmapPath)) continue;
54
+
55
+ const roadmap = parseRoadmap(readFileSync(roadmapPath, "utf-8"));
56
+ counts.slices += roadmap.slices.length;
57
+
58
+ for (const slice of roadmap.slices) {
59
+ const planPath = resolveSliceFile(basePath, entry.name, slice.id, "PLAN");
60
+ if (!planPath || !existsSync(planPath)) continue;
61
+ const plan = parsePlan(readFileSync(planPath, "utf-8"));
62
+ counts.tasks += plan.tasks.length;
63
+ }
64
+ }
65
+
66
+ return counts;
67
+ }
68
+
69
+ export function countDbHierarchy(): HierarchyCounts {
70
+ if (!isDbAvailable()) return zeroCounts();
71
+ const counts = zeroCounts();
72
+ const milestones = getAllMilestones();
73
+ counts.milestones = milestones.length;
74
+
75
+ for (const milestone of milestones) {
76
+ const slices = getMilestoneSlices(milestone.id);
77
+ counts.slices += slices.length;
78
+ for (const slice of slices) {
79
+ counts.tasks += getSliceTasks(milestone.id, slice.id).length;
80
+ }
81
+ }
82
+
83
+ return counts;
84
+ }
85
+
86
+ export async function autoImportMarkdownHierarchyIfDbMismatch(
87
+ basePath: string,
88
+ ): Promise<MigrationAutoCheckResult> {
89
+ const markdown = countMarkdownHierarchy(basePath);
90
+ if (sameCounts(markdown, zeroCounts())) {
91
+ return {
92
+ action: "none",
93
+ reason: "no-markdown",
94
+ markdown,
95
+ beforeDb: zeroCounts(),
96
+ afterDb: zeroCounts(),
97
+ };
98
+ }
99
+
100
+ const opened = await ensureDbOpen(basePath);
101
+ if (!opened || !isDbAvailable()) {
102
+ throw new Error(`failed to open or create the GSD database at ${basePath}`);
103
+ }
104
+
105
+ const beforeDb = countDbHierarchy();
106
+ if (sameCounts(markdown, beforeDb)) {
107
+ return { action: "none", reason: "in-sync", markdown, beforeDb, afterDb: beforeDb };
108
+ }
109
+
110
+ const reason = sameCounts(beforeDb, zeroCounts()) ? "db-empty" : "count-mismatch";
111
+ const imported = transaction(() => {
112
+ clearEngineHierarchy();
113
+ return migrateHierarchyToDb(basePath);
114
+ });
115
+ invalidateStateCache();
116
+
117
+ const afterDb = {
118
+ milestones: imported.milestones,
119
+ slices: imported.slices,
120
+ tasks: imported.tasks,
121
+ };
122
+ if (!sameCounts(markdown, afterDb)) {
123
+ throw new Error(
124
+ `migration auto-import verification failed: markdown ${markdown.milestones}M/${markdown.slices}S/${markdown.tasks}T, db ${afterDb.milestones}M/${afterDb.slices}S/${afterDb.tasks}T`,
125
+ );
126
+ }
127
+
128
+ return { action: "imported", reason, markdown, beforeDb, afterDb };
129
+ }
@@ -0,0 +1,35 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { normalizePlannedFileReference } from "./files.js";
3
+
4
+ export interface PlanningPathScopeField {
5
+ field: string;
6
+ values: string[];
7
+ }
8
+
9
+ function isInsideBase(basePath: string, candidate: string): boolean {
10
+ const base = resolve(basePath);
11
+ const abs = resolve(candidate);
12
+ const rel = relative(base, abs);
13
+ return rel === "" || (!!rel && !rel.startsWith("..") && !isAbsolute(rel));
14
+ }
15
+
16
+ /**
17
+ * Planning IO fields are execution contracts. Absolute paths are only safe when
18
+ * they stay inside the active working directory; in worktree mode, an absolute
19
+ * path to the original checkout makes executors edit the wrong tree.
20
+ */
21
+ export function validatePlanningPathScope(
22
+ basePath: string,
23
+ fields: PlanningPathScopeField[],
24
+ ): string | null {
25
+ for (const { field, values } of fields) {
26
+ for (const raw of values) {
27
+ const candidate = normalizePlannedFileReference(raw);
28
+ if (!isAbsolute(candidate)) continue;
29
+ if (isInsideBase(basePath, candidate)) continue;
30
+ return `${field} contains absolute path outside working directory: ${candidate}. Use a path relative to ${basePath}.`;
31
+ }
32
+ }
33
+
34
+ return null;
35
+ }
@@ -11,6 +11,7 @@ export interface PrEvidenceInput {
11
11
  changeType?: PrChangeType;
12
12
  linkedIssue?: string;
13
13
  summaries?: string[];
14
+ blockers?: string[];
14
15
  roadmapItems?: string[];
15
16
  metrics?: string[];
16
17
  testsRun?: string[];
@@ -34,8 +35,54 @@ const CHANGE_TYPE_LABELS: Record<PrChangeType, string> = {
34
35
  chore: "Build, CI, or tooling changes",
35
36
  };
36
37
 
38
+ // Per-item cap for user-supplied content. 2 KB gives slice titles plus
39
+ // descriptions room while still bounding malicious DoS-via-PR-body input.
40
+ const USER_CONTENT_CAP_BYTES = 2048;
41
+ const TRUNCATION_SUFFIX = " … [truncated]";
42
+
43
+ // Strips HTML comments, fake commit trailers (Co-Authored-By, Signed-off-by —
44
+ // case-insensitive on the trailer name), and caps total length. Designed to
45
+ // be a no-op for well-formed input; golden fixtures must remain byte-stable.
46
+ // Trailer lines are removed (not rejected) so that a single bad line in an
47
+ // otherwise legitimate description does not block the entire PR.
48
+ function sanitizeUserContent(s: string): string {
49
+ if (!s) return s;
50
+ // Strip HTML comments greedily across newlines.
51
+ let out = s.replace(/<!--[\s\S]*?-->/g, "");
52
+ // Drop lines that look like commit trailers we do not want forged.
53
+ out = out
54
+ .split("\n")
55
+ .filter((line) => !/^\s*(co-authored-by|signed-off-by)\s*:/i.test(line))
56
+ .join("\n");
57
+ if (Buffer.byteLength(out, "utf8") > USER_CONTENT_CAP_BYTES) {
58
+ const budget = USER_CONTENT_CAP_BYTES - Buffer.byteLength(TRUNCATION_SUFFIX, "utf8");
59
+ // Truncate by code units to stay safely under the byte budget for ASCII;
60
+ // for multibyte content we conservatively walk back until under budget.
61
+ let sliced = out.slice(0, Math.max(0, budget));
62
+ while (Buffer.byteLength(sliced, "utf8") > budget && sliced.length > 0) {
63
+ sliced = sliced.slice(0, -1);
64
+ }
65
+ out = sliced + TRUNCATION_SUFFIX;
66
+ }
67
+ return out;
68
+ }
69
+
70
+ // Strips HTML comments and fake trailers without applying the length cap.
71
+ // Used for short fields like linkedIssue where truncation would be confusing.
72
+ function sanitizeIssueRef(s: string): string {
73
+ if (!s) return s;
74
+ let out = s.replace(/<!--[\s\S]*?-->/g, "");
75
+ out = out
76
+ .split("\n")
77
+ .filter((line) => !/^\s*(co-authored-by|signed-off-by)\s*:/i.test(line))
78
+ .join("\n");
79
+ return out;
80
+ }
81
+
37
82
  function normalizeList(values: readonly string[] | undefined): string[] {
38
- return (values ?? []).map((value) => value.trim()).filter(Boolean);
83
+ return (values ?? [])
84
+ .map((value) => sanitizeUserContent(value).trim())
85
+ .filter(Boolean);
39
86
  }
40
87
 
41
88
  function changeTypeChecklist(selected: PrChangeType): string[] {
@@ -56,13 +103,17 @@ export function buildPrEvidence(input: PrEvidenceInput): PrEvidence {
56
103
  const subjectTitle = input.milestoneTitle?.trim() || subjectId;
57
104
  const changeType = input.changeType ?? "feat";
58
105
  const summaries = normalizeList(input.summaries);
106
+ const blockers = normalizeList(input.blockers);
59
107
  const roadmapItems = normalizeList(input.roadmapItems);
60
108
  const metrics = normalizeList(input.metrics);
61
109
  const testsRun = normalizeList(input.testsRun);
62
110
  const rollbackNotes = normalizeList(input.rollbackNotes);
63
- const linkedIssue = input.linkedIssue?.trim() || "Not specified. Add an issue link before marking this PR ready if CONTRIBUTING.md requires one.";
64
- const why = input.why?.trim() || `${capitalize(subjectKind)} work is complete and ready for review.`;
65
- const how = input.how?.trim() || "Generated from GSD evidence and local workflow artifacts.";
111
+ // linkedIssue is sanitized but not length-capped: legitimate issue refs
112
+ // are short by nature, and truncating "Closes #123" would be unhelpful.
113
+ const linkedIssueRaw = input.linkedIssue ? sanitizeIssueRef(input.linkedIssue).trim() : "";
114
+ const linkedIssue = linkedIssueRaw || "Not specified. Add an issue link before marking this PR ready if CONTRIBUTING.md requires one.";
115
+ const why = (input.why ? sanitizeUserContent(input.why).trim() : "") || `${capitalize(subjectKind)} work is complete and ready for review.`;
116
+ const how = (input.how ? sanitizeUserContent(input.how).trim() : "") || "Generated from GSD evidence and local workflow artifacts.";
66
117
  const title = `${changeType}: ${subjectTitle}`;
67
118
 
68
119
  const sections: string[] = [
@@ -75,6 +126,13 @@ export function buildPrEvidence(input: PrEvidenceInput): PrEvidence {
75
126
  "## What",
76
127
  "",
77
128
  summaries.length > 0 ? summaries.join("\n\n") : `${capitalize(subjectKind)} ${subjectId} completed.`,
129
+ ];
130
+
131
+ if (blockers.length > 0) {
132
+ sections.push("", "## Blockers", "", blockers.map((blocker) => `- ${blocker}`).join("\n"));
133
+ }
134
+
135
+ sections.push(
78
136
  "",
79
137
  "## Why",
80
138
  "",
@@ -87,7 +145,7 @@ export function buildPrEvidence(input: PrEvidenceInput): PrEvidence {
87
145
  "## Linked Issue",
88
146
  "",
89
147
  linkedIssue,
90
- ];
148
+ );
91
149
 
92
150
  if (roadmapItems.length > 0) {
93
151
  sections.push("", "## Roadmap", "", roadmapItems.join("\n"));
@@ -380,6 +380,8 @@ function shouldValidateInputAsPath(raw: string): boolean {
380
380
  const trimmed = raw.trim();
381
381
  if (!trimmed) return false;
382
382
 
383
+ if (isRuntimeOnlyInput(trimmed)) return false;
384
+
383
385
  const candidate = extractPathFromAnnotation(trimmed);
384
386
  if (!candidate) return false;
385
387
 
@@ -405,6 +407,10 @@ function shouldValidateInputAsPath(raw: string): boolean {
405
407
  );
406
408
  }
407
409
 
410
+ function isRuntimeOnlyInput(raw: string): boolean {
411
+ return /\(\s*runtime\s*\)/i.test(raw);
412
+ }
413
+
408
414
  function containsGlobPattern(candidate: string): boolean {
409
415
  return ["*", "?", "[", "]", "{", "}"].some((char) => candidate.includes(char));
410
416
  }
@@ -535,6 +541,7 @@ export function checkTaskOrdering(
535
541
  const filesToCheck = [...task.inputs];
536
542
 
537
543
  for (const file of filesToCheck) {
544
+ if (isRuntimeOnlyInput(file)) continue;
538
545
  if (!shouldValidateInputAsPath(file)) continue;
539
546
 
540
547
  const normalizedFile = normalizeFilePath(file);
@@ -32,7 +32,7 @@ export interface ContextManagementConfig {
32
32
  /**
33
33
  * Opt-in tool-output sandboxing for sub-sessions. When enabled, the gsd_exec
34
34
  * MCP tool runs scripts in an isolated subprocess and returns only a short
35
- * digest to the calling agent's context window; full stdout/stderr persist
35
+ * digest to the calling agent's context window; capped stdout/stderr persist
36
36
  * in the project memory store and can be retrieved by id later.
37
37
  *
38
38
  * Inspired by mksglu/context-mode (Elastic License 2.0). This is an
@@ -123,17 +123,42 @@ function warmCache(): void {
123
123
  }
124
124
 
125
125
  let warmCacheScheduled = false;
126
+ let warmCacheRan = false;
127
+ let warmCacheTimer: ReturnType<typeof setTimeout> | undefined;
128
+
129
+ /**
130
+ * Synchronously snapshot the prompt/template tree into the cache.
131
+ *
132
+ * Safe to call immediately after `initResources()` because that function uses
133
+ * synchronous fs APIs — there is no race window that requires deferring the
134
+ * cache warm via setTimeout. Idempotent: subsequent calls are no-ops.
135
+ *
136
+ * Cancels the fallback `scheduleWarmCache` timer if it is still pending.
137
+ */
138
+ export function primeCache(): void {
139
+ if (warmCacheRan) return;
140
+ if (warmCacheTimer) {
141
+ clearTimeout(warmCacheTimer);
142
+ warmCacheTimer = undefined;
143
+ }
144
+ warmCacheScheduled = true;
145
+ warmCacheRan = true;
146
+ warmCache();
147
+ }
126
148
 
127
149
  function scheduleWarmCache(): void {
128
150
  if (warmCacheScheduled) return;
129
151
  warmCacheScheduled = true;
130
152
 
131
153
  const run = () => {
154
+ warmCacheTimer = undefined;
155
+ if (warmCacheRan) return;
156
+ warmCacheRan = true;
132
157
  warmCache();
133
158
  };
134
159
 
135
- const timer = setTimeout(run, 1000);
136
- timer.unref?.();
160
+ warmCacheTimer = setTimeout(run, 1000);
161
+ warmCacheTimer.unref?.();
137
162
  }
138
163
 
139
164
  // Snapshot the full prompt/template tree after import so extension startup only
@@ -16,28 +16,28 @@ Start with what the excerpts give you. Read full files when the section heads si
16
16
 
17
17
  **On-demand Read ordering:** Complete all slice SUMMARY Reads you need for cross-slice synthesis, the Decision Re-evaluation table, and LEARNINGS **before** calling `gsd_complete_milestone` (step 12). Once that tool runs, the milestone is marked complete in the DB, so it must be the final persistent milestone-closeout write.
18
18
 
19
- ### Delegate Review Work
19
+ ### Closeout Review Mode
20
20
 
21
- Use `subagent` for review work needing fresh context, before drafting LEARNINGS:
21
+ The inlined context includes a validation status block.
22
22
 
23
- - Cross-slice integrations or new public APIs -> **reviewer** with milestone diff and roadmap.
24
- - Auth, network, parsing, file IO, shell exec, or crypto -> **security** audit.
25
- - Significant tests added or changed -> **tester** coverage check against success criteria.
23
+ - If it says a passing validation artifact is present, treat that artifact as authoritative for success criteria, requirement coverage, verification classes, and cross-slice integration. Do not delegate fresh reviewer/security/tester audits unless the validation artifact is internally inconsistent with the inlined summaries.
24
+ - If validation is missing, stale, non-pass, or internally inconsistent, use `subagent` for review work needing fresh context before drafting LEARNINGS: cross-slice integrations or new public APIs -> **reviewer**; auth, network, parsing, file IO, shell exec, or crypto -> **security**; significant tests added or changed -> **tester**.
26
25
 
27
- Subagents report only; they do not write user source. Fold findings into Decision Re-evaluation and LEARNINGS before completion.
26
+ Subagents report only; they do not write user source. Fold any findings into Decision Re-evaluation and LEARNINGS before completion.
28
27
 
29
28
  {{inlinedContext}}
30
29
 
31
30
  ## Steps
32
31
 
33
- 1. Use the **Milestone Summary** output template from the inlined context above
34
- 2. {{skillActivation}}
35
- 3. **Verify code changes exist.** Compare milestone work against the integration branch (`main`, `master`, or recorded branch), using merge-base as older revision and `HEAD` as newer. If the diff lists non-`.gsd/` files, pass. If `HEAD` equals the integration branch/merge-base, treat it as a self-diff retry: inspect milestone-scoped commit evidence (`GSD-Unit: {{milestoneId}}` or production `GSD-Task: Sxx/Tyy` trailers touching `.gsd/milestones/{{milestoneId}}/`) and verify those commits touched non-`.gsd/` files. Record **verification failure** only when neither source shows implementation files.
36
- 4. Verify every **success criterion** from `{{roadmapPath}}` with evidence from summaries, tests, or observable behavior. Record unmet criteria as **verification failure**.
37
- 5. Verify **definition of done**: all slices `[x]`, summaries exist, and integrations work. Record unmet items as **verification failure**.
38
- 6. If the roadmap includes a **Horizontal Checklist**, verify each item and note unchecked items in the summary.
39
- 7. Fill the **Decision Re-evaluation** table: compare each key `.gsd/DECISIONS.md` decision from this milestone with what shipped, and flag decisions to revisit.
40
- 8. Validate **requirement status transitions**. For each changed requirement, confirm evidence supports the new status. Requirements may move between Active, Validated, Deferred, Blocked, or Out of Scope only with proof.
32
+ 1. **Duplicate completion guard:** Call `gsd_milestone_status` for `{{milestoneId}}` before any durable writes. If the returned milestone **status is `complete`**, this is a stale or duplicate closeout turn: do NOT mutate requirements, do NOT refresh the project document, do NOT write LEARNINGS, and do NOT persist milestone completion again. Say: "Milestone {{milestoneId}} is already complete." and stop.
33
+ 2. Use the **Milestone Summary** output template from the inlined context above
34
+ 3. {{skillActivation}}
35
+ 4. **Verify code changes exist.** Compare milestone work against the integration branch (`main`, `master`, or recorded branch), using merge-base as older revision and `HEAD` as newer. If the diff lists non-`.gsd/` files, pass. If `HEAD` equals the integration branch/merge-base, treat it as a self-diff retry: inspect milestone-scoped commit evidence (`GSD-Unit: {{milestoneId}}` or production `GSD-Task: Sxx/Tyy` trailers touching `.gsd/milestones/{{milestoneId}}/`) and verify those commits touched non-`.gsd/` files. Record **verification failure** only when neither source shows implementation files.
36
+ 5. Verify every **success criterion** from `{{roadmapPath}}`. If passing validation is present, summarize the validation evidence instead of re-auditing it; otherwise verify with evidence from summaries, tests, or observable behavior. Record unmet criteria as **verification failure**.
37
+ 6. Verify **definition of done**: all slices `[x]`, summaries exist, and integrations work. If passing validation is present, trust its integration/verification verdict unless inconsistent with current artifacts. Record unmet items as **verification failure**.
38
+ 7. If the roadmap includes a **Horizontal Checklist**, verify each item and note unchecked items in the summary.
39
+ 8. Fill the **Decision Re-evaluation** table: compare each key `.gsd/DECISIONS.md` decision from this milestone with what shipped, and flag decisions to revisit.
40
+ 9. Validate **requirement status transitions**. For each changed requirement, confirm evidence supports the new status. Requirements may move between Active, Validated, Deferred, Blocked, or Out of Scope only with proof.
41
41
 
42
42
  **DB access safety:** Do NOT query `.gsd/gsd.db` directly via `sqlite3` or `node -e require('better-sqlite3')`; the engine owns the WAL connection. Use `gsd_milestone_status`, inlined context, or `gsd_*` tools; never direct SQL.
43
43
 
@@ -54,13 +54,13 @@ Subagents report only; they do not write user source. Fold findings into Decisio
54
54
 
55
55
  **Success path** (all verifications passed):
56
56
 
57
- 9. For each requirement whose status changed in step 8, call `gsd_requirement_update` with the requirement ID and updated `status` and `validation` fields — the tool regenerates `.gsd/REQUIREMENTS.md` automatically. Do this BEFORE completing the milestone so requirement updates are persisted.
58
- 10. Update `.gsd/PROJECT.md`: use the `write` tool with `path: ".gsd/PROJECT.md"` and `content` containing the full updated document reflecting milestone completion and current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh.
59
- 11. Extract structured learnings from this milestone and persist them to the GSD memory store. Follow the procedure block immediately below — it writes `{{milestoneId}}-LEARNINGS.md` as the audit trail and persists Patterns, Lessons, and Decisions via `capture_thought` (categories: pattern, gotcha/convention, architecture). The memory store is the single source of truth for cross-session durable knowledge (ADR-013).
57
+ 10. For each requirement whose status changed in step 9, call `gsd_requirement_update` with the requirement ID and updated `status` and `validation` fields — the tool regenerates `.gsd/REQUIREMENTS.md` automatically. Do this BEFORE completing the milestone so requirement updates are persisted.
58
+ 11. Update `.gsd/PROJECT.md`: use the `write` tool with `path: ".gsd/PROJECT.md"` and `content` containing the full updated document reflecting milestone completion and current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh.
59
+ 12. Extract structured learnings from this milestone and persist them to the GSD memory store. Follow the procedure block immediately below — it writes `{{milestoneId}}-LEARNINGS.md` as the audit trail and persists Patterns, Lessons, and Decisions via `capture_thought` (categories: pattern, gotcha/convention, architecture). The memory store is the single source of truth for cross-session durable knowledge (ADR-013).
60
60
 
61
61
  {{extractLearningsSteps}}
62
62
 
63
- 12. **Persist completion through `gsd_complete_milestone`.** Call it with the parameters below. This must be the final persistent write in the unit. The tool updates the milestone status in the DB, renders `{{milestoneSummaryPath}}`, and validates all slices are complete.
63
+ 13. **Persist completion through `gsd_complete_milestone`.** Call it with the parameters below. This must be the final persistent write in the unit. The tool updates the milestone status in the DB, renders `{{milestoneSummaryPath}}`, and validates all slices are complete.
64
64
 
65
65
  **Required parameters:**
66
66
  - `milestoneId` (string) — Milestone ID (e.g. M001)
@@ -79,7 +79,7 @@ Subagents report only; they do not write user source. Fold findings into Decisio
79
79
  - `followUps` (string) — Follow-up items for future milestones
80
80
  - `deviations` (string) — Deviations from the original plan
81
81
 
82
- 13. Do not commit manually — the system auto-commits your changes after this unit completes.
82
+ 14. Do not commit manually — the system auto-commits your changes after this unit completes.
83
83
  - Say: "Milestone {{milestoneId}} complete."
84
84
 
85
85
  **Important:** Do NOT skip code-change, success-criteria, or definition-of-done verification (steps 3-5). The summary must reflect verified outcomes. Verification failures block completion; there is no override. If a verification tool fails, errors, or returns unexpected output, treat it as failure.
@@ -16,7 +16,7 @@ Dispatch ALL slices simultaneously using the `subagent` tool in **parallel mode*
16
16
 
17
17
  1. Call `subagent` with `tasks: [...]` containing one entry per slice below
18
18
  2. Wait for ALL subagents to complete
19
- 3. Verify each slice's RESEARCH file was written (check the `.gsd/{{mid}}/` directory)
19
+ 3. Verify each slice's RESEARCH file was written (check `.gsd/milestones/{{mid}}/slices/<slice-id>/`)
20
20
  4. If a subagent failed to write its RESEARCH file, retry it **once** individually
21
21
  5. If it fails a second time, write a partial RESEARCH file for that slice with a `## BLOCKER` section explaining the failure — do NOT retry again
22
22
  6. Report which slices completed research and which (if any) needed a blocker note
@@ -48,7 +48,7 @@ Narrate decomposition reasoning in complete sentences: grouping, risk order, ver
48
48
  Then:
49
49
  1. Use the **Roadmap** output template from the inlined context above
50
50
  2. {{skillActivation}}
51
- 3. Create only as many demoable vertical slices as the work genuinely needs.
51
+ 3. Create only as many demoable vertical slices as the work genuinely needs. Use 1-10 slices, sized to the work; tiny/single-file/static work should usually be one slice.
52
52
  4. Order by risk, high-risk first.
53
53
  5. Call `gsd_plan_milestone` to persist milestone fields, slice rows, and **Horizontal Checklist** through the DB-backed path. Fill checklist concerns considered during planning: requirements, decisions, shutdown, revenue, auth, shared resources, reconnection. Omit for trivial milestones. Do **not** write `{{outputPath}}`, `ROADMAP.md`, or other planning artifacts manually; the tool owns rendering and persistence.
54
54
  6. If planning produced structural decisions (slice ordering, technology choices, scope exclusions), call `gsd_decision_save` for each; the tool assigns IDs and regenerates `.gsd/DECISIONS.md`.
@@ -78,6 +78,8 @@ Apply these when decomposing and ordering slices:
78
78
  - Ship features, not proofs; use clearly marked realistic stubs only when necessary.
79
79
  - **Dependency format is comma-separated, never range syntax.** Write `depends:[S01,S02,S03]`, not `depends:[S01-S03]`.
80
80
  - Roadmap ambition must match the milestone; right-size decomposition.
81
+ - Missing ecosystem markers are not a reason to over-plan. If Project Classification says `untyped-existing`, treat the listed content files as the project surface and use generic file-level workflow guidance.
82
+ - For `untyped-existing` projects with 1-2 content files, prefer exactly one slice unless the request clearly spans multiple independent user-visible capabilities. For 3-5 content files, prefer 1-2 slices.
81
83
 
82
84
  ## Progressive Planning (ADR-011)
83
85
 
@@ -39,7 +39,7 @@ If slice research is inlined, trust it. Explore enough code to confirm paths, bo
39
39
  5. Define slice verification before tasks. Non-trivial slices need real tests or executable assertions; boundary contracts need contract-exercising checks. Tests must not read .gitignore/gitignored paths such as `.gsd/`, `.planning/`, or `.audits/`.
40
40
  6. Include Threat Surface (Q3), Requirement Impact (Q4), proof level, observability, integration closure, Failure Modes (Q5), Load Profile (Q6), and Negative Tests (Q7) only where applicable.
41
41
  7. Right-size tasks. Simple slices can be one task; split only when context, ownership, or verification boundaries justify it.
42
- 8. Each task needs a concrete title, Why / Files / Do / Verify / Done when, plus task-plan description, steps, must-haves, verification, inputs, and expected output. Inputs and Expected Output must include concrete backtick-wrapped paths; each task needs at least one output path.
42
+ 8. Each task needs a concrete title, Why / Files / Do / Verify / Done when, plus task-plan description, steps, must-haves, verification, inputs, and expected output. Inputs and Expected Output must include concrete backtick-wrapped paths; each task needs at least one output path. Use paths relative to `{{workingDirectory}}`; do not put absolute paths to the original checkout or any directory outside `{{workingDirectory}}` in `files`, `inputs`, `expectedOutput`, or verification commands.
43
43
  9. Persist with `gsd_plan_slice` using goal, successCriteria, optional proofLevel/integrationClosure/observabilityImpact, and tasks. `gsd_plan_slice` handles task persistence transactionally and renders `{{outputPath}}` plus task plans; do not call `gsd_plan_task`. The DB-backed tool is the canonical write path. Do **not** rely on direct `PLAN.md` writes as the source of truth.
44
44
  10. Self-audit before finishing: goal/demo closure, requirement coverage, locked decisions, concrete paths, dependency order, wiring, scope size, proof truthfulness, feature completeness, and quality gates. Quality gates: non-trivial slices/tasks include specific Q3-Q7 coverage where applicable.
45
45
  11. If planning creates structural decisions, append them to `.gsd/DECISIONS.md`.
@@ -17,11 +17,7 @@ You are executing a GSD quick task — a lightweight, focused unit of work outsi
17
17
  5. Verify your work:
18
18
  - Run tests if applicable.
19
19
  - Verify both happy path and failure modes for non-trivial changes.
20
- 6. Commit your changes atomically:
21
- - Use conventional commit messages (feat:, fix:, refactor:, etc.)
22
- - Stage only relevant files — never commit secrets or runtime files.
23
- - Commit logical units separately if the task involves distinct changes.
24
- - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.
20
+ 6. {{commitInstruction}}
25
21
  7. Write a brief summary to `{{summaryPath}}`:
26
22
  - Quick tasks operate outside the milestone/slice/task DB structure, so `gsd_summary_save` (which requires a `milestone_id`) cannot be used here. Write the file directly.
27
23
 
@@ -27,13 +27,13 @@ Roadmap, slice summaries, assessments, requirements, decisions, and project cont
27
27
  Call `subagent` with `tasks: [...]` containing ALL THREE reviewers simultaneously:
28
28
 
29
29
  **Reviewer A - Requirements Coverage**
30
- Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.gsd/{{milestoneId}}/REQUIREMENTS.md` or equivalent. For each requirement, check slice SUMMARY files in `.gsd/{{milestoneId}}/` and mark COVERED, PARTIAL, or MISSING. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
30
+ Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.gsd/REQUIREMENTS.md` or use the inlined requirements context. For each requirement, check slice SUMMARY files under `.gsd/milestones/{{milestoneId}}/slices/` and mark COVERED, PARTIAL, or MISSING. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
31
31
 
32
32
  **Reviewer B - Cross-Slice Integration**
33
33
  Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Read `{{roadmapPath}}` and find the boundary map (produces/consumes contracts). For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
34
34
 
35
35
  **Reviewer C - Assessment & Acceptance Criteria**
36
- Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/{{milestoneId}}/CONTEXT.md` for criteria. Check slice ASSESSMENT files. Verify each criterion maps to a passing assessment or clear SUMMARY evidence. Then review inlined milestone verification classes. For each non-empty planned class, output table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered, NEEDS-ATTENTION if gaps exist."
36
+ Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.gsd/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md` for criteria. Check slice SUMMARY/UAT files under `.gsd/milestones/{{milestoneId}}/slices/`. Verify each criterion maps to passing evidence. Then review inlined milestone verification classes. For each non-empty planned class, output table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered, NEEDS-ATTENTION if gaps exist."
37
37
 
38
38
  ### Step 2 - Synthesize Findings
39
39
 
@@ -10,8 +10,8 @@
10
10
  */
11
11
 
12
12
  import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
13
- import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
14
- import { join } from "node:path";
13
+ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
14
+ import { isAbsolute, join, relative } from "node:path";
15
15
  import { loadPrompt } from "./prompt-loader.js";
16
16
  import { gsdRoot } from "./paths.js";
17
17
  import { GitServiceImpl, runGit } from "./git-service.js";
@@ -77,6 +77,40 @@ function ensureQuickDir(basePath: string, taskNum: number, slug: string): string
77
77
  return taskDir;
78
78
  }
79
79
 
80
+ function isPathInside(parent: string, child: string): boolean {
81
+ const rel = relative(parent, child);
82
+ return rel === "" || (!!rel && !rel.startsWith("..") && !isAbsolute(rel));
83
+ }
84
+
85
+ function isExternalGsdRoot(basePath: string, root: string): boolean {
86
+ try {
87
+ return !isPathInside(realpathSync(basePath), realpathSync(root));
88
+ } catch {
89
+ return !isPathInside(basePath, root);
90
+ }
91
+ }
92
+
93
+ export function buildQuickCommitInstruction(basePath: string, root: string): string {
94
+ const externalState = isExternalGsdRoot(basePath, root);
95
+ if (externalState) {
96
+ return [
97
+ "Commit repo changes atomically, but do not stage or commit `.gsd/quick/...`:",
98
+ " - `.gsd/` resolves outside this git repository, so Git cannot stage quick-task summary files from the project repo.",
99
+ " - Write the quick summary file directly at the requested path; that file is persisted by GSD external state.",
100
+ " - Stage and commit only implementation/test/docs files that live inside the repository.",
101
+ " - If the task only writes quick-task research/summary files and no repository files changed, do not run `git commit`; report that there was nothing in the project repo to commit.",
102
+ ].join("\n");
103
+ }
104
+
105
+ return [
106
+ "Commit your changes atomically:",
107
+ " - Use conventional commit messages (feat:, fix:, refactor:, etc.)",
108
+ " - Stage only relevant files — never commit secrets or runtime files.",
109
+ " - Commit logical units separately if the task involves distinct changes.",
110
+ " - Quick tasks run outside the auto-mode lifecycle — there is no system auto-commit, so commit directly here.",
111
+ ].join("\n");
112
+ }
113
+
80
114
  function quickReturnStatePath(basePath: string): string {
81
115
  return join(gsdRoot(basePath), "runtime", "quick-return.json");
82
116
  }
@@ -246,6 +280,7 @@ export async function handleQuick(
246
280
  taskDir: taskDirRel,
247
281
  branch: actualBranch,
248
282
  summaryPath,
283
+ commitInstruction: buildQuickCommitInstruction(basePath, root),
249
284
  date,
250
285
  taskNum: String(taskNum),
251
286
  slug,