@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
@@ -32,9 +32,16 @@ import {
32
32
  recordAutoToolSurfaceSnapshot,
33
33
  recordToolInvocationError,
34
34
  } from "../auto-runtime-state.js";
35
+ import {
36
+ isDeterministicPolicyError,
37
+ isQueuedUserMessageSkip,
38
+ isToolInvocationError,
39
+ isToolUnavailableError,
40
+ } from "../auto-tool-tracking.js";
35
41
  import { applyProviderPayloadPolicy } from "../provider-payload-policy.js";
36
42
 
37
- import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
43
+ import { checkToolCallLoop, recordToolCallLoopMutation, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
44
+ import { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
38
45
  import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
39
46
  import { saveActivityLog } from "../activity-log.js";
40
47
  import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
@@ -75,9 +82,25 @@ import { supportsSourceObservationsForUnit } from "../source-observations.js";
75
82
  import { clearPendingAutoStart } from "../pending-auto-start.js";
76
83
  import { resolveWorkflowToolBasePath } from "./dynamic-tools.js";
77
84
  import { getRequiredWorkflowToolsForUnit } from "../unit-tool-contracts.js";
85
+ import { flushAllManifests } from "../workflow-manifest.js";
86
+ import { recordUnitHarnessAbort, type UnitHarnessAbortRecord } from "../unit-runtime.js";
78
87
 
79
88
  let approvalQuestionAbortInFlight = false;
80
89
 
90
+ function recordCurrentUnitHarnessAbort(
91
+ abort: Omit<UnitHarnessAbortRecord, "recordedAt"> & { recordedAt?: number },
92
+ ): void {
93
+ const dash = getAutoRuntimeSnapshot();
94
+ if (!dash.active || !dash.basePath || !dash.currentUnit) return;
95
+ recordUnitHarnessAbort(
96
+ dash.basePath,
97
+ dash.currentUnit.type,
98
+ dash.currentUnit.id,
99
+ dash.currentUnit.startedAt,
100
+ abort,
101
+ );
102
+ }
103
+
81
104
  type WelcomeScreenModule = {
82
105
  buildWelcomeScreenLines(opts: { version: string; remoteChannel?: string; width?: number }): string[];
83
106
  };
@@ -178,22 +201,7 @@ export const MINIMAL_GSD_TOOL_NAMES = [
178
201
  "gsd_capture_thought",
179
202
  ] as const;
180
203
 
181
- export const MINIMAL_AUTO_BASE_TOOL_NAMES = [
182
- "ask_user_questions",
183
- "bash",
184
- "bg_shell",
185
- "edit",
186
- "find",
187
- "glob",
188
- "grep",
189
- "fetch_page",
190
- "search-the-web",
191
- "ls",
192
- "read",
193
- "subagent",
194
- "write",
195
- "ToolSearch",
196
- ] as const;
204
+ export { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
197
205
 
198
206
  function withPreservedShimTools(toolNames: readonly string[]): string[] {
199
207
  return [...new Set([...toolNames, ...ALWAYS_PRESERVED_SHIM_TOOL_NAMES])];
@@ -222,10 +230,26 @@ const WORKFLOW_GSD_TOOL_NAMES = [
222
230
  ...Object.values(AUTO_UNIT_SCOPED_TOOLS).flat(),
223
231
  ].filter(isGsdManagedTool);
224
232
 
233
+ const WORKFLOW_ONLY_AUTO_BASE_TOOL_NAMES = [
234
+ "find",
235
+ "glob",
236
+ "grep",
237
+ "ls",
238
+ "read",
239
+ "subagent",
240
+ ] as const;
241
+
225
242
  function isGsdManagedTool(name: string): boolean {
226
243
  return name.startsWith("gsd_") || name === "memory_query" || name === "capture_thought" || name === "gsd_graph";
227
244
  }
228
245
 
246
+ function autoBaseToolNamesForUnit(unitType: string | undefined): readonly string[] {
247
+ const manifest = unitType ? resolveManifest(unitType) : null;
248
+ return manifest?.tools.mode === "workflow-only"
249
+ ? WORKFLOW_ONLY_AUTO_BASE_TOOL_NAMES
250
+ : MINIMAL_AUTO_BASE_TOOL_NAMES;
251
+ }
252
+
229
253
  /**
230
254
  * Resolves requested tool names against active tools using exact and MCP-scoped matches.
231
255
  *
@@ -288,7 +312,7 @@ export function buildMinimalAutoGsdToolSet(
288
312
  return buildRunUatGsdToolSet(activeToolNames, registeredToolNames);
289
313
  }
290
314
  const unitTools = unitType ? AUTO_UNIT_SCOPED_TOOLS[unitType] ?? [] : [];
291
- const autoBaseTools = new Set<string>(MINIMAL_AUTO_BASE_TOOL_NAMES);
315
+ const autoBaseTools = new Set<string>(autoBaseToolNamesForUnit(unitType));
292
316
  const availableBaseTools = registeredToolNames.filter((name) => autoBaseTools.has(name));
293
317
  const preserved = [...new Set([
294
318
  ...activeToolNames.filter((name) => autoBaseTools.has(name)),
@@ -597,6 +621,87 @@ function contextBasePath(ctx?: { cwd?: string }): string {
597
621
  return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
598
622
  }
599
623
 
624
+ const LOOP_GUARD_INTERACTIVE_INSTRUCTIONS = [
625
+ "Do not retry this tool or call other tools this turn — stop and respond to the user in text.",
626
+ "Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.",
627
+ ];
628
+ const LOOP_GUARD_AUTO_INSTRUCTION =
629
+ "Do not re-issue this blocked tool. In /gsd auto, stop tool calls for this turn and return control to the auto-mode recovery/replan path.";
630
+
631
+ function formatLoopGuardBlockReason(reason: string | undefined): string | undefined {
632
+ if (!reason || !getAutoRuntimeSnapshot().active) return reason;
633
+ return LOOP_GUARD_INTERACTIVE_INSTRUCTIONS.reduce(
634
+ (formatted, instruction) => formatted.replace(instruction, LOOP_GUARD_AUTO_INSTRUCTION),
635
+ reason,
636
+ );
637
+ }
638
+
639
+ function isGateResultPersistenceTool(toolName: string): boolean {
640
+ return toolName === "gsd_save_gate_result" || toolName === "gsd_uat_result_save";
641
+ }
642
+
643
+ function resultDetails(result: unknown): Record<string, unknown> {
644
+ if (!result || typeof result !== "object") return {};
645
+ const details = (result as { details?: unknown }).details;
646
+ return details && typeof details === "object" ? details as Record<string, unknown> : {};
647
+ }
648
+
649
+ function isAbortedExecutionToolResult(toolName: string, result: unknown): boolean {
650
+ if (toolName !== "gsd_exec" && toolName !== "gsd_uat_exec") return false;
651
+ const details = resultDetails(result);
652
+ return details.aborted === true || details.force_resolved === true || details.timed_out === true;
653
+ }
654
+
655
+ function isRetryableHarnessToolError(toolName: string, result: unknown, errorText: string): boolean {
656
+ if (isGateResultPersistenceTool(toolName)) return false;
657
+ if (isDeterministicPolicyError(errorText)) return false;
658
+ if (toolName === "gsd_exec" || toolName === "gsd_uat_exec") {
659
+ if (isAbortedExecutionToolResult(toolName, result)) return true;
660
+ if (isToolUnavailableError(errorText)) return true;
661
+ if (isQueuedUserMessageSkip(errorText)) return true;
662
+ return isToolInvocationError(errorText);
663
+ }
664
+ if (isToolUnavailableError(errorText)) return true;
665
+ if (isQueuedUserMessageSkip(errorText)) return true;
666
+ return false;
667
+ }
668
+
669
+ function recordRetryableHarnessToolError(toolName: string, result: unknown, errorText: string): void {
670
+ if (!isRetryableHarnessToolError(toolName, result, errorText)) return;
671
+ recordCurrentUnitHarnessAbort({
672
+ kind: "tool-error",
673
+ reason: errorText || "Tool execution failed before the unit could complete its gate evaluation.",
674
+ toolName,
675
+ });
676
+ }
677
+
678
+ function recordRetryableTurnAbort(event: { abortOrigin?: unknown; messages?: unknown[] }): void {
679
+ const origin = typeof event.abortOrigin === "string" ? event.abortOrigin : undefined;
680
+ if (origin === "session-transition") return;
681
+
682
+ const messages = Array.isArray(event.messages) ? event.messages : [];
683
+ const lastMsg = messages[messages.length - 1];
684
+ const stopReason = lastMsg && typeof lastMsg === "object"
685
+ ? (lastMsg as { stopReason?: unknown }).stopReason
686
+ : undefined;
687
+ if (stopReason !== "aborted" && stopReason !== "error") return;
688
+
689
+ const errorMessage = lastMsg && typeof lastMsg === "object"
690
+ ? (lastMsg as { errorMessage?: unknown }).errorMessage
691
+ : undefined;
692
+ const reason = [
693
+ "Agent turn aborted before the unit could complete its gate evaluation.",
694
+ origin ? `origin=${origin}` : undefined,
695
+ typeof stopReason === "string" ? `stopReason=${stopReason}` : undefined,
696
+ typeof errorMessage === "string" && errorMessage.trim() ? `error=${errorMessage.trim()}` : undefined,
697
+ ].filter(Boolean).join(" ");
698
+
699
+ recordCurrentUnitHarnessAbort({
700
+ kind: "turn-abort",
701
+ reason,
702
+ });
703
+ }
704
+
600
705
  function beginSourceObservationStoreForCurrentUnit(
601
706
  ctx?: { cwd?: string },
602
707
  ): ReturnType<typeof getSourceObservationStore> | null {
@@ -900,8 +1005,8 @@ export function registerHooks(
900
1005
  await prepareWorkflowMcpForHookContext(ctx, basePath);
901
1006
 
902
1007
  // Migrate legacy .gsd/milestones/ to flat-phase .gsd/phases/ when detected.
903
- // Best-effort never blocks session startup. Skipped inside auto-worktrees
904
- // (migration already ran on the project root before the worktree was created).
1008
+ // Fail closed on migration errors: resolvers assume flat-phase paths after
1009
+ // startup, so continuing with nested disk state corrupts later checks.
905
1010
  try {
906
1011
  const { isInAutoWorktree } = await import("../auto-worktree.js");
907
1012
  if (!isInAutoWorktree(basePath)) {
@@ -915,13 +1020,32 @@ export function registerHooks(
915
1020
  } else {
916
1021
  safetyLogWarning(
917
1022
  "bootstrap",
918
- "flat-phase migration deferred: legacy .gsd/milestones/ layout detected but the workflow database could not be opened — will retry on next session",
1023
+ "flat-phase migration required: legacy .gsd/milestones/ layout detected but the workflow database could not be opened — fix database access before starting GSD",
1024
+ );
1025
+ throw new Error(
1026
+ "flat-phase migration required but the workflow database could not be opened; fix database access before starting GSD",
919
1027
  );
920
1028
  }
921
1029
  }
922
1030
  }
923
1031
  } catch (err) {
924
- safetyLogWarning("bootstrap", `flat-phase migration: ${err instanceof Error ? err.message : String(err)}`);
1032
+ const message = err instanceof Error ? err.message : String(err);
1033
+ safetyLogWarning("bootstrap", `flat-phase migration failed: ${message}`);
1034
+ throw new Error(`flat-phase migration failed: ${message}`);
1035
+ }
1036
+
1037
+ try {
1038
+ const projectRoot = resolveWorktreeProjectRoot(basePath);
1039
+ const { pruneStaleFlatPhaseBackups } = await import("../flat-phase-migration.js");
1040
+ const pruned = pruneStaleFlatPhaseBackups(projectRoot);
1041
+ if (pruned > 0) {
1042
+ safetyLogWarning(
1043
+ "bootstrap",
1044
+ `pruned ${pruned} stale flat-phase migration backup(s) from .gsd-backups/ (retention exceeded)`,
1045
+ );
1046
+ }
1047
+ } catch (err) {
1048
+ safetyLogWarning("bootstrap", `flat-phase backup pruning: ${err instanceof Error ? err.message : String(err)}`);
925
1049
  }
926
1050
 
927
1051
  // Apply show_token_cost preference (#1515)
@@ -1079,12 +1203,26 @@ export function registerHooks(
1079
1203
 
1080
1204
  pi.on("agent_end", async (event, ctx: ExtensionContext) => {
1081
1205
  approvalQuestionAbortInFlight = false;
1206
+ recordRetryableTurnAbort(event);
1082
1207
  resetToolCallLoopGuard();
1083
1208
  resetPendingGatePauseGuard();
1084
1209
  await resetAskUserQuestionsTurnCache();
1085
1210
  const { handleAgentEnd } = await import("./agent-end-recovery.js");
1086
1211
  const agentEndBasePath = contextBasePath(ctx);
1087
1212
  try {
1213
+ // The manifest is a non-critical projection (the append-only event log is
1214
+ // the authoritative recovery source), so a flush failure must not skip
1215
+ // agent_end recovery. drainManifestWrites still propagates write failures
1216
+ // to explicit flush callers; here we deliberately log and continue so
1217
+ // handleAgentEnd (and the finally below) always run.
1218
+ try {
1219
+ await flushAllManifests();
1220
+ } catch (err) {
1221
+ safetyLogWarning(
1222
+ "manifest",
1223
+ `flushAllManifests on agent_end failed: ${err instanceof Error ? err.message : String(err)}`,
1224
+ );
1225
+ }
1088
1226
  await handleAgentEnd(pi, event, ctx);
1089
1227
  } finally {
1090
1228
  activateDeferredApprovalGate(agentEndBasePath);
@@ -1291,7 +1429,13 @@ export function registerHooks(
1291
1429
  // ── Loop guard: block repeated identical tool calls ──
1292
1430
  const loopCheck = checkToolCallLoop(toolName, event.input as Record<string, unknown>);
1293
1431
  if (loopCheck.block) {
1294
- return { block: true, reason: loopCheck.reason };
1432
+ recordCurrentUnitHarnessAbort({
1433
+ kind: "tool-loop-guard",
1434
+ reason: loopCheck.reason ?? "Tool-call loop guard blocked a repeated tool call.",
1435
+ toolName,
1436
+ count: loopCheck.count,
1437
+ });
1438
+ return { block: true, reason: formatLoopGuardBlockReason(loopCheck.reason) };
1295
1439
  }
1296
1440
 
1297
1441
  const deferredGateGuard = shouldBlockDeferredApprovalTool(
@@ -1563,6 +1707,7 @@ export function registerHooks(
1563
1707
  }
1564
1708
  }
1565
1709
  if (!event.isError) {
1710
+ recordToolCallLoopMutation(toolName);
1566
1711
  refreshSourceObservationAfterMutation(toolName, event.input, ctx);
1567
1712
  clearSourceObservationsAfterShell(toolName);
1568
1713
  }
@@ -1578,6 +1723,7 @@ export function registerHooks(
1578
1723
  // Let recordToolInvocationError classify the failure so non-gsd_ harness
1579
1724
  // errors and deterministic policy rejections are handled consistently.
1580
1725
  recordToolInvocationError(event.toolName, errorText);
1726
+ recordRetryableHarnessToolError(toolName, resultPayload, errorText);
1581
1727
  } else if (isAutoActive()) {
1582
1728
  clearToolInvocationError();
1583
1729
  }
@@ -1774,6 +1920,7 @@ export function registerHooks(
1774
1920
  // for every finalized tool call on every engine, so error classification
1775
1921
  // and evidence persistence here cover external engines that skip tool_result.
1776
1922
  pi.on("tool_execution_end", async (event) => {
1923
+ const toolName = canonicalToolName(event.toolName);
1777
1924
  markToolEnd(event.toolCallId);
1778
1925
  // #2883/#4974: Capture deterministic invocation/policy errors
1779
1926
  // so postUnitPreVerification can break the retry loop instead of re-dispatching.
@@ -1784,6 +1931,7 @@ export function registerHooks(
1784
1931
  // Let recordToolInvocationError classify the failure so non-gsd_ harness
1785
1932
  // errors and deterministic policy rejections are handled consistently.
1786
1933
  recordToolInvocationError(event.toolName, errorText);
1934
+ recordRetryableHarnessToolError(toolName, event.result, errorText);
1787
1935
  } else if (isAutoActive()) {
1788
1936
  clearToolInvocationError();
1789
1937
  }
@@ -9,13 +9,14 @@
9
9
 
10
10
  import { test, describe, before, after } from "node:test";
11
11
  import assert from "node:assert/strict";
12
- import { mkdtempSync, rmSync, existsSync } from "node:fs";
12
+ import { mkdtempSync, rmSync, existsSync, mkdirSync } from "node:fs";
13
13
  import { tmpdir } from "node:os";
14
14
  import { join } from "node:path";
15
15
 
16
16
  import {
17
17
  markDepthVerified,
18
18
  loadWriteGateSnapshot,
19
+ shouldBlockContextArtifactSaveInSnapshot,
19
20
  clearDiscussionFlowState,
20
21
  } from "../write-gate.js";
21
22
 
@@ -100,4 +101,51 @@ describe("write-gate basePath regression", () => {
100
101
  "loadWriteGateSnapshot(baseDirB) must not bleed state from baseDirA",
101
102
  );
102
103
  });
104
+
105
+ test("worktree basePath reads depth verification from project-root snapshot", (t) => {
106
+ const prev = process.env.GSD_PERSIST_WRITE_GATE_STATE;
107
+ t.after(() => {
108
+ if (prev === undefined) {
109
+ delete process.env.GSD_PERSIST_WRITE_GATE_STATE;
110
+ } else {
111
+ process.env.GSD_PERSIST_WRITE_GATE_STATE = prev;
112
+ }
113
+ });
114
+ process.env.GSD_PERSIST_WRITE_GATE_STATE = "1";
115
+
116
+ const projectRoot = makeTempDir();
117
+ const worktreePath = join(projectRoot, ".gsd-worktrees", "M020");
118
+ t.after(() => {
119
+ rmSync(projectRoot, { recursive: true, force: true });
120
+ });
121
+
122
+ clearDiscussionFlowState(projectRoot);
123
+ clearDiscussionFlowState(worktreePath);
124
+
125
+ // Simulate MCP routing: verification recorded at project root.
126
+ markDepthVerified("M020", projectRoot);
127
+
128
+ // Worktree has a local .gsd projection but no write-gate snapshot file.
129
+ mkdirSync(join(worktreePath, ".gsd", "runtime"), { recursive: true });
130
+ mkdirSync(join(projectRoot, ".gsd", "milestones"), { recursive: true });
131
+
132
+ const projectSnapshotPath = join(projectRoot, ".gsd", "runtime", "write-gate-state.json");
133
+ const worktreeSnapshotPath = join(worktreePath, ".gsd", "runtime", "write-gate-state.json");
134
+ assert.ok(existsSync(projectSnapshotPath), "verification snapshot lives at project root");
135
+ assert.ok(!existsSync(worktreeSnapshotPath), "worktree must not have its own snapshot file");
136
+
137
+ const snapshotFromWorktree = loadWriteGateSnapshot(worktreePath);
138
+ assert.ok(
139
+ snapshotFromWorktree.verifiedDepthMilestones.includes("M020"),
140
+ "loadWriteGateSnapshot(worktree) must inherit project-root verification",
141
+ );
142
+
143
+ const guard = shouldBlockContextArtifactSaveInSnapshot(
144
+ snapshotFromWorktree,
145
+ "CONTEXT",
146
+ "M020",
147
+ null,
148
+ );
149
+ assert.equal(guard.block, false, "CONTEXT save must unblock once project-root gate is verified");
150
+ });
103
151
  });
@@ -1,25 +1,32 @@
1
1
  /**
2
2
  * Tool-call loop guard.
3
3
  *
4
- * Detects when a model calls the same tool with identical arguments
5
- * repeatedly within a single agent turn. Works in both auto-mode and
6
- * interactive sessions by hooking into the `tool_call` event, which
7
- * fires before execution and can block the call.
4
+ * Detects when a model repeats tool calls within a single Agent Turn.
5
+ * Works in both auto-mode and interactive sessions by hooking into the
6
+ * native engine's `tool_call` event, which fires before execution and can
7
+ * block the call.
8
8
  *
9
- * The guard uses a sliding window: it tracks the last N tool signatures
10
- * and blocks when the same signature appears more than MAX_CONSECUTIVE
11
- * times in a row. Resets on each agent turn (session_start, agent_end)
12
- * and when a different tool call breaks the streak.
9
+ * The guard has two independent checks: a sliding window for identical
10
+ * tool signatures, and a per-tool-name cap for repeated calls with varied
11
+ * arguments. State resets at Agent Turn boundaries (session_start,
12
+ * agent_end) and the identical-signature streak also resets when a
13
+ * different tool call breaks the streak. Block messages instruct the model
14
+ * to stop tooling for the rest of that turn and answer in text.
13
15
  *
14
- * A second, independent check (#783 Brief C) tracks per-tool-name call
15
- * counts within a turn regardless of args. This catches improvisation
16
+ * The per-tool-name check (#783 Brief C) tracks call counts within a
17
+ * turn regardless of args, decaying after successful state-mutating tools.
18
+ * This catches improvisation
16
19
  * loops where the model attempts the same missing workflow tool through
17
20
  * varied surfaces (bash → `node -e` → CLI), each with a different
18
- * signature, so the identical-args streak never trips. Whichever guard
21
+ * signature, so the identical-args streak never trips, while allowing
22
+ * tool-heavy turns that are making file-mutation progress. Whichever guard
19
23
  * trips first blocks.
20
24
  */
21
25
 
22
26
  import { createHash } from "node:crypto";
27
+ import { INHERENTLY_REPEATABLE_TOOL_SET } from "./core-session-tools.js";
28
+ import { hasBrowserContractPrefix } from "../../shared/browser-contract.js";
29
+ import { canonicalToolName } from "../engine-hook-contract.js";
23
30
 
24
31
  const MAX_CONSECUTIVE_IDENTICAL_CALLS = 4;
25
32
 
@@ -39,27 +46,8 @@ const MAX_CONSECUTIVE_STRICT = 1;
39
46
  */
40
47
  const PER_TOOL_DEFAULT_CAP = 6;
41
48
  const PER_TOOL_REPEATABLE_CAP = 15;
42
-
43
- /**
44
- * Inherently-repeatable tools: called many times per turn in normal work
45
- * (reading/writing several files, running several commands, searching). These
46
- * get PER_TOOL_REPEATABLE_CAP rather than the default. Keep this list
47
- * conservative — a tool here can be invoked up to PER_TOOL_REPEATABLE_CAP times
48
- * per turn before the guard blocks.
49
- */
50
- const REPEATABLE_TOOLS = new Set([
51
- "read",
52
- "write",
53
- "edit",
54
- "multi_edit",
55
- "bash",
56
- "grep",
57
- "glob",
58
- "search-the-web",
59
- "fetch_page",
60
- "todo_write",
61
- "notebook_edit",
62
- ]);
49
+ const PER_TOOL_CAP_EXEMPT_TOOLS = new Set(["find", "glob", "grep", "ls", "read", "search_and_read"]);
50
+ const STATE_MUTATING_TOOL_SET = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
63
51
 
64
52
  let consecutiveCount = 0;
65
53
  let lastSignature = "";
@@ -68,6 +56,8 @@ let enabled = true;
68
56
 
69
57
  /** Per-tool-name call counts within the current turn (#783 Brief C). */
70
58
  const perToolCounts = new Map<string, number>();
59
+ let mutationEpoch = 0;
60
+ const perToolLastMutationEpoch = new Map<string, number>();
71
61
 
72
62
  /** Hash tool name + args into a compact signature for comparison. */
73
63
  function hashToolCall(toolName: string, args: Record<string, unknown>): string {
@@ -95,7 +85,8 @@ function hashToolCall(toolName: string, args: Record<string, unknown>): string {
95
85
  * 1. Identical-signature streak (MAX_CONSECUTIVE_IDENTICAL_CALLS, strict for
96
86
  * ask_user_questions).
97
87
  * 2. Per-tool-name cap (PER_TOOL_DEFAULT_CAP / PER_TOOL_REPEATABLE_CAP),
98
- * independent of args catches improvisation loops (#783).
88
+ * independent of args, reset after file-mutation progress — catches
89
+ * improvisation loops (#783).
99
90
  */
100
91
  export function checkToolCallLoop(
101
92
  toolName: string,
@@ -124,7 +115,7 @@ export function checkToolCallLoop(
124
115
  reason:
125
116
  `Tool loop detected (identical args): ${toolName} called ${consecutiveCount} times ` +
126
117
  `with identical arguments. Blocking to prevent infinite loop. ` +
127
- `Try a different approach or modify your arguments.`,
118
+ `Do not retry this tool or call other tools this turn — stop and respond to the user in text.`,
128
119
  count: consecutiveCount,
129
120
  };
130
121
  }
@@ -132,9 +123,29 @@ export function checkToolCallLoop(
132
123
  // ── Guard 2: per-tool-name cap, independent of args (#783 Brief C) ──
133
124
  // Catches improvisation loops where the same tool is invoked many times with
134
125
  // varied args (e.g. retrying a missing workflow tool via bash/node -e/CLI).
135
- const perToolCount = (perToolCounts.get(toolName) ?? 0) + 1;
126
+ const priorPerToolCount =
127
+ (perToolLastMutationEpoch.get(toolName) ?? mutationEpoch) < mutationEpoch
128
+ ? 0
129
+ : (perToolCounts.get(toolName) ?? 0);
130
+ const perToolCount = priorPerToolCount + 1;
136
131
  perToolCounts.set(toolName, perToolCount);
137
- const perToolCap = REPEATABLE_TOOLS.has(toolName)
132
+ perToolLastMutationEpoch.set(toolName, mutationEpoch);
133
+
134
+ // Read-only navigation tools are normal context gathering; Guard 1 still
135
+ // catches true reread loops with identical arguments. Browser Automation
136
+ // Contract tools (browser_*) are the same shape: a browser-backed UAT makes
137
+ // many distinct-arg calls (read a message, count edits, inspect a card, …),
138
+ // so the arg-independent per-tool cap misfires on legitimate verification;
139
+ // Guard 1's identical-signature streak still catches a genuinely stuck
140
+ // browser loop.
141
+ if (
142
+ PER_TOOL_CAP_EXEMPT_TOOLS.has(toolName) ||
143
+ hasBrowserContractPrefix(canonicalToolName(toolName))
144
+ ) {
145
+ return { block: false, count: consecutiveCount };
146
+ }
147
+
148
+ const perToolCap = INHERENTLY_REPEATABLE_TOOL_SET.has(toolName)
138
149
  ? PER_TOOL_REPEATABLE_CAP
139
150
  : PER_TOOL_DEFAULT_CAP;
140
151
 
@@ -144,7 +155,8 @@ export function checkToolCallLoop(
144
155
  reason:
145
156
  `Tool loop detected (repeated tool): ${toolName} called ${perToolCount} times ` +
146
157
  `this turn (cap ${perToolCap}). Blocking to prevent infinite loop. ` +
147
- `The tool may be unavailable or failing repeatedly try a different approach.`,
158
+ `The tool may be unavailable or failing repeatedly. ` +
159
+ `Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.`,
148
160
  count: perToolCount,
149
161
  };
150
162
  }
@@ -152,6 +164,13 @@ export function checkToolCallLoop(
152
164
  return { block: false, count: consecutiveCount };
153
165
  }
154
166
 
167
+ /** Record successful mutation progress so Guard 2 can decay on the next count. */
168
+ export function recordToolCallLoopMutation(toolName: string): void {
169
+ if (!enabled) return;
170
+ if (!STATE_MUTATING_TOOL_SET.has(toolName)) return;
171
+ mutationEpoch++;
172
+ }
173
+
155
174
  /** Reset the guard state. Call at agent turn boundaries. */
156
175
  export function resetToolCallLoopGuard(): void {
157
176
  consecutiveCount = 0;
@@ -159,6 +178,8 @@ export function resetToolCallLoopGuard(): void {
159
178
  lastToolName = "";
160
179
  enabled = true;
161
180
  perToolCounts.clear();
181
+ mutationEpoch = 0;
182
+ perToolLastMutationEpoch.clear();
162
183
  }
163
184
 
164
185
  /** Disable the guard (e.g. during shutdown). */
@@ -168,6 +189,8 @@ export function disableToolCallLoopGuard(): void {
168
189
  lastSignature = "";
169
190
  lastToolName = "";
170
191
  perToolCounts.clear();
192
+ mutationEpoch = 0;
193
+ perToolLastMutationEpoch.clear();
171
194
  }
172
195
 
173
196
  /** Get current consecutive count for diagnostics. */
@@ -97,8 +97,19 @@ function createEmptyWriteGateState(): InMemoryWriteGateState {
97
97
 
98
98
  const writeGateStatesByBasePath = new Map<string, InMemoryWriteGateState>();
99
99
 
100
+ /**
101
+ * Write-gate snapshots are project-scoped, not worktree-scoped. When auto-mode
102
+ * routes MCP tool writes to `.gsd-worktrees/<MID>/`, depth verification still
103
+ * lands in the authoritative project `.gsd/runtime/` tree (or external-state
104
+ * symlink target). Without this canonicalization, `loadWriteGateSnapshot(worktree)`
105
+ * sees an empty snapshot and CONTEXT saves loop forever (#M020 gate loop).
106
+ */
107
+ function resolveWriteGateSnapshotRoot(basePath: string): string {
108
+ return resolve(resolveWorktreeProjectRoot(basePath));
109
+ }
110
+
100
111
  function writeGateStateKey(basePath: string): string {
101
- return resolve(basePath);
112
+ return resolveWriteGateSnapshotRoot(basePath);
102
113
  }
103
114
 
104
115
  function getWriteGateState(basePath: string = process.cwd()): InMemoryWriteGateState {
@@ -161,17 +172,18 @@ function shouldPersistWriteGateSnapshot(env: NodeJS.ProcessEnv = process.env): b
161
172
  }
162
173
 
163
174
  function writeGateSnapshotPath(basePath: string): string {
164
- return join(basePath, ".gsd", "runtime", "write-gate-state.json");
175
+ return join(resolveWriteGateSnapshotRoot(basePath), ".gsd", "runtime", "write-gate-state.json");
165
176
  }
166
177
 
167
178
  function ensureWriteGateSnapshotDirectory(basePath: string): void {
168
- const gsdPath = join(basePath, ".gsd");
179
+ const snapshotRoot = resolveWriteGateSnapshotRoot(basePath);
180
+ const gsdPath = join(snapshotRoot, ".gsd");
169
181
  if (!existsSync(gsdPath)) {
170
182
  try {
171
183
  const stat = lstatSync(gsdPath);
172
184
  if (stat.isSymbolicLink()) {
173
185
  const target = readlinkSync(gsdPath);
174
- mkdirSync(isAbsolute(target) ? target : resolve(basePath, target), { recursive: true });
186
+ mkdirSync(isAbsolute(target) ? target : resolve(snapshotRoot, target), { recursive: true });
175
187
  }
176
188
  } catch {
177
189
  // If .gsd truly does not exist, the runtime mkdir below will create it.
@@ -1157,7 +1169,7 @@ function allowsControlledSubagentDispatch(
1157
1169
  policy: ToolsPolicy,
1158
1170
  ): policy is ToolsPolicy & { readonly allowedSubagents: readonly string[] } {
1159
1171
  return (
1160
- (policy.mode === "planning-dispatch" || policy.mode === "verification") &&
1172
+ (policy.mode === "planning-dispatch" || policy.mode === "verification" || policy.mode === "workflow-only") &&
1161
1173
  Array.isArray((policy as { readonly allowedSubagents?: unknown }).allowedSubagents)
1162
1174
  );
1163
1175
  }
@@ -1187,6 +1199,7 @@ function warnMissingControlledDispatchAgentClasses(unitType: string, mode: strin
1187
1199
  const PLANNING_SAFE_TOOLS = new Set([
1188
1200
  "read", "grep", "find", "ls", "glob",
1189
1201
  "ask_user_questions",
1202
+ "memory_query",
1190
1203
  "search-the-web", "resolve_library", "get_library_docs", "fetch_page",
1191
1204
  "search_and_read",
1192
1205
  ]);
@@ -1253,6 +1266,9 @@ type PlanningUnitBlockResult = {
1253
1266
  * → allows Bash for project verification commands, keeps
1254
1267
  * writes restricted to .gsd/, and permits subagent dispatch
1255
1268
  * only when the manifest declares allowedSubagents.
1269
+ * - "workflow-only"
1270
+ * → allows reads, GSD workflow tools, and declared read-only
1271
+ * subagents; blocks generic Bash and direct file writes.
1256
1272
  *
1257
1273
  * `pathOrCommand` is the file path for write/edit-shaped tools and the
1258
1274
  * shell command for bash. Other tools ignore this argument.
@@ -1342,6 +1358,24 @@ export function shouldBlockPlanningUnit(
1342
1358
  return planningBlock(unitType, policy.mode, "subagent dispatch is not permitted in planning units");
1343
1359
  }
1344
1360
 
1361
+ if (policy.mode === "workflow-only") {
1362
+ if (tool === "bash") {
1363
+ return planningBlock(
1364
+ unitType,
1365
+ policy.mode,
1366
+ `bash is not permitted; use the unit's dedicated GSD workflow tools for durable validation output`,
1367
+ );
1368
+ }
1369
+ if (PLANNING_WRITE_TOOLS.has(tool)) {
1370
+ return planningBlock(
1371
+ unitType,
1372
+ policy.mode,
1373
+ `cannot ${tool} "${pathOrCommand}" — direct artifact writes are disabled; call the required GSD workflow tool instead`,
1374
+ );
1375
+ }
1376
+ return planningBlock(unitType, policy.mode, `tool "${tool}" is not on the workflow-only allowlist`);
1377
+ }
1378
+
1345
1379
  if (tool === "bash") {
1346
1380
  if (policy.mode === "verification") {
1347
1381
  if (BASH_VERIFICATION_RE.test(pathOrCommand) || BASH_READ_ONLY_RE.test(pathOrCommand)) return { block: false };
@@ -18,7 +18,7 @@ import {
18
18
  getWorkflowDatabasePath,
19
19
  refreshWorkflowDatabaseFromDisk,
20
20
  } from "./db-workspace.js";
21
- import { isClosedStatus } from "./status-guards.js";
21
+ import { isClosedStatus, isDeferredStatus } from "./status-guards.js";
22
22
  import { closeQualityGatesFromEvidence } from "./quality-gate-closure.js";
23
23
  import { insertMilestoneValidationGates } from "./milestone-validation-gates.js";
24
24
  import { relMilestoneFile, resolveSliceFile } from "./paths.js";
@@ -229,6 +229,7 @@ export function checkCloseoutConsistencyGate(
229
229
  }
230
230
 
231
231
  for (const slice of slices) {
232
+ if (isDeferredStatus(slice.status)) continue;
232
233
  if (!isClosedStatus(slice.status)) {
233
234
  return blocked(
234
235
  "slice-open",