@opengsd/gsd-pi 1.2.0-dev.9ad8ae33 → 1.2.0-dev.a6376d75

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 (264) hide show
  1. package/dist/cli-model-override.d.ts +15 -0
  2. package/dist/cli-model-override.js +21 -0
  3. package/dist/cli.js +1 -18
  4. package/dist/loader.js +6 -4
  5. package/dist/register-agent-bundles.d.ts +11 -2
  6. package/dist/register-agent-bundles.js +18 -4
  7. package/dist/resources/.managed-resources-content-hash +1 -1
  8. package/dist/resources/extensions/ask-user-questions.js +3 -2
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  10. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  11. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  12. package/dist/resources/extensions/gsd/auto/dispatch-history.js +21 -6
  13. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  14. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  15. package/dist/resources/extensions/gsd/auto/loop.js +4 -1
  16. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  17. package/dist/resources/extensions/gsd/auto/orchestrator.js +85 -15
  18. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  19. package/dist/resources/extensions/gsd/auto/phases.js +17 -2372
  20. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
  21. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  22. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  23. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  24. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  25. package/dist/resources/extensions/gsd/auto.js +15 -1
  26. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
  27. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  28. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  29. package/dist/resources/extensions/gsd/db/queries.js +30 -0
  30. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  31. package/dist/resources/extensions/gsd/guided-flow.js +88 -2
  32. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  33. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  34. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  35. package/dist/resources/extensions/gsd/notifications.js +12 -7
  36. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  37. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -1
  38. package/dist/resources/extensions/gsd/prompts/run-uat.md +2 -0
  39. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  40. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  41. package/dist/resources/extensions/gsd/state.js +6 -2
  42. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  43. package/dist/resources/extensions/gsd/tools/complete-task.js +62 -0
  44. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  45. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  46. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  47. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  48. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  49. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  50. package/dist/runtime-checks.d.ts +10 -0
  51. package/dist/runtime-checks.js +27 -0
  52. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  53. package/dist/web/standalone/.next/BUILD_ID +1 -1
  54. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  55. package/dist/web/standalone/.next/build-manifest.json +2 -2
  56. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  57. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/index.html +1 -1
  74. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  81. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  83. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  84. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  85. package/package.json +2 -2
  86. package/packages/cloud-mcp-gateway/package.json +2 -2
  87. package/packages/contracts/package.json +1 -1
  88. package/packages/daemon/package.json +4 -4
  89. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  90. package/packages/gsd-agent-core/dist/sdk.js +6 -4
  91. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  92. package/packages/gsd-agent-core/package.json +5 -5
  93. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  94. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  95. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  96. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  97. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  98. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  99. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +50 -6
  100. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  101. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
  102. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  103. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
  104. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  105. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
  106. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  107. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +12 -0
  108. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  109. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  110. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  111. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  112. package/packages/gsd-agent-modes/package.json +7 -7
  113. package/packages/mcp-server/README.md +12 -3
  114. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  115. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  116. package/packages/mcp-server/dist/cli-runner.js +137 -0
  117. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  118. package/packages/mcp-server/dist/cli.js +2 -58
  119. package/packages/mcp-server/dist/cli.js.map +1 -1
  120. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  121. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  122. package/packages/mcp-server/dist/pid-registry.js +452 -0
  123. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  124. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  125. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  126. package/packages/mcp-server/dist/probe-mode.js +10 -0
  127. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  128. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  129. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  130. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  131. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  132. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  133. package/packages/mcp-server/dist/workflow-tools.js +62 -43
  134. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  135. package/packages/mcp-server/package.json +5 -5
  136. package/packages/native/package.json +1 -1
  137. package/packages/pi-agent-core/dist/agent-loop.js +43 -2
  138. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  139. package/packages/pi-agent-core/package.json +1 -1
  140. package/packages/pi-ai/package.json +1 -1
  141. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  142. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  143. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  144. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  145. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  146. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  147. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  148. package/packages/pi-coding-agent/package.json +7 -7
  149. package/packages/pi-tui/dist/index.d.ts +1 -1
  150. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  151. package/packages/pi-tui/dist/index.js +1 -1
  152. package/packages/pi-tui/dist/index.js.map +1 -1
  153. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  154. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  155. package/packages/pi-tui/dist/terminal-image.js +54 -2
  156. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  157. package/packages/pi-tui/dist/tui.d.ts +8 -0
  158. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  159. package/packages/pi-tui/dist/tui.js +63 -18
  160. package/packages/pi-tui/dist/tui.js.map +1 -1
  161. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  162. package/packages/pi-tui/dist/utils.js +110 -36
  163. package/packages/pi-tui/dist/utils.js.map +1 -1
  164. package/packages/pi-tui/package.json +2 -2
  165. package/packages/rpc-client/package.json +2 -2
  166. package/pkg/dist/theme/theme.d.ts.map +1 -1
  167. package/pkg/dist/theme/theme.js +45 -17
  168. package/pkg/dist/theme/theme.js.map +1 -1
  169. package/pkg/package.json +1 -1
  170. package/src/resources/extensions/ask-user-questions.ts +7 -2
  171. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  172. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  173. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  174. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  175. package/src/resources/extensions/gsd/auto/dispatch-history.ts +22 -6
  176. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  177. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  178. package/src/resources/extensions/gsd/auto/loop.ts +4 -1
  179. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  180. package/src/resources/extensions/gsd/auto/orchestrator.ts +95 -15
  181. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  182. package/src/resources/extensions/gsd/auto/phases.ts +58 -3061
  183. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
  184. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  185. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  186. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  187. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  188. package/src/resources/extensions/gsd/auto.ts +20 -1
  189. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
  190. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  191. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  192. package/src/resources/extensions/gsd/db/queries.ts +29 -0
  193. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  194. package/src/resources/extensions/gsd/guided-flow.ts +128 -2
  195. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  196. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  197. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  198. package/src/resources/extensions/gsd/notifications.ts +13 -6
  199. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  200. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -1
  201. package/src/resources/extensions/gsd/prompts/run-uat.md +2 -0
  202. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  203. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  204. package/src/resources/extensions/gsd/state.ts +7 -1
  205. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  206. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  207. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  208. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +76 -12
  209. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  210. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
  211. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  212. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  213. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  214. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +2 -1
  215. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +36 -0
  216. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +55 -0
  217. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  218. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  219. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  220. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +16 -0
  221. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  222. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  223. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +18 -0
  224. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  225. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  226. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  227. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  228. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  229. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  230. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  231. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  232. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  233. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +5 -0
  234. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  235. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +1 -1
  236. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  237. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
  238. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  239. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  240. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -1
  241. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  242. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  243. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  244. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
  245. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  246. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  247. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  248. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  249. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  250. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  251. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  252. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  253. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  254. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  255. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  256. package/src/resources/extensions/gsd/tools/complete-task.ts +87 -0
  257. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  258. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  259. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  260. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  261. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  262. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  263. /package/dist/web/standalone/.next/static/{FBNo5cT_chy7YNoAQsU3o → xyMkEaICFHJoa98VgJyzY}/_buildManifest.js +0 -0
  264. /package/dist/web/standalone/.next/static/{FBNo5cT_chy7YNoAQsU3o → xyMkEaICFHJoa98VgJyzY}/_ssgManifest.js +0 -0
@@ -10,7 +10,7 @@ import type {
10
10
  } from "./types.js";
11
11
  import { ExecutionGraphScheduler } from "../uok/execution-graph.js";
12
12
  import type { UokGraphNode } from "../uok/contracts.js";
13
- import { runUnitPhase } from "./phases.js";
13
+ import { runUnitPhase } from "./unit-phase.js";
14
14
  import { decideDispatchNodeKind } from "./workflow-kernel.js";
15
15
 
16
16
  export type DispatchContract = "legacy-direct" | "uok-scheduler";
@@ -0,0 +1,149 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Worktree-safety helpers shared across auto-loop phase modules.
3
+
4
+ import { classifyProject } from "../detection.js";
5
+ import { resolveEffectiveUnitIsolationMode, getIsolationMode } from "../preferences.js";
6
+ import { createWorktreeSafetyModule, type WorktreeSafetyResult } from "../worktree-safety.js";
7
+ import { resolveWorktreeProjectRoot } from "../worktree-root.js";
8
+ import { resolveManifest } from "../unit-context-manifest.js";
9
+ import { debugLog } from "../debug-logger.js";
10
+ import { isSamePathLocal } from "./phase-helpers.js";
11
+ import { hasHeldMilestoneLease, reclaimMissingMilestoneLease } from "./milestone-lease-reclaim.js";
12
+ import type { IterationContext } from "./types.js";
13
+
14
+ export function shouldDegradeEmptyWorktreeToProjectRoot(
15
+ worktreeClassification: ReturnType<typeof classifyProject>,
16
+ projectRootClassification: ReturnType<typeof classifyProject>,
17
+ ): boolean {
18
+ return (
19
+ worktreeClassification.kind === "greenfield" &&
20
+ projectRootClassification.kind !== "greenfield" &&
21
+ projectRootClassification.kind !== "invalid-repo"
22
+ );
23
+ }
24
+
25
+ export function unitWritesSource(unitType: string): boolean | null {
26
+ if (unitType.startsWith("hook/")) return false;
27
+ // Backward compatibility: sidecar queues from older builds may persist
28
+ // prefixed unit types (e.g. "sidecar/quick-task").
29
+ const normalizedUnitType = unitType.startsWith("sidecar/")
30
+ ? unitType.slice("sidecar/".length)
31
+ : unitType;
32
+ const manifest = resolveManifest(normalizedUnitType);
33
+ if (!manifest) return null;
34
+ return manifest.tools.mode === "all" || manifest.tools.mode === "docs";
35
+ }
36
+
37
+ export function formatWorktreeSafetyFailure(result: Extract<WorktreeSafetyResult, { ok: false }>): string {
38
+ return `Worktree Safety failed (${result.kind}): ${result.reason} ${result.remediation}`;
39
+ }
40
+
41
+ export function formatWorktreeSafetyStopReason(result: Extract<WorktreeSafetyResult, { ok: false }>): string {
42
+ if (result.kind === "empty-worktree-with-project-content") {
43
+ return `Worktree Safety failed (${result.kind}). Run /gsd doctor fix, then /gsd auto.`;
44
+ }
45
+ return `Worktree Safety failed (${result.kind}).`;
46
+ }
47
+
48
+ export function resolveEmptyWorktreeWithProjectContent(
49
+ unitRoot: string,
50
+ projectRoot: string,
51
+ ): boolean {
52
+ if (isSamePathLocal(unitRoot, projectRoot)) return false;
53
+ const worktreeClassification = classifyProject(unitRoot);
54
+ if (worktreeClassification.kind !== "greenfield") return false;
55
+ const projectRootClassification = classifyProject(projectRoot);
56
+ return shouldDegradeEmptyWorktreeToProjectRoot(worktreeClassification, projectRootClassification);
57
+ }
58
+
59
+ export async function validateSourceWriteWorktreeSafety(
60
+ ic: IterationContext,
61
+ unitType: string,
62
+ unitId: string,
63
+ milestoneId: string | undefined,
64
+ phase: string,
65
+ ): Promise<{ action: "break"; reason: string } | null> {
66
+ const { ctx, pi, s, deps } = ic;
67
+ if (!s.basePath) return null;
68
+
69
+ // Custom engine workflows (graph-driven, registered via run dirs) define
70
+ // their own step ids that are not in the GSD UnitContextManifest. Don't
71
+ // fail closed for those — the custom engine owns its own dispatch
72
+ // contract. The fail-closed safety check applies only to built-in GSD
73
+ // units whose Tool Contract is registered in the manifest. Use a truthy
74
+ // check so undefined (test sessions that never set the field) routes
75
+ // through the safety check, matching the regression test contract.
76
+ if (s.activeEngineId) return null;
77
+
78
+ const writesSource = unitWritesSource(unitType);
79
+ if (writesSource === null) {
80
+ const msg = `Worktree Safety failed (missing-tool-contract): missing Tool Contract for ${unitType}. Add a UnitContextManifest entry before dispatching this Unit.`;
81
+ debugLog("worktreeSafety", {
82
+ phase,
83
+ unitType,
84
+ unitId,
85
+ milestoneId,
86
+ result: { ok: false, kind: "missing-tool-contract", reason: msg },
87
+ basePath: s.basePath,
88
+ });
89
+ ctx.ui.notify(msg, "error");
90
+ await deps.stopAuto(ctx, pi, msg);
91
+ return { action: "break", reason: "missing-tool-contract" };
92
+ }
93
+ if (!writesSource) return null;
94
+
95
+ const projectRoot = s.canonicalProjectRoot ?? resolveWorktreeProjectRoot(s.basePath, s.originalBasePath);
96
+ // A degraded session already fell back to the milestone branch in the
97
+ // project root — validating against the canonical worktree root there
98
+ // would fail every dispatch with a false invalid-root. The same applies
99
+ // to a stranded-recovery session that adopted the milestone branch.
100
+ const isolationMode = resolveEffectiveUnitIsolationMode(
101
+ deps.getIsolationMode(projectRoot),
102
+ s.isolationDegraded,
103
+ s.strandedRecoveryIsolationMode,
104
+ );
105
+ reclaimMissingMilestoneLease(s, milestoneId, isolationMode, phase);
106
+ const safety = createWorktreeSafetyModule();
107
+ const result = safety.validateUnitRoot({
108
+ unitType,
109
+ unitId,
110
+ writeScope: "source-writing",
111
+ projectRoot,
112
+ unitRoot: s.basePath,
113
+ milestoneId,
114
+ isolationMode,
115
+ expectedBranch:
116
+ isolationMode !== "none" && milestoneId ? deps.autoWorktreeBranch(milestoneId) : null,
117
+ emptyWorktreeWithProjectContent: resolveEmptyWorktreeWithProjectContent(s.basePath, projectRoot),
118
+ // The milestone lease coordinates concurrent workers on an isolated
119
+ // milestone worktree/branch, which is established by enterMilestone in
120
+ // worktree/branch modes. `none` mode has no per-milestone isolation and
121
+ // does not reliably claim a lease (e.g. a fresh headless resume of an
122
+ // already-active milestone never re-enters it), so requiring a held lease
123
+ // there would falsely fail dispatch. Enforce the lease only in isolated
124
+ // modes; none-mode safety still validates the unit root.
125
+ lease: s.workerId
126
+ ? {
127
+ required: isolationMode !== "none",
128
+ held: hasHeldMilestoneLease(s, milestoneId),
129
+ owner: s.workerId,
130
+ }
131
+ : undefined,
132
+ });
133
+
134
+ if (result.ok) return null;
135
+
136
+ const msg = formatWorktreeSafetyFailure(result);
137
+ debugLog("worktreeSafety", {
138
+ phase,
139
+ unitType,
140
+ unitId,
141
+ milestoneId,
142
+ result,
143
+ basePath: s.basePath,
144
+ projectRoot,
145
+ });
146
+ ctx.ui.notify(msg, "error");
147
+ await deps.stopAuto(ctx, pi, formatWorktreeSafetyStopReason(result));
148
+ return { action: "break", reason: result.kind };
149
+ }
@@ -1258,7 +1258,7 @@ export function teardownAutoWorktree(
1258
1258
  * still works after process restart when module state has been reset.
1259
1259
  */
1260
1260
  export function isInAutoWorktree(basePath: string): boolean {
1261
- const targetPath = isGsdWorktreePath(basePath) ? basePath : process.cwd();
1261
+ const targetPath = isGsdWorktreePath(basePath) ? basePath : safeCwd("");
1262
1262
  if (!isGsdWorktreePath(targetPath)) return false;
1263
1263
 
1264
1264
  const storedBase = getAutoWorktreeOriginalBase();
@@ -859,6 +859,20 @@ export function _warnIfWorktreeMissingForTest(
859
859
  return false;
860
860
  }
861
861
 
862
+ export function anchorProcessCwdForAutoResume(basePath: string): boolean {
863
+ try {
864
+ process.chdir(basePath);
865
+ return true;
866
+ } catch (err) {
867
+ logWarning(
868
+ "session",
869
+ `resume cwd anchor failed: ${err instanceof Error ? err.message : String(err)}`,
870
+ { file: "auto.ts", basePath },
871
+ );
872
+ return false;
873
+ }
874
+ }
875
+
862
876
  export function isAutoPaused(): boolean {
863
877
  return s.paused;
864
878
  }
@@ -1160,6 +1174,10 @@ function pauseAutoUnitIdentityMatches(expected: PauseAutoUnitIdentity | null): b
1160
1174
  s.currentUnit.startedAt === expected.startedAt;
1161
1175
  }
1162
1176
 
1177
+ function shouldPreserveCoordinationForPause(errorContext?: ErrorContext): boolean {
1178
+ return errorContext?.category === "provider" && errorContext.isTransient === true;
1179
+ }
1180
+
1163
1181
  function setLifecycleOutcome(
1164
1182
  ctx: ExtensionContext | undefined,
1165
1183
  input: {
@@ -2120,7 +2138,7 @@ export async function pauseAuto(
2120
2138
  clearLock(lockBase());
2121
2139
  }
2122
2140
 
2123
- if (s.workerId) {
2141
+ if (s.workerId && !shouldPreserveCoordinationForPause(_errorContext)) {
2124
2142
  try {
2125
2143
  if (s.currentMilestoneId && s.milestoneLeaseToken) {
2126
2144
  releaseMilestoneLease(s.workerId, s.currentMilestoneId, s.milestoneLeaseToken);
@@ -2638,6 +2656,7 @@ export async function startAuto(
2638
2656
  }
2639
2657
  // ADR-016 phase 2 / B3 (#5621): paused-resume worktree-path adoption.
2640
2658
  buildLifecycle().resumeFromPausedSession(base, resumeWorktreePath);
2659
+ anchorProcessCwdForAutoResume(s.basePath || base);
2641
2660
  // Rebuild scope now that s.basePath reflects the actual worktree (or project root).
2642
2661
  rebuildScope(s.basePath, s.currentMilestoneId);
2643
2662
  // Ensure the workflow-logger audit log is pinned to the project root
@@ -8,7 +8,12 @@ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
8
8
  import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@gsd/pi-coding-agent";
9
9
 
10
10
  import { logWarning } from "../workflow-logger.js";
11
- import { openWorkflowDatabase } from "../db-workspace.js";
11
+ import {
12
+ getWorkflowDatabaseStatus,
13
+ openWorkflowDatabase,
14
+ type WorkflowDatabaseOpenResult,
15
+ type WorkflowDatabaseStatus,
16
+ } from "../db-workspace.js";
12
17
  import { getAutoWorktreePath } from "../auto-worktree.js";
13
18
  import { resolveWorktreeProjectRoot } from "../worktree-root.js";
14
19
  import { worktreesDirs } from "../worktree-placement.js";
@@ -69,15 +74,60 @@ export function resolveWorkflowToolBasePath(
69
74
 
70
75
  export { resolveProjectRootDbPath } from "../db-workspace.js";
71
76
 
77
+ type WorkflowDatabaseOpenFailure = Extract<WorkflowDatabaseOpenResult, { ok: false }>;
78
+
79
+ function sqliteProviderHint(status: WorkflowDatabaseStatus, nodeVersion: string): string {
80
+ if (status.provider) return `Provider: ${status.provider}.`;
81
+
82
+ const major = Number.parseInt(nodeVersion.split(".")[0] ?? "", 10);
83
+ if (Number.isFinite(major) && major < 22) {
84
+ return (
85
+ `No SQLite provider available. Upgrade Node to >= 22.0.0 (current: v${nodeVersion}), ` +
86
+ "use the packaged GSD runtime, or install/restore better-sqlite3 in this runtime."
87
+ );
88
+ }
89
+
90
+ return (
91
+ "No SQLite provider available. Use a Node build with node:sqlite enabled, " +
92
+ "run the packaged GSD runtime, or install/restore better-sqlite3 in this runtime."
93
+ );
94
+ }
95
+
96
+ function dbOpenPhaseHint(status: WorkflowDatabaseStatus): string {
97
+ if (status.lastPhase === "open") return "The database file could not be opened";
98
+ if (status.lastPhase === "initSchema") return "The database schema could not be initialized";
99
+ if (status.lastPhase === "vacuum-recovery") return "Corruption recovery (VACUUM) failed";
100
+ if (status.attempted) return "The database could not be opened";
101
+ return "The database provider could not be loaded";
102
+ }
103
+
104
+ export function formatWorkflowDatabaseOpenFailure(
105
+ result: WorkflowDatabaseOpenFailure,
106
+ status?: WorkflowDatabaseStatus,
107
+ nodeVersion: string = process.versions.node,
108
+ ): string {
109
+ if (result.reason === "missing-gsd-dir") {
110
+ return `ensureDbOpen failed — no .gsd directory found at ${result.location.projectGsd}`;
111
+ }
112
+
113
+ if (result.reason === "missing-database") {
114
+ return `ensureDbOpen failed — no GSD database found at ${result.location.projectDb}`;
115
+ }
116
+
117
+ const resolvedStatus = status ?? getWorkflowDatabaseStatus();
118
+ const detail = result.error?.message ?? resolvedStatus.lastError?.message ?? "";
119
+ const detailSuffix = detail ? ` (${detail})` : "";
120
+ return (
121
+ `ensureDbOpen failed for ${result.location.projectDb}: ` +
122
+ `${dbOpenPhaseHint(resolvedStatus)}${detailSuffix}. ${sqliteProviderHint(resolvedStatus, nodeVersion)}`
123
+ );
124
+ }
125
+
72
126
  export async function ensureDbOpen(basePath: string = safeWorkspaceCwd()): Promise<boolean> {
73
127
  const result = openWorkflowDatabase(basePath);
74
128
  if (result.ok) return true;
75
129
 
76
- if (result.reason === "missing-gsd-dir") {
77
- logWarning("bootstrap", "ensureDbOpen failed — no .gsd directory found");
78
- } else {
79
- logWarning("bootstrap", `ensureDbOpen failed: ${result.error?.message ?? "open failed"}`);
80
- }
130
+ logWarning("bootstrap", formatWorkflowDatabaseOpenFailure(result));
81
131
  return false;
82
132
  }
83
133
 
@@ -102,7 +102,7 @@ export function formatMcpStatusReport(servers: McpServerStatus[]): string {
102
102
  : s.connected
103
103
  ? `connected — ${s.toolCount} tools`
104
104
  : s.available
105
- ? `available — ${s.toolCount} tools`
105
+ ? `probe available — ${s.toolCount} tools`
106
106
  : "disconnected";
107
107
  const warningText = s.envWarnings?.length ? ` — ${s.envWarnings.length} warning(s)` : "";
108
108
  lines.push(` ${icon} ${s.name} (${s.transport}) — ${status}${warningText}`);
@@ -128,7 +128,7 @@ export function formatMcpServerDetail(server: McpServerDetail): string {
128
128
  lines.push(` Status: error`);
129
129
  lines.push(` Error: ${server.error}`);
130
130
  } else if (server.connected || server.available) {
131
- lines.push(` Status: ${server.connected ? "connected" : "available"}`);
131
+ lines.push(` Status: ${server.connected ? "connected" : "probe available"}`);
132
132
  lines.push(` Tools: ${server.toolCount}`);
133
133
  if (server.tools.length > 0) {
134
134
  lines.push("");
@@ -80,13 +80,13 @@ function datePrefix(): string {
80
80
 
81
81
  // ─── State Types ─────────────────────────────────────────────────────────────
82
82
 
83
- interface WorkflowPhaseState {
83
+ export interface WorkflowPhaseState {
84
84
  name: string;
85
85
  index: number;
86
86
  status: "pending" | "active" | "completed";
87
87
  }
88
88
 
89
- interface WorkflowState {
89
+ export interface WorkflowState {
90
90
  template: string;
91
91
  templateName: string;
92
92
  description: string;
@@ -99,6 +99,13 @@ interface WorkflowState {
99
99
  artifactDir: string;
100
100
  }
101
101
 
102
+ export function isWorkflowStateComplete(state: WorkflowState): boolean {
103
+ if (state.completedAt) return true;
104
+ return Array.isArray(state.phases) &&
105
+ state.phases.length > 0 &&
106
+ state.phases.every((phase) => phase.status === "completed");
107
+ }
108
+
102
109
  /**
103
110
  * Write a STATE.json file to track workflow execution state.
104
111
  */
@@ -133,7 +140,7 @@ function writeWorkflowState(
133
140
  * Scan all workflow artifact directories for in-progress STATE.json files.
134
141
  * Returns workflows that were started but not completed.
135
142
  */
136
- function findInProgressWorkflows(basePath: string): WorkflowState[] {
143
+ export function findInProgressWorkflows(basePath: string): WorkflowState[] {
137
144
  const workflowsRoot = join(gsdRoot(basePath), "workflows");
138
145
  if (!existsSync(workflowsRoot)) return [];
139
146
 
@@ -152,7 +159,7 @@ function findInProgressWorkflows(basePath: string): WorkflowState[] {
152
159
  try {
153
160
  const raw = readFileSync(statePath, "utf-8");
154
161
  const state = JSON.parse(raw) as WorkflowState;
155
- if (!state.completedAt) {
162
+ if (!isWorkflowStateComplete(state)) {
156
163
  results.push(state);
157
164
  }
158
165
  } catch { /* corrupted state file — skip */ }
@@ -270,6 +270,35 @@ export function getMilestoneSlices(milestoneId: string): SliceRow[] {
270
270
  return rows.map(rowToSlice);
271
271
  }
272
272
 
273
+ /**
274
+ * Load slices for many milestones in a single query. Returns a Map keyed by
275
+ * milestone_id, preserving `ORDER BY sequence, id` within each bucket.
276
+ */
277
+ export function getSlicesByMilestoneIds(milestoneIds: readonly string[]): Map<string, SliceRow[]> {
278
+ const db = getDbOrNull();
279
+ if (!db || milestoneIds.length === 0) return new Map();
280
+ const idList = [...milestoneIds];
281
+ const placeholders = idList.map((_, i) => `:mid${i}`).join(",");
282
+ const params: Record<string, unknown> = {};
283
+ idList.forEach((id, i) => {
284
+ params[`:mid${i}`] = id;
285
+ });
286
+ const rows = db
287
+ .prepare(`SELECT * FROM slices WHERE milestone_id IN (${placeholders}) ORDER BY milestone_id, sequence, id`)
288
+ .all(params) as Record<string, unknown>[];
289
+ const byMilestone = new Map<string, SliceRow[]>();
290
+ for (const row of rows) {
291
+ const slice = rowToSlice(row);
292
+ const bucket = byMilestone.get(slice.milestone_id);
293
+ if (bucket) {
294
+ bucket.push(slice);
295
+ } else {
296
+ byMilestone.set(slice.milestone_id, [slice]);
297
+ }
298
+ }
299
+ return byMilestone;
300
+ }
301
+
273
302
  /** Dispatch-eligibility shape consumed by decision-path callers (ADR-017). */
274
303
  export interface MilestoneSliceSummary {
275
304
  id: string;