@opengsd/gsd-pi 1.2.0-dev.4c756166 → 1.2.0-dev.955e4da0

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 (246) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/bg-shell/utilities.js +2 -2
  3. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  4. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +8 -2
  5. package/dist/resources/extensions/gsd/auto/orchestrator.js +33 -4
  6. package/dist/resources/extensions/gsd/auto/phases.js +6 -1
  7. package/dist/resources/extensions/gsd/auto-post-unit.js +8 -6
  8. package/dist/resources/extensions/gsd/auto-start.js +8 -13
  9. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  10. package/dist/resources/extensions/gsd/auto-worktree.js +13 -270
  11. package/dist/resources/extensions/gsd/auto.js +4 -7
  12. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -6
  13. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +32 -3
  14. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +26 -4
  15. package/dist/resources/extensions/gsd/captures.js +5 -13
  16. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  17. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  18. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  19. package/dist/resources/extensions/gsd/db/queries.js +372 -0
  20. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  21. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  22. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  23. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  24. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  25. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  26. package/dist/resources/extensions/gsd/doctor-environment.js +8 -10
  27. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
  28. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +9 -2
  29. package/dist/resources/extensions/gsd/git-service.js +1 -0
  30. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  31. package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
  32. package/dist/resources/extensions/gsd/guided-flow.js +34 -3
  33. package/dist/resources/extensions/gsd/migrate/safety.js +17 -9
  34. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  35. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  36. package/dist/resources/extensions/gsd/model-router.js +3 -0
  37. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  38. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +7 -5
  39. package/dist/resources/extensions/gsd/paths.js +10 -24
  40. package/dist/resources/extensions/gsd/preferences.js +14 -0
  41. package/dist/resources/extensions/gsd/recovery-classification.js +12 -1
  42. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  43. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  44. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  45. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  46. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  47. package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
  48. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -5
  49. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
  50. package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
  51. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  52. package/dist/resources/extensions/gsd/undo.js +8 -7
  53. package/dist/resources/extensions/gsd/worktree-git-recovery.js +287 -0
  54. package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
  55. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  56. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  57. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  58. package/dist/resources/extensions/gsd/worktree-root.js +17 -6
  59. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  60. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -10
  61. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  62. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  63. package/dist/web/standalone/.next/BUILD_ID +1 -1
  64. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  65. package/dist/web/standalone/.next/build-manifest.json +2 -2
  66. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  67. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  84. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  85. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  86. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  87. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  89. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  90. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  91. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  92. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  93. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  94. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  95. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  96. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  97. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  98. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  99. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  100. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  101. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  102. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  103. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  104. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  106. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  107. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  108. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  109. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  110. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  111. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  112. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  113. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  114. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  115. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  116. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  117. package/dist/web/standalone/.next/server/app/index.html +1 -1
  118. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  125. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  126. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  127. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  129. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  130. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  131. package/dist/worktree-status-banner.js +7 -3
  132. package/package.json +1 -1
  133. package/packages/cloud-mcp-gateway/package.json +2 -2
  134. package/packages/contracts/package.json +1 -1
  135. package/packages/daemon/package.json +4 -4
  136. package/packages/gsd-agent-core/package.json +5 -5
  137. package/packages/gsd-agent-modes/package.json +7 -7
  138. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  139. package/packages/mcp-server/dist/workflow-tools.js +30 -21
  140. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  141. package/packages/mcp-server/package.json +3 -3
  142. package/packages/native/package.json +1 -1
  143. package/packages/pi-agent-core/package.json +1 -1
  144. package/packages/pi-ai/dist/models.generated.d.ts +266 -35
  145. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  146. package/packages/pi-ai/dist/models.generated.js +235 -46
  147. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  148. package/packages/pi-ai/package.json +1 -1
  149. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  150. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  151. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  152. package/packages/pi-coding-agent/package.json +7 -7
  153. package/packages/pi-tui/package.json +2 -2
  154. package/packages/rpc-client/package.json +2 -2
  155. package/pkg/package.json +1 -1
  156. package/src/resources/extensions/bg-shell/utilities.ts +2 -2
  157. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  158. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +6 -0
  159. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  160. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  161. package/src/resources/extensions/gsd/auto/orchestrator.ts +39 -5
  162. package/src/resources/extensions/gsd/auto/phases.ts +10 -1
  163. package/src/resources/extensions/gsd/auto-post-unit.ts +12 -5
  164. package/src/resources/extensions/gsd/auto-start.ts +8 -14
  165. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  166. package/src/resources/extensions/gsd/auto-worktree.ts +20 -280
  167. package/src/resources/extensions/gsd/auto.ts +12 -9
  168. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -6
  169. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +32 -3
  170. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +25 -3
  171. package/src/resources/extensions/gsd/captures.ts +5 -14
  172. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  173. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  174. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  175. package/src/resources/extensions/gsd/db/queries.ts +453 -0
  176. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  177. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  178. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  179. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  180. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  181. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  182. package/src/resources/extensions/gsd/doctor-environment.ts +8 -11
  183. package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
  184. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +10 -3
  185. package/src/resources/extensions/gsd/git-service.ts +1 -0
  186. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  187. package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
  188. package/src/resources/extensions/gsd/guided-flow.ts +34 -3
  189. package/src/resources/extensions/gsd/migrate/safety.ts +15 -7
  190. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  191. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  192. package/src/resources/extensions/gsd/model-router.ts +3 -0
  193. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  194. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -5
  195. package/src/resources/extensions/gsd/paths.ts +9 -22
  196. package/src/resources/extensions/gsd/preferences.ts +18 -0
  197. package/src/resources/extensions/gsd/recovery-classification.ts +14 -1
  198. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  199. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  200. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  201. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  202. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  203. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  204. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  205. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  206. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  207. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  208. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -0
  209. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  210. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  211. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +5 -4
  212. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +1 -1
  213. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  214. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  215. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  216. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +91 -1
  217. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  218. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  219. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  220. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  221. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  222. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  223. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  224. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  225. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  226. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  227. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  228. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  229. package/src/resources/extensions/gsd/tests/write-gate.test.ts +42 -0
  230. package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
  231. package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -5
  232. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
  233. package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
  234. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  235. package/src/resources/extensions/gsd/undo.ts +9 -8
  236. package/src/resources/extensions/gsd/worktree-git-recovery.ts +308 -0
  237. package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
  238. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  239. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  240. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  241. package/src/resources/extensions/gsd/worktree-root.ts +17 -6
  242. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  243. package/src/resources/extensions/gsd/worktree-session-state.ts +12 -10
  244. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  245. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → C24pqUd-aru-l0Dp0gLZP}/_buildManifest.js +0 -0
  246. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → C24pqUd-aru-l0Dp0gLZP}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- 9a23824a70bd2722
1
+ 749698fd346380ec
@@ -40,7 +40,7 @@ export function formatTimeAgo(timestamp) {
40
40
  function deriveProjectRootFromAutoWorktree(cachedCwd) {
41
41
  if (!cachedCwd)
42
42
  return undefined;
43
- const match = cachedCwd.match(/^(.*?)[\\/]\.gsd[\\/]worktrees[\\/][^\\/]+(?:[\\/].*)?$/);
43
+ const match = cachedCwd.match(/^(.*?)[\\/]\.gsd(?:-worktrees|[\\/]worktrees)[\\/][^\\/]+(?:[\\/].*)?$/);
44
44
  return match?.[1];
45
45
  }
46
46
  export function getBgShellLiveCwd(cachedCwd, pathExists = existsSync, getCwd = () => process.cwd(), chdir = (path) => process.chdir(path)) {
@@ -67,7 +67,7 @@ export function getBgShellLiveCwd(cachedCwd, pathExists = existsSync, getCwd = (
67
67
  }
68
68
  export function resolveBgShellPersistenceCwd(cachedCwd, liveCwd = undefined, pathExists = existsSync) {
69
69
  const resolvedLiveCwd = liveCwd ?? getBgShellLiveCwd(cachedCwd, pathExists);
70
- const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd[\\/]worktrees[\\/]/.test(cachedCwd);
70
+ const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd(?:-worktrees|[\\/]worktrees)[\\/]/.test(cachedCwd);
71
71
  if (!cachedIsAutoWorktree)
72
72
  return cachedCwd;
73
73
  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)",
@@ -1242,6 +1242,8 @@ function modelSupportsAdaptiveThinking(modelId) {
1242
1242
  || modelId.includes("opus-4.7")
1243
1243
  || modelId.includes("opus-4-8")
1244
1244
  || modelId.includes("opus-4.8")
1245
+ || modelId.includes("fable-5")
1246
+ || modelId.includes("fable.5")
1245
1247
  || modelId.includes("sonnet-4-6")
1246
1248
  || modelId.includes("sonnet-4.6")
1247
1249
  || modelId.includes("sonnet-4-7")
@@ -1263,7 +1265,9 @@ function mapThinkingLevelToAnthropicEffort(level, modelId) {
1263
1265
  if (modelId.includes("opus-4-7")
1264
1266
  || modelId.includes("opus-4.7")
1265
1267
  || modelId.includes("opus-4-8")
1266
- || modelId.includes("opus-4.8"))
1268
+ || modelId.includes("opus-4.8")
1269
+ || modelId.includes("fable-5")
1270
+ || modelId.includes("fable.5"))
1267
1271
  return "xhigh";
1268
1272
  if (modelId.includes("opus-4-6") || modelId.includes("opus-4.6"))
1269
1273
  return "max";
@@ -1564,7 +1568,9 @@ export function buildSdkOptions(modelId, prompt, overrides, extraOptions = {}) {
1564
1568
  || modelId.includes("opus-4-7")
1565
1569
  || modelId.includes("opus-4.7")
1566
1570
  || modelId.includes("opus-4-8")
1567
- || modelId.includes("opus-4.8")) ? ["context-1m-2025-08-07"] : [],
1571
+ || modelId.includes("opus-4.8")
1572
+ || modelId.includes("fable-5")
1573
+ || modelId.includes("fable.5")) ? ["context-1m-2025-08-07"] : [],
1568
1574
  ...(thinkingConfig ?? {}),
1569
1575
  ...(effort ? { effort } : {}),
1570
1576
  ...sdkExtraOptions,
@@ -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";
@@ -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) {
@@ -11,6 +11,7 @@
11
11
  * remains in auto.ts — this module handles only the fresh-start path.
12
12
  */
13
13
  import { deriveState } from "./state.js";
14
+ import { findWorktreeSegment, isGsdWorktreePath } from "./worktree-root.js";
14
15
  import { loadFile, getManifestStatus } from "./files.js";
15
16
  import { loadEffectiveGSDPreferences, resolveSkillDiscoveryMode, getIsolationMode, } from "./preferences.js";
16
17
  import { ensureGsdSymlink, isInheritedRepo, validateProjectId } from "./repo-identity.js";
@@ -45,7 +46,6 @@ import { debugLog, enableDebug, isDebugEnabled, getDebugLogPath, } from "./debug
45
46
  import { logWarning, logError } from "./workflow-logger.js";
46
47
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, } from "node:fs";
47
48
  import { join } from "node:path";
48
- import { sep as pathSep } from "node:path";
49
49
  import { validateDirectory } from "./validate-directory.js";
50
50
  import { isCustomProvider, resolveDefaultSessionModel, resolveDynamicRoutingConfig, } from "./preferences-models.js";
51
51
  import { getSessionModelOverride } from "./session-model-override.js";
@@ -403,7 +403,7 @@ export function auditOrphanedMilestoneBranches(basePath, _isolationMode, gitDeps
403
403
  }
404
404
  }
405
405
  else {
406
- warnings.push(`Orphaned worktree directory for ${milestoneId} is outside .gsd/worktrees/ — skipping removal for safety.`);
406
+ warnings.push(`Orphaned worktree directory for ${milestoneId} is outside the GSD worktrees containers — skipping removal for safety.`);
407
407
  }
408
408
  }
409
409
  else {
@@ -522,7 +522,7 @@ export function auditOrphanedMilestoneBranches(basePath, _isolationMode, gitDeps
522
522
  if (!existsSync(wtDir))
523
523
  continue;
524
524
  if (!isInsideWorktreesDir(basePath, wtDir)) {
525
- warnings.push(`Orphaned worktree directory for ${m.id} is outside .gsd/worktrees/ — skipping removal for safety.`);
525
+ warnings.push(`Orphaned worktree directory for ${m.id} is outside the GSD worktrees containers — skipping removal for safety.`);
526
526
  continue;
527
527
  }
528
528
  // Try `git worktree remove` first in case the dir is still registered
@@ -1010,7 +1010,7 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
1010
1010
  (state.phase === "pre-planning" || state.phase === "complete") &&
1011
1011
  survivorIsolationMode !== "none" &&
1012
1012
  !detectWorktreeName(base) &&
1013
- !base.includes(`${pathSep}.gsd${pathSep}worktrees${pathSep}`)) {
1013
+ !isGsdWorktreePath(base)) {
1014
1014
  const milestoneBranch = `milestone/${survivorMilestoneId}`;
1015
1015
  const { nativeBranchExists } = await import("./native-git-bridge.js");
1016
1016
  hasSurvivorBranch = nativeBranchExists(base, milestoneBranch);
@@ -1246,16 +1246,11 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
1246
1246
  // (ADR-016 phase 2 / B2, #5620). The redundant assignment that used to
1247
1247
  // live here is gone.
1248
1248
  const isUnderGsdWorktrees = (p) => {
1249
- // Direct layout: /.gsd/worktrees/
1250
- const marker = `${pathSep}.gsd${pathSep}worktrees${pathSep}`;
1251
- if (p.includes(marker))
1249
+ const normalized = p.replaceAll("\\", "/");
1250
+ if (findWorktreeSegment(normalized) !== null)
1252
1251
  return true;
1253
- const worktreesSuffix = `${pathSep}.gsd${pathSep}worktrees`;
1254
- if (p.endsWith(worktreesSuffix))
1255
- return true;
1256
- // Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/
1257
- const symlinkRe = new RegExp(`\\${pathSep}\\.gsd\\${pathSep}projects\\${pathSep}[a-f0-9]+\\${pathSep}worktrees(?:\\${pathSep}|$)`);
1258
- return symlinkRe.test(p);
1252
+ // The container directory itself (no trailing worktree name).
1253
+ return normalized.endsWith("/.gsd/worktrees") || normalized.endsWith("/.gsd-worktrees");
1259
1254
  };
1260
1255
  if (s.currentMilestoneId &&
1261
1256
  (getIsolationMode(base) !== "none" || strandedRecoveryAction?.recoveryMode) &&
@@ -3,6 +3,7 @@
3
3
  import { existsSync, lstatSync, readdirSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { worktreePath } from "./worktree-manager.js";
6
+ import { worktreesDirs } from "./worktree-placement.js";
6
7
  import { normalizeWorktreePathForCompare } from "./worktree-root.js";
7
8
  const defaultFs = {
8
9
  existsSync,
@@ -22,6 +23,13 @@ export function expectedAutoWorktreePath(projectRoot, milestoneId) {
22
23
  return null;
23
24
  return worktreePath(projectRoot, id);
24
25
  }
26
+ /** Every path the milestone worktree may legitimately live at (canonical + legacy). */
27
+ function candidateAutoWorktreePaths(projectRoot, milestoneId) {
28
+ const id = milestoneId?.trim();
29
+ if (!id || !isValidMilestoneId(id))
30
+ return [];
31
+ return worktreesDirs(projectRoot).map((dir) => join(dir, id));
32
+ }
25
33
  export function resolvePausedAutoWorktreePath(input) {
26
34
  if (input.baseIsAutoWorktree)
27
35
  return input.basePath;
@@ -43,8 +51,8 @@ export function assessAutoWorktreeRepairTarget(input) {
43
51
  if (!expectedPath) {
44
52
  return { ok: false, reason: "missing expected worktree path" };
45
53
  }
46
- const computedExpectedPath = expectedAutoWorktreePath(input.projectRoot, input.milestoneId);
47
- if (!computedExpectedPath || !samePath(expectedPath, computedExpectedPath)) {
54
+ const candidatePaths = candidateAutoWorktreePaths(input.projectRoot, input.milestoneId);
55
+ if (candidatePaths.length === 0 || !candidatePaths.some((candidate) => samePath(expectedPath, candidate))) {
48
56
  return { ok: false, reason: "expected worktree path does not match milestone" };
49
57
  }
50
58
  if (!samePath(input.activeRoot, input.projectRoot) && !samePath(input.activeRoot, expectedPath)) {