@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
@@ -42,6 +42,7 @@ import {
42
42
  type ReconciliationDeps,
43
43
  } from "../state-reconciliation.ts";
44
44
  import { classifyFailure } from "../recovery-classification.ts";
45
+ import { handlerPhaseIndex, RECONCILIATION_REPAIR_PHASES } from "../state-reconciliation/registry.ts";
45
46
  import { staleRenderHandler } from "../state-reconciliation/drift/stale-render.ts";
46
47
  import type { GSDState } from "../types.ts";
47
48
 
@@ -160,6 +161,29 @@ test("ADR-017 (#5700): repair failure throws ReconciliationFailedError with shap
160
161
  );
161
162
  });
162
163
 
164
+ test("ADR-017 (#5700): custom registry handlers outside built-in phases are repaired", async () => {
165
+ const drift = { kind: "custom-drift", id: "D001" } as unknown as DriftRecord;
166
+ let repaired = false;
167
+ const handler = {
168
+ kind: "custom-drift",
169
+ detect: () => (repaired ? [] : [drift]),
170
+ repair: () => {
171
+ repaired = true;
172
+ },
173
+ } as unknown as DriftHandler;
174
+
175
+ const result = await reconcileBeforeDispatch("/project", {
176
+ invalidateStateCache: () => {},
177
+ deriveState: async () => makeState(),
178
+ registry: [handler],
179
+ });
180
+
181
+ assert.equal(result.ok, true);
182
+ assert.equal(repaired, true);
183
+ assert.equal(result.repaired.length, 1);
184
+ assert.equal(result.repaired[0]?.kind, "custom-drift");
185
+ });
186
+
163
187
  test("ADR-017 (#5700): a detector failure degrades to a blocker without aborting other handlers", async () => {
164
188
  // A single detector throwing (e.g. a transient file read error) must NOT
165
189
  // abort the whole cycle and hide every later handler's drift. It is collected
@@ -772,6 +796,51 @@ test("#1003: stale-render plan repair switches back from an open wrong DB", asyn
772
796
  assert.equal(getSliceTasks("M001", "S01").length, 1, "repair should leave the project DB active");
773
797
  });
774
798
 
799
+ test("#1034: validation-blocked milestone summary drift returns blocker instead of exhausting repair passes", async () => {
800
+ const drift: Extract<DriftRecord, { kind: "stale-render" }> = {
801
+ kind: "stale-render",
802
+ renderPath: "/repo/.gsd/milestones/M001/M001-SUMMARY.md",
803
+ reason: "M001 is complete with summary in DB but SUMMARY.md missing on disk",
804
+ };
805
+ let repairCalled = false;
806
+ const handler: DriftHandler<Extract<DriftRecord, { kind: "stale-render" }>> = {
807
+ kind: "stale-render",
808
+ detect: () => [drift],
809
+ blocker: staleRenderHandler.blocker!,
810
+ repair: () => {
811
+ repairCalled = true;
812
+ },
813
+ };
814
+
815
+ const validationBlocker = [
816
+ "Milestone M001 is blocked because milestone validation returned needs-attention.",
817
+ "Fix options:",
818
+ "1. Review the validation details: `/gsd status`",
819
+ ].join("\n");
820
+
821
+ const result = await reconcileBeforeDispatch("/repo", {
822
+ invalidateStateCache: () => {},
823
+ deriveState: async () =>
824
+ makeState({
825
+ phase: "blocked",
826
+ blockers: [validationBlocker],
827
+ nextAction: "Resolve M001 validation attention before proceeding.",
828
+ }),
829
+ registry: [handler],
830
+ });
831
+
832
+ assert.equal(result.ok, true);
833
+ assert.equal(repairCalled, false, "validation-blocked milestone summary drift should not attempt repair");
834
+ assert.ok(
835
+ result.blockers.some((blocker) => blocker.includes("milestone validation returned needs-attention")),
836
+ "validation blocker should be returned to the caller",
837
+ );
838
+ assert.ok(
839
+ result.blockers.some((blocker) => blocker.includes("Stale milestone summary render")),
840
+ "stale-render blocker should explain why repair did not run",
841
+ );
842
+ });
843
+
775
844
  test("ADR-017 (#5702): stale-render detector reason strings match repair contract", (t) => {
776
845
  t.skip("TODO(flat-phase): stale-render detection temporarily disabled during layout transition"); return;
777
846
  const base = mkdtempSync(join(tmpdir(), "gsd-adr017-render-reasons-"));
@@ -1887,3 +1956,49 @@ test("ADR-017 (#5700): cascading drift triggers second pass within cap", async (
1887
1956
  assert.equal(result.repaired.length, 2, "both passes' repairs collected");
1888
1957
  assert.equal(repaired.length, 2);
1889
1958
  });
1959
+
1960
+ test("deriveState is pure: stale sketch healed only via reconcileBeforeDispatch", async (t) => {
1961
+ const base = makeFixtureBase();
1962
+ t.after(() => cleanup(base));
1963
+
1964
+ openDatabase(join(base, ".gsd", "gsd.db"));
1965
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
1966
+ insertSlice({
1967
+ id: "S02",
1968
+ milestoneId: "M001",
1969
+ title: "Feature",
1970
+ status: "pending",
1971
+ risk: "medium",
1972
+ depends: [],
1973
+ demo: "S02 demo.",
1974
+ sequence: 1,
1975
+ isSketch: true,
1976
+ sketchScope: "limited",
1977
+ });
1978
+ writeFileSync(
1979
+ join(base, ".gsd", "phases", "01-test", "01-02-PLAN.md"),
1980
+ "# S02 Plan\n",
1981
+ );
1982
+
1983
+ const { deriveState } = await import("../state.ts");
1984
+ invalidateStateCache();
1985
+
1986
+ const beforeReconcile = await deriveState(base);
1987
+ assert.equal(beforeReconcile.phase, "refining", "derive alone must not heal stale sketch flag");
1988
+ assert.equal(getSlice("M001", "S02")?.is_sketch, 1, "DB flag unchanged before reconcile");
1989
+
1990
+ const result = await reconcileBeforeDispatch(base);
1991
+ assert.equal(result.ok, true);
1992
+ assert.equal(getSlice("M001", "S02")?.is_sketch, 0, "reconcile clears sketch flag");
1993
+
1994
+ invalidateStateCache();
1995
+ const afterReconcile = await deriveState(base);
1996
+ assert.notEqual(afterReconcile.phase, "refining", "derive after reconcile advances past sketch gate");
1997
+ });
1998
+
1999
+ test("reconciliation repair phases: external edits precede re-project handlers", () => {
2000
+ assert.equal(RECONCILIATION_REPAIR_PHASES.length, 3);
2001
+ assert.ok(handlerPhaseIndex("external-markdown-edit") < handlerPhaseIndex("stale-render"));
2002
+ assert.ok(handlerPhaseIndex("external-planning-edit") < handlerPhaseIndex("roadmap-divergence"));
2003
+ assert.ok(handlerPhaseIndex("stale-sketch-flag") < handlerPhaseIndex("stale-render"));
2004
+ });
@@ -0,0 +1,94 @@
1
+ /**
2
+ * status-per-repo.test.ts — `/gsd status` per-repository git-health block (#818).
3
+ *
4
+ * Covers the parent-workspace addition to formatTextStatus:
5
+ * - parent mode with child repos → "Repositories:" section listing each
6
+ * - dirty vs clean markers
7
+ * - single-repo (project-mode) project → no Repositories section
8
+ */
9
+
10
+ import test from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { tmpdir } from "node:os";
15
+ import { execFileSync } from "node:child_process";
16
+
17
+ import { formatTextStatus } from "../commands/handlers/core.ts";
18
+ import type { GSDState } from "../types.ts";
19
+
20
+ function gitInit(cwd: string): void {
21
+ execFileSync("git", ["init"], { cwd, stdio: "ignore" });
22
+ }
23
+
24
+ function makeBaseState(): GSDState {
25
+ return {
26
+ activeMilestone: null,
27
+ activeSlice: null,
28
+ activeTask: null,
29
+ phase: "planning",
30
+ recentDecisions: [],
31
+ blockers: [],
32
+ nextAction: "None",
33
+ registry: [],
34
+ };
35
+ }
36
+
37
+ function writeParentPrefs(base: string, repos: Record<string, { path: string; role?: string }>): void {
38
+ const repoLines = Object.entries(repos)
39
+ .map(([id, cfg]) => ` ${id}:\n path: ${cfg.path}${cfg.role ? `\n role: ${cfg.role}` : ""}`)
40
+ .join("\n");
41
+ writeFileSync(
42
+ join(base, ".gsd", "PREFERENCES.md"),
43
+ `---\nversion: 1\nworkspace:\n mode: parent\n repositories:\n${repoLines}\n---\n`,
44
+ "utf-8",
45
+ );
46
+ }
47
+
48
+ test("formatTextStatus shows a Repositories section for a clean parent workspace", () => {
49
+ const base = mkdtempSync(join(tmpdir(), "gsd-status-repo-clean-"));
50
+ try {
51
+ mkdirSync(join(base, ".gsd"), { recursive: true });
52
+ gitInit(base);
53
+ mkdirSync(join(base, "frontend"), { recursive: true });
54
+ gitInit(join(base, "frontend"));
55
+ writeParentPrefs(base, { frontend: { path: "frontend", role: "web UI" } });
56
+
57
+ const out = formatTextStatus(makeBaseState(), base);
58
+ assert.match(out, /Repositories:/);
59
+ assert.match(out, /✓ frontend — web UI \(clean\)/);
60
+ } finally {
61
+ rmSync(base, { recursive: true, force: true });
62
+ }
63
+ });
64
+
65
+ test("formatTextStatus marks a dirty child repo with ✗", () => {
66
+ const base = mkdtempSync(join(tmpdir(), "gsd-status-repo-dirty-"));
67
+ try {
68
+ mkdirSync(join(base, ".gsd"), { recursive: true });
69
+ gitInit(base);
70
+ mkdirSync(join(base, "backend"), { recursive: true });
71
+ gitInit(join(base, "backend"));
72
+ writeParentPrefs(base, { backend: { path: "backend" } });
73
+ // Make the backend repo dirty.
74
+ writeFileSync(join(base, "backend", "README.md"), "# dirty\n", "utf-8");
75
+
76
+ const out = formatTextStatus(makeBaseState(), base);
77
+ assert.match(out, /✗ backend \(uncommitted changes\)/);
78
+ } finally {
79
+ rmSync(base, { recursive: true, force: true });
80
+ }
81
+ });
82
+
83
+ test("formatTextStatus omits the Repositories section for single-repo projects", () => {
84
+ const base = mkdtempSync(join(tmpdir(), "gsd-status-repo-single-"));
85
+ try {
86
+ mkdirSync(join(base, ".gsd"), { recursive: true });
87
+ gitInit(base);
88
+ // No workspace config → project mode (default).
89
+ const out = formatTextStatus(makeBaseState(), base);
90
+ assert.doesNotMatch(out, /Repositories:/);
91
+ } finally {
92
+ rmSync(base, { recursive: true, force: true });
93
+ }
94
+ });
@@ -552,6 +552,41 @@ test("discuss-milestone dispatch keeps required headless milestone tools after t
552
552
  assert.ok(!activeTools.includes("gsd_complete_milestone"));
553
553
  });
554
554
 
555
+ test("#1157: validate-milestone dispatch surface removes generic write and bash tools", () => {
556
+ const result = buildMinimalAutoGsdToolSet([
557
+ "ask_user_questions",
558
+ "bash",
559
+ "bg_shell",
560
+ "edit",
561
+ "find",
562
+ "glob",
563
+ "grep",
564
+ "ls",
565
+ "read",
566
+ "subagent",
567
+ "write",
568
+ "gsd_exec",
569
+ "gsd_exec_search",
570
+ "gsd_resume",
571
+ "gsd_milestone_status",
572
+ "gsd_validate_milestone",
573
+ "gsd_reassess_roadmap",
574
+ ], "validate-milestone");
575
+
576
+ assert.ok(result.includes("read"));
577
+ assert.ok(result.includes("find"));
578
+ assert.ok(result.includes("subagent"));
579
+ assert.ok(result.includes("gsd_validate_milestone"));
580
+ assert.ok(result.includes("gsd_milestone_status"));
581
+ assert.ok(result.includes("gsd_exec"));
582
+ assert.ok(result.includes("gsd_reassess_roadmap"));
583
+ assert.ok(!result.includes("bash"));
584
+ assert.ok(!result.includes("bg_shell"));
585
+ assert.ok(!result.includes("write"));
586
+ assert.ok(!result.includes("edit"));
587
+ assert.ok(!result.includes("ask_user_questions"));
588
+ });
589
+
555
590
  test("scopeGsdWorkflowToolsForDispatch applies and restores per-unit skill visibility", () => {
556
591
  const calls: Array<{ kind: "tools" | "skills"; value: string[] | undefined }> = [];
557
592
  let activeTools = [
@@ -7,6 +7,7 @@ import { test } from 'node:test';
7
7
  import assert from 'node:assert/strict';
8
8
  import {
9
9
  checkToolCallLoop,
10
+ recordToolCallLoopMutation,
10
11
  resetToolCallLoopGuard,
11
12
  disableToolCallLoopGuard,
12
13
  getToolCallLoopCount,
@@ -223,6 +224,62 @@ console.log('\n── Loop guard: repeatable tools get the higher cap (#783) ─
223
224
  assert.ok(blocked.reason!.includes('cap 15'), 'reason should mention the repeatable cap');
224
225
  }
225
226
 
227
+ // ═══════════════════════════════════════════════════════════════════════════
228
+ // Mutation progress decays per-tool counts (#1092)
229
+ // ═══════════════════════════════════════════════════════════════════════════
230
+
231
+ console.log('\n── Loop guard: mutation progress decays per-tool counts (#1092) ──');
232
+
233
+ {
234
+ resetToolCallLoopGuard();
235
+
236
+ // bash is called more than the repeatable cap, but each count is separated
237
+ // by a successful file mutation. Guard 2 should treat that as progress and
238
+ // avoid blocking the progressing unit.
239
+ for (let i = 1; i <= 20; i++) {
240
+ const result = checkToolCallLoop('bash', { command: `echo ${i}` });
241
+ assert.ok(result.block === false, `bash call ${i} after mutation progress should be allowed`);
242
+ assert.deepStrictEqual(getToolCallCountForTool('bash'), 1, `bash count should decay before call ${i}`);
243
+
244
+ const mutationTool = i % 2 === 0 ? 'write' : 'edit';
245
+ const mutation = checkToolCallLoop(mutationTool, {
246
+ path: `file-${i}.ts`,
247
+ content: `content ${i}`,
248
+ });
249
+ assert.ok(mutation.block === false, `${mutationTool} mutation ${i} should be allowed`);
250
+ recordToolCallLoopMutation(mutationTool);
251
+ }
252
+ }
253
+
254
+ // ═══════════════════════════════════════════════════════════════════════════
255
+ // Distinct read-only navigation calls are context gathering, not repeated-tool loops.
256
+ // ═══════════════════════════════════════════════════════════════════════════
257
+
258
+ console.log('\n── Loop guard: distinct read-only navigation calls are not capped by per-tool count ──');
259
+
260
+ {
261
+ const exemptTools = ['find', 'glob', 'grep', 'ls', 'read', 'search_and_read'];
262
+
263
+ for (const toolName of exemptTools) {
264
+ resetToolCallLoopGuard();
265
+
266
+ for (let i = 1; i <= 20; i++) {
267
+ const result = checkToolCallLoop(toolName, { path: `file-${i}.ts` });
268
+ assert.ok(result.block === false, `distinct ${toolName} call ${i} should be allowed`);
269
+ }
270
+
271
+ resetToolCallLoopGuard();
272
+ for (let i = 1; i <= 4; i++) {
273
+ const result = checkToolCallLoop(toolName, { path: 'same-file.ts' });
274
+ assert.ok(result.block === false, `identical ${toolName} call ${i} should be allowed`);
275
+ }
276
+
277
+ const blocked = checkToolCallLoop(toolName, { path: 'same-file.ts' });
278
+ assert.ok(blocked.block === true, `5th identical ${toolName} call should still be blocked`);
279
+ assert.ok(blocked.reason?.includes('identical args'), `${toolName} loops should be caught by Guard 1`);
280
+ }
281
+ }
282
+
226
283
  // ═══════════════════════════════════════════════════════════════════════════
227
284
  // Per-tool counts are independent per tool and reset together
228
285
  // ═══════════════════════════════════════════════════════════════════════════
@@ -245,3 +302,149 @@ console.log('\n── Loop guard: per-tool counts are independent and reset toge
245
302
  }
246
303
 
247
304
  // ═══════════════════════════════════════════════════════════════════════════
305
+ // Non-exempt repeatable tools from core-session-tools.ts get the higher cap.
306
+ // Read-only navigation tools are exempted earlier; mutating/execution repeatable
307
+ // tools (e.g. gsd_exec) must still trip the per-tool cap.
308
+ // ═══════════════════════════════════════════════════════════════════════════
309
+
310
+ console.log('\n── Loop guard: non-exempt repeatable tools get high cap ──');
311
+
312
+ {
313
+ for (const toolName of ['bg_shell', 'gsd_exec', 'write']) {
314
+ resetToolCallLoopGuard();
315
+
316
+ // Should allow up to 15 varied calls without blocking.
317
+ for (let i = 1; i <= 15; i++) {
318
+ const result = checkToolCallLoop(toolName, { arg: `v${i}` });
319
+ assert.ok(result.block === false, `${toolName} call ${i} (varied args) should be allowed`);
320
+ }
321
+ // 16th call with varied args must be blocked by the per-tool repeatable cap.
322
+ const blocked = checkToolCallLoop(toolName, { arg: 'v16' });
323
+ assert.ok(blocked.block === true, `${toolName}: 16th call must be blocked by repeatable cap`);
324
+ assert.ok(blocked.reason?.includes('cap 15'), `${toolName}: reason must mention cap 15`);
325
+ }
326
+ }
327
+
328
+ // ═══════════════════════════════════════════════════════════════════════════
329
+ // Non-repeatable tools excluded from INHERENTLY_REPEATABLE_TOOL_SET use the
330
+ // default cap (6), not the repeatable cap (15).
331
+ // ═══════════════════════════════════════════════════════════════════════════
332
+
333
+ console.log('\n── Loop guard: ToolSearch (excluded from repeatable set) hits default cap ──');
334
+
335
+ {
336
+ // ToolSearch is in MINIMAL_AUTO_BASE but explicitly excluded from repeatable.
337
+ // It should hit the default cap of 6, not 15.
338
+ resetToolCallLoopGuard();
339
+ for (let i = 1; i <= 6; i++) {
340
+ const result = checkToolCallLoop('ToolSearch', { query: `q${i}` });
341
+ assert.ok(result.block === false, `ToolSearch call ${i} should be allowed`);
342
+ }
343
+ const blocked = checkToolCallLoop('ToolSearch', { query: 'q7' });
344
+ assert.ok(blocked.block === true, 'ToolSearch: 7th varied call must be blocked by default cap');
345
+ assert.ok(!blocked.reason?.includes('cap 15'), 'ToolSearch must NOT use the repeatable cap');
346
+ }
347
+
348
+ // ═══════════════════════════════════════════════════════════════════════════
349
+ // Block reasons instruct the model to stop tooling this turn
350
+ // ═══════════════════════════════════════════════════════════════════════════
351
+
352
+ console.log('\n── Loop guard: block reasons tell model to respond in text ──');
353
+
354
+ {
355
+ resetToolCallLoopGuard();
356
+
357
+ for (let i = 0; i < 4; i++) {
358
+ checkToolCallLoop('web_search', { query: 'same query' });
359
+ }
360
+ const identicalBlocked = checkToolCallLoop('web_search', { query: 'same query' });
361
+ assert.ok(identicalBlocked.block === true, 'identical-args guard should block');
362
+ assert.ok(
363
+ identicalBlocked.reason!.includes('respond to the user in text'),
364
+ 'identical-args reason should tell the model to stop tooling',
365
+ );
366
+ assert.ok(
367
+ !identicalBlocked.reason!.includes('Try a different approach'),
368
+ 'identical-args reason should not suggest retrying another tool',
369
+ );
370
+
371
+ resetToolCallLoopGuard();
372
+ for (let i = 0; i < 6; i++) {
373
+ checkToolCallLoop('gsd_complete_milestone', { milestone: `M${i}` });
374
+ }
375
+ const perToolBlocked = checkToolCallLoop('gsd_complete_milestone', { milestone: 'M7' });
376
+ assert.ok(perToolBlocked.block === true, 'per-tool guard should block');
377
+ assert.ok(
378
+ perToolBlocked.reason!.includes('respond to the user in text'),
379
+ 'per-tool reason should tell the model to stop tooling',
380
+ );
381
+ assert.ok(
382
+ perToolBlocked.reason!.includes('Do not retry this tool'),
383
+ 'per-tool reason should forbid retrying the blocked tool',
384
+ );
385
+ }
386
+
387
+ // ═══════════════════════════════════════════════════════════════════════════
388
+ // Distinct-arg browser-automation calls are a legitimate UAT, not a loop (#1120)
389
+ // ═══════════════════════════════════════════════════════════════════════════
390
+
391
+ console.log('\n── Loop guard: distinct-arg browser automation calls are not capped by per-tool count (#1120) ──');
392
+
393
+ {
394
+ // A browser-backed UAT legitimately calls one browser verb many times with
395
+ // DIFFERENT arguments (read a validation message, count staged edits, inspect
396
+ // a control card, …). Guard 1's identical-signature streak never trips because
397
+ // the args vary; Guard 2's arg-independent per-tool cap must NOT block it.
398
+ for (const toolName of ['browser_evaluate', 'browser_act', 'browser_find']) {
399
+ resetToolCallLoopGuard();
400
+ for (let i = 1; i <= 12; i++) {
401
+ const result = checkToolCallLoop(toolName, { script: `step ${i}` });
402
+ assert.ok(result.block === false, `distinct ${toolName} call ${i} should be allowed`);
403
+ }
404
+ }
405
+
406
+ // MCP-prefixed browser tools canonicalize to `browser_*` and are exempt too.
407
+ resetToolCallLoopGuard();
408
+ for (let i = 1; i <= 12; i++) {
409
+ const result = checkToolCallLoop('mcp__agent-browser__browser_evaluate', { script: `step ${i}` });
410
+ assert.ok(result.block === false, `distinct MCP-prefixed browser_evaluate call ${i} should be allowed`);
411
+ }
412
+ }
413
+
414
+ // ═══════════════════════════════════════════════════════════════════════════
415
+ // Identical-arg browser loops are STILL caught by Guard 1 (#1120)
416
+ // ═══════════════════════════════════════════════════════════════════════════
417
+
418
+ console.log('\n── Loop guard: identical-arg browser loops are still caught by Guard 1 (#1120) ──');
419
+
420
+ {
421
+ resetToolCallLoopGuard();
422
+ for (let i = 1; i <= 4; i++) {
423
+ const result = checkToolCallLoop('browser_evaluate', { script: 'document.title' });
424
+ assert.ok(result.block === false, `identical browser_evaluate call ${i} should be allowed`);
425
+ }
426
+ const blocked = checkToolCallLoop('browser_evaluate', { script: 'document.title' });
427
+ assert.ok(blocked.block === true, '5th identical browser_evaluate call should be blocked by Guard 1');
428
+ assert.ok(blocked.reason?.includes('identical args'), 'identical browser loops should be caught by Guard 1, not Guard 2');
429
+ }
430
+
431
+ // ═══════════════════════════════════════════════════════════════════════════
432
+ // The browser exemption must NOT widen to other non-exempt tools (#1120)
433
+ // ═══════════════════════════════════════════════════════════════════════════
434
+
435
+ console.log('\n── Loop guard: browser exemption does not widen to other tools (#1120) ──');
436
+
437
+ {
438
+ // Negative invariant: an arbitrary non-exempt, non-browser tool called past
439
+ // the default cap with varied args must still be blocked by Guard 2.
440
+ resetToolCallLoopGuard();
441
+ for (let i = 1; i <= 6; i++) {
442
+ const result = checkToolCallLoop('some_workflow_tool', { arg: `v${i}` });
443
+ assert.ok(result.block === false, `non-exempt tool call ${i} should be allowed`);
444
+ }
445
+ const blocked = checkToolCallLoop('some_workflow_tool', { arg: 'v7' });
446
+ assert.ok(blocked.block === true, '7th varied-arg non-exempt call must still trip Guard 2');
447
+ assert.ok(blocked.reason?.includes('repeated tool'), 'non-exempt overflow should be caught by Guard 2');
448
+ }
449
+
450
+ // ═══════════════════════════════════════════════════════════════════════════
@@ -385,14 +385,17 @@ test("gsd_plan_slice — enrichment fields are optional", () => {
385
385
 
386
386
  const required = new Set(getRequiredProps(tool));
387
387
 
388
- // Core fields
389
- const coreRequired = ["milestoneId", "sliceId", "goal", "tasks"];
388
+ // Core fields. `tasks` is intentionally NOT here: incremental planning
389
+ // (#1027) lets gsd_plan_slice persist slice metadata only, then add tasks
390
+ // one at a time via gsd_plan_task, so tasks must be optional.
391
+ const coreRequired = ["milestoneId", "sliceId", "goal"];
390
392
  for (const field of coreRequired) {
391
393
  assert.ok(required.has(field), `core field "${field}" must be required`);
392
394
  }
393
395
 
394
- // Enrichment fields
396
+ // Enrichment fields (plus tasks, optional for incremental planning).
395
397
  const enrichmentFields = [
398
+ "tasks",
396
399
  "successCriteria",
397
400
  "proofLevel",
398
401
  "integrationClosure",
@@ -10,6 +10,7 @@ import {
10
10
  handleUndo,
11
11
  handleUndoTask,
12
12
  handleResetSlice,
13
+ parseActivityLogFilename,
13
14
  uncheckTaskInPlan,
14
15
  } from "../undo.ts";
15
16
  import {
@@ -67,6 +68,37 @@ test("handleUndo without --force only warns and leaves completed units intact",
67
68
  }
68
69
  });
69
70
 
71
+ test("handleUndo execute-task with --force reopens the task row and re-renders plan", async () => {
72
+ const base = makeTempDir("gsd-undo-execute-task");
73
+ try {
74
+ setupTaskFixture(base);
75
+ mkdirSync(join(base, ".gsd", "activity"), { recursive: true });
76
+ writeFileSync(
77
+ join(base, ".gsd", "activity", "001-execute-task-M001-S01-T01.jsonl"),
78
+ "",
79
+ "utf-8",
80
+ );
81
+
82
+ const { notifications, ctx } = makeCtx();
83
+ await handleUndo("--force", ctx, {} as any, base);
84
+
85
+ const task = getTask("M001", "S01", "T01");
86
+ assert.equal(task?.status, "pending");
87
+
88
+ const planContent = readFileSync(
89
+ join(base, ".gsd", "phases", "01-test", "01-01-PLAN.md"),
90
+ "utf-8",
91
+ );
92
+ assert.match(planContent, /\[ \] \*\*T01\*\*:/);
93
+
94
+ assert.equal(notifications[0]?.level, "success");
95
+ assert.match(notifications[0]?.message ?? "", /Unchecked task in PLAN/);
96
+ } finally {
97
+ closeDatabase();
98
+ rmSync(base, { recursive: true, force: true });
99
+ }
100
+ });
101
+
70
102
  test("uncheckTaskInPlan flips a checked task back to unchecked", () => {
71
103
  const base = makeTempDir("gsd-undo-plan");
72
104
  try {
@@ -154,6 +186,48 @@ test("extractCommitShas ignores malformed commit tokens", () => {
154
186
  assert.deepEqual(extractCommitShas(content), ["1234567"]);
155
187
  });
156
188
 
189
+ test("parseActivityLogFilename splits hyphenated unit types from their IDs", () => {
190
+ // Task-level: unit type and ID both contain hyphens.
191
+ assert.deepEqual(parseActivityLogFilename("001-execute-task-M001-S01-T01.jsonl"), {
192
+ unitType: "execute-task",
193
+ unitId: "M001-S01-T01",
194
+ });
195
+ // Variant must win over its shorter prefix ("execute-task").
196
+ assert.deepEqual(parseActivityLogFilename("002-execute-task-simple-M001-S02-T03.jsonl"), {
197
+ unitType: "execute-task-simple",
198
+ unitId: "M001-S02-T03",
199
+ });
200
+ // Milestone- and slice-shaped IDs.
201
+ assert.deepEqual(parseActivityLogFilename("003-research-milestone-M001.jsonl"), {
202
+ unitType: "research-milestone",
203
+ unitId: "M001",
204
+ });
205
+ assert.deepEqual(parseActivityLogFilename("004-plan-slice-M001-S01.jsonl"), {
206
+ unitType: "plan-slice",
207
+ unitId: "M001-S01",
208
+ });
209
+ });
210
+
211
+ test("parseActivityLogFilename accepts non-milestone-shaped unit IDs", () => {
212
+ // Regression (#1057): project-level units use IDs that do not start with
213
+ // "M<digit>". A milestone-shaped regex made /gsd undo bail out with
214
+ // "could not parse latest activity log" when one of these was most recent.
215
+ assert.deepEqual(parseActivityLogFilename("005-discuss-project-PROJECT.jsonl"), {
216
+ unitType: "discuss-project",
217
+ unitId: "PROJECT",
218
+ });
219
+ assert.deepEqual(parseActivityLogFilename("006-workflow-preferences-WORKFLOW-PREFS.jsonl"), {
220
+ unitType: "workflow-preferences",
221
+ unitId: "WORKFLOW-PREFS",
222
+ });
223
+ });
224
+
225
+ test("parseActivityLogFilename returns null for unrecognized names", () => {
226
+ assert.equal(parseActivityLogFilename("007-not-a-real-unit-M001.jsonl"), null);
227
+ assert.equal(parseActivityLogFilename("no-sequence-prefix.jsonl"), null);
228
+ assert.equal(parseActivityLogFilename("001-execute-task-M001-S01-T01.txt"), null);
229
+ });
230
+
157
231
  // ─── handleUndoTask tests ────────────────────────────────────────────────────
158
232
 
159
233
  function makeCtx(): { notifications: Array<{ message: string; level: string }>; ctx: any } {