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

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 (342) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/GSD-WORKFLOW.md +2 -2
  3. package/dist/resources/extensions/github-sync/templates.js +39 -8
  4. package/dist/resources/extensions/gsd/auto/loop.js +48 -10
  5. package/dist/resources/extensions/gsd/auto/phases.js +37 -30
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -15
  7. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
  9. package/dist/resources/extensions/gsd/auto-post-unit.js +10 -10
  10. package/dist/resources/extensions/gsd/auto-prompts.js +111 -1
  11. package/dist/resources/extensions/gsd/auto-recovery.js +154 -8
  12. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  13. package/dist/resources/extensions/gsd/auto.js +9 -1
  14. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +15 -1
  15. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -1
  16. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  17. package/dist/resources/extensions/gsd/clean-root-preflight.js +42 -4
  18. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  19. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  20. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  21. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  22. package/dist/resources/extensions/gsd/db-base-schema.js +14 -0
  23. package/dist/resources/extensions/gsd/db-migration-steps.js +16 -0
  24. package/dist/resources/extensions/gsd/detection.js +106 -0
  25. package/dist/resources/extensions/gsd/graph.js +9 -3
  26. package/dist/resources/extensions/gsd/gsd-db.js +102 -2
  27. package/dist/resources/extensions/gsd/guided-flow.js +49 -12
  28. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  29. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  30. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
  31. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  32. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  33. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  34. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  35. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  36. package/dist/resources/extensions/gsd/unit-runtime.js +11 -0
  37. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  38. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  39. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  40. package/dist/web/standalone/.next/BUILD_ID +1 -1
  41. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  42. package/dist/web/standalone/.next/build-manifest.json +3 -3
  43. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  44. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  45. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  46. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  62. package/dist/web/standalone/.next/server/app/index.html +1 -1
  63. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  70. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  71. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  72. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  73. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  74. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  75. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  76. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  77. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  78. package/package.json +10 -6
  79. package/packages/contracts/package.json +1 -1
  80. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  81. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  82. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  83. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  84. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  85. package/packages/pi-ai/dist/models/index.js +8 -0
  86. package/packages/pi-ai/dist/models/index.js.map +1 -1
  87. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  88. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  89. package/packages/pi-ai/dist/providers/fake.js +319 -0
  90. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  91. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  92. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  93. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  94. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  95. package/packages/pi-ai/src/models/index.ts +9 -0
  96. package/packages/pi-ai/src/providers/fake.ts +376 -0
  97. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  98. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  99. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +74 -0
  100. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  101. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  102. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  103. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  104. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  105. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  106. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  107. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  108. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  109. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  110. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/extensions/runner.js +14 -1
  112. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +97 -0
  114. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  115. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  117. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +4 -0
  119. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  120. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  121. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  122. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  124. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  125. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  126. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  128. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  129. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  130. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  131. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  132. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  133. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  134. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  135. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  136. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  137. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  138. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  139. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  140. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  141. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  143. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  144. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  145. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  146. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  147. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  148. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +16 -0
  149. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +106 -17
  151. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  152. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  153. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +60 -1
  154. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  155. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +40 -1
  156. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  158. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  159. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  160. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  161. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  162. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  164. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +23 -0
  165. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  167. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  168. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  169. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  170. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  171. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  172. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  173. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  174. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  176. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  179. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  183. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  185. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  186. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  187. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  188. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  189. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  190. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  191. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  192. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  193. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  194. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  195. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  196. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  197. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  198. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  199. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +87 -0
  200. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  201. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  202. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +108 -0
  203. package/packages/pi-coding-agent/src/core/extensions/runner.ts +16 -1
  204. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  205. package/packages/pi-coding-agent/src/core/settings-manager.ts +12 -0
  206. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  207. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  208. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  209. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  210. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  211. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  212. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  213. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  214. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  215. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +118 -17
  216. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +43 -1
  217. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +75 -1
  218. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  219. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  220. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +25 -0
  221. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  222. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  223. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  224. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  225. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  226. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  227. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  228. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  229. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  230. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  231. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  232. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  233. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  234. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  235. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  236. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  237. package/packages/pi-tui/dist/index.d.ts +1 -0
  238. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  239. package/packages/pi-tui/dist/index.js +2 -0
  240. package/packages/pi-tui/dist/index.js.map +1 -1
  241. package/packages/pi-tui/dist/style.d.ts +41 -0
  242. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  243. package/packages/pi-tui/dist/style.js +158 -0
  244. package/packages/pi-tui/dist/style.js.map +1 -0
  245. package/packages/pi-tui/dist/tui.d.ts +0 -1
  246. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  247. package/packages/pi-tui/dist/tui.js +3 -8
  248. package/packages/pi-tui/dist/tui.js.map +1 -1
  249. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  250. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  251. package/packages/pi-tui/src/index.ts +9 -0
  252. package/packages/pi-tui/src/style.ts +225 -0
  253. package/packages/pi-tui/src/tui.ts +3 -8
  254. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  255. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  256. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  257. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  258. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  259. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  260. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  261. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  262. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  263. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  264. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  265. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  266. package/src/resources/GSD-WORKFLOW.md +2 -2
  267. package/src/resources/extensions/github-sync/templates.ts +38 -8
  268. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  269. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  270. package/src/resources/extensions/gsd/auto/loop.ts +67 -18
  271. package/src/resources/extensions/gsd/auto/phases.ts +42 -28
  272. package/src/resources/extensions/gsd/auto/run-unit.ts +24 -14
  273. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  274. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
  275. package/src/resources/extensions/gsd/auto-post-unit.ts +10 -10
  276. package/src/resources/extensions/gsd/auto-prompts.ts +116 -1
  277. package/src/resources/extensions/gsd/auto-recovery.ts +153 -7
  278. package/src/resources/extensions/gsd/auto-start.ts +7 -6
  279. package/src/resources/extensions/gsd/auto.ts +12 -1
  280. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -1
  281. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -1
  282. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  283. package/src/resources/extensions/gsd/clean-root-preflight.ts +41 -3
  284. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  285. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  286. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  287. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  288. package/src/resources/extensions/gsd/db-base-schema.ts +15 -0
  289. package/src/resources/extensions/gsd/db-migration-steps.ts +17 -0
  290. package/src/resources/extensions/gsd/detection.ts +128 -0
  291. package/src/resources/extensions/gsd/graph.ts +12 -5
  292. package/src/resources/extensions/gsd/gsd-db.ts +119 -1
  293. package/src/resources/extensions/gsd/guided-flow.ts +49 -12
  294. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  295. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  296. package/src/resources/extensions/gsd/prompts/complete-milestone.md +7 -8
  297. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  298. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  299. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  300. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  301. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  302. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +84 -5
  303. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +170 -1
  304. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +88 -2
  305. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  306. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  307. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  308. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +112 -6
  309. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  310. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  311. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  312. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  313. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  314. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  315. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  316. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  317. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  318. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  319. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  320. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  321. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  322. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  323. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  324. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  325. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  326. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  327. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +46 -2
  328. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +7 -0
  329. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  330. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  331. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  332. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  333. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  334. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  335. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  336. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  337. package/src/resources/extensions/gsd/unit-runtime.ts +14 -0
  338. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  339. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  340. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  341. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → y73quA-XdLo9n41nxphjW}/_buildManifest.js +0 -0
  342. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → y73quA-XdLo9n41nxphjW}/_ssgManifest.js +0 -0
@@ -11,12 +11,14 @@
11
11
  import test from "node:test";
12
12
  import assert from "node:assert/strict";
13
13
  import { mkdirSync, writeFileSync, rmSync, existsSync } from "node:fs";
14
+ import { execFileSync } from "node:child_process";
14
15
  import { join } from "node:path";
15
16
  import { tmpdir } from "node:os";
16
17
  import {
17
18
  detectProjectState,
18
19
  detectV1Planning,
19
20
  detectProjectSignals,
21
+ classifyProject,
20
22
  scanProjectFiles,
21
23
  } from "../detection.ts";
22
24
 
@@ -37,6 +39,18 @@ function cleanup(dir: string): void {
37
39
  }
38
40
  }
39
41
 
42
+ function git(dir: string, args: string[]): void {
43
+ execFileSync("git", args, { cwd: dir, stdio: "ignore" });
44
+ }
45
+
46
+ function makeGitRepo(prefix: string): string {
47
+ const dir = makeTempDir(prefix);
48
+ git(dir, ["init"]);
49
+ git(dir, ["config", "user.email", "test@example.com"]);
50
+ git(dir, ["config", "user.name", "Test User"]);
51
+ return dir;
52
+ }
53
+
40
54
  // ─── detectProjectState ─────────────────────────────────────────────────────────
41
55
 
42
56
  test("detectProjectState: empty directory returns state=none", (t) => {
@@ -49,6 +63,132 @@ test("detectProjectState: empty directory returns state=none", (t) => {
49
63
  assert.equal(result.v2, undefined);
50
64
  });
51
65
 
66
+ test("classifyProject: no git repo is invalid", (t) => {
67
+ const dir = makeTempDir("classify-invalid");
68
+ t.after(() => cleanup(dir));
69
+
70
+ const classification = classifyProject(dir);
71
+ assert.equal(classification.kind, "invalid-repo");
72
+ });
73
+
74
+ test("classifyProject: empty git repo is greenfield", (t) => {
75
+ const dir = makeGitRepo("classify-greenfield");
76
+ t.after(() => cleanup(dir));
77
+
78
+ const classification = classifyProject(dir);
79
+ assert.equal(classification.kind, "greenfield");
80
+ });
81
+
82
+ test("classifyProject: nested empty git repo does not inherit ancestor markers", (t) => {
83
+ const parent = makeGitRepo("classify-parent-marker");
84
+ t.after(() => cleanup(parent));
85
+
86
+ writeFileSync(join(parent, "package.json"), JSON.stringify({ name: "parent" }), "utf-8");
87
+ git(parent, ["add", "package.json"]);
88
+ git(parent, ["commit", "-m", "add parent marker"]);
89
+ const child = join(parent, "nested");
90
+ mkdirSync(child, { recursive: true });
91
+ git(child, ["init"]);
92
+ git(child, ["config", "user.email", "test@example.com"]);
93
+ git(child, ["config", "user.name", "Test User"]);
94
+
95
+ const classification = classifyProject(child);
96
+ assert.equal(classification.kind, "greenfield");
97
+ });
98
+
99
+ test("classifyProject: tracked static HTML is existing untyped content", (t) => {
100
+ const dir = makeGitRepo("classify-index");
101
+ t.after(() => cleanup(dir));
102
+
103
+ writeFileSync(join(dir, "index.html"), "<main></main>\n", "utf-8");
104
+ git(dir, ["add", "index.html"]);
105
+ git(dir, ["commit", "-m", "add static page"]);
106
+
107
+ const classification = classifyProject(dir);
108
+ assert.equal(classification.kind, "untyped-existing");
109
+ assert.deepEqual(classification.contentFiles, ["index.html"]);
110
+ });
111
+
112
+ test("classifyProject: README-only repo is existing untyped content", (t) => {
113
+ const dir = makeGitRepo("classify-readme");
114
+ t.after(() => cleanup(dir));
115
+
116
+ writeFileSync(join(dir, "README.md"), "# docs\n", "utf-8");
117
+ git(dir, ["add", "README.md"]);
118
+ git(dir, ["commit", "-m", "add docs"]);
119
+
120
+ const classification = classifyProject(dir);
121
+ assert.equal(classification.kind, "untyped-existing");
122
+ });
123
+
124
+ test("classifyProject: src-only content is untyped existing, not typed marker", (t) => {
125
+ const dir = makeGitRepo("classify-src-only");
126
+ t.after(() => cleanup(dir));
127
+
128
+ mkdirSync(join(dir, "src"), { recursive: true });
129
+ writeFileSync(join(dir, "src", "index.txt"), "content\n", "utf-8");
130
+ git(dir, ["add", "src/index.txt"]);
131
+ git(dir, ["commit", "-m", "add source content"]);
132
+
133
+ const classification = classifyProject(dir);
134
+ assert.equal(classification.kind, "untyped-existing");
135
+ assert.deepEqual(classification.contentFiles, ["src/index.txt"]);
136
+ });
137
+
138
+ test("classifyProject: nested untracked files count as project content", (t) => {
139
+ const dir = makeGitRepo("classify-untracked-nested");
140
+ t.after(() => cleanup(dir));
141
+
142
+ mkdirSync(join(dir, "docs"), { recursive: true });
143
+ writeFileSync(join(dir, "docs", "index.html"), "<main></main>\n", "utf-8");
144
+
145
+ const classification = classifyProject(dir);
146
+ assert.equal(classification.kind, "untyped-existing");
147
+ assert.deepEqual(classification.untrackedFiles, ["docs/index.html"]);
148
+ });
149
+
150
+ test("classifyProject: known markers produce typed existing project", (t) => {
151
+ const dir = makeGitRepo("classify-typed");
152
+ t.after(() => cleanup(dir));
153
+
154
+ writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "typed" }), "utf-8");
155
+ git(dir, ["add", "package.json"]);
156
+ git(dir, ["commit", "-m", "add package"]);
157
+
158
+ const classification = classifyProject(dir);
159
+ assert.equal(classification.kind, "typed-existing");
160
+ assert.ok(classification.markers.includes("package.json"));
161
+ });
162
+
163
+ test("classifyProject: ignored build/cache-only files do not count as content", (t) => {
164
+ const dir = makeGitRepo("classify-ignored");
165
+ t.after(() => cleanup(dir));
166
+
167
+ writeFileSync(join(dir, ".gitignore"), "dist/\n.cache/\n", "utf-8");
168
+ git(dir, ["add", ".gitignore"]);
169
+ git(dir, ["commit", "-m", "ignore generated files"]);
170
+ mkdirSync(join(dir, "dist"), { recursive: true });
171
+ writeFileSync(join(dir, "dist", "bundle.js"), "generated\n", "utf-8");
172
+ mkdirSync(join(dir, ".cache"), { recursive: true });
173
+ writeFileSync(join(dir, ".cache", "x"), "cache\n", "utf-8");
174
+
175
+ const classification = classifyProject(dir);
176
+ assert.equal(classification.kind, "greenfield");
177
+ });
178
+
179
+ test("classifyProject: generated framework/cache dirs do not count as content", (t) => {
180
+ const dir = makeGitRepo("classify-generated-dirs");
181
+ t.after(() => cleanup(dir));
182
+
183
+ mkdirSync(join(dir, ".next", "server"), { recursive: true });
184
+ writeFileSync(join(dir, ".next", "server", "page.js"), "generated\n", "utf-8");
185
+ mkdirSync(join(dir, ".venv", "lib"), { recursive: true });
186
+ writeFileSync(join(dir, ".venv", "lib", "site.py"), "generated\n", "utf-8");
187
+
188
+ const classification = classifyProject(dir);
189
+ assert.equal(classification.kind, "greenfield");
190
+ });
191
+
52
192
  test("detectProjectState: directory with .gsd/milestones/M001 returns v2-gsd", (t) => {
53
193
  const dir = makeTempDir("v2-gsd");
54
194
  t.after(() => cleanup(dir));
@@ -0,0 +1,52 @@
1
+ ## TL;DR
2
+
3
+ **What:** Ship milestone M001 - Authentication
4
+ **Why:** Users need to authenticate before accessing protected resources.
5
+ **How:** Added password hash check and session token issuance.
6
+
7
+ ## What
8
+
9
+ ### S01
10
+ Implemented login flow.
11
+
12
+ ## Why
13
+
14
+ Users need to authenticate before accessing protected resources.
15
+
16
+ ## How
17
+
18
+ Added password hash check and session token issuance.
19
+
20
+ ## Linked Issue
21
+
22
+ Closes #123
23
+
24
+ ## Roadmap
25
+
26
+ - [x] **S01: Login**
27
+
28
+ ## Metrics
29
+
30
+ - **Units executed:** 3
31
+
32
+ ## Tests Run
33
+
34
+ - npm test
35
+ - npm run typecheck:extensions
36
+
37
+ ## Change Type
38
+
39
+ - [x] `feat` - New feature or capability
40
+ - [ ] `fix` - Bug fix
41
+ - [ ] `refactor` - Code restructuring
42
+ - [ ] `test` - Adding or updating tests
43
+ - [ ] `docs` - Documentation only
44
+ - [ ] `chore` - Build, CI, or tooling changes
45
+
46
+ ## Rollback And Compatibility
47
+
48
+ - Revert the merge commit.
49
+
50
+ ## AI Assistance Disclosure
51
+
52
+ This PR was prepared with AI assistance.
@@ -0,0 +1,42 @@
1
+ ## TL;DR
2
+
3
+ **What:** Ship milestone M001 - Authentication
4
+ **Why:** Milestone work is complete and ready for review.
5
+ **How:** Generated from GSD evidence and local workflow artifacts.
6
+
7
+ ## What
8
+
9
+ Milestone M001 completed.
10
+
11
+ ## Why
12
+
13
+ Milestone work is complete and ready for review.
14
+
15
+ ## How
16
+
17
+ Generated from GSD evidence and local workflow artifacts.
18
+
19
+ ## Linked Issue
20
+
21
+ Not specified. Add an issue link before marking this PR ready if CONTRIBUTING.md requires one.
22
+
23
+ ## Tests Run
24
+
25
+ - Not specified. Add exact verification commands before requesting review.
26
+
27
+ ## Change Type
28
+
29
+ - [x] `feat` - New feature or capability
30
+ - [ ] `fix` - Bug fix
31
+ - [ ] `refactor` - Code restructuring
32
+ - [ ] `test` - Adding or updating tests
33
+ - [ ] `docs` - Documentation only
34
+ - [ ] `chore` - Build, CI, or tooling changes
35
+
36
+ ## Rollback And Compatibility
37
+
38
+ - No behavior-changing rollback notes recorded.
39
+
40
+ ## AI Assistance Disclosure
41
+
42
+ This PR was prepared with AI assistance.
@@ -0,0 +1,55 @@
1
+ ## TL;DR
2
+
3
+ **What:** Ship workflow lane/writer - lane/writer
4
+ **Why:** Workflow work is complete and ready for review.
5
+ **How:** Generated by GSD GitHub Sync swarm routines from lane evidence.
6
+
7
+ ## What
8
+
9
+ ### Swarm lane
10
+ **Lane:** `lane/writer`
11
+ **Branch:** `lane/single-writer`
12
+ **Owner:** @owner
13
+ **Latest commit:** `abc1234`
14
+
15
+ ### Impact area
16
+ Single-writer UOK metadata.
17
+
18
+ ### Changed contracts
19
+ - [ ] WriterToken
20
+
21
+ ### Transition risks
22
+ - [ ] Writer token lifecycle regression
23
+
24
+ ## Why
25
+
26
+ Workflow work is complete and ready for review.
27
+
28
+ ## How
29
+
30
+ Generated by GSD GitHub Sync swarm routines from lane evidence.
31
+
32
+ ## Linked Issue
33
+
34
+ Closes #123
35
+
36
+ ## Tests Run
37
+
38
+ - npm run typecheck:extensions
39
+
40
+ ## Change Type
41
+
42
+ - [ ] `feat` - New feature or capability
43
+ - [ ] `fix` - Bug fix
44
+ - [x] `refactor` - Code restructuring
45
+ - [ ] `test` - Adding or updating tests
46
+ - [ ] `docs` - Documentation only
47
+ - [ ] `chore` - Build, CI, or tooling changes
48
+
49
+ ## Rollback And Compatibility
50
+
51
+ - Disable writer sequence enrichment
52
+
53
+ ## AI Assistance Disclosure
54
+
55
+ This PR was prepared with AI assistance.
@@ -0,0 +1,60 @@
1
+ ## TL;DR
2
+
3
+ **What:** Ship workflow lane/writer - lane/writer
4
+ **Why:** Workflow work is complete and ready for review.
5
+ **How:** Generated by GSD GitHub Sync swarm routines from lane evidence.
6
+
7
+ ## What
8
+
9
+ ### Swarm lane
10
+ **Lane:** `lane/writer`
11
+ **Branch:** `lane/single-writer`
12
+ **Owner:** @owner
13
+ **Latest commit:** `abc1234`
14
+
15
+ ### Impact area
16
+ Single-writer UOK metadata.
17
+
18
+ ### Changed contracts
19
+ - [ ] WriterToken
20
+
21
+ ### Transition risks
22
+ - [ ] Writer token lifecycle regression
23
+
24
+ ## Blockers
25
+
26
+ - Awaiting state-lane writer-sequence merge
27
+ - Parity report incomplete
28
+
29
+ ## Why
30
+
31
+ Workflow work is complete and ready for review.
32
+
33
+ ## How
34
+
35
+ Generated by GSD GitHub Sync swarm routines from lane evidence.
36
+
37
+ ## Linked Issue
38
+
39
+ Closes #123
40
+
41
+ ## Tests Run
42
+
43
+ - npm run typecheck:extensions
44
+
45
+ ## Change Type
46
+
47
+ - [ ] `feat` - New feature or capability
48
+ - [ ] `fix` - Bug fix
49
+ - [x] `refactor` - Code restructuring
50
+ - [ ] `test` - Adding or updating tests
51
+ - [ ] `docs` - Documentation only
52
+ - [ ] `chore` - Build, CI, or tooling changes
53
+
54
+ ## Rollback And Compatibility
55
+
56
+ - Disable writer sequence enrichment
57
+
58
+ ## AI Assistance Disclosure
59
+
60
+ This PR was prepared with AI assistance.
@@ -233,6 +233,16 @@ describe("getNextPendingStep", () => {
233
233
  const next = getNextPendingStep(graph);
234
234
  assert.equal(next?.id, "b");
235
235
  });
236
+
237
+ it("treats expanded dependencies as satisfied", (t) => {
238
+ const graph = makeGraph([
239
+ makeStep({ id: "iter", status: "expanded" }),
240
+ makeStep({ id: "after", dependsOn: ["iter"] }),
241
+ ]);
242
+
243
+ const next = getNextPendingStep(graph);
244
+ assert.equal(next?.id, "after");
245
+ });
236
246
  });
237
247
 
238
248
  // ─── markStepComplete ────────────────────────────────────────────────────
@@ -30,6 +30,10 @@ import {
30
30
  insertTask,
31
31
  getTask,
32
32
  getSliceTasks,
33
+ deleteMilestone,
34
+ clearEngineHierarchy,
35
+ recordMilestoneCommitAttribution,
36
+ getMilestoneCommitAttributionShas,
33
37
  checkpointDatabase,
34
38
  refreshOpenDatabaseFromDisk,
35
39
  tryCreateMemoriesFts,
@@ -1047,6 +1051,46 @@ describe('gsd-db', () => {
1047
1051
  });
1048
1052
  });
1049
1053
 
1054
+ // ─── milestone_commit_attributions teardown ───────────────────────────────
1055
+
1056
+ describe('milestone commit attribution teardown', () => {
1057
+ test('deleteMilestone removes persisted milestone commit attributions', () => {
1058
+ openDatabase(':memory:');
1059
+ insertMilestone({ id: 'M001', title: 'Milestone', status: 'active' });
1060
+ recordMilestoneCommitAttribution({
1061
+ commitSha: '0123456789abcdef0123456789abcdef01234567',
1062
+ milestoneId: 'M001',
1063
+ source: 'backfill',
1064
+ confidence: 0.8,
1065
+ files: ['app.js'],
1066
+ createdAt: '2026-05-05T00:00:00.000Z',
1067
+ });
1068
+
1069
+ assert.deepEqual(getMilestoneCommitAttributionShas('M001'), ['0123456789abcdef0123456789abcdef01234567']);
1070
+ deleteMilestone('M001');
1071
+ assert.deepEqual(getMilestoneCommitAttributionShas('M001'), []);
1072
+ closeDatabase();
1073
+ });
1074
+
1075
+ test('clearEngineHierarchy removes persisted milestone commit attributions', () => {
1076
+ openDatabase(':memory:');
1077
+ insertMilestone({ id: 'M001', title: 'Milestone', status: 'active' });
1078
+ recordMilestoneCommitAttribution({
1079
+ commitSha: 'fedcba9876543210fedcba9876543210fedcba98',
1080
+ milestoneId: 'M001',
1081
+ source: 'backfill',
1082
+ confidence: 0.8,
1083
+ files: ['app.js'],
1084
+ createdAt: '2026-05-05T00:00:00.000Z',
1085
+ });
1086
+
1087
+ assert.deepEqual(getMilestoneCommitAttributionShas('M001'), ['fedcba9876543210fedcba9876543210fedcba98']);
1088
+ clearEngineHierarchy();
1089
+ assert.deepEqual(getMilestoneCommitAttributionShas('M001'), []);
1090
+ closeDatabase();
1091
+ });
1092
+ });
1093
+
1050
1094
  // ─── getDbStatus ───────────────────────────────────────────────────────────
1051
1095
 
1052
1096
  describe('getDbStatus', () => {
@@ -15,7 +15,7 @@ import { tmpdir } from "node:os";
15
15
  import { join } from "node:path";
16
16
  import { randomUUID } from "node:crypto";
17
17
 
18
- import { hasPendingDeepStage } from "../auto-dispatch.ts";
18
+ import { hasPendingDeepStage, shouldRunDeepProjectSetup } from "../auto-dispatch.ts";
19
19
  import type { GSDPreferences } from "../preferences.ts";
20
20
  import { loadEffectiveGSDPreferences } from "../preferences.ts";
21
21
 
@@ -57,6 +57,38 @@ test("hasPendingDeepStage: returns true in deep mode when nothing has been captu
57
57
  }
58
58
  });
59
59
 
60
+ test("shouldRunDeepProjectSetup: complete state wins over pending deep setup", async () => {
61
+ const base = makeBase();
62
+ try {
63
+ assert.equal(hasPendingDeepStage(deepPrefs, base), true);
64
+ assert.equal(
65
+ shouldRunDeepProjectSetup({ phase: "complete" }, deepPrefs, base),
66
+ false,
67
+ "completed projects must not restart deep setup and loop through auto-mode",
68
+ );
69
+ } finally {
70
+ rmSync(base, { recursive: true, force: true });
71
+ }
72
+ });
73
+
74
+ test("shouldRunDeepProjectSetup: only setup phases can trigger pending deep setup", () => {
75
+ const base = makeBase();
76
+ try {
77
+ assert.equal(hasPendingDeepStage(deepPrefs, base), true);
78
+ assert.equal(shouldRunDeepProjectSetup({ phase: "pre-planning" }, deepPrefs, base), true);
79
+ assert.equal(shouldRunDeepProjectSetup({ phase: "needs-discussion" }, deepPrefs, base), true);
80
+ assert.equal(shouldRunDeepProjectSetup({ phase: "planning" }, deepPrefs, base), true);
81
+ assert.equal(shouldRunDeepProjectSetup({ phase: "executing" }, deepPrefs, base), false);
82
+ assert.equal(shouldRunDeepProjectSetup({ phase: "blocked" }, deepPrefs, base), false);
83
+ assert.equal(
84
+ shouldRunDeepProjectSetup({ phase: "pre-planning" }, deepPrefs, base, { hasSurvivorBranch: true }),
85
+ false,
86
+ );
87
+ } finally {
88
+ rmSync(base, { recursive: true, force: true });
89
+ }
90
+ });
91
+
60
92
  test("hasPendingDeepStage: returns true in deep mode when only some gates pass", () => {
61
93
  // workflow-preferences captured but PROJECT.md still missing.
62
94
  const base = makeBase();
@@ -172,6 +172,56 @@ test('handlePlanSlice rejects invalid payloads', async () => {
172
172
  }
173
173
  });
174
174
 
175
+ test('handlePlanSlice rejects absolute task IO paths outside the active worktree', async () => {
176
+ const base = makeTmpBase();
177
+ openDatabase(join(base, '.gsd', 'gsd.db'));
178
+
179
+ try {
180
+ seedParentSlice();
181
+ const outside = join(tmpdir(), 'outside-checkout', 'index.html');
182
+ const result = await handlePlanSlice({
183
+ ...validParams(),
184
+ tasks: [
185
+ {
186
+ ...validParams().tasks[0],
187
+ inputs: [outside],
188
+ expectedOutput: [outside],
189
+ },
190
+ ],
191
+ }, base);
192
+
193
+ assert.ok('error' in result);
194
+ assert.match(result.error, /validation failed: tasks\[0\]\.inputs contains absolute path outside working directory/);
195
+ assert.equal(getSliceTasks('M001', 'S02').length, 0, 'invalid planning IO must not persist tasks');
196
+ } finally {
197
+ cleanup(base);
198
+ }
199
+ });
200
+
201
+ test('handlePlanSlice accepts absolute task IO paths inside the active worktree', async () => {
202
+ const base = makeTmpBase();
203
+ openDatabase(join(base, '.gsd', 'gsd.db'));
204
+
205
+ try {
206
+ seedParentSlice();
207
+ const inside = join(base, 'index.html');
208
+ const result = await handlePlanSlice({
209
+ ...validParams(),
210
+ tasks: [
211
+ {
212
+ ...validParams().tasks[0],
213
+ inputs: [inside],
214
+ expectedOutput: [inside],
215
+ },
216
+ ],
217
+ }, base);
218
+
219
+ assert.ok(!('error' in result), `unexpected error: ${'error' in result ? result.error : ''}`);
220
+ } finally {
221
+ cleanup(base);
222
+ }
223
+ });
224
+
175
225
  test('handlePlanSlice rejects missing parent slice', async () => {
176
226
  const base = makeTmpBase();
177
227
  openDatabase(join(base, '.gsd', 'gsd.db'));
@@ -79,6 +79,27 @@ test('handlePlanTask rejects invalid payloads', async () => {
79
79
  }
80
80
  });
81
81
 
82
+ test('handlePlanTask rejects absolute task IO paths outside the active worktree', async () => {
83
+ const base = makeTmpBase();
84
+ openDatabase(join(base, '.gsd', 'gsd.db'));
85
+
86
+ try {
87
+ seedParent();
88
+ const outside = join(tmpdir(), 'outside-checkout', 'index.html');
89
+ const result = await handlePlanTask({
90
+ ...validParams(),
91
+ inputs: [outside],
92
+ expectedOutput: [outside],
93
+ }, base);
94
+
95
+ assert.ok('error' in result);
96
+ assert.match(result.error, /validation failed: inputs contains absolute path outside working directory/);
97
+ assert.equal(getTask('M001', 'S02', 'T02'), null, 'invalid planning IO must not persist the task');
98
+ } finally {
99
+ cleanup(base);
100
+ }
101
+ });
102
+
82
103
  test('handlePlanTask rejects missing parent slice', async () => {
83
104
  const base = makeTmpBase();
84
105
  openDatabase(join(base, '.gsd', 'gsd.db'));
@@ -0,0 +1,102 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Golden-fixture equivalence tests pinning PR-body output for buildPrEvidence and formatSwarmLanePRBody.
3
+
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { readFileSync, writeFileSync } from "node:fs";
7
+ import { fileURLToPath } from "node:url";
8
+ import { dirname, join } from "node:path";
9
+
10
+ import { buildPrEvidence, type PrEvidenceInput } from "../pr-evidence.ts";
11
+ import {
12
+ formatSwarmLanePRBody,
13
+ type SwarmLanePRData,
14
+ } from "../../github-sync/templates.ts";
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const FIXTURES_DIR = join(__dirname, "fixtures", "pr-body");
18
+
19
+ const UPDATE = process.env.UPDATE_GOLDENS === "1";
20
+
21
+ function compareGolden(name: string, actual: string): void {
22
+ const path = join(FIXTURES_DIR, name);
23
+ if (UPDATE) {
24
+ writeFileSync(path, actual, "utf8");
25
+ return;
26
+ }
27
+ const expected = readFileSync(path, "utf8");
28
+ assert.equal(actual, expected, `golden mismatch for ${name}`);
29
+ }
30
+
31
+ const SHIP_BASIC: PrEvidenceInput = {
32
+ milestoneId: "M001",
33
+ milestoneTitle: "Authentication",
34
+ changeType: "feat",
35
+ linkedIssue: "Closes #123",
36
+ summaries: ["### S01\nImplemented login flow."],
37
+ roadmapItems: ["- [x] **S01: Login**"],
38
+ metrics: ["**Units executed:** 3"],
39
+ testsRun: ["npm test", "npm run typecheck:extensions"],
40
+ why: "Users need to authenticate before accessing protected resources.",
41
+ how: "Added password hash check and session token issuance.",
42
+ rollbackNotes: ["Revert the merge commit."],
43
+ };
44
+
45
+ const SHIP_EMPTY_OPTIONALS: PrEvidenceInput = {
46
+ milestoneId: "M001",
47
+ milestoneTitle: "Authentication",
48
+ changeType: "feat",
49
+ };
50
+
51
+ const SWARM_WITH_BLOCKERS: SwarmLanePRData = {
52
+ lane: {
53
+ id: "writer",
54
+ branch: "lane/single-writer",
55
+ owner: "@owner",
56
+ latestCommit: "abc1234",
57
+ changedContracts: ["WriterToken"],
58
+ testEvidence: ["npm run typecheck:extensions"],
59
+ blockers: ["Awaiting state-lane writer-sequence merge", "Parity report incomplete"],
60
+ },
61
+ impactArea: "Single-writer UOK metadata.",
62
+ transitionRisks: ["Writer token lifecycle regression"],
63
+ rollbackPlan: ["Disable writer sequence enrichment"],
64
+ linkedIssue: 123,
65
+ };
66
+
67
+ const SWARM_NO_BLOCKERS: SwarmLanePRData = {
68
+ lane: {
69
+ id: "writer",
70
+ branch: "lane/single-writer",
71
+ owner: "@owner",
72
+ latestCommit: "abc1234",
73
+ changedContracts: ["WriterToken"],
74
+ testEvidence: ["npm run typecheck:extensions"],
75
+ },
76
+ impactArea: "Single-writer UOK metadata.",
77
+ transitionRisks: ["Writer token lifecycle regression"],
78
+ rollbackPlan: ["Disable writer sequence enrichment"],
79
+ linkedIssue: 123,
80
+ };
81
+
82
+ test("pr-evidence golden: commands-ship basic", () => {
83
+ compareGolden("commands-ship-basic.md", buildPrEvidence(SHIP_BASIC).body);
84
+ });
85
+
86
+ test("pr-evidence golden: commands-ship empty optionals", () => {
87
+ compareGolden("commands-ship-empty-optionals.md", buildPrEvidence(SHIP_EMPTY_OPTIONALS).body);
88
+ });
89
+
90
+ test("pr-evidence golden: swarm-lane with blockers", () => {
91
+ const body = formatSwarmLanePRBody(SWARM_WITH_BLOCKERS);
92
+ compareGolden("swarm-lane-with-blockers.md", body);
93
+ // Cross-check: top-level ## Blockers heading must appear (regression guard
94
+ // for the silent-drop fixed in this PR).
95
+ assert.ok(body.includes("\n## Blockers\n"), "swarm-lane body must emit a top-level ## Blockers heading");
96
+ });
97
+
98
+ test("pr-evidence golden: swarm-lane no blockers (no Blockers heading)", () => {
99
+ const body = formatSwarmLanePRBody(SWARM_NO_BLOCKERS);
100
+ compareGolden("swarm-lane-no-blockers.md", body);
101
+ assert.ok(!body.includes("## Blockers"), "swarm-lane body without blockers must not emit ## Blockers heading");
102
+ });