@opengsd/gsd-pi 1.2.0-dev.4c756166 → 1.2.0-dev.5457a158

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 (338) hide show
  1. package/dist/cli-style.d.ts +17 -0
  2. package/dist/cli-style.js +28 -0
  3. package/dist/cli.js +1 -1
  4. package/dist/headless-events.d.ts +4 -2
  5. package/dist/headless-events.js +7 -29
  6. package/dist/models-resolver.d.ts +3 -13
  7. package/dist/models-resolver.js +3 -22
  8. package/dist/resource-loader.js +2 -14
  9. package/dist/resources/.managed-resources-content-hash +1 -1
  10. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  11. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  12. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +35 -4
  13. package/dist/resources/extensions/gsd/auto/orchestrator.js +33 -4
  14. package/dist/resources/extensions/gsd/auto/phases.js +6 -1
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +19 -8
  16. package/dist/resources/extensions/gsd/auto-prompts.js +3 -0
  17. package/dist/resources/extensions/gsd/auto-start.js +12 -14
  18. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  19. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
  20. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  21. package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
  22. package/dist/resources/extensions/gsd/auto.js +8 -20
  23. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  24. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -6
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +86 -6
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +30 -4
  27. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  28. package/dist/resources/extensions/gsd/captures.js +5 -15
  29. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  30. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  31. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  32. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  33. package/dist/resources/extensions/gsd/db/queries.js +372 -0
  34. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  35. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  36. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  37. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  38. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  39. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  40. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  41. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  42. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
  43. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  44. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  45. package/dist/resources/extensions/gsd/git-service.js +1 -0
  46. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  47. package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
  48. package/dist/resources/extensions/gsd/guidance.js +98 -0
  49. package/dist/resources/extensions/gsd/guided-flow.js +51 -5
  50. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  51. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  52. package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  54. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  55. package/dist/resources/extensions/gsd/model-router.js +3 -0
  56. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  57. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  58. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  59. package/dist/resources/extensions/gsd/paths.js +37 -24
  60. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  61. package/dist/resources/extensions/gsd/preferences-models.js +12 -46
  62. package/dist/resources/extensions/gsd/preferences.js +14 -0
  63. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  64. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  66. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  67. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  68. package/dist/resources/extensions/gsd/publication.js +87 -0
  69. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  70. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  71. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  72. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  73. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  74. package/dist/resources/extensions/gsd/state.js +1 -20
  75. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  76. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  77. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  78. package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
  79. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -8
  80. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  81. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
  82. package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
  83. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  84. package/dist/resources/extensions/gsd/undo.js +8 -7
  85. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  86. package/dist/resources/extensions/gsd/unit-context-composer.js +9 -1
  87. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  88. package/dist/resources/extensions/gsd/unit-registry.js +350 -0
  89. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  90. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  91. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  92. package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
  93. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  94. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  95. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  96. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  97. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  98. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  99. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  100. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  101. package/dist/web/standalone/.next/BUILD_ID +1 -1
  102. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  103. package/dist/web/standalone/.next/build-manifest.json +2 -2
  104. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  105. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  125. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  126. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  130. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  132. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  134. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  136. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/index.html +1 -1
  156. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  158. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  163. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  164. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  165. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  166. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  168. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  169. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  170. package/dist/worktree-cli.js +3 -6
  171. package/dist/worktree-status-banner.js +7 -11
  172. package/package.json +1 -1
  173. package/packages/cloud-mcp-gateway/package.json +2 -2
  174. package/packages/contracts/dist/workflow.d.ts +4 -0
  175. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  176. package/packages/contracts/dist/workflow.js.map +1 -1
  177. package/packages/contracts/package.json +1 -1
  178. package/packages/daemon/package.json +4 -4
  179. package/packages/gsd-agent-core/package.json +5 -5
  180. package/packages/gsd-agent-modes/package.json +7 -7
  181. package/packages/mcp-server/dist/cli.js +6 -3
  182. package/packages/mcp-server/dist/cli.js.map +1 -1
  183. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  184. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  185. package/packages/mcp-server/dist/workflow-tools.js +46 -21
  186. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  187. package/packages/mcp-server/package.json +3 -3
  188. package/packages/native/package.json +1 -1
  189. package/packages/pi-agent-core/package.json +1 -1
  190. package/packages/pi-ai/dist/models.generated.d.ts +294 -239
  191. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  192. package/packages/pi-ai/dist/models.generated.js +260 -256
  193. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  194. package/packages/pi-ai/package.json +1 -1
  195. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  197. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  198. package/packages/pi-coding-agent/package.json +7 -7
  199. package/packages/pi-tui/package.json +2 -2
  200. package/packages/rpc-client/package.json +2 -2
  201. package/pkg/package.json +1 -1
  202. package/src/resources/extensions/bg-shell/utilities.ts +5 -2
  203. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  204. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +37 -2
  205. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  206. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  207. package/src/resources/extensions/gsd/auto/orchestrator.ts +39 -5
  208. package/src/resources/extensions/gsd/auto/phases.ts +10 -1
  209. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -7
  210. package/src/resources/extensions/gsd/auto-prompts.ts +3 -0
  211. package/src/resources/extensions/gsd/auto-start.ts +12 -15
  212. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  213. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
  214. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  215. package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
  216. package/src/resources/extensions/gsd/auto.ts +20 -24
  217. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  218. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -6
  219. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +87 -6
  220. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +29 -3
  221. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  222. package/src/resources/extensions/gsd/captures.ts +5 -16
  223. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  224. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  225. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  226. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  227. package/src/resources/extensions/gsd/db/queries.ts +453 -0
  228. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  229. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  230. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  231. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  232. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  233. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  234. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  235. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  236. package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
  237. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  238. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  239. package/src/resources/extensions/gsd/git-service.ts +1 -0
  240. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  241. package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
  242. package/src/resources/extensions/gsd/guidance.ts +139 -0
  243. package/src/resources/extensions/gsd/guided-flow.ts +50 -5
  244. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  245. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  246. package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
  247. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  248. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  249. package/src/resources/extensions/gsd/model-router.ts +3 -0
  250. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  251. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  252. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  253. package/src/resources/extensions/gsd/paths.ts +42 -22
  254. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  255. package/src/resources/extensions/gsd/preferences-models.ts +10 -46
  256. package/src/resources/extensions/gsd/preferences.ts +18 -0
  257. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  258. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  259. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  260. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  261. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  262. package/src/resources/extensions/gsd/publication.ts +122 -0
  263. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  264. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  265. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  266. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  267. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  268. package/src/resources/extensions/gsd/state.ts +4 -21
  269. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  270. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  271. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  272. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  273. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  274. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  275. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  276. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  277. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  278. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  279. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  280. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  281. package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
  282. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +51 -4
  283. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +54 -1
  284. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  285. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  286. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  287. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  288. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  289. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  290. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  291. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
  292. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  293. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  294. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  295. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  296. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  297. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  298. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  299. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  300. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  301. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  302. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +23 -2
  303. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  304. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  305. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  306. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  307. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  308. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  309. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  310. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  311. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  312. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  313. package/src/resources/extensions/gsd/tests/write-gate.test.ts +42 -0
  314. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  315. package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
  316. package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -8
  317. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  318. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
  319. package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
  320. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  321. package/src/resources/extensions/gsd/undo.ts +9 -8
  322. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  323. package/src/resources/extensions/gsd/unit-context-composer.ts +12 -1
  324. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  325. package/src/resources/extensions/gsd/unit-registry.ts +425 -0
  326. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  327. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  328. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  329. package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
  330. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  331. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  332. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  333. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  334. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  335. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  336. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  337. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → 2p9Rv9pQflAxCBbGVI2vb}/_buildManifest.js +0 -0
  338. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → 2p9Rv9pQflAxCBbGVI2vb}/_ssgManifest.js +0 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Terminal presentation helpers for CLI-side notices on stderr — warnings,
3
+ * hints, and names. Pairs with the extension-side glyph set in
4
+ * resources/extensions/shared/ui.ts. Adopt incrementally: banner-shaped CLI
5
+ * surfaces (worktree banners today; update checks et al. as they're touched)
6
+ * should render through these instead of ad-hoc chalk.
7
+ */
8
+ /** Dim "[gsd] " line tag that prefixes CLI banner lines. */
9
+ export declare function gsdTag(): string;
10
+ /** A yellow warning fragment. */
11
+ export declare function warn(text: string): string;
12
+ /** A dim "what to do next" hint fragment. */
13
+ export declare function hint(text: string): string;
14
+ /** A cyan user-supplied name (worktree, branch, file). */
15
+ export declare function name(text: string): string;
16
+ /** One banner line: tagged warning followed by a tagged hint line. */
17
+ export declare function bannerLines(warning: string, hintText: string): string;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Terminal presentation helpers for CLI-side notices on stderr — warnings,
3
+ * hints, and names. Pairs with the extension-side glyph set in
4
+ * resources/extensions/shared/ui.ts. Adopt incrementally: banner-shaped CLI
5
+ * surfaces (worktree banners today; update checks et al. as they're touched)
6
+ * should render through these instead of ad-hoc chalk.
7
+ */
8
+ import chalk from 'chalk';
9
+ /** Dim "[gsd] " line tag that prefixes CLI banner lines. */
10
+ export function gsdTag() {
11
+ return chalk.dim('[gsd] ');
12
+ }
13
+ /** A yellow warning fragment. */
14
+ export function warn(text) {
15
+ return chalk.yellow(text);
16
+ }
17
+ /** A dim "what to do next" hint fragment. */
18
+ export function hint(text) {
19
+ return chalk.dim(text);
20
+ }
21
+ /** A cyan user-supplied name (worktree, branch, file). */
22
+ export function name(text) {
23
+ return chalk.cyan(text);
24
+ }
25
+ /** One banner line: tagged warning followed by a tagged hint line. */
26
+ export function bannerLines(warning, hintText) {
27
+ return gsdTag() + warning + '\n' + gsdTag() + hint(hintText) + '\n\n';
28
+ }
package/dist/cli.js CHANGED
@@ -524,7 +524,7 @@ const authStorage = AuthStorage.create(authFilePath);
524
524
  markStartup('AuthStorage.create');
525
525
  loadStoredEnvKeys(authStorage);
526
526
  migratePiCredentials(authStorage);
527
- // Resolve models.json path with fallback to ~/.pi/agent/models.json
527
+ // Resolve models.json path
528
528
  const { resolveModelsJsonPath } = await import('./models-resolver.js');
529
529
  const modelsJsonPath = resolveModelsJsonPath();
530
530
  const modelRegistry = ModelRegistry.create(authStorage, modelsJsonPath);
@@ -5,6 +5,10 @@
5
5
  * and classifies commands as quick (single-turn) vs long-running.
6
6
  *
7
7
  * Also defines exit code constants and the status→exit-code mapping function.
8
+ *
9
+ * The stop/pause notice vocabulary itself (prefixes + message classifiers)
10
+ * lives in the Stop Notice module — the same module the emitters format with,
11
+ * so wording stays in lockstep with detection.
8
12
  */
9
13
  export declare const EXIT_SUCCESS = 0;
10
14
  export declare const EXIT_ERROR = 1;
@@ -42,8 +46,6 @@ export declare function mapStatusToExitCode(status: string): number;
42
46
  *
43
47
  * Blocked detection is separate — checked via isBlockedNotification.
44
48
  */
45
- export declare const PAUSED_PREFIXES: string[];
46
- export declare const TERMINAL_PREFIXES: string[];
47
49
  export declare const IDLE_TIMEOUT_MS = 15000;
48
50
  export declare const NEW_MILESTONE_IDLE_TIMEOUT_MS = 120000;
49
51
  export declare function canonicalHeadlessToolName(toolName: string | undefined): string;
@@ -5,7 +5,12 @@
5
5
  * and classifies commands as quick (single-turn) vs long-running.
6
6
  *
7
7
  * Also defines exit code constants and the status→exit-code mapping function.
8
+ *
9
+ * The stop/pause notice vocabulary itself (prefixes + message classifiers)
10
+ * lives in the Stop Notice module — the same module the emitters format with,
11
+ * so wording stays in lockstep with detection.
8
12
  */
13
+ import { isBlockedNoticeMessage, isManualResolutionNotice, isPauseNotice, isTerminalNotice, } from './resources/extensions/gsd/stop-notice.js';
9
14
  // ---------------------------------------------------------------------------
10
15
  // Exit Code Constants
11
16
  // ---------------------------------------------------------------------------
@@ -65,14 +70,6 @@ export function mapStatusToExitCode(status) {
65
70
  *
66
71
  * Blocked detection is separate — checked via isBlockedNotification.
67
72
  */
68
- export const PAUSED_PREFIXES = ['auto-mode paused', 'step-mode paused'];
69
- export const TERMINAL_PREFIXES = [
70
- 'auto-mode stopped',
71
- 'step-mode stopped',
72
- 'auto-mode complete',
73
- 'no active milestone',
74
- 'auto-mode idle',
75
- ];
76
73
  export const IDLE_TIMEOUT_MS = 15_000;
77
74
  // new-milestone is a long-running creative task where the LLM may pause
78
75
  // between tool calls (e.g. after mkdir, before writing files). Use a
@@ -86,20 +83,6 @@ export function canonicalHeadlessToolName(toolName) {
86
83
  const toolSeparator = name.indexOf('__', 'mcp__'.length);
87
84
  return toolSeparator >= 0 ? name.slice(toolSeparator + 2) : name;
88
85
  }
89
- function isManualResolutionNotification(message) {
90
- return (message.includes('resolve manually and re-run /gsd auto') ||
91
- message.includes('resolve conflicts manually and run /gsd auto to resume') ||
92
- message.includes('resolve and run /gsd auto to resume'));
93
- }
94
- function isNonBlockingPauseNotification(message) {
95
- return message.includes('idempotent advance: unit already active');
96
- }
97
- function isPauseNotification(message) {
98
- return PAUSED_PREFIXES.some((prefix) => message.startsWith(prefix));
99
- }
100
- function isPauseNotificationRequiringIntervention(message) {
101
- return isPauseNotification(message) && !isNonBlockingPauseNotification(message);
102
- }
103
86
  function getCommandBlockContent(event) {
104
87
  if (event.type !== 'message_start' && event.type !== 'message_end')
105
88
  return null;
@@ -122,20 +105,15 @@ export function isTerminalNotification(event) {
122
105
  if (event.type !== 'extension_ui_request' || event.method !== 'notify')
123
106
  return false;
124
107
  const message = String(event.message ?? '').toLowerCase();
125
- return (TERMINAL_PREFIXES.some((prefix) => message.startsWith(prefix)) ||
126
- isPauseNotification(message) ||
127
- isManualResolutionNotification(message));
108
+ return isTerminalNotice(message) || isPauseNotice(message) || isManualResolutionNotice(message);
128
109
  }
129
110
  export function isBlockedNotification(event) {
130
111
  if (isBlockingCommandBlock(event))
131
112
  return true;
132
113
  if (event.type !== 'extension_ui_request' || event.method !== 'notify')
133
114
  return false;
134
- const message = String(event.message ?? '').toLowerCase();
135
115
  // Recoverable pauses need operator intervention in headless mode.
136
- return (message.includes('blocked:') ||
137
- isPauseNotificationRequiringIntervention(message) ||
138
- isManualResolutionNotification(message));
116
+ return isBlockedNoticeMessage(String(event.message ?? '').toLowerCase());
139
117
  }
140
118
  export function isMilestoneReadyNotification(event) {
141
119
  if (event.type !== 'extension_ui_request' || event.method !== 'notify')
@@ -1,20 +1,10 @@
1
1
  /**
2
- * Models.json resolution with fallback to ~/.pi/agent/models.json
2
+ * Models.json resolution for GSD.
3
3
  *
4
- * GSD uses ~/.gsd/agent/models.json, but for a smooth migration/development
5
- * experience, this module provides resolution logic that:
6
- *
7
- * 1. Reads ~/.gsd/agent/models.json if it exists
8
- * 2. Falls back to ~/.pi/agent/models.json if GSD file doesn't exist
9
- * 3. Merges both files if both exist (GSD takes precedence)
4
+ * Uses ~/.gsd/agent/models.json exclusively.
10
5
  */
11
6
  /**
12
- * Resolve the path to models.json with fallback logic.
13
- *
14
- * Priority:
15
- * 1. ~/.gsd/agent/models.json (exists) → return this path
16
- * 2. ~/.pi/agent/models.json (exists) → return this path (fallback)
17
- * 3. Neither exists → return GSD path (will be created)
7
+ * Resolve the path to models.json.
18
8
  *
19
9
  * @returns The path to use for models.json
20
10
  */
@@ -1,35 +1,16 @@
1
1
  /**
2
- * Models.json resolution with fallback to ~/.pi/agent/models.json
2
+ * Models.json resolution for GSD.
3
3
  *
4
- * GSD uses ~/.gsd/agent/models.json, but for a smooth migration/development
5
- * experience, this module provides resolution logic that:
6
- *
7
- * 1. Reads ~/.gsd/agent/models.json if it exists
8
- * 2. Falls back to ~/.pi/agent/models.json if GSD file doesn't exist
9
- * 3. Merges both files if both exist (GSD takes precedence)
4
+ * Uses ~/.gsd/agent/models.json exclusively.
10
5
  */
11
- import { existsSync } from 'node:fs';
12
- import { homedir } from 'node:os';
13
6
  import { join } from 'node:path';
14
7
  import { agentDir } from './app-paths.js';
15
8
  const GSD_MODELS_PATH = join(agentDir, 'models.json');
16
- const PI_MODELS_PATH = join(homedir(), '.pi', 'agent', 'models.json');
17
9
  /**
18
- * Resolve the path to models.json with fallback logic.
19
- *
20
- * Priority:
21
- * 1. ~/.gsd/agent/models.json (exists) → return this path
22
- * 2. ~/.pi/agent/models.json (exists) → return this path (fallback)
23
- * 3. Neither exists → return GSD path (will be created)
10
+ * Resolve the path to models.json.
24
11
  *
25
12
  * @returns The path to use for models.json
26
13
  */
27
14
  export function resolveModelsJsonPath() {
28
- if (existsSync(GSD_MODELS_PATH)) {
29
- return GSD_MODELS_PATH;
30
- }
31
- if (existsSync(PI_MODELS_PATH)) {
32
- return PI_MODELS_PATH;
33
- }
34
15
  return GSD_MODELS_PATH;
35
16
  }
@@ -701,9 +701,8 @@ function collectRelativeFiles(rootDir) {
701
701
  return files;
702
702
  }
703
703
  /**
704
- * Constructs a DefaultResourceLoader that loads extensions from both
705
- * ~/.gsd/agent/extensions/ (GSD's default) and ~/.pi/agent/extensions/ (pi's default).
706
- * This allows users to use extensions from either location.
704
+ * Constructs a DefaultResourceLoader that loads extensions from
705
+ * ~/.gsd/agent/extensions/ (GSD's default) only.
707
706
  */
708
707
  // Cache bundled extension keys at module load — avoids re-scanning the extensions
709
708
  // directory in buildResourceLoader() (already scanned by loader.ts for env var).
@@ -718,19 +717,8 @@ export async function buildResourceLoader(agentDir, options = {}) {
718
717
  const { DefaultResourceLoader } = await loadPiCodingAgentModule();
719
718
  const { sortExtensionPaths } = await import('./extension-sort.js');
720
719
  const registry = loadRegistry();
721
- const piAgentDir = join(homedir(), '.pi', 'agent');
722
- const piExtensionsDir = join(piAgentDir, 'extensions');
723
720
  const bundledKeys = getBundledExtensionKeys();
724
- const piExtensionPaths = discoverExtensionEntryPaths(piExtensionsDir)
725
- .filter((entryPath) => !bundledKeys.has(getExtensionKey(entryPath, piExtensionsDir)))
726
- .filter((entryPath) => {
727
- const manifest = readManifestFromEntryPath(entryPath);
728
- if (!manifest)
729
- return true;
730
- return isExtensionEnabled(registry, manifest.id);
731
- });
732
721
  const additionalExtensionPaths = [
733
- ...piExtensionPaths,
734
722
  ...(options.additionalExtensionPaths ?? []),
735
723
  ];
736
724
  return new DefaultResourceLoader({
@@ -1 +1 @@
1
- 9a23824a70bd2722
1
+ eb84bf3c0ea71702
@@ -37,10 +37,13 @@ export const formatUptime = formatDuration;
37
37
  export function formatTimeAgo(timestamp) {
38
38
  return formatDuration(Date.now() - timestamp) + " ago";
39
39
  }
40
+ // NOTE: these worktree-layout regexes mirror findWorktreeSegment in
41
+ // src/resources/extensions/gsd/worktree-root.ts (bg-shell does not import the
42
+ // gsd extension). Keep them synchronized when a layout changes.
40
43
  function deriveProjectRootFromAutoWorktree(cachedCwd) {
41
44
  if (!cachedCwd)
42
45
  return undefined;
43
- const match = cachedCwd.match(/^(.*?)[\\/]\.gsd[\\/]worktrees[\\/][^\\/]+(?:[\\/].*)?$/);
46
+ const match = cachedCwd.match(/^(.*?)[\\/]\.gsd(?:-worktrees|[\\/]worktrees)[\\/][^\\/]+(?:[\\/].*)?$/);
44
47
  return match?.[1];
45
48
  }
46
49
  export function getBgShellLiveCwd(cachedCwd, pathExists = existsSync, getCwd = () => process.cwd(), chdir = (path) => process.chdir(path)) {
@@ -67,7 +70,7 @@ export function getBgShellLiveCwd(cachedCwd, pathExists = existsSync, getCwd = (
67
70
  }
68
71
  export function resolveBgShellPersistenceCwd(cachedCwd, liveCwd = undefined, pathExists = existsSync) {
69
72
  const resolvedLiveCwd = liveCwd ?? getBgShellLiveCwd(cachedCwd, pathExists);
70
- const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd[\\/]worktrees[\\/]/.test(cachedCwd);
73
+ const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd(?:-worktrees|[\\/]worktrees)[\\/]/.test(cachedCwd);
71
74
  if (!cachedIsAutoWorktree)
72
75
  return cachedCwd;
73
76
  if (cachedCwd === resolvedLiveCwd && pathExists(cachedCwd))
@@ -37,6 +37,15 @@ export const CLAUDE_CODE_MODELS = [
37
37
  contextWindow: 1_000_000,
38
38
  maxTokens: 128_000,
39
39
  },
40
+ {
41
+ id: "claude-fable-5",
42
+ name: "Claude Fable 5 (via Claude Code)",
43
+ reasoning: true,
44
+ input: ["text", "image"],
45
+ cost: ZERO_COST,
46
+ contextWindow: 1_000_000,
47
+ maxTokens: 128_000,
48
+ },
40
49
  {
41
50
  id: "claude-sonnet-4-6",
42
51
  name: "Claude Sonnet 4.6 (via Claude Code)",
@@ -24,6 +24,7 @@ import { markToolStart, markToolEnd } from "../gsd/auto.js";
24
24
  import { markInteractiveElicitationStart, markInteractiveElicitationEnd, } from "../gsd/auto-tool-tracking.js";
25
25
  import { discoverBrowserMcpServerName, discoverMcpServers, discoverMcpServerNames, discoverUserMcpServerNames, discoverWorkflowMcpServerName, computeMcpDisallowedTools, } from "../gsd/mcp-filter.js";
26
26
  import { RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES, RUN_UAT_FORBIDDEN_TOOL_NAMES, RUN_UAT_WORKFLOW_TOOL_NAMES, resolveToolPresentationPlan } from "../gsd/tool-presentation-plan.js";
27
+ import { getToolSurfaceReadinessError } from "../gsd/tool-surface-readiness.js";
27
28
  import { showInterviewRound } from "../shared/tui.js";
28
29
  export { buildFinalAssistantContent, extractToolResultsFromSdkUserMessage, handleClaudeCodePartialStreamEvent, mergePendingToolCalls, } from "./turn-assembler.js";
29
30
  export function serverToolUseToToolCallLike(block) {
@@ -1242,6 +1243,8 @@ function modelSupportsAdaptiveThinking(modelId) {
1242
1243
  || modelId.includes("opus-4.7")
1243
1244
  || modelId.includes("opus-4-8")
1244
1245
  || modelId.includes("opus-4.8")
1246
+ || modelId.includes("fable-5")
1247
+ || modelId.includes("fable.5")
1245
1248
  || modelId.includes("sonnet-4-6")
1246
1249
  || modelId.includes("sonnet-4.6")
1247
1250
  || modelId.includes("sonnet-4-7")
@@ -1263,7 +1266,9 @@ function mapThinkingLevelToAnthropicEffort(level, modelId) {
1263
1266
  if (modelId.includes("opus-4-7")
1264
1267
  || modelId.includes("opus-4.7")
1265
1268
  || modelId.includes("opus-4-8")
1266
- || modelId.includes("opus-4.8"))
1269
+ || modelId.includes("opus-4.8")
1270
+ || modelId.includes("fable-5")
1271
+ || modelId.includes("fable.5"))
1267
1272
  return "xhigh";
1268
1273
  if (modelId.includes("opus-4-6") || modelId.includes("opus-4.6"))
1269
1274
  return "max";
@@ -1564,7 +1569,9 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1564
1569
  || modelId.includes("opus-4-7")
1565
1570
  || modelId.includes("opus-4.7")
1566
1571
  || modelId.includes("opus-4-8")
1567
- || modelId.includes("opus-4.8")) ? ["context-1m-2025-08-07"] : [],
1572
+ || modelId.includes("opus-4.8")
1573
+ || modelId.includes("fable-5")
1574
+ || modelId.includes("fable.5")) ? ["context-1m-2025-08-07"] : [],
1568
1575
  ...(thinkingConfig ?? {}),
1569
1576
  ...(effort ? { effort } : {}),
1570
1577
  ...sdkExtraOptions,
@@ -1629,8 +1636,9 @@ async function pumpSdkMessages(model, context, options, stream) {
1629
1636
  }
1630
1637
  : {}),
1631
1638
  });
1639
+ const workflowMcpServerName = workflowMcpServerNameFromAllowedTools(sdkOpts.allowedTools);
1632
1640
  const prompt = buildPromptFromContext(context, {
1633
- workflowMcpServerName: workflowMcpServerNameFromAllowedTools(sdkOpts.allowedTools),
1641
+ workflowMcpServerName,
1634
1642
  browserMcpServerName: browserMcpServerNameFromAllowedTools(sdkOpts.allowedTools),
1635
1643
  });
1636
1644
  const queryPrompt = buildSdkQueryPrompt(context, prompt);
@@ -1668,7 +1676,30 @@ async function pumpSdkMessages(model, context, options, stream) {
1668
1676
  switch (msg.type) {
1669
1677
  // -- Init --
1670
1678
  case "system": {
1671
- // Nothing to emit the stream is already started.
1679
+ // Tool Surface Readiness gate: the init message is the first (and
1680
+ // only) point where the session reports its live tool surface and
1681
+ // MCP server statuses. If the workflow server failed or has not
1682
+ // registered this Unit's required tools, abort before the first
1683
+ // model turn with a transient, recovery-classifiable error
1684
+ // (tool-unavailable → retry) instead of letting the model hit
1685
+ // "No such tool available" mid-Unit and improvise around it.
1686
+ const init = msg;
1687
+ if (init.subtype === "init") {
1688
+ const readinessError = getToolSurfaceReadinessError({
1689
+ unitType: gsdPhase,
1690
+ workflowServerName: workflowMcpServerName,
1691
+ observation: { tools: init.tools ?? [], mcpServers: init.mcp_servers ?? [] },
1692
+ });
1693
+ if (readinessError) {
1694
+ controller.abort();
1695
+ stream.push({
1696
+ type: "error",
1697
+ reason: "error",
1698
+ error: makeErrorMessage(modelId, readinessError),
1699
+ });
1700
+ return;
1701
+ }
1702
+ }
1672
1703
  break;
1673
1704
  }
1674
1705
  // -- Streaming partial messages --
@@ -9,8 +9,9 @@
9
9
  // the real collaborators (state-reconciliation, doctor-proactive,
10
10
  // auto-dispatch, recovery-classification, tool-contract, worktree-safety,
11
11
  // uok/gate-runner, journal, session-lock, ctx.ui.notify) directly.
12
- import { debugCount, debugTime } from "../debug-logger.js";
12
+ import { debugCount, debugLog, debugTime } from "../debug-logger.js";
13
13
  import { reconcileBeforeDispatch } from "../state-reconciliation.js";
14
+ import { isLegalEdge, IllegalPhaseTransitionError } from "../state-transition-matrix.js";
14
15
  import { resolveDispatch } from "../auto-dispatch.js";
15
16
  import { classifyFailure } from "../recovery-classification.js";
16
17
  import { verifyExpectedArtifact, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
@@ -24,7 +25,7 @@ import { checkResourcesStale, autoWorktreeBranch, mergeMilestoneToMain } from ".
24
25
  import { getSessionLockStatus } from "../session-lock.js";
25
26
  import { resolveUokFlags } from "../uok/flags.js";
26
27
  import { emitJournalEvent as _emitJournalEvent } from "../journal.js";
27
- import { loadEffectiveGSDPreferences, getIsolationMode } from "../preferences.js";
28
+ import { loadEffectiveGSDPreferences, getIsolationMode, resolveEffectiveUnitIsolationMode } from "../preferences.js";
28
29
  import { detectWorktreeName, getMainBranch, resolveProjectRoot, resolveWorktreeProjectRoot, } from "../worktree.js";
29
30
  import { getPriorSliceCompletionBlocker } from "../dispatch-guard.js";
30
31
  import { GitServiceImpl } from "../git-service.js";
@@ -244,6 +245,10 @@ export class AutoOrchestrator {
244
245
  lastAdvanceKey = null;
245
246
  lastFinalizedUnitKey = null;
246
247
  dispatchKeyWindow = [];
248
+ // ADR-030 Phase Transition Invariant: the prior advance's reconciled Phase,
249
+ // the "from" endpoint of the edge check. In-memory; reset on start/resume/stop
250
+ // so the first advance of a session has no edge to assert.
251
+ lastDerivedPhase = null;
247
252
  // #442: the unit key we last attempted graduated stuck-recovery for. Bounds
248
253
  // recovery to one attempt per stuck episode per run (reset on start/resume/
249
254
  // stop), mirroring the legacy Level-1-then-Level-2 escalation in phases.ts.
@@ -476,8 +481,7 @@ export class AutoOrchestrator {
476
481
  }
477
482
  // ── WorktreeAdapter (folded) ─────────────────────────────────────────────
478
483
  getEffectiveUnitIsolationMode(basePath) {
479
- const configuredMode = getIsolationMode(basePath);
480
- return configuredMode === "worktree" && this.s.isolationDegraded ? "branch" : configuredMode;
484
+ return resolveEffectiveUnitIsolationMode(getIsolationMode(basePath), this.s.isolationDegraded, this.s.strandedRecoveryIsolationMode);
481
485
  }
482
486
  buildLifecycle() {
483
487
  return new WorktreeLifecycle(this.s, {
@@ -576,6 +580,21 @@ export class AutoOrchestrator {
576
580
  const recovery = classifyFailure(input);
577
581
  return { action: recovery.action, reason: recovery.reason };
578
582
  }
583
+ /**
584
+ * ADR-030 Phase Transition Invariant (advisory mode). The matrix is an
585
+ * assertion, not a decision-maker — deriveState already chose the phase; we
586
+ * only observe illegal *derived* edges that survived reconciliation. The
587
+ * matrix is still a sparse hardening spec, so this is telemetry-only (no
588
+ * block) until it is expanded into a validated legal-edge graph. To enforce:
589
+ * `throw violation;` instead of logging — recovery-classification maps
590
+ * IllegalPhaseTransitionError to kind "illegal-transition" (escalate).
591
+ */
592
+ observePhaseTransition(from, to) {
593
+ if (isLegalEdge(from, to))
594
+ return;
595
+ const violation = new IllegalPhaseTransitionError(from, to);
596
+ debugLog("phase-transition-advisory", { from, to, message: violation.message });
597
+ }
579
598
  // ── Lifecycle verbs ──────────────────────────────────────────────────────
580
599
  /**
581
600
  * #442: graduated stuck recovery, ported from the legacy
@@ -636,6 +655,7 @@ export class AutoOrchestrator {
636
655
  this.lastFinalizedUnitKey = null;
637
656
  this.dispatchKeyWindow = [];
638
657
  this.lastStuckRecoveryKey = null;
658
+ this.lastDerivedPhase = null;
639
659
  this.status.phase = "running";
640
660
  this.bumpTransition();
641
661
  this.journalTransition({ name: "start" });
@@ -721,6 +741,11 @@ export class AutoOrchestrator {
721
741
  this.postAdvanceRecord(blocked);
722
742
  return blocked;
723
743
  }
744
+ const reconciledPhase = reconciliation.stateSnapshot.phase;
745
+ if (this.lastDerivedPhase !== null) {
746
+ this.observePhaseTransition(this.lastDerivedPhase, reconciledPhase);
747
+ }
748
+ this.lastDerivedPhase = reconciledPhase;
724
749
  const decision = await this.decideNextUnit({ stateSnapshot: reconciliation.stateSnapshot });
725
750
  if (!decision) {
726
751
  const settlementBlock = this.evaluateNoRemainingUnitsSettlement(reconciliation.stateSnapshot);
@@ -981,6 +1006,9 @@ export class AutoOrchestrator {
981
1006
  // Preserve dispatchKeyWindow across resume so stuck-loop detection
982
1007
  // accumulates across pause/resume cycles rather than resetting each time.
983
1008
  this.lastStuckRecoveryKey = null;
1009
+ // ADR-030: drop the prior "from" — the first advance after resume has no
1010
+ // edge to assert (avoids a false illegal-edge across the pause boundary).
1011
+ this.lastDerivedPhase = null;
984
1012
  this.status.phase = "running";
985
1013
  this.bumpTransition();
986
1014
  this.journalTransition({ name: "resume" });
@@ -996,6 +1024,7 @@ export class AutoOrchestrator {
996
1024
  this.status.activeUnit = undefined;
997
1025
  this.lastAdvanceKey = null;
998
1026
  this.lastFinalizedUnitKey = null;
1027
+ this.lastDerivedPhase = null;
999
1028
  // Preserve dispatchKeyWindow on pause so stuck-loop detection accumulates
1000
1029
  // across pause/resume cycles. Only clear on a hard stop.
1001
1030
  if (reason !== "pause") {
@@ -11,6 +11,7 @@
11
11
  import { importExtensionModule } from "@gsd/pi-coding-agent";
12
12
  import { USER_DRIVEN_DEEP_UNITS, isAwaitingUserInput, } from "../auto-post-unit.js";
13
13
  import { lastAssistantText } from "../user-input-boundary.js";
14
+ import { resolveEffectiveUnitIsolationMode } from "../preferences.js";
14
15
  import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from "./types.js";
15
16
  import { detectStuck } from "./detect-stuck.js";
16
17
  import { runUnit } from "./run-unit.js";
@@ -265,7 +266,11 @@ async function validateSourceWriteWorktreeSafety(ic, unitType, unitId, milestone
265
266
  if (!writesSource)
266
267
  return null;
267
268
  const projectRoot = s.canonicalProjectRoot ?? resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
268
- const isolationMode = deps.getIsolationMode(projectRoot);
269
+ // A degraded session already fell back to the milestone branch in the
270
+ // project root — validating against the canonical worktree root there
271
+ // would fail every dispatch with a false invalid-root. The same applies
272
+ // to a stranded-recovery session that adopted the milestone branch.
273
+ const isolationMode = resolveEffectiveUnitIsolationMode(deps.getIsolationMode(projectRoot), s.isolationDegraded, s.strandedRecoveryIsolationMode);
269
274
  if (isolationMode !== "worktree")
270
275
  return null;
271
276
  const safety = createWorktreeSafetyModule();
@@ -39,7 +39,7 @@ import { debugLog } from "./debug-logger.js";
39
39
  import { runSafely } from "./auto-utils.js";
40
40
  import { isMilestoneCloseoutSettled, runMilestoneCloseoutGitHub, } from "./milestone-closeout.js";
41
41
  import { getEvidence, clearEvidenceFromDisk, isExecutionToolName } from "./safety/evidence-collector.js";
42
- import { validateFileChanges } from "./safety/file-change-validator.js";
42
+ import { validateFileChanges, effectiveFileChangeAllowlist } from "./safety/file-change-validator.js";
43
43
  import { crossReferenceEvidence } from "./safety/evidence-cross-ref.js";
44
44
  import { validateContent } from "./safety/content-validator.js";
45
45
  import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
@@ -55,7 +55,7 @@ import { writeTurnGitTransaction } from "./uok/gitops.js";
55
55
  import { isClosedStatus } from "./status-guards.js";
56
56
  import { detectAbandonMilestone } from "./abandon-detect.js";
57
57
  import { getPendingGate } from "./bootstrap/write-gate.js";
58
- import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
58
+ import { isDeterministicPolicyError, isToolUnavailableError } from "./auto-tool-tracking.js";
59
59
  import { formatConnectedStepStack, formatPostUnitStatusCard } from "./auto-status-message.js";
60
60
  import { clearProjectResearchInflightMarker, finalizeProjectResearchTimeout, } from "./project-research-policy.js";
61
61
  import { validateArtifact } from "./schemas/validate.js";
@@ -507,9 +507,10 @@ export function _hasExecutionToolCallsInSessionForTest(entries) {
507
507
  if (e?.type === "toolCall" && isExecutionToolName(e?.name ?? e?.toolName)) {
508
508
  return true;
509
509
  }
510
- if (e?.type !== "message")
511
- continue;
512
- const msg = e?.message;
510
+ // Accept both session-manager entries ({type: "message", message}) and
511
+ // bare agent-end messages ({role, content}) — the auto loop passes the
512
+ // latter via opts.agentEndMessages.
513
+ const msg = e?.type === "message" ? e?.message : e;
513
514
  if (!msg || msg.role !== "assistant" || !Array.isArray(msg.content))
514
515
  continue;
515
516
  for (const block of msg.content) {
@@ -1289,6 +1290,7 @@ export async function postUnitPreVerification(pctx, opts) {
1289
1290
  const safetyConfig = resolveSafetyHarnessConfig(prefs?.safety_harness);
1290
1291
  if (safetyConfig.enabled) {
1291
1292
  const { milestone: sMid, slice: sSid, task: sTid } = parseUnitId(s.currentUnit.id);
1293
+ const fileChangeAllowlist = effectiveFileChangeAllowlist(safetyConfig.file_change_allowlist, prefs?.git?.manage_gitignore);
1292
1294
  // File change validation (execute-task only, after unit execution)
1293
1295
  if (safetyConfig.file_change_validation && s.currentUnit.type === "execute-task" && sMid && sSid && sTid) {
1294
1296
  try {
@@ -1303,7 +1305,7 @@ export async function postUnitPreVerification(pctx, opts) {
1303
1305
  const plannedFiles = getPlannedKeyFiles(sliceTaskRows.map((taskRow) => ({
1304
1306
  files: taskRow.files,
1305
1307
  })));
1306
- const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
1308
+ const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, fileChangeAllowlist);
1307
1309
  if (audit && audit.violations.length > 0) {
1308
1310
  const warnings = audit.violations.filter(v => v.severity === "warning");
1309
1311
  for (const v of warnings) {
@@ -1319,7 +1321,7 @@ export async function postUnitPreVerification(pctx, opts) {
1319
1321
  if (taskRow) {
1320
1322
  const expectedOutput = taskRow.expected_output ?? [];
1321
1323
  const plannedFiles = taskRow.files ?? [];
1322
- const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, safetyConfig.file_change_allowlist);
1324
+ const audit = validateFileChanges(s.basePath, expectedOutput, plannedFiles, fileChangeAllowlist);
1323
1325
  if (audit && audit.violations.length > 0) {
1324
1326
  const warnings = audit.violations.filter(v => v.severity === "warning");
1325
1327
  for (const v of warnings) {
@@ -1699,7 +1701,16 @@ export async function postUnitPreVerification(pctx, opts) {
1699
1701
  ctx.ui.notify(`Artifact missing for ${s.currentUnit.type} ${s.currentUnit.id} — DB unavailable, skipping retry.${dbSkipDiag ? ` Expected: ${dbSkipDiag}` : ""}`, "error");
1700
1702
  }
1701
1703
  else if (!triggerArtifactVerified) {
1702
- if (s.lastToolInvocationError) {
1704
+ if (s.lastToolInvocationError && isToolUnavailableError(s.lastToolInvocationError)) {
1705
+ // Tool-unavailable is the one transient invocation error: the
1706
+ // workflow MCP server registers its surface asynchronously, so a
1707
+ // Unit's first call can race the registration. Fall through to the
1708
+ // bounded verification retry instead of pausing.
1709
+ debugLog("postUnit", { phase: "tool-unavailable-retry", unitType: s.currentUnit.type, unitId: s.currentUnit.id, error: s.lastToolInvocationError });
1710
+ ctx.ui.notify(`Tool unavailable for ${s.currentUnit.type}: ${s.lastToolInvocationError}. The tool surface may still be registering — retrying.`, "warning");
1711
+ s.lastToolInvocationError = null;
1712
+ }
1713
+ else if (s.lastToolInvocationError) {
1703
1714
  const isUserSkip = /queued user message/i.test(s.lastToolInvocationError);
1704
1715
  const errMsg = isUserSkip
1705
1716
  ? `Tool skipped for ${s.currentUnit.type}: ${s.lastToolInvocationError}. Queued user message interrupted the turn — pausing auto-mode.`
@@ -2146,6 +2146,9 @@ export async function buildPlanSlicePrompt(mid, _midTitle, sid, sTitle, base, le
2146
2146
  `Either (a) add an earlier task that creates X on disk before the task that needs it, ` +
2147
2147
  `or (b) if this task IS the one that creates X, move X from inputs to expected_output. ` +
2148
2148
  `Do NOT put X in a task's expected_output if that task only reads or verifies X — only tasks that actually write X to disk should list it in expected_output.\n` +
2149
+ `- **"[file] X: ... GSD planning artifacts are projections preloaded as context / written by workflow tools"**: ` +
2150
+ `Remove X from the task's inputs, files, and expectedOutput entirely. Planning artifacts (anything under .gsd/, .planning/, or .audits/, or names like M001-CONTEXT.md / S01-PLAN.md) are preloaded as context and written by workflow tools — ` +
2151
+ `do NOT add a task that creates X and do NOT move X to expectedOutput.\n` +
2149
2152
  `- **"[file] X: Task T_early reads X but it's created by task T_late (sequence violation)"**: ` +
2150
2153
  `Either (a) reorder tasks so T_late (the creator) runs before T_early (the reader), ` +
2151
2154
  `or (b) if T_late doesn't actually create X (it only reads/tests it), remove X from T_late's expected_output entirely.\n` +