gsd-pi 2.80.0-dev.b62439b9f → 2.80.0-dev.c5c38454b

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 (431) hide show
  1. package/dist/{cli/cli-web-branch.d.ts → cli-web-branch.d.ts} +1 -1
  2. package/dist/{cli/cli-web-branch.js → cli-web-branch.js} +3 -3
  3. package/dist/{cli/cli.js → cli.js} +25 -25
  4. package/dist/{extension-runtime/extension-registry.js → extension-registry.js} +1 -1
  5. package/dist/{headless/headless-query.d.ts → headless-query.d.ts} +1 -1
  6. package/dist/{headless/headless-query.js → headless-query.js} +2 -3
  7. package/dist/{headless/headless-recover.js → headless-recover.js} +2 -3
  8. package/dist/{headless/headless.js → headless.js} +3 -3
  9. package/dist/loader.js +10 -10
  10. package/dist/{providers/models-resolver.js → models-resolver.js} +1 -1
  11. package/dist/{onboarding/onboarding.js → onboarding.js} +8 -8
  12. package/dist/{providers/remote-questions-config.js → remote-questions-config.js} +1 -1
  13. package/dist/{resource-runtime/resource-loader.d.ts → resource-loader.d.ts} +1 -1
  14. package/dist/{resource-runtime/resource-loader.js → resource-loader.js} +6 -6
  15. package/dist/resources/.managed-resources-content-hash +1 -1
  16. package/dist/resources/extensions/github-sync/templates.js +39 -8
  17. package/dist/resources/extensions/gsd/auto/loop.js +13 -9
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -15
  19. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  20. package/dist/resources/extensions/gsd/auto-dispatch.js +10 -0
  21. package/dist/resources/extensions/gsd/auto-recovery.js +154 -8
  22. package/dist/resources/extensions/gsd/auto-start.js +2 -3
  23. package/dist/resources/extensions/gsd/auto-worktree.js +6 -4
  24. package/dist/resources/extensions/gsd/auto.js +3 -3
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +15 -1
  26. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -1
  27. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  28. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  29. package/dist/resources/extensions/gsd/db-base-schema.js +14 -0
  30. package/dist/resources/extensions/gsd/db-migration-steps.js +16 -0
  31. package/dist/resources/extensions/gsd/gsd-db.js +102 -2
  32. package/dist/resources/extensions/gsd/guided-flow.js +2 -2
  33. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  34. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  35. package/dist/{security/security-overrides.js → security-overrides.js} +1 -1
  36. package/dist/{startup/startup-model-validation.js → startup-model-validation.js} +1 -1
  37. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  38. package/dist/{update/update-check.js → update-check.js} +1 -1
  39. package/dist/web/standalone/.next/BUILD_ID +1 -1
  40. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  41. package/dist/web/standalone/.next/build-manifest.json +3 -3
  42. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  43. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  44. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  45. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  58. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  61. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  62. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  63. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  64. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  65. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  66. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  67. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  68. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  69. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  70. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  71. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  72. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  73. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  74. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  75. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  76. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  77. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  78. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  80. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  82. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  84. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  85. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  86. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  90. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  92. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  93. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  94. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  96. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  97. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  99. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  101. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  103. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  107. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  109. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  111. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  113. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  115. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  117. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  118. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  119. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  120. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  121. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +3 -3
  122. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  123. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  125. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  128. package/dist/web/standalone/.next/server/app/index.html +1 -1
  129. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  136. package/dist/web/standalone/.next/server/chunks/6897.js +12 -0
  137. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  140. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  141. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  142. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  143. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  144. package/dist/{cli/web-mode.js → web-mode.js} +3 -3
  145. package/dist/{onboarding/welcome-screen.js → welcome-screen.js} +1 -1
  146. package/dist/{worktrees/worktree-cli.js → worktree-cli.js} +2 -3
  147. package/package.json +7 -3
  148. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  149. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  150. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  151. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  152. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  153. package/packages/pi-ai/dist/models/index.js +8 -0
  154. package/packages/pi-ai/dist/models/index.js.map +1 -1
  155. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  156. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  157. package/packages/pi-ai/dist/providers/fake.js +319 -0
  158. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  159. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  160. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  161. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  162. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  163. package/packages/pi-ai/src/models/index.ts +9 -0
  164. package/packages/pi-ai/src/providers/fake.ts +376 -0
  165. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  166. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  167. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +44 -0
  168. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  169. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  170. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  171. package/packages/pi-coding-agent/dist/core/extensions/runner.js +14 -1
  172. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  173. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +97 -0
  174. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  175. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  176. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  177. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  178. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +4 -0
  179. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  180. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  181. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  184. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  186. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  188. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  190. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  191. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  192. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  193. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  194. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  195. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  196. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  197. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  201. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  207. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +16 -0
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +106 -17
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +58 -1
  214. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +40 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  223. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +23 -0
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  227. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  228. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  229. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  230. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  231. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  232. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  233. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  234. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  237. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  238. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  240. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  243. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  245. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  246. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  248. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  249. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  251. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  252. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +51 -0
  253. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +108 -0
  254. package/packages/pi-coding-agent/src/core/extensions/runner.ts +16 -1
  255. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  256. package/packages/pi-coding-agent/src/core/settings-manager.ts +12 -0
  257. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  258. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  259. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  260. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  261. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  262. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  263. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  264. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  265. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  266. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +118 -17
  267. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +43 -1
  268. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +73 -1
  269. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  270. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  271. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +25 -0
  272. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  273. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  274. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  275. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  276. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  277. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  278. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  279. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  280. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  281. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  282. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  283. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  284. package/packages/pi-tui/dist/__tests__/tui.test.js +1 -2
  285. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  286. package/packages/pi-tui/dist/index.d.ts +1 -0
  287. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  288. package/packages/pi-tui/dist/index.js +2 -0
  289. package/packages/pi-tui/dist/index.js.map +1 -1
  290. package/packages/pi-tui/dist/style.d.ts +41 -0
  291. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  292. package/packages/pi-tui/dist/style.js +158 -0
  293. package/packages/pi-tui/dist/style.js.map +1 -0
  294. package/packages/pi-tui/dist/tui.d.ts +1 -3
  295. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  296. package/packages/pi-tui/dist/tui.js +2 -3
  297. package/packages/pi-tui/dist/tui.js.map +1 -1
  298. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  299. package/packages/pi-tui/src/__tests__/tui.test.ts +1 -2
  300. package/packages/pi-tui/src/index.ts +9 -0
  301. package/packages/pi-tui/src/style.ts +225 -0
  302. package/packages/pi-tui/src/tui.ts +2 -3
  303. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  304. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  305. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  306. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  307. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  308. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  309. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  310. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  311. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  312. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  313. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  314. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  315. package/src/resources/extensions/github-sync/templates.ts +38 -8
  316. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  317. package/src/resources/extensions/gsd/auto/loop.ts +14 -10
  318. package/src/resources/extensions/gsd/auto/run-unit.ts +24 -14
  319. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  320. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -0
  321. package/src/resources/extensions/gsd/auto-recovery.ts +153 -7
  322. package/src/resources/extensions/gsd/auto-start.ts +7 -6
  323. package/src/resources/extensions/gsd/auto-worktree.ts +6 -4
  324. package/src/resources/extensions/gsd/auto.ts +3 -3
  325. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -1
  326. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -1
  327. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  328. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  329. package/src/resources/extensions/gsd/db-base-schema.ts +15 -0
  330. package/src/resources/extensions/gsd/db-migration-steps.ts +17 -0
  331. package/src/resources/extensions/gsd/gsd-db.ts +119 -1
  332. package/src/resources/extensions/gsd/guided-flow.ts +2 -2
  333. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  334. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  335. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  336. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +83 -4
  337. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +170 -1
  338. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  339. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  340. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  341. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  342. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  343. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  344. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  345. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  346. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  347. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +1 -1
  348. package/src/resources/extensions/gsd/tests/headless-query.test.ts +2 -2
  349. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  350. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  351. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +1 -1
  352. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  353. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +7 -8
  354. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  355. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +1 -1
  356. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  357. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  358. package/dist/web/standalone/.next/server/chunks/7020.js +0 -12
  359. /package/dist/{app/app-paths.d.ts → app-paths.d.ts} +0 -0
  360. /package/dist/{app/app-paths.js → app-paths.js} +0 -0
  361. /package/dist/{extension-runtime/bundled-extension-paths.d.ts → bundled-extension-paths.d.ts} +0 -0
  362. /package/dist/{extension-runtime/bundled-extension-paths.js → bundled-extension-paths.js} +0 -0
  363. /package/dist/{extension-runtime/bundled-resource-path.d.ts → bundled-resource-path.d.ts} +0 -0
  364. /package/dist/{extension-runtime/bundled-resource-path.js → bundled-resource-path.js} +0 -0
  365. /package/dist/{startup/claude-cli-check.d.ts → claude-cli-check.d.ts} +0 -0
  366. /package/dist/{startup/claude-cli-check.js → claude-cli-check.js} +0 -0
  367. /package/dist/{cli/cli-auto-routing.d.ts → cli-auto-routing.d.ts} +0 -0
  368. /package/dist/{cli/cli-auto-routing.js → cli-auto-routing.js} +0 -0
  369. /package/dist/{cli/cli-policy.d.ts → cli-policy.d.ts} +0 -0
  370. /package/dist/{cli/cli-policy.js → cli-policy.js} +0 -0
  371. /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
  372. /package/dist/{extension-runtime/extension-discovery.d.ts → extension-discovery.d.ts} +0 -0
  373. /package/dist/{extension-runtime/extension-discovery.js → extension-discovery.js} +0 -0
  374. /package/dist/{extension-runtime/extension-registry.d.ts → extension-registry.d.ts} +0 -0
  375. /package/dist/{extension-runtime/extension-sort.d.ts → extension-sort.d.ts} +0 -0
  376. /package/dist/{extension-runtime/extension-sort.js → extension-sort.js} +0 -0
  377. /package/dist/{extension-runtime/extension-validator.d.ts → extension-validator.d.ts} +0 -0
  378. /package/dist/{extension-runtime/extension-validator.js → extension-validator.js} +0 -0
  379. /package/dist/{headless/headless-answers.d.ts → headless-answers.d.ts} +0 -0
  380. /package/dist/{headless/headless-answers.js → headless-answers.js} +0 -0
  381. /package/dist/{headless/headless-context.d.ts → headless-context.d.ts} +0 -0
  382. /package/dist/{headless/headless-context.js → headless-context.js} +0 -0
  383. /package/dist/{headless/headless-events.d.ts → headless-events.d.ts} +0 -0
  384. /package/dist/{headless/headless-events.js → headless-events.js} +0 -0
  385. /package/dist/{headless/headless-recover.d.ts → headless-recover.d.ts} +0 -0
  386. /package/dist/{headless/headless-types.d.ts → headless-types.d.ts} +0 -0
  387. /package/dist/{headless/headless-types.js → headless-types.js} +0 -0
  388. /package/dist/{headless/headless-ui.d.ts → headless-ui.d.ts} +0 -0
  389. /package/dist/{headless/headless-ui.js → headless-ui.js} +0 -0
  390. /package/dist/{headless/headless.d.ts → headless.d.ts} +0 -0
  391. /package/dist/{cli/help-text.d.ts → help-text.d.ts} +0 -0
  392. /package/dist/{cli/help-text.js → help-text.js} +0 -0
  393. /package/dist/{cli/logo.d.ts → logo.d.ts} +0 -0
  394. /package/dist/{cli/logo.js → logo.js} +0 -0
  395. /package/dist/{mcp/mcp-server.d.ts → mcp-server.d.ts} +0 -0
  396. /package/dist/{mcp/mcp-server.js → mcp-server.js} +0 -0
  397. /package/dist/{providers/models-resolver.d.ts → models-resolver.d.ts} +0 -0
  398. /package/dist/{onboarding/onboarding.d.ts → onboarding.d.ts} +0 -0
  399. /package/dist/{providers/pi-migration.d.ts → pi-migration.d.ts} +0 -0
  400. /package/dist/{providers/pi-migration.js → pi-migration.js} +0 -0
  401. /package/dist/{app/project-sessions.d.ts → project-sessions.d.ts} +0 -0
  402. /package/dist/{app/project-sessions.js → project-sessions.js} +0 -0
  403. /package/dist/{providers/provider-migrations.d.ts → provider-migrations.d.ts} +0 -0
  404. /package/dist/{providers/provider-migrations.js → provider-migrations.js} +0 -0
  405. /package/dist/{providers/remote-questions-config.d.ts → remote-questions-config.d.ts} +0 -0
  406. /package/dist/{rtk/rtk-shared.d.ts → rtk-shared.d.ts} +0 -0
  407. /package/dist/{rtk/rtk-shared.js → rtk-shared.js} +0 -0
  408. /package/dist/{rtk/rtk.d.ts → rtk.d.ts} +0 -0
  409. /package/dist/{rtk/rtk.js → rtk.js} +0 -0
  410. /package/dist/{startup/runtime-checks.d.ts → runtime-checks.d.ts} +0 -0
  411. /package/dist/{startup/runtime-checks.js → runtime-checks.js} +0 -0
  412. /package/dist/{security/security-overrides.d.ts → security-overrides.d.ts} +0 -0
  413. /package/dist/{startup/startup-model-validation.d.ts → startup-model-validation.d.ts} +0 -0
  414. /package/dist/{startup/startup-timings.d.ts → startup-timings.d.ts} +0 -0
  415. /package/dist/{startup/startup-timings.js → startup-timings.js} +0 -0
  416. /package/dist/{app/tool-bootstrap.d.ts → tool-bootstrap.d.ts} +0 -0
  417. /package/dist/{app/tool-bootstrap.js → tool-bootstrap.js} +0 -0
  418. /package/dist/{update/update-check.d.ts → update-check.d.ts} +0 -0
  419. /package/dist/{update/update-cmd.d.ts → update-cmd.d.ts} +0 -0
  420. /package/dist/{update/update-cmd.js → update-cmd.js} +0 -0
  421. /package/dist/web/standalone/.next/static/{-WDXZiiJHGZDbYH75Mu6f → TCSim36ZpcPu2WgeoC45g}/_buildManifest.js +0 -0
  422. /package/dist/web/standalone/.next/static/{-WDXZiiJHGZDbYH75Mu6f → TCSim36ZpcPu2WgeoC45g}/_ssgManifest.js +0 -0
  423. /package/dist/{cli/web-mode.d.ts → web-mode.d.ts} +0 -0
  424. /package/dist/{onboarding/welcome-screen.d.ts → welcome-screen.d.ts} +0 -0
  425. /package/dist/{onboarding/wizard.d.ts → wizard.d.ts} +0 -0
  426. /package/dist/{onboarding/wizard.js → wizard.js} +0 -0
  427. /package/dist/{worktrees/worktree-cli.d.ts → worktree-cli.d.ts} +0 -0
  428. /package/dist/{worktrees/worktree-name-gen.d.ts → worktree-name-gen.d.ts} +0 -0
  429. /package/dist/{worktrees/worktree-name-gen.js → worktree-name-gen.js} +0 -0
  430. /package/dist/{worktrees/worktree-status-banner.d.ts → worktree-status-banner.d.ts} +0 -0
  431. /package/dist/{worktrees/worktree-status-banner.js → worktree-status-banner.js} +0 -0
@@ -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();
@@ -11,7 +11,7 @@ import assert from 'node:assert/strict';
11
11
  import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
12
12
  import { join } from 'node:path';
13
13
  import { tmpdir } from 'node:os';
14
- import { loadAndValidateAnswerFile, AnswerInjector } from '../../../../headless/headless-answers.ts';
14
+ import { loadAndValidateAnswerFile, AnswerInjector } from '../../../../headless-answers.ts';
15
15
 
16
16
  function makeTempDir(prefix: string): string {
17
17
  const dir = join(tmpdir(), `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
@@ -11,8 +11,8 @@ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
11
11
  import { join } from 'node:path'
12
12
  import { tmpdir } from 'node:os'
13
13
 
14
- import { handleQuery } from '../../../../headless/headless-query.ts'
15
- import type { QuerySnapshot } from '../../../../headless/headless-query.ts'
14
+ import { handleQuery } from '../../../../headless-query.ts'
15
+ import type { QuerySnapshot } from '../../../../headless-query.ts'
16
16
  import { invalidateStateCache } from '../state.ts'
17
17
 
18
18
  // ─── Fixture Helpers ────────────────────────────────────────────────────────
@@ -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
+ });
@@ -0,0 +1,165 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Hardening tests for buildPrEvidence — HTML-comment stripping, fake commit-trailer removal, and per-item length capping.
3
+
4
+ import test from "node:test";
5
+ import assert from "node:assert/strict";
6
+
7
+ import { buildPrEvidence, type PrEvidenceInput } from "../pr-evidence.ts";
8
+
9
+ test("pr-evidence hardening: strips HTML comments from summaries", () => {
10
+ const evidence = buildPrEvidence({
11
+ milestoneId: "M001",
12
+ summaries: ["visible<!-- hidden secret -->tail"],
13
+ });
14
+ assert.ok(!evidence.body.includes("<!--"), "raw <!-- must not appear");
15
+ assert.ok(!evidence.body.includes("hidden secret"), "comment contents must be stripped");
16
+ assert.ok(evidence.body.includes("visibletail"), "non-comment text must remain");
17
+ });
18
+
19
+ test("pr-evidence hardening: removes Co-Authored-By trailer from why", () => {
20
+ const evidence = buildPrEvidence({
21
+ milestoneId: "M001",
22
+ why: "Real reason here.\nCo-Authored-By: Evil <e@evil.com>\nMore reason.",
23
+ });
24
+ assert.ok(!evidence.body.includes("Evil <e@evil.com>"));
25
+ assert.ok(!/Co-Authored-By:/i.test(evidence.body));
26
+ assert.ok(evidence.body.includes("Real reason here."));
27
+ assert.ok(evidence.body.includes("More reason."));
28
+ });
29
+
30
+ test("pr-evidence hardening: removes Signed-off-by trailer from how", () => {
31
+ const evidence = buildPrEvidence({
32
+ milestoneId: "M001",
33
+ how: "Step one.\nSigned-off-by: Forged <f@x.com>\nStep two.",
34
+ });
35
+ assert.ok(!evidence.body.includes("Forged <f@x.com>"));
36
+ assert.ok(!/Signed-off-by:/i.test(evidence.body));
37
+ assert.ok(evidence.body.includes("Step one."));
38
+ assert.ok(evidence.body.includes("Step two."));
39
+ });
40
+
41
+ test("pr-evidence hardening: trailer-name match is case-insensitive", () => {
42
+ const evidence = buildPrEvidence({
43
+ milestoneId: "M001",
44
+ why: "ok\nco-authored-by: lower <l@l.com>\nSIGNED-OFF-BY: upper <u@u.com>\nend",
45
+ });
46
+ assert.ok(!evidence.body.includes("lower <l@l.com>"));
47
+ assert.ok(!evidence.body.includes("upper <u@u.com>"));
48
+ assert.ok(evidence.body.includes("ok"));
49
+ assert.ok(evidence.body.includes("end"));
50
+ });
51
+
52
+ test("pr-evidence hardening: caps oversize summaries item with truncation suffix", () => {
53
+ const big = "A".repeat(5 * 1024); // 5 KB
54
+ const evidence = buildPrEvidence({
55
+ milestoneId: "M001",
56
+ summaries: [big],
57
+ });
58
+ // Find the truncated A-block in the body and assert it is bounded.
59
+ const lines = evidence.body.split("\n");
60
+ const longLine = lines.find((l) => l.startsWith("AAAA"));
61
+ assert.ok(longLine, "expected truncated A-line in body");
62
+ assert.ok(longLine!.endsWith(" … [truncated]"), "must end with truncation suffix");
63
+ assert.ok(
64
+ Buffer.byteLength(longLine!, "utf8") <= 2048,
65
+ `truncated item must be within 2 KB cap, got ${Buffer.byteLength(longLine!, "utf8")}`,
66
+ );
67
+ });
68
+
69
+ test("pr-evidence hardening: HTML comment split across summary items is preserved literally", () => {
70
+ // Documented behavior: each item is sanitized independently. A comment
71
+ // that begins in one item and closes in the next is NOT joined, so the
72
+ // open/close markers remain as literal text. This is intentional — joining
73
+ // items before sanitizing would let an attacker straddle items to inject
74
+ // an aligned comment that hides the second item from rendered view.
75
+ const evidence = buildPrEvidence({
76
+ milestoneId: "M001",
77
+ summaries: ["first item ends <!--", "--> second item begins"],
78
+ });
79
+ // The literal markers survive because each item was sanitized alone.
80
+ assert.ok(evidence.body.includes("<!--"), "open marker preserved as literal");
81
+ assert.ok(evidence.body.includes("-->"), "close marker preserved as literal");
82
+ assert.ok(evidence.body.includes("first item ends"));
83
+ assert.ok(evidence.body.includes("second item begins"));
84
+ });
85
+
86
+ test("pr-evidence hardening: clean input is byte-identical to pre-hardening output", () => {
87
+ // This test is the contract that protects the golden fixtures: the
88
+ // sanitizer must be a true no-op for well-formed input. If this fails,
89
+ // there is a bug in the sanitizer (not in the goldens).
90
+ const cleanInput: PrEvidenceInput = {
91
+ milestoneId: "M001",
92
+ milestoneTitle: "Authentication",
93
+ changeType: "feat",
94
+ linkedIssue: "Closes #123",
95
+ summaries: ["### S01\nImplemented login flow."],
96
+ blockers: ["Awaiting design review"],
97
+ roadmapItems: ["- [x] **S01: Login**"],
98
+ metrics: ["**Units executed:** 3"],
99
+ testsRun: ["npm test", "npm run typecheck:extensions"],
100
+ why: "Users need to authenticate before accessing protected resources.",
101
+ how: "Added password hash check and session token issuance.",
102
+ rollbackNotes: ["Revert the merge commit."],
103
+ };
104
+
105
+ const expected = [
106
+ "## TL;DR",
107
+ "",
108
+ "**What:** Ship milestone M001 - Authentication",
109
+ "**Why:** Users need to authenticate before accessing protected resources.",
110
+ "**How:** Added password hash check and session token issuance.",
111
+ "",
112
+ "## What",
113
+ "",
114
+ "### S01\nImplemented login flow.",
115
+ "",
116
+ "## Blockers",
117
+ "",
118
+ "- Awaiting design review",
119
+ "",
120
+ "## Why",
121
+ "",
122
+ "Users need to authenticate before accessing protected resources.",
123
+ "",
124
+ "## How",
125
+ "",
126
+ "Added password hash check and session token issuance.",
127
+ "",
128
+ "## Linked Issue",
129
+ "",
130
+ "Closes #123",
131
+ "",
132
+ "## Roadmap",
133
+ "",
134
+ "- [x] **S01: Login**",
135
+ "",
136
+ "## Metrics",
137
+ "",
138
+ "- **Units executed:** 3",
139
+ "",
140
+ "## Tests Run",
141
+ "",
142
+ "- npm test",
143
+ "- npm run typecheck:extensions",
144
+ "",
145
+ "## Change Type",
146
+ "",
147
+ "- [x] `feat` - New feature or capability",
148
+ "- [ ] `fix` - Bug fix",
149
+ "- [ ] `refactor` - Code restructuring",
150
+ "- [ ] `test` - Adding or updating tests",
151
+ "- [ ] `docs` - Documentation only",
152
+ "- [ ] `chore` - Build, CI, or tooling changes",
153
+ "",
154
+ "## Rollback And Compatibility",
155
+ "",
156
+ "- Revert the merge commit.",
157
+ "",
158
+ "## AI Assistance Disclosure",
159
+ "",
160
+ "This PR was prepared with AI assistance.",
161
+ ].join("\n");
162
+
163
+ const actual = buildPrEvidence(cleanInput).body;
164
+ assert.equal(actual, expected, "clean input must produce byte-identical output (sanitizer is no-op)");
165
+ });
@@ -24,7 +24,7 @@ describe("resource-loader import path", () => {
24
24
 
25
25
  test("uses GSD_PKG_ROOT to resolve resource-loader from package root", () => {
26
26
  // The fix uses GSD_PKG_ROOT (set by loader.ts) to construct an absolute
27
- // file URL to dist/resource-runtime/resource-loader.js — works in both source and deployed,
27
+ // file URL to dist/resource-loader.js — works in both source and deployed,
28
28
  // and on Windows where raw paths fail with ERR_UNSUPPORTED_ESM_URL_SCHEME.
29
29
  assert.ok(
30
30
  autoSrc.includes('process.env.GSD_PKG_ROOT'),
@@ -118,7 +118,7 @@ test("guided flow checks pending deep setup before plan-v2 gate", () => {
118
118
  const source = readFileSync(join(gsdDir, "guided-flow.ts"), "utf-8");
119
119
  const showSmartEntryIdx = source.indexOf("export async function showSmartEntry");
120
120
  assert.notEqual(showSmartEntryIdx, -1);
121
- const deepIdx = source.indexOf("hasPendingDeepStage(prefs, basePath)", showSmartEntryIdx);
121
+ const deepIdx = source.indexOf("shouldRunDeepProjectSetup(state, prefs, basePath)", showSmartEntryIdx);
122
122
  const planIdx = source.indexOf("runPlanV2Gate(ctx, basePath, state)", showSmartEntryIdx);
123
123
  assert.ok(
124
124
  deepIdx > -1 && planIdx > -1 && deepIdx < planIdx,
@@ -20,7 +20,6 @@ import {
20
20
 
21
21
  const __dirname = dirname(fileURLToPath(import.meta.url));
22
22
  const gsdDir = join(__dirname, "..");
23
- const WORKFLOW_MCP_TEST_TIMEOUT_MS = 90_000;
24
23
 
25
24
  type ElicitPayload = {
26
25
  message: string;
@@ -296,9 +295,9 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
296
295
  });
297
296
 
298
297
  try {
299
- await client.connect(transport, { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS });
298
+ await client.connect(transport, { timeout: 30_000 });
300
299
 
301
- const tools = await client.listTools(undefined, { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS });
300
+ const tools = await client.listTools(undefined, { timeout: 30_000 });
302
301
  assert.ok(
303
302
  (tools.tools ?? []).some((tool) => tool.name === "gsd_plan_slice"),
304
303
  "expected workflow MCP surface to expose gsd_plan_slice",
@@ -326,7 +325,7 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
326
325
  },
327
326
  },
328
327
  undefined,
329
- { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS },
328
+ { timeout: 30_000 },
330
329
  );
331
330
  assert.equal(askResult.isError, undefined);
332
331
  assert.equal(
@@ -365,7 +364,7 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
365
364
  },
366
365
  },
367
366
  undefined,
368
- { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS },
367
+ { timeout: 30_000 },
369
368
  );
370
369
  assert.equal(milestoneResult.isError, undefined);
371
370
  assert.match(
@@ -396,7 +395,7 @@ test("workflow MCP launch config reaches mutation tools over stdio", async () =>
396
395
  },
397
396
  },
398
397
  undefined,
399
- { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS },
398
+ { timeout: 30_000 },
400
399
  );
401
400
  assert.equal(sliceResult.isError, undefined);
402
401
  assert.match(
@@ -467,7 +466,7 @@ test("workflow MCP ask_user_questions uses stdio elicitation round-trip", async
467
466
  });
468
467
 
469
468
  try {
470
- await client.connect(transport, { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS });
469
+ await client.connect(transport, { timeout: 30_000 });
471
470
 
472
471
  const result = await client.callTool(
473
472
  {
@@ -487,7 +486,7 @@ test("workflow MCP ask_user_questions uses stdio elicitation round-trip", async
487
486
  },
488
487
  },
489
488
  undefined,
490
- { timeout: WORKFLOW_MCP_TEST_TIMEOUT_MS },
489
+ { timeout: 30_000 },
491
490
  );
492
491
 
493
492
  assert.ok(requestSeen, "expected stdio transport to forward an elicitation request");
@@ -0,0 +1,93 @@
1
+ // GSD-2 + src/resources/extensions/gsd/tests/working-output-messages.test.ts - Regression coverage for user-facing working-state message quality.
2
+
3
+ import test from "node:test";
4
+ import assert from "node:assert/strict";
5
+
6
+ import {
7
+ evaluateWorkingOutputMessage,
8
+ evaluateWorkingOutputMessages,
9
+ formatAutoUnitWorkingMessage,
10
+ } from "../working-output-messages.ts";
11
+
12
+ test("auto unit loader messages name the active work", () => {
13
+ assert.equal(
14
+ formatAutoUnitWorkingMessage("research-milestone", "M001"),
15
+ "Researching M001: waiting for provider response",
16
+ );
17
+ assert.equal(
18
+ evaluateWorkingOutputMessage({
19
+ surface: "loader",
20
+ message: formatAutoUnitWorkingMessage("research-milestone", "M001"),
21
+ context: { unitType: "research-milestone", unitId: "M001", health: "waiting" },
22
+ }).length,
23
+ 0,
24
+ );
25
+ });
26
+
27
+ test("generic working messages are flagged", () => {
28
+ const findings = evaluateWorkingOutputMessage({
29
+ surface: "loader",
30
+ message: "Working...",
31
+ context: { health: "waiting" },
32
+ });
33
+
34
+ assert.deepEqual(findings.map(f => f.code), ["generic-working-message"]);
35
+ });
36
+
37
+ test("dashboard messages cannot claim healthy progress while recovering", () => {
38
+ const findings = evaluateWorkingOutputMessage({
39
+ surface: "dashboard",
40
+ message: "GSD AUTO Progressing well",
41
+ context: { health: "recovering", recoveryAttempts: 1 },
42
+ });
43
+
44
+ assert.deepEqual(findings.map(f => f.code), ["misleading-healthy-message"]);
45
+ });
46
+
47
+ test("pre-roadmap zero-slice counters are flagged", () => {
48
+ const findings = evaluateWorkingOutputMessage({
49
+ surface: "dashboard",
50
+ message: "0/0 slices",
51
+ context: { health: "waiting" },
52
+ });
53
+
54
+ assert.deepEqual(findings.map(f => f.code), ["fake-zero-progress"]);
55
+ });
56
+
57
+ test("stalled/provider-error/timeout messages need an action", () => {
58
+ const noAction = evaluateWorkingOutputMessage({
59
+ surface: "notification",
60
+ message: "Provider stalled after 2m",
61
+ context: { health: "stalled" },
62
+ });
63
+ assert.deepEqual(noAction.map(f => f.code), ["missing-action"]);
64
+
65
+ const withAction = evaluateWorkingOutputMessage({
66
+ surface: "notification",
67
+ message: "Provider stalled after 2m. Type /gsd stop or wait for retry.",
68
+ context: { health: "stalled" },
69
+ });
70
+ assert.equal(withAction.length, 0);
71
+ });
72
+
73
+ test("current fixed research working surfaces pass the audit", () => {
74
+ const findings = evaluateWorkingOutputMessages([
75
+ {
76
+ surface: "loader",
77
+ message: "Researching M001: waiting for provider response",
78
+ context: { unitType: "research-milestone", unitId: "M001", health: "waiting" },
79
+ },
80
+ {
81
+ surface: "dashboard",
82
+ message: "Recovering\nretry 1 after idle stall",
83
+ context: { unitType: "research-milestone", unitId: "M001", health: "recovering", recoveryAttempts: 1 },
84
+ },
85
+ {
86
+ surface: "notification",
87
+ message: "Auto-mode stopped - User requested stop.",
88
+ context: { health: "stopped" },
89
+ },
90
+ ]);
91
+
92
+ assert.equal(findings.length, 0);
93
+ });
@@ -184,7 +184,7 @@ describe("removeWorktree preserves submodule uncommitted state (#2337)", () => {
184
184
  assert.ok(!existsSync(wt.path), "worktree directory should be removed");
185
185
 
186
186
  // The code path that fires on dirty submodules emits one of these
187
- // warnings. Any of these indicates the detection ran — the ONLY
187
+ // two warnings. Either indicates the detection ran — the ONLY
188
188
  // observable that would fail if someone removed the
189
189
  // `if (hasSubmoduleChanges)` branch and went straight to force
190
190
  // removal. This is the assertion that #4823 demanded in place of