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

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 (505) hide show
  1. package/README.md +10 -10
  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/resources/.managed-resources-content-hash +1 -1
  8. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  9. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  10. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  11. package/dist/resources/extensions/gsd/auto/verification-retry-policy.js +1 -1
  12. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  13. package/dist/resources/extensions/gsd/auto-budget.js +5 -1
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -6
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +1 -1
  16. package/dist/resources/extensions/gsd/auto-prompts.js +8 -24
  17. package/dist/resources/extensions/gsd/auto-recovery.js +9 -517
  18. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  19. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  20. package/dist/resources/extensions/gsd/auto-verification.js +5 -2
  21. package/dist/resources/extensions/gsd/auto.js +19 -10
  22. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +39 -0
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +5 -4
  24. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  26. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +48 -36
  27. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +15 -4
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +3 -1
  29. package/dist/resources/extensions/gsd/commands/handlers/auto.js +1 -1
  30. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  31. package/dist/resources/extensions/gsd/commands-usage.js +1 -1
  32. package/dist/resources/extensions/gsd/db/engine.js +4 -1
  33. package/dist/resources/extensions/gsd/db-memory-fts-schema.js +34 -0
  34. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  35. package/dist/resources/extensions/gsd/delegation-policy.js +1 -1
  36. package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  37. package/dist/resources/extensions/gsd/doctor-engine-checks.js +192 -4
  38. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +3 -0
  39. package/dist/resources/extensions/gsd/exec-sandbox.js +8 -2
  40. package/dist/resources/extensions/gsd/flat-phase-migration.js +45 -0
  41. package/dist/resources/extensions/gsd/git-service.js +57 -0
  42. package/dist/resources/extensions/gsd/gitignore.js +4 -1
  43. package/dist/resources/extensions/gsd/guided-flow-queue.js +20 -13
  44. package/dist/resources/extensions/gsd/json-persistence.js +20 -0
  45. package/dist/resources/extensions/gsd/knowledge-backfill.js +18 -11
  46. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  47. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -7
  48. package/dist/resources/extensions/gsd/memory-backfill.js +28 -21
  49. package/dist/resources/extensions/gsd/metrics.js +4 -4
  50. package/dist/resources/extensions/gsd/migrate-external.js +11 -2
  51. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  52. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  53. package/dist/resources/extensions/gsd/orphan-stash-audit.js +92 -16
  54. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  55. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  56. package/dist/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  57. package/dist/resources/extensions/gsd/root-write-leak-guard.js +7 -1
  58. package/dist/resources/extensions/gsd/safety/destructive-guard.js +8 -1
  59. package/dist/resources/extensions/gsd/safety/evidence-collector.js +16 -1
  60. package/dist/resources/extensions/gsd/safety/file-change-validator.js +5 -2
  61. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  62. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  63. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  64. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  65. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  66. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  67. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +27 -33
  68. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  69. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  70. package/dist/resources/extensions/gsd/state.js +12 -611
  71. package/dist/resources/extensions/gsd/tools/complete-milestone.js +4 -2
  72. package/dist/resources/extensions/gsd/tools/complete-slice.js +3 -34
  73. package/dist/resources/extensions/gsd/tools/complete-task.js +8 -41
  74. package/dist/resources/extensions/gsd/tools/plan-slice.js +59 -44
  75. package/dist/resources/extensions/gsd/tools/plan-task.js +28 -5
  76. package/dist/resources/extensions/gsd/undo.js +43 -6
  77. package/dist/resources/extensions/gsd/unit-registry.js +11 -3
  78. package/dist/resources/extensions/gsd/verification-gate.js +7 -0
  79. package/dist/resources/extensions/gsd/workflow-manifest.js +126 -13
  80. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  81. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  85. package/dist/web/standalone/.next/build-manifest.json +4 -4
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  88. package/dist/web/standalone/.next/required-server-files.json +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  100. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  160. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  166. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  186. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/index.html +1 -1
  196. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  197. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  199. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  201. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/page.js +2 -2
  203. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  205. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  206. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  207. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/middleware.js +3 -3
  210. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  211. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  212. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  213. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  214. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  215. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  216. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  217. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/app/{layout-4ae2d68984392bbf.js → layout-b35cbfff38aaf4cf.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/{main-app-90d1d8d5e5d2dc6b.js → main-app-590a74400e35f685.js} +1 -1
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  226. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  227. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  228. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  229. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +6 -6
  232. package/packages/cloud-mcp-gateway/package.json +2 -2
  233. package/packages/contracts/package.json +1 -1
  234. package/packages/daemon/package.json +4 -4
  235. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  236. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  237. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  238. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  239. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  240. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  241. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  242. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  243. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  244. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  245. package/packages/gsd-agent-core/dist/index.js +2 -0
  246. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  247. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  248. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  249. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  250. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  251. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  252. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  253. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  254. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  255. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  256. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  257. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  258. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  259. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  260. package/packages/gsd-agent-core/package.json +5 -5
  261. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  262. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  263. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  264. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  265. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  266. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  267. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  268. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  269. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  270. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  271. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -841
  272. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  273. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  274. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  275. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  276. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  277. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  278. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  279. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  280. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  281. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  282. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  283. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  284. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  285. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  286. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  287. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  288. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  289. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  290. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  291. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  292. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  293. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  294. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  295. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  296. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  297. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  298. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  299. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  300. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  301. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  302. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  303. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  304. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  305. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  306. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  307. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  308. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  309. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts +2 -0
  310. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  311. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +23 -5
  312. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  313. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  314. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  315. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  316. package/packages/gsd-agent-modes/package.json +7 -7
  317. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  318. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  319. package/packages/mcp-server/package.json +4 -4
  320. package/packages/native/package.json +1 -1
  321. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  322. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  323. package/packages/pi-agent-core/package.json +1 -1
  324. package/packages/pi-ai/dist/models.generated.d.ts +46 -0
  325. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  326. package/packages/pi-ai/dist/models.generated.js +38 -0
  327. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  328. package/packages/pi-ai/package.json +1 -1
  329. package/packages/pi-coding-agent/README.md +3 -2
  330. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  331. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  332. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  333. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  334. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  335. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  336. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  337. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  338. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  339. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  340. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  341. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  342. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  343. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  344. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  345. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  346. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  347. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  349. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  351. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  352. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  353. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  354. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  355. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  356. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  357. package/packages/pi-coding-agent/package.json +7 -7
  358. package/packages/pi-tui/package.json +2 -2
  359. package/packages/rpc-client/package.json +2 -2
  360. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  361. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  362. package/pkg/dist/theme/theme-schema.js +1 -1
  363. package/pkg/dist/theme/theme-schema.js.map +1 -1
  364. package/pkg/dist/theme/theme.d.ts.map +1 -1
  365. package/pkg/dist/theme/theme.js +11 -7
  366. package/pkg/dist/theme/theme.js.map +1 -1
  367. package/pkg/package.json +1 -1
  368. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  369. package/src/resources/extensions/claude-code-cli/tests/index.test.ts +14 -0
  370. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  371. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  372. package/src/resources/extensions/gsd/auto/session.ts +14 -0
  373. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +3 -1
  374. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  375. package/src/resources/extensions/gsd/auto-budget.ts +12 -1
  376. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -7
  377. package/src/resources/extensions/gsd/auto-post-unit.ts +1 -1
  378. package/src/resources/extensions/gsd/auto-prompts.ts +7 -23
  379. package/src/resources/extensions/gsd/auto-recovery.ts +13 -518
  380. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  381. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  382. package/src/resources/extensions/gsd/auto-verification.ts +5 -1
  383. package/src/resources/extensions/gsd/auto.ts +23 -8
  384. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +44 -0
  385. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +5 -4
  386. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  387. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +43 -18
  388. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +49 -1
  389. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +50 -37
  390. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +16 -4
  391. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +2 -1
  392. package/src/resources/extensions/gsd/commands/handlers/auto.ts +1 -1
  393. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  394. package/src/resources/extensions/gsd/commands-usage.ts +1 -1
  395. package/src/resources/extensions/gsd/db/engine.ts +8 -1
  396. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +45 -0
  397. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  398. package/src/resources/extensions/gsd/delegation-policy.ts +1 -1
  399. package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -2
  400. package/src/resources/extensions/gsd/doctor-engine-checks.ts +233 -5
  401. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +3 -0
  402. package/src/resources/extensions/gsd/doctor-types.ts +3 -0
  403. package/src/resources/extensions/gsd/exec-sandbox.ts +7 -2
  404. package/src/resources/extensions/gsd/flat-phase-migration.ts +44 -0
  405. package/src/resources/extensions/gsd/git-service.ts +64 -0
  406. package/src/resources/extensions/gsd/gitignore.ts +4 -1
  407. package/src/resources/extensions/gsd/guided-flow-queue.ts +20 -13
  408. package/src/resources/extensions/gsd/json-persistence.ts +20 -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 +2 -10
  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 +8 -2
  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/orphan-stash-audit.ts +108 -20
  418. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  419. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -2
  420. package/src/resources/extensions/gsd/prompts/plan-slice.md +3 -3
  421. package/src/resources/extensions/gsd/root-write-leak-guard.ts +13 -1
  422. package/src/resources/extensions/gsd/safety/destructive-guard.ts +9 -1
  423. package/src/resources/extensions/gsd/safety/evidence-collector.ts +16 -1
  424. package/src/resources/extensions/gsd/safety/file-change-validator.ts +8 -2
  425. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  426. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  427. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  428. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  429. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  430. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  431. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +36 -30
  432. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  433. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  434. package/src/resources/extensions/gsd/state.ts +32 -732
  435. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +4 -3
  436. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  437. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +14 -5
  438. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +36 -0
  439. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +182 -4
  440. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +35 -0
  441. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +30 -0
  442. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  443. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +28 -0
  444. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +69 -0
  445. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +58 -3
  446. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +51 -0
  447. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +44 -0
  448. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +143 -0
  449. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +239 -2
  450. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +16 -0
  451. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +40 -0
  452. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +37 -2
  453. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +4 -0
  454. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +11 -2
  455. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +47 -0
  456. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +35 -0
  457. package/src/resources/extensions/gsd/tests/memory-store.test.ts +48 -0
  458. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +31 -1
  459. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +6 -0
  460. package/src/resources/extensions/gsd/tests/metrics.test.ts +1 -0
  461. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +57 -0
  462. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  463. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +91 -7
  464. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -1
  465. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +10 -0
  466. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +103 -4
  467. package/src/resources/extensions/gsd/tests/plan-task.test.ts +44 -1
  468. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +4 -2
  469. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  470. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +58 -0
  471. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -6
  472. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +103 -0
  473. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +20 -1
  474. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +15 -3
  475. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  476. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +115 -0
  477. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +140 -0
  478. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +6 -3
  479. package/src/resources/extensions/gsd/tests/undo.test.ts +74 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +38 -0
  481. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +69 -4
  482. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +96 -15
  483. package/src/resources/extensions/gsd/tests/workflow-mcp-preflight.test.ts +1 -0
  484. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +8 -4
  485. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +6 -5
  486. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  487. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  488. package/src/resources/extensions/gsd/tools/complete-slice.ts +3 -30
  489. package/src/resources/extensions/gsd/tools/complete-task.ts +7 -39
  490. package/src/resources/extensions/gsd/tools/plan-slice.ts +60 -47
  491. package/src/resources/extensions/gsd/tools/plan-task.ts +30 -5
  492. package/src/resources/extensions/gsd/undo.ts +47 -6
  493. package/src/resources/extensions/gsd/unit-registry.ts +11 -3
  494. package/src/resources/extensions/gsd/verification-gate.ts +8 -0
  495. package/src/resources/extensions/gsd/workflow-manifest.ts +141 -7
  496. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  497. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  498. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/796.3976108148518f7d.js +0 -10
  500. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +0 -1
  501. package/dist/web/standalone/.next/static/chunks/app/page-6644fc6ee8ca1247.js +0 -1
  502. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +0 -1
  503. package/dist/web/standalone/.next/static/chunks/webpack-7c1d97e39be2da11.js +0 -1
  504. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_buildManifest.js +0 -0
  505. /package/dist/web/standalone/.next/static/{SzEuqWX37DR9MEpEuQjP1 → zQLcXm0Za8lexoXtgDpMG}/_ssgManifest.js +0 -0
@@ -97,8 +97,10 @@ import {
97
97
  getNewBudgetAlertLevel,
98
98
  getBudgetEnforcementAction,
99
99
  getContextPauseAction,
100
+ HARD_CONTEXT_REROOT_THRESHOLD_PERCENT,
100
101
  resolveCompactionThresholdPercent,
101
102
  shouldRerootStepSessionForContext,
103
+ shouldWarnStepSessionForContext,
102
104
  } from "./auto-budget.js";
103
105
  import {
104
106
  markToolStart as _markToolStart,
@@ -701,6 +703,7 @@ export {
701
703
  getContextPauseAction,
702
704
  resolveCompactionThresholdPercent,
703
705
  shouldRerootStepSessionForContext,
706
+ shouldWarnStepSessionForContext,
704
707
  } from "./auto-budget.js";
705
708
 
706
709
  function closeOutSignalInterruptedUnit(currentBasePath: string): void {
@@ -1375,9 +1378,10 @@ export async function rerootCommandSession(
1375
1378
  }
1376
1379
 
1377
1380
  /**
1378
- * After a completed step-mode unit, reclaim context headroom when usage is at
1379
- * or above the compaction threshold. Writes a context-mode snapshot first, then
1380
- * re-roots the visible command session while leaving the NEXT progress surface.
1381
+ * After a completed step-mode unit, warn when usage reaches the configurable
1382
+ * soft context threshold. At the fixed hard boundary, write a context-mode
1383
+ * snapshot and re-root the visible command session while leaving the NEXT
1384
+ * progress surface.
1381
1385
  */
1382
1386
  export async function maybeRerootStepSessionForHighContext(
1383
1387
  ctx: ExtensionContext,
@@ -1392,7 +1396,19 @@ export async function maybeRerootStepSessionForHighContext(
1392
1396
  const prefs = loadEffectiveGSDPreferences(workspaceRoot);
1393
1397
  const compactionThreshold = prefs?.preferences.context_management?.compaction_threshold_percent;
1394
1398
 
1395
- if (!shouldRerootStepSessionForContext(contextPercent, compactionThreshold)) {
1399
+ const shouldWarn = shouldWarnStepSessionForContext(contextPercent, compactionThreshold);
1400
+ const shouldReroot = shouldRerootStepSessionForContext(contextPercent);
1401
+ if (!shouldWarn && !shouldReroot) {
1402
+ return { rerooted: false };
1403
+ }
1404
+
1405
+ const displayPercent = (contextPercent as number).toFixed(1);
1406
+ const thresholdDisplay = resolveCompactionThresholdPercent(compactionThreshold).toFixed(0);
1407
+ if (!shouldReroot) {
1408
+ ctx.ui.notify(
1409
+ `Step complete — context at ${displayPercent}% (soft threshold: ${thresholdDisplay}%). Use /compact when convenient; continuing in this session is still safe.`,
1410
+ "info",
1411
+ );
1396
1412
  return { rerooted: false };
1397
1413
  }
1398
1414
 
@@ -1401,12 +1417,10 @@ export async function maybeRerootStepSessionForHighContext(
1401
1417
  const { writeContextModeCompactionSnapshot } = await import("./context-mode-snapshot.js");
1402
1418
  await writeContextModeCompactionSnapshot(snapshotBase);
1403
1419
 
1404
- const displayPercent = (contextPercent as number).toFixed(1);
1405
- const thresholdDisplay = resolveCompactionThresholdPercent(compactionThreshold).toFixed(0);
1406
1420
  const result = await rerootCommandSession(cmdCtx, workspaceRoot);
1407
1421
  if (result.status === "ok") {
1408
1422
  ctx.ui.notify(
1409
- `Step complete — context at ${displayPercent}% (threshold: ${thresholdDisplay}%). Fresh session ready for /gsd next.`,
1423
+ `Step complete — context at ${displayPercent}% (hard threshold: ${HARD_CONTEXT_REROOT_THRESHOLD_PERCENT}%). Fresh session ready for /gsd next.`,
1410
1424
  "info",
1411
1425
  );
1412
1426
  return { rerooted: true };
@@ -2102,7 +2116,7 @@ export function _selectStopAutoWorktreeExit(args: {
2102
2116
  /**
2103
2117
  * Pause auto-mode without destroying state. Context is preserved.
2104
2118
  * The user can interact with the agent, then `/gsd auto` resumes
2105
- * from disk state. Called when the user presses Escape during auto-mode.
2119
+ * from disk state. Called when the user presses Escape or runs `/gsd pause`.
2106
2120
  */
2107
2121
  export async function pauseAuto(
2108
2122
  ctx?: ExtensionContext,
@@ -2129,6 +2143,7 @@ export async function pauseAuto(
2129
2143
 
2130
2144
  s.active = false;
2131
2145
  s.paused = true;
2146
+ if (options.abortActiveTurn && ctx && !ctx.isIdle()) ctx.abort();
2132
2147
  clearUnitTimeout();
2133
2148
  stopAutoCommandPolling();
2134
2149
 
@@ -0,0 +1,44 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Canonical core session tool surface shared by auto-mode scoping and loop guards.
3
+
4
+ /** Base tools available during auto-mode execution before unit-specific GSD tools are added. */
5
+ export const MINIMAL_AUTO_BASE_TOOL_NAMES = [
6
+ "ask_user_questions",
7
+ "bash",
8
+ "bg_shell",
9
+ "edit",
10
+ "find",
11
+ "glob",
12
+ "grep",
13
+ "fetch_page",
14
+ "search-the-web",
15
+ "ls",
16
+ "read",
17
+ "subagent",
18
+ "write",
19
+ "ToolSearch",
20
+ ] as const;
21
+
22
+ /** Tools excluded from the high per-turn loop-guard cap (strict or orchestration). */
23
+ const NON_REPEATABLE_FROM_MINIMAL_BASE = new Set<string>([
24
+ "ask_user_questions",
25
+ "subagent",
26
+ "ToolSearch",
27
+ ]);
28
+
29
+ /** Additional core tools not in MINIMAL_AUTO_BASE but routinely multi-called per turn. */
30
+ const EXTRA_INHERENTLY_REPEATABLE = [
31
+ "gsd_exec",
32
+ "multi_edit",
33
+ "todo_write",
34
+ "notebook_edit",
35
+ "search_and_read",
36
+ ] as const;
37
+
38
+ /** Core session tools that may be invoked many times per agent turn. */
39
+ export const INHERENTLY_REPEATABLE_TOOL_NAMES = [
40
+ ...MINIMAL_AUTO_BASE_TOOL_NAMES.filter((name) => !NON_REPEATABLE_FROM_MINIMAL_BASE.has(name)),
41
+ ...EXTRA_INHERENTLY_REPEATABLE,
42
+ ] as const;
43
+
44
+ export const INHERENTLY_REPEATABLE_TOOL_SET = new Set<string>(INHERENTLY_REPEATABLE_TOOL_NAMES);
@@ -690,8 +690,9 @@ export function registerDbTools(pi: ExtensionAPI): void {
690
690
  promptSnippet: "Plan a slice via DB write + PLAN render + cache invalidation",
691
691
  promptGuidelines: [
692
692
  "Use gsd_plan_slice for slice planning instead of writing S##-PLAN.md or task PLAN files directly.",
693
- "Keep parameters flat and provide the full slice planning payload, including tasks.",
694
- "The tool validates input, requires an existing parent slice, writes slice/task planning data, renders PLAN.md and task plan files from DB, and clears both state and parse caches after success.",
693
+ "For incremental planning, call gsd_plan_slice with slice metadata only, then call gsd_plan_task once per task.",
694
+ "When tasks is omitted or empty, the tool writes only slice planning metadata and preserves existing tasks.",
695
+ "When tasks is non-empty, the tool validates input, requires an existing parent slice, writes slice/task planning data, renders PLAN.md and task plan files from DB, and clears both state and parse caches after success.",
695
696
  "Use the canonical name gsd_plan_slice; gsd_slice_plan is only an alias.",
696
697
  ],
697
698
  parameters: Type.Object({
@@ -699,7 +700,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
699
700
  milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
700
701
  sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
701
702
  goal: Type.String({ description: "Slice goal" }),
702
- tasks: Type.Array(Type.Object({
703
+ tasks: Type.Optional(Type.Array(Type.Object({
703
704
  taskId: Type.String({ description: "Task ID (e.g. T01)" }),
704
705
  title: Type.String({ description: "Task title" }),
705
706
  description: Type.String({ description: "Task description / steps block" }),
@@ -709,7 +710,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
709
710
  inputs: Type.Array(Type.String(), { description: "Array<string> of input files or references; pass [\"path\"] or [], never a single string" }),
710
711
  expectedOutput: Type.Array(Type.String(), { description: "Array<string> of files this task creates or overwrites; pass [\"path\"] or [], never prose or a single string" }),
711
712
  observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
712
- }), { description: "Planned tasks for the slice" }),
713
+ }), { description: "Optional full task replacement for the slice. Omit for incremental planning, then call gsd_plan_task once per task." })),
713
714
  // ── Enrichment metadata (optional — defaults to empty) ────────────
714
715
  successCriteria: Type.Optional(Type.String({ description: "Slice success criteria block" })),
715
716
  proofLevel: Type.Optional(Type.String({ description: "Slice proof level" })),
@@ -18,6 +18,7 @@ import { registerShortcuts } from "./register-shortcuts.js";
18
18
  import { writeCrashLog } from "./crash-log.js";
19
19
  import { logWarning, isGsdExtensionStderrEnabled } from "../workflow-logger.js";
20
20
  import { UNIT_TOOL_CONTRACTS } from "../unit-tool-contracts.js";
21
+ import { installManifestFlushOnProcessTeardown } from "../workflow-manifest.js";
21
22
  // Static import so cmux event listeners are registered synchronously during
22
23
  // extension bootstrap. Prior implementation used `void import().then()` which
23
24
  // queued listener registration as a microtask — any CMUX_CHANNELS emit fired
@@ -196,6 +197,7 @@ export function registerGsdExtension(pi: ExtensionAPI): void {
196
197
  });
197
198
 
198
199
  installEpipeGuard();
200
+ installManifestFlushOnProcessTeardown();
199
201
 
200
202
  // Ecosystem handlers captured by the GSDExtensionAPI wrapper for the
201
203
  // GSD-owned `before_agent_start` dispatch step (#3338).
@@ -34,7 +34,8 @@ import {
34
34
  } from "../auto-runtime-state.js";
35
35
  import { applyProviderPayloadPolicy } from "../provider-payload-policy.js";
36
36
 
37
- import { checkToolCallLoop, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
37
+ import { checkToolCallLoop, recordToolCallLoopMutation, resetToolCallLoopGuard } from "./tool-call-loop-guard.js";
38
+ import { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
38
39
  import { maybePauseAutoForApprovalGate, resetPendingGatePauseGuard } from "./pending-gate-pause.js";
39
40
  import { saveActivityLog } from "../activity-log.js";
40
41
  import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult, saveEvidenceToDisk } from "../safety/evidence-collector.js";
@@ -75,6 +76,7 @@ import { supportsSourceObservationsForUnit } from "../source-observations.js";
75
76
  import { clearPendingAutoStart } from "../pending-auto-start.js";
76
77
  import { resolveWorkflowToolBasePath } from "./dynamic-tools.js";
77
78
  import { getRequiredWorkflowToolsForUnit } from "../unit-tool-contracts.js";
79
+ import { flushAllManifests } from "../workflow-manifest.js";
78
80
 
79
81
  let approvalQuestionAbortInFlight = false;
80
82
 
@@ -178,22 +180,7 @@ export const MINIMAL_GSD_TOOL_NAMES = [
178
180
  "gsd_capture_thought",
179
181
  ] as const;
180
182
 
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;
183
+ export { MINIMAL_AUTO_BASE_TOOL_NAMES } from "./core-session-tools.js";
197
184
 
198
185
  function withPreservedShimTools(toolNames: readonly string[]): string[] {
199
186
  return [...new Set([...toolNames, ...ALWAYS_PRESERVED_SHIM_TOOL_NAMES])];
@@ -597,6 +584,21 @@ function contextBasePath(ctx?: { cwd?: string }): string {
597
584
  return typeof ctx?.cwd === "string" ? ctx.cwd : process.cwd();
598
585
  }
599
586
 
587
+ const LOOP_GUARD_INTERACTIVE_INSTRUCTIONS = [
588
+ "Do not retry this tool or call other tools this turn — stop and respond to the user in text.",
589
+ "Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.",
590
+ ];
591
+ const LOOP_GUARD_AUTO_INSTRUCTION =
592
+ "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.";
593
+
594
+ function formatLoopGuardBlockReason(reason: string | undefined): string | undefined {
595
+ if (!reason || !getAutoRuntimeSnapshot().active) return reason;
596
+ return LOOP_GUARD_INTERACTIVE_INSTRUCTIONS.reduce(
597
+ (formatted, instruction) => formatted.replace(instruction, LOOP_GUARD_AUTO_INSTRUCTION),
598
+ reason,
599
+ );
600
+ }
601
+
600
602
  function beginSourceObservationStoreForCurrentUnit(
601
603
  ctx?: { cwd?: string },
602
604
  ): ReturnType<typeof getSourceObservationStore> | null {
@@ -920,6 +922,15 @@ export function registerHooks(
920
922
  }
921
923
  }
922
924
  }
925
+ const projectRoot = resolveWorktreeProjectRoot(basePath);
926
+ const { pruneStaleFlatPhaseBackups } = await import("../flat-phase-migration.js");
927
+ const pruned = pruneStaleFlatPhaseBackups(projectRoot);
928
+ if (pruned > 0) {
929
+ safetyLogWarning(
930
+ "bootstrap",
931
+ `pruned ${pruned} stale flat-phase migration backup(s) from .gsd-backups/ (retention exceeded)`,
932
+ );
933
+ }
923
934
  } catch (err) {
924
935
  safetyLogWarning("bootstrap", `flat-phase migration: ${err instanceof Error ? err.message : String(err)}`);
925
936
  }
@@ -1085,6 +1096,19 @@ export function registerHooks(
1085
1096
  const { handleAgentEnd } = await import("./agent-end-recovery.js");
1086
1097
  const agentEndBasePath = contextBasePath(ctx);
1087
1098
  try {
1099
+ // The manifest is a non-critical projection (the append-only event log is
1100
+ // the authoritative recovery source), so a flush failure must not skip
1101
+ // agent_end recovery. drainManifestWrites still propagates write failures
1102
+ // to explicit flush callers; here we deliberately log and continue so
1103
+ // handleAgentEnd (and the finally below) always run.
1104
+ try {
1105
+ await flushAllManifests();
1106
+ } catch (err) {
1107
+ safetyLogWarning(
1108
+ "manifest",
1109
+ `flushAllManifests on agent_end failed: ${err instanceof Error ? err.message : String(err)}`,
1110
+ );
1111
+ }
1088
1112
  await handleAgentEnd(pi, event, ctx);
1089
1113
  } finally {
1090
1114
  activateDeferredApprovalGate(agentEndBasePath);
@@ -1291,7 +1315,7 @@ export function registerHooks(
1291
1315
  // ── Loop guard: block repeated identical tool calls ──
1292
1316
  const loopCheck = checkToolCallLoop(toolName, event.input as Record<string, unknown>);
1293
1317
  if (loopCheck.block) {
1294
- return { block: true, reason: loopCheck.reason };
1318
+ return { block: true, reason: formatLoopGuardBlockReason(loopCheck.reason) };
1295
1319
  }
1296
1320
 
1297
1321
  const deferredGateGuard = shouldBlockDeferredApprovalTool(
@@ -1563,6 +1587,7 @@ export function registerHooks(
1563
1587
  }
1564
1588
  }
1565
1589
  if (!event.isError) {
1590
+ recordToolCallLoopMutation(toolName);
1566
1591
  refreshSourceObservationAfterMutation(toolName, event.input, ctx);
1567
1592
  clearSourceObservationsAfterShell(toolName);
1568
1593
  }
@@ -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,30 @@
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";
23
28
 
24
29
  const MAX_CONSECUTIVE_IDENTICAL_CALLS = 4;
25
30
 
@@ -39,27 +44,8 @@ const MAX_CONSECUTIVE_STRICT = 1;
39
44
  */
40
45
  const PER_TOOL_DEFAULT_CAP = 6;
41
46
  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
- ]);
47
+ const PER_TOOL_CAP_EXEMPT_TOOLS = new Set(["find", "glob", "grep", "ls", "read", "search_and_read"]);
48
+ const STATE_MUTATING_TOOL_SET = new Set(["edit", "write", "multi_edit", "notebook_edit"]);
63
49
 
64
50
  let consecutiveCount = 0;
65
51
  let lastSignature = "";
@@ -68,6 +54,8 @@ let enabled = true;
68
54
 
69
55
  /** Per-tool-name call counts within the current turn (#783 Brief C). */
70
56
  const perToolCounts = new Map<string, number>();
57
+ let mutationEpoch = 0;
58
+ const perToolLastMutationEpoch = new Map<string, number>();
71
59
 
72
60
  /** Hash tool name + args into a compact signature for comparison. */
73
61
  function hashToolCall(toolName: string, args: Record<string, unknown>): string {
@@ -95,7 +83,8 @@ function hashToolCall(toolName: string, args: Record<string, unknown>): string {
95
83
  * 1. Identical-signature streak (MAX_CONSECUTIVE_IDENTICAL_CALLS, strict for
96
84
  * ask_user_questions).
97
85
  * 2. Per-tool-name cap (PER_TOOL_DEFAULT_CAP / PER_TOOL_REPEATABLE_CAP),
98
- * independent of args catches improvisation loops (#783).
86
+ * independent of args, reset after file-mutation progress — catches
87
+ * improvisation loops (#783).
99
88
  */
100
89
  export function checkToolCallLoop(
101
90
  toolName: string,
@@ -124,7 +113,7 @@ export function checkToolCallLoop(
124
113
  reason:
125
114
  `Tool loop detected (identical args): ${toolName} called ${consecutiveCount} times ` +
126
115
  `with identical arguments. Blocking to prevent infinite loop. ` +
127
- `Try a different approach or modify your arguments.`,
116
+ `Do not retry this tool or call other tools this turn — stop and respond to the user in text.`,
128
117
  count: consecutiveCount,
129
118
  };
130
119
  }
@@ -132,9 +121,21 @@ export function checkToolCallLoop(
132
121
  // ── Guard 2: per-tool-name cap, independent of args (#783 Brief C) ──
133
122
  // Catches improvisation loops where the same tool is invoked many times with
134
123
  // varied args (e.g. retrying a missing workflow tool via bash/node -e/CLI).
135
- const perToolCount = (perToolCounts.get(toolName) ?? 0) + 1;
124
+ const priorPerToolCount =
125
+ (perToolLastMutationEpoch.get(toolName) ?? mutationEpoch) < mutationEpoch
126
+ ? 0
127
+ : (perToolCounts.get(toolName) ?? 0);
128
+ const perToolCount = priorPerToolCount + 1;
136
129
  perToolCounts.set(toolName, perToolCount);
137
- const perToolCap = REPEATABLE_TOOLS.has(toolName)
130
+ perToolLastMutationEpoch.set(toolName, mutationEpoch);
131
+
132
+ // Read-only navigation tools are normal context gathering; Guard 1 still
133
+ // catches true reread loops with identical arguments.
134
+ if (PER_TOOL_CAP_EXEMPT_TOOLS.has(toolName)) {
135
+ return { block: false, count: consecutiveCount };
136
+ }
137
+
138
+ const perToolCap = INHERENTLY_REPEATABLE_TOOL_SET.has(toolName)
138
139
  ? PER_TOOL_REPEATABLE_CAP
139
140
  : PER_TOOL_DEFAULT_CAP;
140
141
 
@@ -144,7 +145,8 @@ export function checkToolCallLoop(
144
145
  reason:
145
146
  `Tool loop detected (repeated tool): ${toolName} called ${perToolCount} times ` +
146
147
  `this turn (cap ${perToolCap}). Blocking to prevent infinite loop. ` +
147
- `The tool may be unavailable or failing repeatedly try a different approach.`,
148
+ `The tool may be unavailable or failing repeatedly. ` +
149
+ `Do not retry this tool or pivot to other tools this turn — stop and respond to the user in text.`,
148
150
  count: perToolCount,
149
151
  };
150
152
  }
@@ -152,6 +154,13 @@ export function checkToolCallLoop(
152
154
  return { block: false, count: consecutiveCount };
153
155
  }
154
156
 
157
+ /** Record successful mutation progress so Guard 2 can decay on the next count. */
158
+ export function recordToolCallLoopMutation(toolName: string): void {
159
+ if (!enabled) return;
160
+ if (!STATE_MUTATING_TOOL_SET.has(toolName)) return;
161
+ mutationEpoch++;
162
+ }
163
+
155
164
  /** Reset the guard state. Call at agent turn boundaries. */
156
165
  export function resetToolCallLoopGuard(): void {
157
166
  consecutiveCount = 0;
@@ -159,6 +168,8 @@ export function resetToolCallLoopGuard(): void {
159
168
  lastToolName = "";
160
169
  enabled = true;
161
170
  perToolCounts.clear();
171
+ mutationEpoch = 0;
172
+ perToolLastMutationEpoch.clear();
162
173
  }
163
174
 
164
175
  /** Disable the guard (e.g. during shutdown). */
@@ -168,6 +179,8 @@ export function disableToolCallLoopGuard(): void {
168
179
  lastSignature = "";
169
180
  lastToolName = "";
170
181
  perToolCounts.clear();
182
+ mutationEpoch = 0;
183
+ perToolLastMutationEpoch.clear();
171
184
  }
172
185
 
173
186
  /** 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.
@@ -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",
@@ -200,7 +200,7 @@ export async function handleAutoCommand(trimmed: string, ctx: ExtensionCommandCo
200
200
  }
201
201
  return true;
202
202
  }
203
- await pauseAuto(ctx, pi);
203
+ await pauseAuto(ctx, pi, undefined, { abortActiveTurn: true });
204
204
  return true;
205
205
  }
206
206
 
@@ -1228,7 +1228,7 @@ async function configureContextCodebase(ctx: ExtensionCommandContext, prefs: Rec
1228
1228
  const maskTurns = await promptInteger(ctx, "Observation mask turns (1–50)", cm.observation_mask_turns, "8");
1229
1229
  if (maskTurns !== undefined && maskTurns !== "clear") cm.observation_mask_turns = maskTurns;
1230
1230
  else if (maskTurns === "clear") delete cm.observation_mask_turns;
1231
- const thresh = await promptNumber(ctx, "Compaction threshold percent (0.5–0.95)", cm.compaction_threshold_percent, "0.60");
1231
+ const thresh = await promptNumber(ctx, "Soft context warning threshold percent (0.5–0.95)", cm.compaction_threshold_percent, "0.60");
1232
1232
  if (thresh !== undefined && thresh !== "clear") cm.compaction_threshold_percent = thresh;
1233
1233
  else if (thresh === "clear") delete cm.compaction_threshold_percent;
1234
1234
  const toolMax = await promptInteger(ctx, "Tool result max chars (200–10000)", cm.tool_result_max_chars, "800");
@@ -112,7 +112,7 @@ function formatThresholdLines(): string[] {
112
112
 
113
113
  const compactionThreshold = prefs?.context_management?.compaction_threshold_percent;
114
114
  if (typeof compactionThreshold === "number") {
115
- lines.push(`Compaction: ${Math.round(compactionThreshold * 100)}%`);
115
+ lines.push(`Soft context warning: ${Math.round(compactionThreshold * 100)}%`);
116
116
  }
117
117
 
118
118
  return lines;
@@ -47,7 +47,11 @@ import {
47
47
  applyMigrationV28MemoryLastHitAt,
48
48
  applyMigrationV29RepositoryTargets,
49
49
  } from "../db-migration-steps.js";
50
- import { isMemoriesFtsAvailableSchema, tryCreateMemoriesFtsSchema } from "../db-memory-fts-schema.js";
50
+ import {
51
+ isMemoriesFtsAvailableSchema,
52
+ rebuildMemoriesFtsSchemaOnce,
53
+ tryCreateMemoriesFtsSchema,
54
+ } from "../db-memory-fts-schema.js";
51
55
  import { createDbOpenState, type DbOpenPhase } from "../db-open-state.js";
52
56
  import { createRuntimeKvTableV25 } from "../db-runtime-kv-schema.js";
53
57
  import { getCurrentSchemaVersion, recordSchemaVersion } from "../db-schema-metadata.js";
@@ -134,6 +138,9 @@ function initSchema(db: DbAdapter, fileBacked: boolean, dbPath: string | null):
134
138
  }
135
139
 
136
140
  migrateSchema(db, dbPath);
141
+ rebuildMemoriesFtsSchemaOnce(db, {
142
+ onRebuildFailed: (message) => logWarning("db", message),
143
+ });
137
144
  }
138
145
 
139
146
  export function _isLikelyWslDrvFsPathForTest(dbPath: string | null): boolean {