@opengsd/gsd-pi 1.3.0-dev.eed73bea → 1.4.0-dev.5fc22c6f

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 (550) hide show
  1. package/README.md +11 -11
  2. package/dist/cli.js +17 -4
  3. package/dist/headless-answers.js +1 -1
  4. package/dist/headless-ui.d.ts +1 -1
  5. package/dist/headless-ui.js +1 -1
  6. package/dist/headless.js +1 -1
  7. package/dist/onboarding.js +11 -0
  8. package/dist/resources/.managed-resources-content-hash +1 -1
  9. package/dist/resources/GSD-WORKFLOW.md +20 -25
  10. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  11. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +61 -50
  12. package/dist/resources/extensions/cursor-cli/index.js +16 -0
  13. package/dist/resources/extensions/cursor-cli/models.js +63 -0
  14. package/dist/resources/extensions/cursor-cli/package.json +11 -0
  15. package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
  16. package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
  17. package/dist/resources/extensions/gsd/activity-log.js +4 -1
  18. package/dist/resources/extensions/gsd/artifact-verification.js +431 -0
  19. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  20. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  22. package/dist/resources/extensions/gsd/auto-budget.js +5 -1
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +32 -11
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  26. package/dist/resources/extensions/gsd/auto-prompts.js +83 -25
  27. package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
  28. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  29. package/dist/resources/extensions/gsd/auto-start.js +4 -3
  30. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -3
  31. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  32. package/dist/resources/extensions/gsd/auto-worktree.js +38 -11
  33. package/dist/resources/extensions/gsd/auto.js +32 -10
  34. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
  35. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +8 -4
  36. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  37. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +147 -23
  38. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +56 -36
  39. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +29 -5
  40. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  41. package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
  42. package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
  43. package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
  44. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +154 -2
  45. package/dist/resources/extensions/gsd/commands-usage.js +1 -1
  46. package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
  47. package/dist/resources/extensions/gsd/db/engine.js +4 -1
  48. package/dist/resources/extensions/gsd/db/queries.js +39 -0
  49. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
  50. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  51. package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
  52. package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
  53. package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -4
  54. package/dist/resources/extensions/gsd/doctor-engine-checks.js +227 -5
  55. package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
  56. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  57. package/dist/resources/extensions/gsd/doctor.js +93 -3
  58. package/dist/resources/extensions/gsd/exec-sandbox.js +14 -4
  59. package/dist/resources/extensions/gsd/flat-phase-migration.js +119 -23
  60. package/dist/resources/extensions/gsd/git-service.js +61 -8
  61. package/dist/resources/extensions/gsd/gitignore.js +4 -1
  62. package/dist/resources/extensions/gsd/guidance.js +1 -0
  63. package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
  64. package/dist/resources/extensions/gsd/guided-flow.js +40 -2
  65. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  66. package/dist/resources/extensions/gsd/key-manager.js +1 -0
  67. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  68. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  69. package/dist/resources/extensions/gsd/markdown-renderer.js +27 -15
  70. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  71. package/dist/resources/extensions/gsd/metrics.js +4 -4
  72. package/dist/resources/extensions/gsd/migrate-external.js +22 -5
  73. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  74. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  75. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  76. package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
  77. package/dist/resources/extensions/gsd/preferences-models.js +6 -4
  78. package/dist/resources/extensions/gsd/preferences-validation.js +25 -2
  79. package/dist/resources/extensions/gsd/preferences.js +29 -2
  80. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  81. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  82. package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  83. package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
  84. package/dist/resources/extensions/gsd/repository-registry.js +6 -1
  85. package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
  86. package/dist/resources/extensions/gsd/safe-fs.js +23 -2
  87. package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
  88. package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
  89. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  90. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  91. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -1
  92. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  93. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  94. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  95. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  96. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  97. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
  98. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  99. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  100. package/dist/resources/extensions/gsd/state.js +12 -611
  101. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  102. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
  103. package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
  104. package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
  105. package/dist/resources/extensions/gsd/tools/plan-task.js +103 -12
  106. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
  107. package/dist/resources/extensions/gsd/undo.js +43 -6
  108. package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
  109. package/dist/resources/extensions/gsd/unit-registry.js +11 -3
  110. package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
  111. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  112. package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
  113. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  114. package/dist/resources/extensions/gsd/workspace.js +26 -8
  115. package/dist/resources/extensions/gsd/worktree-manager.js +140 -5
  116. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  117. package/dist/web/standalone/.next/BUILD_ID +1 -1
  118. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  119. package/dist/web/standalone/.next/build-manifest.json +3 -3
  120. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  121. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  122. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/index.html +1 -1
  142. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  143. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  144. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  145. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  146. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  150. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  151. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  154. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  155. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  156. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  157. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  158. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  159. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  160. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  161. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  162. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  163. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  164. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  165. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  166. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  167. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  168. package/dist/wizard.d.ts +8 -0
  169. package/dist/wizard.js +8 -1
  170. package/integrations/hermes/__init__.py +31 -0
  171. package/integrations/hermes/tests/test_directory_loader.py +37 -0
  172. package/package.json +8 -8
  173. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
  174. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
  175. package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
  176. package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
  177. package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
  178. package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
  179. package/packages/cloud-mcp-gateway/package.json +2 -2
  180. package/packages/contracts/package.json +1 -1
  181. package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
  182. package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
  183. package/packages/daemon/dist/cloud-runtime.js +25 -1
  184. package/packages/daemon/dist/cloud-runtime.js.map +1 -1
  185. package/packages/daemon/dist/cloud-runtime.test.js +51 -0
  186. package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
  187. package/packages/daemon/dist/message-batcher.d.ts +7 -0
  188. package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
  189. package/packages/daemon/dist/message-batcher.js +13 -0
  190. package/packages/daemon/dist/message-batcher.js.map +1 -1
  191. package/packages/daemon/dist/message-batcher.test.js +48 -0
  192. package/packages/daemon/dist/message-batcher.test.js.map +1 -1
  193. package/packages/daemon/package.json +5 -5
  194. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  195. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  196. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  197. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  198. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
  199. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  200. package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
  201. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  202. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  203. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  204. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  205. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  206. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  207. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  208. package/packages/gsd-agent-core/dist/index.js +2 -0
  209. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  210. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  211. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  212. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  213. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  214. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  215. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  216. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  217. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  218. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  219. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  220. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  221. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  222. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  223. package/packages/gsd-agent-core/package.json +5 -5
  224. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  225. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  226. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  227. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  228. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  229. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  230. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  231. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  232. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  233. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  234. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -841
  235. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  236. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  237. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  238. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  239. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  240. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  241. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  242. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  243. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  244. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  245. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  246. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +259 -0
  247. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  248. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  249. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  250. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  251. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  252. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  253. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  254. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  256. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  260. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  261. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  262. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  263. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  264. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  265. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  266. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  267. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  268. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  269. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  270. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  271. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  272. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
  273. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  274. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +24 -6
  275. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  276. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  277. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  278. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  279. package/packages/gsd-agent-modes/package.json +7 -7
  280. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  281. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  282. package/packages/mcp-server/package.json +4 -4
  283. package/packages/native/package.json +1 -1
  284. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  285. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  286. package/packages/pi-agent-core/package.json +1 -1
  287. package/packages/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  288. package/packages/pi-ai/dist/env-api-keys.js +3 -0
  289. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  290. package/packages/pi-ai/dist/models.generated.d.ts +46 -0
  291. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  292. package/packages/pi-ai/dist/models.generated.js +38 -0
  293. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  294. package/packages/pi-ai/dist/types.d.ts +2 -2
  295. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  296. package/packages/pi-ai/dist/types.js.map +1 -1
  297. package/packages/pi-ai/package.json +1 -1
  298. package/packages/pi-coding-agent/README.md +3 -2
  299. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  301. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  303. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  304. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  305. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  306. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  307. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  308. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  309. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  310. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  311. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  312. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  313. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  314. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  315. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  316. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  317. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  318. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  319. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  320. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  321. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  323. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  324. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  325. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  326. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  328. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  329. package/packages/pi-coding-agent/package.json +7 -7
  330. package/packages/pi-tui/package.json +2 -2
  331. package/packages/rpc-client/dist/rpc-client.js +1 -1
  332. package/packages/rpc-client/dist/rpc-client.js.map +1 -1
  333. package/packages/rpc-client/package.json +2 -2
  334. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  335. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  336. package/pkg/dist/theme/theme-schema.js +1 -1
  337. package/pkg/dist/theme/theme-schema.js.map +1 -1
  338. package/pkg/dist/theme/theme.d.ts.map +1 -1
  339. package/pkg/dist/theme/theme.js +11 -7
  340. package/pkg/dist/theme/theme.js.map +1 -1
  341. package/pkg/package.json +1 -1
  342. package/scripts/link-workspace-packages.cjs +14 -4
  343. package/src/resources/GSD-WORKFLOW.md +20 -25
  344. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  345. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +67 -49
  346. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
  347. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +159 -0
  348. package/src/resources/extensions/cursor-cli/index.ts +18 -0
  349. package/src/resources/extensions/cursor-cli/models.ts +65 -0
  350. package/src/resources/extensions/cursor-cli/package.json +11 -0
  351. package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
  352. package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
  353. package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
  354. package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
  355. package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
  356. package/src/resources/extensions/gsd/activity-log.ts +4 -1
  357. package/src/resources/extensions/gsd/artifact-verification.ts +468 -0
  358. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  359. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  360. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  361. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  362. package/src/resources/extensions/gsd/auto-budget.ts +12 -1
  363. package/src/resources/extensions/gsd/auto-dispatch.ts +34 -12
  364. package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
  365. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  366. package/src/resources/extensions/gsd/auto-prompts.ts +80 -25
  367. package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
  368. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  369. package/src/resources/extensions/gsd/auto-start.ts +4 -3
  370. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +7 -2
  371. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  372. package/src/resources/extensions/gsd/auto-worktree.ts +50 -11
  373. package/src/resources/extensions/gsd/auto.ts +36 -8
  374. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
  375. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +8 -4
  376. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  377. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +171 -23
  378. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
  379. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +60 -37
  380. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -5
  381. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  382. package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
  383. package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
  384. package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
  385. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +136 -2
  386. package/src/resources/extensions/gsd/commands-usage.ts +1 -1
  387. package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
  388. package/src/resources/extensions/gsd/db/engine.ts +8 -1
  389. package/src/resources/extensions/gsd/db/queries.ts +40 -0
  390. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
  391. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  392. package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
  393. package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
  394. package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -4
  395. package/src/resources/extensions/gsd/doctor-engine-checks.ts +275 -5
  396. package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
  397. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  398. package/src/resources/extensions/gsd/doctor-types.ts +8 -1
  399. package/src/resources/extensions/gsd/doctor.ts +95 -3
  400. package/src/resources/extensions/gsd/exec-sandbox.ts +13 -4
  401. package/src/resources/extensions/gsd/flat-phase-migration.ts +142 -22
  402. package/src/resources/extensions/gsd/git-service.ts +70 -9
  403. package/src/resources/extensions/gsd/gitignore.ts +4 -1
  404. package/src/resources/extensions/gsd/guidance.ts +2 -0
  405. package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
  406. package/src/resources/extensions/gsd/guided-flow.ts +45 -2
  407. package/src/resources/extensions/gsd/json-persistence.ts +20 -0
  408. package/src/resources/extensions/gsd/key-manager.ts +1 -0
  409. package/src/resources/extensions/gsd/knowledge-backfill.ts +16 -10
  410. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  411. package/src/resources/extensions/gsd/markdown-renderer.ts +27 -17
  412. package/src/resources/extensions/gsd/memory-backfill.ts +26 -20
  413. package/src/resources/extensions/gsd/metrics.ts +4 -4
  414. package/src/resources/extensions/gsd/migrate-external.ts +17 -4
  415. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  416. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  417. package/src/resources/extensions/gsd/model-router.ts +4 -5
  418. package/src/resources/extensions/gsd/orphan-stash-audit.ts +108 -20
  419. package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
  420. package/src/resources/extensions/gsd/preferences-models.ts +6 -3
  421. package/src/resources/extensions/gsd/preferences-validation.ts +28 -2
  422. package/src/resources/extensions/gsd/preferences.ts +38 -4
  423. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  424. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  425. package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
  426. package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
  427. package/src/resources/extensions/gsd/repository-registry.ts +7 -1
  428. package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
  429. package/src/resources/extensions/gsd/safe-fs.ts +22 -2
  430. package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
  431. package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
  432. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  433. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  434. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +2 -1
  435. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  436. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  437. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  438. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  439. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  440. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
  441. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  442. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  443. package/src/resources/extensions/gsd/state.ts +32 -732
  444. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  445. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  446. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
  447. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
  448. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
  449. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
  450. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
  451. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
  452. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
  453. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
  454. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
  455. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
  456. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
  457. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
  458. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +8 -0
  459. package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
  460. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
  461. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
  462. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  463. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
  464. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  465. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  466. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
  467. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  468. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
  469. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
  470. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +138 -1
  471. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +296 -2
  472. package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
  473. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
  474. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  475. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +74 -2
  476. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
  477. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
  478. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  479. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
  480. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
  481. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  482. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  483. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  484. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +122 -0
  485. package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
  486. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  487. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  488. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  489. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
  490. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  491. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  492. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
  493. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
  494. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +27 -0
  495. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
  496. package/src/resources/extensions/gsd/tests/plan-task.test.ts +307 -1
  497. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
  498. package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
  499. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +142 -0
  500. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  501. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
  502. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
  503. package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
  504. package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
  505. package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
  506. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +378 -0
  507. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
  508. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
  509. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
  510. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
  511. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +105 -0
  512. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
  513. package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
  514. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
  515. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +203 -0
  516. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
  517. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  518. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
  519. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
  520. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +90 -0
  521. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
  522. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  523. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
  524. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
  525. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
  526. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +214 -6
  527. package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
  528. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  529. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +31 -1
  530. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
  531. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  532. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
  533. package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
  534. package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
  535. package/src/resources/extensions/gsd/tools/plan-task.ts +135 -12
  536. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
  537. package/src/resources/extensions/gsd/undo.ts +47 -6
  538. package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
  539. package/src/resources/extensions/gsd/unit-registry.ts +11 -3
  540. package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
  541. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  542. package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
  543. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  544. package/src/resources/extensions/gsd/workspace.ts +42 -8
  545. package/src/resources/extensions/gsd/worktree-manager.ts +183 -5
  546. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  547. package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
  548. package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
  549. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_buildManifest.js +0 -0
  550. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → kIEFsCryyGy6RzifULbJl}/_ssgManifest.js +0 -0
@@ -722,3 +722,368 @@ test("ensureCodebaseMapFresh: uses TTL cache before enumerating files", () => {
722
722
  cleanup(base);
723
723
  }
724
724
  });
725
+
726
+ // ─── Workspace-aware (parent mode) ───────────────────────────────────────
727
+
728
+ /**
729
+ * Build a parent workspace: a parent git repo whose .gsd/PREFERENCES.md declares
730
+ * child repositories, each child being its own separate git repo nested inside.
731
+ */
732
+ function makeTmpParentWorkspace(children: string[]): string {
733
+ const base = join(tmpdir(), `gsd-codebase-parent-${randomUUID()}`);
734
+ mkdirSync(join(base, ".gsd"), { recursive: true });
735
+ execSync("git init", { cwd: base, stdio: "ignore" });
736
+
737
+ const repoLines = children.map((id) => ` ${id}:\n path: ${id}`).join("\n");
738
+ writeFileSync(
739
+ join(base, ".gsd", "PREFERENCES.md"),
740
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n${repoLines}\n---\n`,
741
+ "utf-8",
742
+ );
743
+
744
+ for (const child of children) {
745
+ const childPath = join(base, child);
746
+ mkdirSync(childPath, { recursive: true });
747
+ execSync("git init", { cwd: childPath, stdio: "ignore" });
748
+ }
749
+ return base;
750
+ }
751
+
752
+ function addChildFile(base: string, child: string, path: string, content = ""): void {
753
+ const childRoot = join(base, child);
754
+ const fullPath = join(childRoot, path);
755
+ mkdirSync(join(fullPath, ".."), { recursive: true });
756
+ writeFileSync(fullPath, content || `// ${child}/${path}\n`, "utf-8");
757
+ execSync(`git add "${path}"`, { cwd: childRoot, stdio: "ignore" });
758
+ }
759
+
760
+ test("workspace-aware: parent mode enumerates each declared child repo under a repo heading", () => {
761
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
762
+ try {
763
+ addChildFile(base, "frontend", "src/App.tsx");
764
+ addChildFile(base, "backend", "src/server.ts");
765
+
766
+ const result = generateCodebaseMap(base);
767
+
768
+ // Both repos appear as labelled sections.
769
+ assert.match(result.content, /## \[frontend\]/);
770
+ assert.match(result.content, /## \[backend\]/);
771
+ // Child files are rewritten to workspace-relative paths.
772
+ assert.match(result.content, /`frontend\/src\/App\.tsx`/);
773
+ assert.match(result.content, /`backend\/src\/server\.ts`/);
774
+ assert.equal(result.fileCount, 2);
775
+ } finally {
776
+ cleanup(base);
777
+ }
778
+ });
779
+
780
+ test("workspace-aware: metadata records the repositories whose files appear in the map", () => {
781
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
782
+ try {
783
+ addChildFile(base, "frontend", "src/App.tsx");
784
+ addChildFile(base, "backend", "src/server.ts");
785
+
786
+ const result = generateCodebaseMap(base);
787
+ const metadata = parseCodebaseMapMetadata(result.content);
788
+
789
+ assert.ok(metadata, "metadata should be present");
790
+ assert.deepEqual(metadata?.repositories?.sort(), ["backend", "frontend"]);
791
+ } finally {
792
+ cleanup(base);
793
+ }
794
+ });
795
+
796
+ test("workspace-aware: parseCodebaseMap recovers descriptions across repo sections", () => {
797
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
798
+ try {
799
+ addChildFile(base, "frontend", "src/App.tsx");
800
+ addChildFile(base, "backend", "src/server.ts");
801
+
802
+ // Seed descriptions keyed by the workspace-relative paths.
803
+ const descriptions = new Map<string, string>([
804
+ ["frontend/src/App.tsx", "React entry"],
805
+ ["backend/src/server.ts", "Express API"],
806
+ ]);
807
+ const result = generateCodebaseMap(base, undefined, descriptions);
808
+ writeCodebaseMap(base, result.content);
809
+
810
+ const parsed = parseCodebaseMap(readCodebaseMap(base)!);
811
+ assert.equal(parsed.get("frontend/src/App.tsx"), "React entry");
812
+ assert.equal(parsed.get("backend/src/server.ts"), "Express API");
813
+ } finally {
814
+ cleanup(base);
815
+ }
816
+ });
817
+
818
+ test("workspace-aware: project mode (no declared children) stays single-section", () => {
819
+ // A plain single repo with no workspace config must render exactly as before.
820
+ const base = makeTmpRepo();
821
+ try {
822
+ addFile(base, "src/main.ts");
823
+
824
+ const result = generateCodebaseMap(base);
825
+
826
+ assert.doesNotMatch(result.content, /## \[/);
827
+ assert.match(result.content, /`src\/main\.ts`/);
828
+ const metadata = parseCodebaseMapMetadata(result.content);
829
+ assert.equal(metadata?.repositories, undefined);
830
+ } finally {
831
+ cleanup(base);
832
+ }
833
+ });
834
+
835
+ test("workspace-aware: updateCodebaseMap tracks child-repo file additions", () => {
836
+ const base = makeTmpParentWorkspace(["frontend"]);
837
+ try {
838
+ addChildFile(base, "frontend", "src/App.tsx");
839
+ const first = updateCodebaseMap(base);
840
+ writeCodebaseMap(base, first.content);
841
+ assert.equal(first.added, 1);
842
+
843
+ addChildFile(base, "frontend", "src/index.tsx");
844
+ const second = updateCodebaseMap(base);
845
+ assert.equal(second.added, 1);
846
+ assert.equal(second.removed, 0);
847
+ assert.equal(second.fileCount, 2);
848
+ } finally {
849
+ cleanup(base);
850
+ }
851
+ });
852
+
853
+ test("workspace-aware: workspace-relative exclude patterns filter child-repo files", () => {
854
+ // Regression guard: exclude patterns like `frontend/` are workspace-relative,
855
+ // so they must be matched against the rewritten path, not the child-relative one.
856
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
857
+ try {
858
+ addChildFile(base, "frontend", "src/App.tsx");
859
+ addChildFile(base, "backend", "src/server.ts");
860
+
861
+ const result = generateCodebaseMap(base, { excludePatterns: ["frontend/"] });
862
+
863
+ assert.doesNotMatch(result.content, /frontend\/src\/App\.tsx/);
864
+ assert.match(result.content, /backend\/src\/server\.ts/);
865
+ assert.equal(result.fileCount, 1);
866
+ } finally {
867
+ cleanup(base);
868
+ }
869
+ });
870
+
871
+ test("workspace-aware: maxFiles cap does not starve child repos for the project repo", () => {
872
+ // The implicit project repo is enumerated alongside children; the cap must be
873
+ // applied fairly (round-robin) so a large project repo cannot crowd out children.
874
+ const base = makeTmpParentWorkspace(["frontend", "backend"]);
875
+ try {
876
+ addChildFile(base, "frontend", "a.ts");
877
+ addChildFile(base, "frontend", "b.ts");
878
+ addChildFile(base, "backend", "c.ts");
879
+
880
+ // Cap at 2 files — with fair distribution both repos should appear.
881
+ const result = generateCodebaseMap(base, { maxFiles: 2 });
882
+ const repoSections = (result.content.match(/^## \[.+\]/gm) ?? []).length;
883
+
884
+ assert.equal(result.fileCount, 2);
885
+ assert.ok(repoSections >= 2, "both child repos should be represented under a tight cap");
886
+ } finally {
887
+ cleanup(base);
888
+ }
889
+ });
890
+
891
+ test("workspace-aware: overlapping paths dedupe without falsely reporting truncation", () => {
892
+ // Regression guard: a path tracked by both the implicit project repo and a child
893
+ // repo collapses to one workspace-relative entry. Deduplicated duplicates must not
894
+ // count toward the maxFiles cap, so the map must not be flagged as truncated.
895
+ const base = join(tmpdir(), `gsd-codebase-parent-${randomUUID()}`);
896
+ mkdirSync(join(base, ".gsd"), { recursive: true });
897
+ execSync("git init", { cwd: base, stdio: "ignore" });
898
+ writeFileSync(
899
+ join(base, ".gsd", "PREFERENCES.md"),
900
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n lib:\n path: lib\n---\n`,
901
+ "utf-8",
902
+ );
903
+ try {
904
+ // The project repo tracks lib/util.ts before lib becomes its own repo; the child
905
+ // repo then tracks util.ts, so both resolve to the same workspace path lib/util.ts.
906
+ addFile(base, "lib/util.ts");
907
+ execSync("git init", { cwd: join(base, "lib"), stdio: "ignore" });
908
+ execSync("git add util.ts", { cwd: join(base, "lib"), stdio: "ignore" });
909
+
910
+ const result = generateCodebaseMap(base);
911
+
912
+ assert.equal(result.fileCount, 1);
913
+ assert.equal(result.truncated, false);
914
+ assert.equal((result.content.match(/`lib\/util\.ts`/g) ?? []).length, 1);
915
+ } finally {
916
+ cleanup(base);
917
+ }
918
+ });
919
+
920
+ test("workspace-aware: project directories interleaving child prefixes stay under one heading", () => {
921
+ // Regression guard: the implicit project repo has an empty prefix, so its
922
+ // root-level dirs (aaa/, zzz/) sort lexically around a child prefix (mmm/).
923
+ // Groups must be ordered per repo so `## [project]` is emitted exactly once.
924
+ const base = makeTmpParentWorkspace(["mmm"]);
925
+ try {
926
+ addFile(base, "aaa/x.ts"); // project repo, sorts before "mmm"
927
+ addFile(base, "zzz/y.ts"); // project repo, sorts after "mmm"
928
+ addChildFile(base, "mmm", "src/thing.ts");
929
+
930
+ const result = generateCodebaseMap(base);
931
+
932
+ const projectHeadings = (result.content.match(/^## \[project\]$/gm) ?? []).length;
933
+ const mmmHeadings = (result.content.match(/^## \[mmm\]$/gm) ?? []).length;
934
+ const allHeadings = (result.content.match(/^## \[.+\]$/gm) ?? []).length;
935
+
936
+ assert.equal(projectHeadings, 1, "project section must not be split across headings");
937
+ assert.equal(mmmHeadings, 1);
938
+ assert.equal(allHeadings, 2);
939
+ } finally {
940
+ cleanup(base);
941
+ }
942
+ });
943
+
944
+ test("workspace-aware: renaming a declared repo id invalidates map freshness", () => {
945
+ // Regression guard: repo identity is rendered into the map, so renaming a repo id
946
+ // (path unchanged → identical file paths) must be caught by the freshness
947
+ // fingerprint rather than leaving a stale `## [old-id]` heading in place.
948
+ const base = makeTmpParentWorkspace(["frontend"]);
949
+ try {
950
+ addChildFile(base, "frontend", "src/App.tsx");
951
+
952
+ ensureCodebaseMapFresh(base, undefined, { ttlMs: 0, force: true });
953
+ assert.match(readCodebaseMap(base)!, /^## \[frontend\]$/m);
954
+
955
+ // Rename the repo id to `web`; the path (and therefore the file paths) is unchanged.
956
+ writeFileSync(
957
+ join(base, ".gsd", "PREFERENCES.md"),
958
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n web:\n path: frontend\n---\n`,
959
+ "utf-8",
960
+ );
961
+
962
+ const refreshed = ensureCodebaseMapFresh(base, undefined, { ttlMs: 0, force: true });
963
+ const written = readCodebaseMap(base)!;
964
+
965
+ assert.equal(refreshed.status, "updated");
966
+ assert.match(written, /^## \[web\]$/m);
967
+ assert.doesNotMatch(written, /^## \[frontend\]$/m);
968
+ assert.deepEqual(parseCodebaseMapMetadata(written)?.repositories, ["web"]);
969
+ } finally {
970
+ cleanup(base);
971
+ }
972
+ });
973
+
974
+ test("single-repo: directory order stays byte-identical code-unit sort (not locale-aware)", () => {
975
+ // Byte-identical single-repo invariant: pre-workspace output ordered
976
+ // directories with a bare `.sort()` (UTF-16 code-unit order), so uppercase
977
+ // sorts before lowercase ("Zoo" < "apple"). A locale-aware comparator inverts
978
+ // these and silently changes project-mode CODEBASE.md, so guard the ordering.
979
+ const base = makeTmpRepo();
980
+ try {
981
+ addFile(base, "Zoo/keeper.ts"); // 'Z' (0x5A) < 'a' (0x61) → sorts first
982
+ addFile(base, "apple/tree.ts");
983
+
984
+ const content = generateCodebaseMap(base).content;
985
+ const zooIdx = content.indexOf("### Zoo/");
986
+ const appleIdx = content.indexOf("### apple/");
987
+
988
+ assert.notEqual(zooIdx, -1);
989
+ assert.notEqual(appleIdx, -1);
990
+ assert.ok(zooIdx < appleIdx, "code-unit order must place Zoo/ before apple/");
991
+ // Project mode emits no repo partition heading.
992
+ assert.doesNotMatch(content, /^## \[.+\]$/m);
993
+ } finally {
994
+ cleanup(base);
995
+ }
996
+ });
997
+
998
+ test("workspace-aware: an invalid workspace registry surfaces an error instead of silently falling back", () => {
999
+ // Regression guard: a broken parent-mode config (here a child path escaping the
1000
+ // project root) must propagate as an error. Swallowing it and falling back to a
1001
+ // single-root map would silently drop every child repo from planning context.
1002
+ const base = makeTmpRepo();
1003
+ try {
1004
+ addFile(base, "src/main.ts");
1005
+ writeFileSync(
1006
+ join(base, ".gsd", "PREFERENCES.md"),
1007
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n frontend:\n path: ../escapes-root\n---\n`,
1008
+ "utf-8",
1009
+ );
1010
+
1011
+ assert.throws(() => generateCodebaseMap(base), /resolves outside project root/);
1012
+ } finally {
1013
+ cleanup(base);
1014
+ }
1015
+ });
1016
+
1017
+ test("workspace-aware: files sharing a directory across repos keep their own repo heading", () => {
1018
+ // Regression guard: the implicit project repo and a child repo can own different
1019
+ // files under the same workspace-relative directory (lib/). Groups are keyed by
1020
+ // (repo, dir), so each file must render under its own `## [repo-id]` heading
1021
+ // instead of collapsing into one section labelled with a single (wrong) repo.
1022
+ const base = join(tmpdir(), `gsd-codebase-parent-${randomUUID()}`);
1023
+ mkdirSync(join(base, ".gsd"), { recursive: true });
1024
+ execSync("git init", { cwd: base, stdio: "ignore" });
1025
+ writeFileSync(
1026
+ join(base, ".gsd", "PREFERENCES.md"),
1027
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n lib:\n path: lib\n---\n`,
1028
+ "utf-8",
1029
+ );
1030
+ try {
1031
+ // Project repo tracks lib/app.ts before lib becomes its own repo; the child
1032
+ // repo then tracks helper.ts → workspace path lib/helper.ts. Different files,
1033
+ // same directory, different repos.
1034
+ addFile(base, "lib/app.ts");
1035
+ execSync("git init", { cwd: join(base, "lib"), stdio: "ignore" });
1036
+ writeFileSync(join(base, "lib", "helper.ts"), "// helper\n", "utf-8");
1037
+ execSync("git add helper.ts", { cwd: join(base, "lib"), stdio: "ignore" });
1038
+
1039
+ const content = generateCodebaseMap(base).content;
1040
+
1041
+ // Both files present, each under its own repo section (not merged under one).
1042
+ assert.match(content, /## \[project\]/);
1043
+ assert.match(content, /## \[lib\]/);
1044
+ const projectIdx = content.indexOf("## [project]");
1045
+ const appIdx = content.indexOf("`lib/app.ts`");
1046
+ const libIdx = content.indexOf("## [lib]");
1047
+ const helperIdx = content.indexOf("`lib/helper.ts`");
1048
+ assert.ok(
1049
+ projectIdx < appIdx && appIdx < libIdx && libIdx < helperIdx,
1050
+ "lib/app.ts must sit under [project] and lib/helper.ts under [lib]",
1051
+ );
1052
+ } finally {
1053
+ cleanup(base);
1054
+ }
1055
+ });
1056
+
1057
+ test("ensureCodebaseMapFresh: editing declared repos within the TTL window bypasses the cache", () => {
1058
+ // Regression guard: the freshness TTL cache key folds in the workspace signature
1059
+ // (mode + declared repos). Adding a child repo must miss the cache and re-enumerate
1060
+ // rather than serve a stale map that omits the new repo until the TTL expires.
1061
+ const base = makeTmpParentWorkspace(["frontend"]);
1062
+ try {
1063
+ addChildFile(base, "frontend", "src/App.tsx");
1064
+
1065
+ const initial = ensureCodebaseMapFresh(base, undefined, { ttlMs: 60_000 });
1066
+ assert.equal(initial.status, "generated");
1067
+ assert.doesNotMatch(readCodebaseMap(base)!, /## \[backend\]/);
1068
+
1069
+ // Declare a second child repo and back it with a real nested repo + file.
1070
+ mkdirSync(join(base, "backend"), { recursive: true });
1071
+ execSync("git init", { cwd: join(base, "backend"), stdio: "ignore" });
1072
+ addChildFile(base, "backend", "src/server.ts");
1073
+ writeFileSync(
1074
+ join(base, ".gsd", "PREFERENCES.md"),
1075
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n frontend:\n path: frontend\n backend:\n path: backend\n---\n`,
1076
+ "utf-8",
1077
+ );
1078
+
1079
+ // Same TTL window, no force: the changed workspace signature must miss the cache.
1080
+ const refreshed = ensureCodebaseMapFresh(base, undefined, { ttlMs: 60_000 });
1081
+ const written = readCodebaseMap(base)!;
1082
+
1083
+ assert.equal(refreshed.status, "updated");
1084
+ assert.match(written, /## \[backend\]/);
1085
+ assert.match(written, /`backend\/src\/server\.ts`/);
1086
+ } finally {
1087
+ cleanup(base);
1088
+ }
1089
+ });
@@ -460,6 +460,7 @@ describe("Batch 3 prompt templates resolve", () => {
460
460
  const out = loadPrompt("code-review", { scope: "s", depth: "deep", fixMode: "off", reviewId: "001" });
461
461
  assert.match(out, /deep/);
462
462
  assert.match(out, /001/);
463
+ assert.match(out, /diff-first/i, "code-review prompt should require diff-first context gathering");
463
464
  });
464
465
  test("review.md loads with target + reviewers", () => {
465
466
  const out = loadPrompt("review", { target: "t", reviewers: "claude, codex" });
@@ -12,7 +12,14 @@ import { tmpdir } from "node:os";
12
12
 
13
13
  import { buildSliceSummaryExcerpt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt } from "../auto-prompts.ts";
14
14
  import { invalidateAllCaches } from "../cache.ts";
15
- import { closeDatabase, insertMilestone, openDatabase } from "../gsd-db.ts";
15
+ import {
16
+ closeDatabase,
17
+ insertGateRow,
18
+ insertMilestone,
19
+ insertSlice,
20
+ openDatabase,
21
+ saveGateResult,
22
+ } from "../gsd-db.ts";
16
23
 
17
24
  // ─── Fixture helpers ──────────────────────────────────────────────────────
18
25
 
@@ -366,6 +373,60 @@ test("validate-milestone prompt uses slice excerpts and on-demand paths instead
366
373
  );
367
374
  });
368
375
 
376
+ test("validate-milestone prompt inlines persisted slice-level Q3/Q4 gate flags", async (t) => {
377
+ const base = createBase();
378
+ t.after(() => {
379
+ try { closeDatabase(); } catch { /* ignore */ }
380
+ cleanup(base);
381
+ });
382
+ invalidateAllCaches();
383
+
384
+ openDatabase(join(base, ".gsd", "gsd.db"));
385
+ insertMilestone({ id: "M001", title: "Test Milestone", status: "active" });
386
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Risky Slice", status: "complete" });
387
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
388
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
389
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q8", scope: "slice" });
390
+ saveGateResult({
391
+ milestoneId: "M001",
392
+ sliceId: "S01",
393
+ gateId: "Q3",
394
+ verdict: "flag",
395
+ rationale: "New callback boundary.",
396
+ findings: "Re-check token exposure in the web callback.",
397
+ });
398
+ saveGateResult({
399
+ milestoneId: "M001",
400
+ sliceId: "S01",
401
+ gateId: "Q4",
402
+ verdict: "flag",
403
+ rationale: "Requirement touched but not re-tested.",
404
+ findings: "R012 must be re-tested; revisit decision D-3.",
405
+ });
406
+ saveGateResult({
407
+ milestoneId: "M001",
408
+ sliceId: "S01",
409
+ gateId: "Q8",
410
+ verdict: "flag",
411
+ rationale: "Operational readiness gap.",
412
+ findings: "Operational finding should not be milestone validation input.",
413
+ });
414
+ writeRoadmap(base, makeRoadmap());
415
+ writeSummary(base, "S01", makeFatSummary("S01"));
416
+
417
+ const prompt = await buildValidateMilestonePrompt("M001", "Test Milestone", base);
418
+
419
+ assert.match(prompt, /### Persisted Slice-Level Gate Flags \(from quality_gates\)/);
420
+ assert.match(prompt, /S01 \/ Q3 \(Threat Surface\) \/ flag/);
421
+ assert.match(prompt, /Re-check token exposure in the web callback\./);
422
+ assert.match(prompt, /S01 \/ Q4 \(Requirement Impact\) \/ flag/);
423
+ assert.match(prompt, /R012 must be re-tested; revisit decision D-3\./);
424
+ assert.ok(
425
+ !prompt.includes("Operational finding should not be milestone validation input."),
426
+ "validate-milestone should not inline unrelated Q8 gate findings",
427
+ );
428
+ });
429
+
369
430
  test("validate-milestone prompt inlines planned verification classes as canonical rows", async (t) => {
370
431
  const base = createBase();
371
432
  t.after(() => {
@@ -312,6 +312,34 @@ console.log('\n=== complete-milestone: incomplete slices block closeout ===');
312
312
  cleanup(dbPath);
313
313
  }
314
314
 
315
+ // ═══════════════════════════════════════════════════════════════════════════
316
+ // complete-milestone: deferred slices are inactive for closeout
317
+ // ═══════════════════════════════════════════════════════════════════════════
318
+
319
+ console.log('\n=== complete-milestone: deferred slices do not block closeout ===');
320
+ {
321
+ const dbPath = tempDbPath();
322
+ openDatabase(dbPath);
323
+ const { basePath } = createTempProject();
324
+ seedCompletedMilestone({ basePath, validationVerdict: 'pass' });
325
+ insertSlice({ id: 'S02', milestoneId: 'M001', title: 'Deferred Slice', status: 'deferred' });
326
+ insertTask({
327
+ id: 'T02',
328
+ sliceId: 'S02',
329
+ milestoneId: 'M001',
330
+ status: 'pending',
331
+ title: 'Deferred Slice Task',
332
+ });
333
+
334
+ const result = await handleCompleteMilestone(makeValidParams(), basePath);
335
+
336
+ assertTrue(!('error' in result), 'deferred slice should not block milestone completion');
337
+ assertEq(getMilestone('M001')!.status, 'complete', 'milestone should complete with deferred inactive slice');
338
+
339
+ cleanupDir(basePath);
340
+ cleanup(dbPath);
341
+ }
342
+
315
343
  // ═══════════════════════════════════════════════════════════════════════════
316
344
  // complete-milestone: deep task check (slice closed, task not)
317
345
  // ═══════════════════════════════════════════════════════════════════════════
@@ -7,6 +7,10 @@ import { join } from "node:path";
7
7
 
8
8
  import { postUnitPreVerification } from "../auto-post-unit.ts";
9
9
  import { AutoSession } from "../auto/session.ts";
10
+ import {
11
+ decideVerificationRetry,
12
+ hashVerificationFailureContext,
13
+ } from "../auto/verification-retry-policy.ts";
10
14
  import { cleanup, makeTempRepo } from "./test-utils.ts";
11
15
 
12
16
  function makePostUnitContext(base: string, s: AutoSession, notifications: string[]) {
@@ -227,3 +231,68 @@ test("complete-slice with gsd_replan_slice but no REPLAN artifact retries", asyn
227
231
  cleanup(base);
228
232
  }
229
233
  });
234
+
235
+ test("artifact retry context stays stable across attempts while notifications show attempt count", async () => {
236
+ const base = makeTempRepo("gsd-artifact-retry-stable-context-");
237
+ try {
238
+ mkdirSync(join(base, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
239
+
240
+ const s = new AutoSession();
241
+ s.active = true;
242
+ s.basePath = base;
243
+ s.currentUnit = { type: "complete-slice", id: "M001/S01", startedAt: Date.now() };
244
+
245
+ const notifications: string[] = [];
246
+ const pctx = makePostUnitContext(base, s, notifications);
247
+ const opts = {
248
+ skipSettleDelay: true,
249
+ skipWorktreeSync: true,
250
+ agentEndMessages: [
251
+ {
252
+ role: "toolResult",
253
+ toolName: "gsd_replan_slice",
254
+ isError: false,
255
+ content: "Slice replanned with reopened task T02.",
256
+ },
257
+ ],
258
+ };
259
+
260
+ assert.equal(await postUnitPreVerification(pctx, opts), "retry");
261
+ const firstRetry = s.pendingVerificationRetry;
262
+ assert.ok(firstRetry);
263
+ assert.equal(firstRetry.attempt, 1);
264
+ assert.doesNotMatch(firstRetry.failureContext, /\(attempt \d\/3\)\.$/);
265
+ const firstFailureHash = hashVerificationFailureContext(firstRetry.failureContext);
266
+
267
+ assert.equal(await postUnitPreVerification(pctx, opts), "retry");
268
+ const secondRetry = s.pendingVerificationRetry;
269
+ assert.ok(secondRetry);
270
+ assert.equal(secondRetry.attempt, 2);
271
+ assert.equal(secondRetry.failureContext, firstRetry.failureContext);
272
+ assert.equal(hashVerificationFailureContext(secondRetry.failureContext), firstFailureHash);
273
+ assert.deepEqual(
274
+ decideVerificationRetry({
275
+ unitType: s.currentUnit.type,
276
+ retryInfo: secondRetry,
277
+ previousFailureHash: firstFailureHash,
278
+ random: () => 0.5,
279
+ }),
280
+ {
281
+ action: "pause",
282
+ reason: "duplicate-failure-context",
283
+ key: "complete-slice:M001/S01",
284
+ failureHash: firstFailureHash,
285
+ },
286
+ );
287
+ assert.ok(
288
+ notifications.some((message) => message.includes("Retrying (attempt 1/3).")),
289
+ `expected first attempt notification, got: ${notifications.join("\n")}`,
290
+ );
291
+ assert.ok(
292
+ notifications.some((message) => message.includes("Retrying (attempt 2/3).")),
293
+ `expected second attempt notification, got: ${notifications.join("\n")}`,
294
+ );
295
+ } finally {
296
+ cleanup(base);
297
+ }
298
+ });
@@ -3,11 +3,16 @@
3
3
 
4
4
  import { describe, test } from "node:test";
5
5
  import assert from "node:assert/strict";
6
+ import { createRequire } from "node:module";
6
7
  import {
8
+ MEMORIES_FTS_REBUILT_KEY,
7
9
  isMemoriesFtsAvailableSchema,
10
+ rebuildMemoriesFtsSchemaOnce,
8
11
  tryCreateMemoriesFtsSchema,
9
12
  } from "../db-memory-fts-schema.ts";
10
- import type { DbAdapter, DbStatement } from "../db-adapter.ts";
13
+ import { createDbAdapter, type DbAdapter, type DbStatement } from "../db-adapter.ts";
14
+
15
+ const _require = createRequire(import.meta.url);
11
16
 
12
17
  class FakeStatement implements DbStatement {
13
18
  private readonly row: Record<string, unknown> | undefined;
@@ -32,6 +37,7 @@ class FakeStatement implements DbStatement {
32
37
  class FakeAdapter implements DbAdapter {
33
38
  readonly execCalls: string[] = [];
34
39
  hasFts = false;
40
+ hasRebuildMarker = false;
35
41
  failExec = false;
36
42
 
37
43
  exec(sql: string): void {
@@ -39,13 +45,26 @@ class FakeAdapter implements DbAdapter {
39
45
  if (this.failExec) throw new Error("fts unavailable");
40
46
  }
41
47
 
42
- prepare(): DbStatement {
43
- return new FakeStatement(this.hasFts ? { name: "memories_fts" } : undefined);
48
+ prepare(sql: string): DbStatement {
49
+ if (sql.includes("sqlite_master")) {
50
+ return new FakeStatement(this.hasFts ? { name: "memories_fts" } : undefined);
51
+ }
52
+ if (sql.includes("runtime_kv")) {
53
+ return new FakeStatement(this.hasRebuildMarker ? { present: 1 } : undefined);
54
+ }
55
+ return new FakeStatement(undefined);
44
56
  }
45
57
 
46
58
  close(): void {}
47
59
  }
48
60
 
61
+ function openMemoryAdapter(): { db: DbAdapter; close: () => void } {
62
+ const sqlite = _require("node:sqlite") as { DatabaseSync: new (path: string) => unknown };
63
+ const raw = new sqlite.DatabaseSync(":memory:");
64
+ const db = createDbAdapter(raw);
65
+ return { db, close: () => db.close() };
66
+ }
67
+
49
68
  describe("db-memory-fts-schema", () => {
50
69
  test("creates memories_fts and insert/delete/update triggers", () => {
51
70
  const db = new FakeAdapter();
@@ -83,4 +102,40 @@ describe("db-memory-fts-schema", () => {
83
102
  db.hasFts = true;
84
103
  assert.equal(isMemoriesFtsAvailableSchema(db), true);
85
104
  });
105
+
106
+ test("rebuilds the external-content index once and records a marker", () => {
107
+ const { db, close } = openMemoryAdapter();
108
+ try {
109
+ db.exec("CREATE TABLE memories (seq INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL)");
110
+ db.exec("INSERT INTO memories (content) VALUES ('pre FTS auth memory must be searchable')");
111
+
112
+ const ok = tryCreateMemoriesFtsSchema(db);
113
+ if (!ok) return;
114
+
115
+ const before = db.prepare("SELECT rowid FROM memories_fts WHERE memories_fts MATCH 'auth'").all();
116
+ assert.equal(before.length, 0, "external-content FTS starts empty for existing rows");
117
+
118
+ rebuildMemoriesFtsSchemaOnce(db);
119
+
120
+ const after = db.prepare("SELECT rowid FROM memories_fts WHERE memories_fts MATCH 'auth'").all();
121
+ assert.deepEqual(after.map((row) => row["rowid"]), [1]);
122
+ const marker = db.prepare(
123
+ "SELECT value_json FROM runtime_kv WHERE scope = 'global' AND scope_id = '' AND key = :key",
124
+ ).get({ ":key": MEMORIES_FTS_REBUILT_KEY });
125
+ assert.ok(marker, "rebuild marker should be stored");
126
+ } finally {
127
+ close();
128
+ }
129
+ });
130
+
131
+ test("skips rebuild when marker already exists", () => {
132
+ const db = new FakeAdapter();
133
+ db.hasFts = true;
134
+ db.hasRebuildMarker = true;
135
+
136
+ rebuildMemoriesFtsSchemaOnce(db);
137
+
138
+ assert.ok(db.execCalls.some((sql) => sql.includes("CREATE TABLE IF NOT EXISTS runtime_kv")));
139
+ assert.ok(!db.execCalls.some((sql) => sql.includes("VALUES('rebuild')")));
140
+ });
86
141
  });