gsd-pi 2.67.0-dev.1cd1e0f → 2.67.0-dev.2367d7e

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 (257) hide show
  1. package/README.md +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +155 -70
  3. package/dist/resources/extensions/gsd/auto/phases.js +17 -0
  4. package/dist/resources/extensions/gsd/auto/session.js +10 -0
  5. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +12 -0
  6. package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
  7. package/dist/resources/extensions/gsd/auto-start.js +16 -30
  8. package/dist/resources/extensions/gsd/auto-worktree.js +62 -15
  9. package/dist/resources/extensions/gsd/auto.js +121 -59
  10. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +11 -435
  11. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -4
  12. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +7 -64
  13. package/dist/resources/extensions/gsd/bootstrap/system-context.js +7 -2
  14. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -8
  15. package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
  16. package/dist/resources/extensions/gsd/commands/handlers/core.js +39 -25
  17. package/dist/resources/extensions/gsd/commands/index.js +8 -1
  18. package/dist/resources/extensions/gsd/commands-mcp-status.js +43 -7
  19. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -4
  20. package/dist/resources/extensions/gsd/doctor-proactive.js +3 -3
  21. package/dist/resources/extensions/gsd/doctor.js +8 -4
  22. package/dist/resources/extensions/gsd/gsd-db.js +11 -0
  23. package/dist/resources/extensions/gsd/guided-flow.js +56 -31
  24. package/dist/resources/extensions/gsd/init-wizard.js +37 -0
  25. package/dist/resources/extensions/gsd/interrupted-session.js +146 -0
  26. package/dist/resources/extensions/gsd/mcp-project-config.js +83 -0
  27. package/dist/resources/extensions/gsd/state.js +7 -2
  28. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +508 -0
  29. package/dist/resources/extensions/gsd/workflow-logger.js +18 -3
  30. package/dist/resources/extensions/gsd/workflow-mcp.js +261 -0
  31. package/dist/web/standalone/.next/BUILD_ID +1 -1
  32. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  33. package/dist/web/standalone/.next/build-manifest.json +3 -3
  34. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  35. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  36. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  43. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  46. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  51. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/index.html +1 -1
  55. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  56. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  57. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  58. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  63. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  64. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  65. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  66. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  67. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  68. package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +9 -0
  69. package/dist/web/standalone/.next/static/chunks/app/{page-0c485498795110d6.js → page-f1e30ab6bb269149.js} +1 -1
  70. package/dist/web/standalone/.next/static/chunks/{webpack-b49b09f97429b5d0.js → webpack-6e4d7e9a4f57bed4.js} +1 -1
  71. package/package.json +4 -2
  72. package/packages/mcp-server/README.md +38 -0
  73. package/packages/mcp-server/dist/cli.d.ts +9 -0
  74. package/packages/mcp-server/dist/cli.d.ts.map +1 -0
  75. package/packages/mcp-server/dist/cli.js +58 -0
  76. package/packages/mcp-server/dist/cli.js.map +1 -0
  77. package/packages/mcp-server/dist/index.d.ts +20 -0
  78. package/packages/mcp-server/dist/index.d.ts.map +1 -0
  79. package/packages/mcp-server/dist/index.js +14 -0
  80. package/packages/mcp-server/dist/index.js.map +1 -0
  81. package/packages/mcp-server/dist/readers/captures.d.ts +25 -0
  82. package/packages/mcp-server/dist/readers/captures.d.ts.map +1 -0
  83. package/packages/mcp-server/dist/readers/captures.js +67 -0
  84. package/packages/mcp-server/dist/readers/captures.js.map +1 -0
  85. package/packages/mcp-server/dist/readers/doctor-lite.d.ts +20 -0
  86. package/packages/mcp-server/dist/readers/doctor-lite.d.ts.map +1 -0
  87. package/packages/mcp-server/dist/readers/doctor-lite.js +173 -0
  88. package/packages/mcp-server/dist/readers/doctor-lite.js.map +1 -0
  89. package/packages/mcp-server/dist/readers/index.d.ts +14 -0
  90. package/packages/mcp-server/dist/readers/index.d.ts.map +1 -0
  91. package/packages/mcp-server/dist/readers/index.js +10 -0
  92. package/packages/mcp-server/dist/readers/index.js.map +1 -0
  93. package/packages/mcp-server/dist/readers/knowledge.d.ts +18 -0
  94. package/packages/mcp-server/dist/readers/knowledge.d.ts.map +1 -0
  95. package/packages/mcp-server/dist/readers/knowledge.js +82 -0
  96. package/packages/mcp-server/dist/readers/knowledge.js.map +1 -0
  97. package/packages/mcp-server/dist/readers/metrics.d.ts +32 -0
  98. package/packages/mcp-server/dist/readers/metrics.d.ts.map +1 -0
  99. package/packages/mcp-server/dist/readers/metrics.js +74 -0
  100. package/packages/mcp-server/dist/readers/metrics.js.map +1 -0
  101. package/packages/mcp-server/dist/readers/paths.d.ts +42 -0
  102. package/packages/mcp-server/dist/readers/paths.d.ts.map +1 -0
  103. package/packages/mcp-server/dist/readers/paths.js +199 -0
  104. package/packages/mcp-server/dist/readers/paths.js.map +1 -0
  105. package/packages/mcp-server/dist/readers/roadmap.d.ts +26 -0
  106. package/packages/mcp-server/dist/readers/roadmap.d.ts.map +1 -0
  107. package/packages/mcp-server/dist/readers/roadmap.js +194 -0
  108. package/packages/mcp-server/dist/readers/roadmap.js.map +1 -0
  109. package/packages/mcp-server/dist/readers/state.d.ts +43 -0
  110. package/packages/mcp-server/dist/readers/state.d.ts.map +1 -0
  111. package/packages/mcp-server/dist/readers/state.js +184 -0
  112. package/packages/mcp-server/dist/readers/state.js.map +1 -0
  113. package/packages/mcp-server/dist/server.d.ts +28 -0
  114. package/packages/mcp-server/dist/server.d.ts.map +1 -0
  115. package/packages/mcp-server/dist/server.js +319 -0
  116. package/packages/mcp-server/dist/server.js.map +1 -0
  117. package/packages/mcp-server/dist/session-manager.d.ts +54 -0
  118. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -0
  119. package/packages/mcp-server/dist/session-manager.js +284 -0
  120. package/packages/mcp-server/dist/session-manager.js.map +1 -0
  121. package/packages/mcp-server/dist/types.d.ts +61 -0
  122. package/packages/mcp-server/dist/types.d.ts.map +1 -0
  123. package/packages/mcp-server/dist/types.js +11 -0
  124. package/packages/mcp-server/dist/types.js.map +1 -0
  125. package/packages/mcp-server/dist/workflow-tools.d.ts +9 -0
  126. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -0
  127. package/packages/mcp-server/dist/workflow-tools.js +532 -0
  128. package/packages/mcp-server/dist/workflow-tools.js.map +1 -0
  129. package/packages/mcp-server/src/server.ts +6 -2
  130. package/packages/mcp-server/src/workflow-tools.test.ts +976 -0
  131. package/packages/mcp-server/src/workflow-tools.ts +997 -0
  132. package/packages/mcp-server/tsconfig.json +1 -1
  133. package/packages/pi-agent-core/dist/agent-loop.js +14 -6
  134. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  135. package/packages/pi-agent-core/src/agent-loop.test.ts +53 -0
  136. package/packages/pi-agent-core/src/agent-loop.ts +20 -6
  137. package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts +43 -0
  138. package/packages/pi-coding-agent/dist/core/contextual-tips.d.ts.map +1 -0
  139. package/packages/pi-coding-agent/dist/core/contextual-tips.js +208 -0
  140. package/packages/pi-coding-agent/dist/core/contextual-tips.js.map +1 -0
  141. package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts +2 -0
  142. package/packages/pi-coding-agent/dist/core/contextual-tips.test.d.ts.map +1 -0
  143. package/packages/pi-coding-agent/dist/core/contextual-tips.test.js +227 -0
  144. package/packages/pi-coding-agent/dist/core/contextual-tips.test.js.map +1 -0
  145. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
  146. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  147. package/packages/pi-coding-agent/dist/core/index.js +1 -0
  148. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  149. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts +2 -0
  150. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.d.ts.map +1 -0
  151. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +28 -0
  152. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -0
  153. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  154. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  155. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +17 -12
  156. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  157. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  158. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +19 -0
  159. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts +4 -0
  161. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  162. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +14 -0
  163. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  164. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  165. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  166. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +15 -12
  167. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  168. package/packages/pi-coding-agent/src/core/contextual-tips.test.ts +259 -0
  169. package/packages/pi-coding-agent/src/core/contextual-tips.ts +232 -0
  170. package/packages/pi-coding-agent/src/core/index.ts +2 -0
  171. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +54 -0
  172. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +18 -12
  173. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +21 -0
  174. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +19 -0
  175. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +19 -15
  176. package/packages/rpc-client/dist/index.d.ts +10 -0
  177. package/packages/rpc-client/dist/index.d.ts.map +1 -0
  178. package/packages/rpc-client/dist/index.js +9 -0
  179. package/packages/rpc-client/dist/index.js.map +1 -0
  180. package/packages/rpc-client/dist/jsonl.d.ts +17 -0
  181. package/packages/rpc-client/dist/jsonl.d.ts.map +1 -0
  182. package/packages/rpc-client/dist/jsonl.js +54 -0
  183. package/packages/rpc-client/dist/jsonl.js.map +1 -0
  184. package/packages/rpc-client/dist/rpc-client.d.ts +259 -0
  185. package/packages/rpc-client/dist/rpc-client.d.ts.map +1 -0
  186. package/packages/rpc-client/dist/rpc-client.js +541 -0
  187. package/packages/rpc-client/dist/rpc-client.js.map +1 -0
  188. package/packages/rpc-client/dist/rpc-client.test.d.ts +2 -0
  189. package/packages/rpc-client/dist/rpc-client.test.d.ts.map +1 -0
  190. package/packages/rpc-client/dist/rpc-client.test.js +477 -0
  191. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -0
  192. package/packages/rpc-client/dist/rpc-types.d.ts +566 -0
  193. package/packages/rpc-client/dist/rpc-types.d.ts.map +1 -0
  194. package/packages/rpc-client/dist/rpc-types.js +12 -0
  195. package/packages/rpc-client/dist/rpc-types.js.map +1 -0
  196. package/scripts/ensure-workspace-builds.cjs +2 -0
  197. package/scripts/link-workspace-packages.cjs +21 -14
  198. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +193 -93
  199. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +173 -79
  200. package/src/resources/extensions/gsd/auto/phases.ts +25 -0
  201. package/src/resources/extensions/gsd/auto/session.ts +10 -0
  202. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +20 -0
  203. package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
  204. package/src/resources/extensions/gsd/auto-start.ts +23 -55
  205. package/src/resources/extensions/gsd/auto-worktree.ts +59 -15
  206. package/src/resources/extensions/gsd/auto.ts +133 -64
  207. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +22 -435
  208. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -5
  209. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +7 -72
  210. package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -2
  211. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +122 -6
  212. package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
  213. package/src/resources/extensions/gsd/commands/handlers/core.ts +53 -26
  214. package/src/resources/extensions/gsd/commands/index.ts +7 -1
  215. package/src/resources/extensions/gsd/commands-mcp-status.ts +53 -7
  216. package/src/resources/extensions/gsd/doctor-git-checks.ts +4 -4
  217. package/src/resources/extensions/gsd/doctor-proactive.ts +3 -3
  218. package/src/resources/extensions/gsd/doctor.ts +9 -5
  219. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  220. package/src/resources/extensions/gsd/guided-flow.ts +66 -36
  221. package/src/resources/extensions/gsd/init-wizard.ts +40 -0
  222. package/src/resources/extensions/gsd/interrupted-session.ts +224 -0
  223. package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
  224. package/src/resources/extensions/gsd/state.ts +7 -1
  225. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +29 -0
  226. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +668 -2
  227. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +14 -4
  228. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +21 -0
  229. package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +101 -0
  230. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +380 -2
  231. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +66 -0
  232. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +30 -0
  233. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +12 -0
  234. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +2 -2
  235. package/src/resources/extensions/gsd/tests/integration/doctor-fixlevel.test.ts +52 -1
  236. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +2 -9
  237. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +0 -33
  238. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +169 -0
  239. package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +146 -0
  240. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +136 -0
  241. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +85 -0
  242. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +15 -0
  243. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +11 -0
  244. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +16 -0
  245. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +500 -0
  246. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +625 -0
  247. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +629 -0
  248. package/src/resources/extensions/gsd/workflow-logger.ts +19 -3
  249. package/src/resources/extensions/gsd/workflow-mcp.ts +320 -0
  250. package/dist/web/standalone/.next/static/chunks/6502.b804e48b7919f55e.js +0 -9
  251. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts +0 -13
  252. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.d.ts.map +0 -1
  253. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js +0 -27
  254. package/packages/pi-coding-agent/dist/modes/interactive/provider-auth-setup.js.map +0 -1
  255. package/packages/pi-coding-agent/src/modes/interactive/provider-auth-setup.ts +0 -40
  256. /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → WMDT_0C0XDkBKtsAI_AX4}/_buildManifest.js +0 -0
  257. /package/dist/web/standalone/.next/static/{PHqEommYRR8CRn3i84CGM → WMDT_0C0XDkBKtsAI_AX4}/_ssgManifest.js +0 -0
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import { deriveState } from "./state.js";
13
13
  import { parseUnitId } from "./unit-id.js";
14
+ import { assessInterruptedSession, readPausedSessionMetadata, } from "./interrupted-session.js";
14
15
  import { getManifestStatus } from "./files.js";
15
16
  export { inlinePriorMilestoneSummary } from "./files.js";
16
17
  import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
@@ -18,7 +19,7 @@ import { gsdRoot, resolveMilestoneFile, resolveMilestonePath, resolveDir, milest
18
19
  import { invalidateAllCaches } from "./cache.js";
19
20
  import { clearActivityLogState } from "./activity-log.js";
20
21
  import { synthesizeCrashRecovery, getDeepDiagnostic, readActiveMilestoneId, } from "./session-forensics.js";
21
- import { writeLock, clearLock, readCrashLock, isLockProcessAlive, } from "./crash-recovery.js";
22
+ import { writeLock, clearLock, readCrashLock, isLockProcessAlive, formatCrashInfo, } from "./crash-recovery.js";
22
23
  import { acquireSessionLock, getSessionLockStatus, releaseSessionLock, updateSessionLock, } from "./session-lock.js";
23
24
  import { resolveAutoSupervisorConfig, loadEffectiveGSDPreferences, getIsolationMode, } from "./preferences.js";
24
25
  import { sendDesktopNotification } from "./notifications.js";
@@ -34,7 +35,8 @@ import { clearSkillSnapshot } from "./skill-discovery.js";
34
35
  import { captureAvailableSkills, resetSkillTelemetry, } from "./skill-telemetry.js";
35
36
  import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
36
37
  import { initMetrics, resetMetrics, getLedger, getProjectTotals, formatCost, formatTokenCount, } from "./metrics.js";
37
- import { setLogBasePath, logWarning } from "./workflow-logger.js";
38
+ import { logWarning } from "./workflow-logger.js";
39
+ import { homedir } from "node:os";
38
40
  import { join } from "node:path";
39
41
  import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
40
42
  import { atomicWriteSync } from "./atomic-write.js";
@@ -79,6 +81,27 @@ export { MAX_UNIT_DISPATCHES, STUB_RECOVERY_THRESHOLD, MAX_LIFETIME_DISPATCHES,
79
81
  const s = new AutoSession();
80
82
  /** Throttle STATE.md rebuilds — at most once per 30 seconds */
81
83
  const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
84
+ function captureProjectRootEnv(projectRoot) {
85
+ if (!s.projectRootEnvCaptured) {
86
+ s.hadProjectRootEnv = Object.prototype.hasOwnProperty.call(process.env, "GSD_PROJECT_ROOT");
87
+ s.previousProjectRootEnv = process.env.GSD_PROJECT_ROOT ?? null;
88
+ s.projectRootEnvCaptured = true;
89
+ }
90
+ process.env.GSD_PROJECT_ROOT = projectRoot;
91
+ }
92
+ function restoreProjectRootEnv() {
93
+ if (!s.projectRootEnvCaptured)
94
+ return;
95
+ if (s.hadProjectRootEnv && s.previousProjectRootEnv !== null) {
96
+ process.env.GSD_PROJECT_ROOT = s.previousProjectRootEnv;
97
+ }
98
+ else {
99
+ delete process.env.GSD_PROJECT_ROOT;
100
+ }
101
+ s.previousProjectRootEnv = null;
102
+ s.hadProjectRootEnv = false;
103
+ s.projectRootEnvCaptured = false;
104
+ }
82
105
  export function shouldUseWorktreeIsolation() {
83
106
  const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
84
107
  if (prefs?.isolation === "worktree")
@@ -315,6 +338,7 @@ function handleLostSessionLock(ctx, lockStatus) {
315
338
  s.active = false;
316
339
  s.paused = false;
317
340
  clearUnitTimeout();
341
+ restoreProjectRootEnv();
318
342
  deregisterSigtermHandler();
319
343
  clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
320
344
  const base = lockBase();
@@ -345,6 +369,7 @@ function cleanupAfterLoopExit(ctx) {
345
369
  s.currentUnit = null;
346
370
  s.active = false;
347
371
  clearUnitTimeout();
372
+ restoreProjectRootEnv();
348
373
  // Clear crash lock and release session lock so the next `/gsd next` does
349
374
  // not see a stale lock with the current PID and treat it as a "remote"
350
375
  // session (which would cause it to SIGTERM itself). (#2730)
@@ -601,6 +626,7 @@ export async function stopAuto(ctx, pi, reason) {
601
626
  ctx?.ui.setStatus("gsd-auto", undefined);
602
627
  ctx?.ui.setWidget("gsd-progress", undefined);
603
628
  ctx?.ui.setFooter(undefined);
629
+ restoreProjectRootEnv();
604
630
  // Reset all session state in one call
605
631
  s.reset();
606
632
  }
@@ -641,6 +667,8 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
641
667
  stepMode: s.stepMode,
642
668
  pausedAt: new Date().toISOString(),
643
669
  sessionFile: s.pausedSessionFile,
670
+ unitType: s.currentUnit?.type ?? undefined,
671
+ unitId: s.currentUnit?.id ?? undefined,
644
672
  activeEngineId: s.activeEngineId,
645
673
  activeRunDir: s.activeRunDir,
646
674
  autoStartTime: s.autoStartTime,
@@ -674,6 +702,7 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
674
702
  _resetPendingResolve();
675
703
  s.active = false;
676
704
  s.paused = true;
705
+ restoreProjectRootEnv();
677
706
  s.pendingVerificationRetry = null;
678
707
  s.verificationRetryCount.clear();
679
708
  ctx?.ui.setStatus("gsd-auto", "paused");
@@ -828,38 +857,54 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
828
857
  return;
829
858
  }
830
859
  const requestedStepMode = options?.step ?? false;
860
+ const interruptedAssessment = options?.interrupted ?? null;
831
861
  // Escape stale worktree cwd from a previous milestone (#608).
832
862
  base = escapeStaleWorktree(base);
863
+ const freshStartAssessment = interruptedAssessment
864
+ ?? await assessInterruptedSession(base);
865
+ if (freshStartAssessment.classification === "running") {
866
+ const pid = freshStartAssessment.lock?.pid;
867
+ ctx.ui.notify(pid
868
+ ? `Another auto-mode session (PID ${pid}) appears to be running.\nStop it with \`kill ${pid}\` before starting a new session.`
869
+ : "Another auto-mode session appears to be running.", "error");
870
+ return;
871
+ }
833
872
  // If resuming from paused state, just re-activate and dispatch next unit.
834
873
  // Check persisted paused-session first (#1383) — survives /exit.
835
874
  if (!s.paused) {
836
875
  try {
876
+ const meta = freshStartAssessment.pausedSession ?? readPausedSessionMetadata(base);
837
877
  const pausedPath = join(gsdRoot(base), "runtime", "paused-session.json");
838
- if (existsSync(pausedPath)) {
839
- const meta = JSON.parse(readFileSync(pausedPath, "utf-8"));
840
- if (meta.activeEngineId && meta.activeEngineId !== "dev") {
841
- // Custom workflow resume — restore engine state
842
- s.activeEngineId = meta.activeEngineId;
843
- s.activeRunDir = meta.activeRunDir ?? null;
844
- s.originalBasePath = meta.originalBasePath || base;
845
- s.stepMode = meta.stepMode ?? requestedStepMode;
846
- s.autoStartTime = meta.autoStartTime || Date.now();
847
- s.paused = true;
848
- // Don't delete pause file yet — defer until lock is acquired.
849
- // If lock fails, the file must survive for retry.
850
- s.pausedSessionFile = pausedPath;
851
- ctx.ui.notify(`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`, "info");
878
+ if (meta?.activeEngineId && meta.activeEngineId !== "dev") {
879
+ // Custom workflow resume — restore engine state
880
+ s.activeEngineId = meta.activeEngineId;
881
+ s.activeRunDir = meta.activeRunDir ?? null;
882
+ s.originalBasePath = meta.originalBasePath || base;
883
+ s.stepMode = meta.stepMode ?? requestedStepMode;
884
+ s.autoStartTime = meta.autoStartTime || Date.now();
885
+ s.paused = true;
886
+ try {
887
+ unlinkSync(pausedPath);
852
888
  }
853
- else if (meta.milestoneId) {
889
+ catch (e) {
890
+ logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
891
+ }
892
+ ctx.ui.notify(`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`, "info");
893
+ }
894
+ else if (meta?.milestoneId) {
895
+ const shouldResumePausedSession = freshStartAssessment.classification === "recoverable"
896
+ && (freshStartAssessment.hasResumableDiskState
897
+ || !!freshStartAssessment.recoveryPrompt
898
+ || !!freshStartAssessment.lock);
899
+ if (shouldResumePausedSession) {
854
900
  // Validate the milestone still exists and isn't already complete (#1664).
855
901
  const mDir = resolveMilestonePath(base, meta.milestoneId);
856
902
  const summaryFile = resolveMilestoneFile(base, meta.milestoneId, "SUMMARY");
857
903
  if (!mDir || summaryFile) {
858
- // Stale milestone — clean up and fall through to fresh bootstrap
859
904
  try {
860
905
  unlinkSync(pausedPath);
861
906
  }
862
- catch (err) { /* non-fatal */
907
+ catch (err) {
863
908
  logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
864
909
  }
865
910
  ctx.ui.notify(`Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`, "info");
@@ -868,12 +913,26 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
868
913
  s.currentMilestoneId = meta.milestoneId;
869
914
  s.originalBasePath = meta.originalBasePath || base;
870
915
  s.stepMode = meta.stepMode ?? requestedStepMode;
916
+ s.pausedSessionFile = meta.sessionFile ?? null;
917
+ s.pausedUnitType = meta.unitType ?? null;
918
+ s.pausedUnitId = meta.unitId ?? null;
871
919
  s.autoStartTime = meta.autoStartTime || Date.now();
872
920
  s.paused = true;
873
- // Don't delete pause file yet — defer until lock is acquired.
874
- // If lock fails, the file must survive for retry.
875
- s.pausedSessionFile = pausedPath;
876
- ctx.ui.notify(`Resuming paused session for ${meta.milestoneId}${meta.worktreePath ? ` (worktree)` : ""}.`, "info");
921
+ try {
922
+ unlinkSync(pausedPath);
923
+ }
924
+ catch (e) {
925
+ logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
926
+ }
927
+ ctx.ui.notify(`Resuming paused session for ${meta.milestoneId}${meta.worktreePath && existsSync(meta.worktreePath) ? ` (worktree)` : ""}.`, "info");
928
+ }
929
+ }
930
+ else if (existsSync(pausedPath)) {
931
+ try {
932
+ unlinkSync(pausedPath);
933
+ }
934
+ catch (e) {
935
+ logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
877
936
  }
878
937
  }
879
938
  }
@@ -882,6 +941,30 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
882
941
  // Malformed or missing — proceed with fresh bootstrap
883
942
  logWarning("session", `paused-session restore failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
884
943
  }
944
+ // Guard against zero/missing autoStartTime after resume (#3585)
945
+ if (!s.autoStartTime || s.autoStartTime <= 0)
946
+ s.autoStartTime = Date.now();
947
+ }
948
+ if (!s.paused) {
949
+ s.stepMode = requestedStepMode;
950
+ }
951
+ if (freshStartAssessment.lock) {
952
+ clearLock(base);
953
+ }
954
+ if (!s.paused) {
955
+ s.pendingCrashRecovery =
956
+ freshStartAssessment.classification === "recoverable"
957
+ ? freshStartAssessment.recoveryPrompt
958
+ : null;
959
+ if (freshStartAssessment.classification === "recoverable" && freshStartAssessment.lock) {
960
+ const info = formatCrashInfo(freshStartAssessment.lock);
961
+ if (freshStartAssessment.recoveryToolCallCount > 0) {
962
+ ctx.ui.notify(`${info}\nRecovered ${freshStartAssessment.recoveryToolCallCount} tool calls from crashed session. Resuming with full context.`, "warning");
963
+ }
964
+ else if (freshStartAssessment.hasResumableDiskState) {
965
+ ctx.ui.notify(`${info}\nResuming from disk state.`, "warning");
966
+ }
967
+ }
885
968
  }
886
969
  if (s.paused) {
887
970
  const resumeLock = acquireSessionLock(base);
@@ -906,29 +989,19 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
906
989
  s.active = true;
907
990
  s.verbose = verboseMode;
908
991
  s.stepMode = requestedStepMode;
909
- // Preserve the original cmdCtx (ExtensionCommandContext with newSession)
910
- // when resuming from a provider-error pause. The resume callback receives
911
- // an ExtensionContext (from the agent_end hook) which lacks newSession —
912
- // using it would crash runUnit with "newSession is not a function".
913
- // Only override if the new ctx actually has newSession (user-initiated resume).
914
- if ("newSession" in ctx && typeof ctx.newSession === "function") {
915
- s.cmdCtx = ctx;
916
- }
917
- else if (!s.cmdCtx) {
918
- // No saved cmdCtx — this shouldn't happen, but handle gracefully
919
- s.cmdCtx = ctx;
920
- }
921
- // else: keep existing s.cmdCtx which has the real newSession
992
+ s.cmdCtx = ctx;
922
993
  s.basePath = base;
923
- setLogBasePath(base);
924
- if (!s.autoStartTime || s.autoStartTime <= 0)
925
- s.autoStartTime = Date.now();
926
994
  s.unitDispatchCount.clear();
927
995
  s.unitLifetimeDispatches.clear();
928
996
  if (!getLedger())
929
997
  initMetrics(base);
930
998
  if (s.currentMilestoneId)
931
999
  setActiveMilestoneId(base, s.currentMilestoneId);
1000
+ // Re-register health level notification callback lost across process restart
1001
+ setLevelChangeCallback((_from, to, summary) => {
1002
+ const level = to === "red" ? "error" : to === "yellow" ? "warning" : "info";
1003
+ ctx.ui.notify(summary, level);
1004
+ });
932
1005
  // ── Auto-worktree: re-enter worktree on resume ──
933
1006
  if (s.currentMilestoneId &&
934
1007
  shouldUseWorktreeIsolation() &&
@@ -945,6 +1018,11 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
945
1018
  ctx.ui.setFooter(hideFooter);
946
1019
  ctx.ui.notify(s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "info");
947
1020
  restoreHookState(s.basePath);
1021
+ // Re-sync managed resources on resume so long-lived auto sessions pick up
1022
+ // bundled extension updates before resume-time verification/state logic runs.
1023
+ const agentDir = process.env.GSD_CODING_AGENT_DIR || join(process.env.GSD_HOME || homedir(), ".gsd", "agent");
1024
+ const { initResources } = await import("../../../" + "resource-loader.js");
1025
+ initResources(agentDir);
948
1026
  // Open the project DB before rebuild/derive so resume uses DB-backed
949
1027
  // state instead of falling back to stale markdown parsing (#2940).
950
1028
  await openProjectDbIfPresent(s.basePath);
@@ -971,7 +1049,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
971
1049
  invalidateAllCaches();
972
1050
  if (s.pausedSessionFile) {
973
1051
  const activityDir = join(gsdRoot(s.basePath), "activity");
974
- const recovery = synthesizeCrashRecovery(s.basePath, s.currentUnit?.type ?? "unknown", s.currentUnit?.id ?? "unknown", s.pausedSessionFile ?? undefined, activityDir);
1052
+ const recovery = synthesizeCrashRecovery(s.basePath, s.currentUnit?.type ?? s.pausedUnitType ?? "unknown", s.currentUnit?.id ?? s.pausedUnitId ?? "unknown", s.pausedSessionFile ?? undefined, activityDir);
975
1053
  if (recovery && recovery.trace.toolCallCount > 0) {
976
1054
  s.pendingCrashRecovery = recovery.prompt;
977
1055
  ctx.ui.notify(`Recovered ${recovery.trace.toolCallCount} tool calls from paused session. Resuming with context.`, "info");
@@ -981,6 +1059,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
981
1059
  updateSessionLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown");
982
1060
  writeLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown");
983
1061
  logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
1062
+ captureProjectRootEnv(s.originalBasePath || s.basePath);
984
1063
  await autoLoop(ctx, pi, s, buildLoopDeps());
985
1064
  cleanupAfterLoopExit(ctx);
986
1065
  return;
@@ -992,9 +1071,10 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
992
1071
  lockBase,
993
1072
  buildResolver,
994
1073
  };
995
- const ready = await bootstrapAutoSession(s, ctx, pi, base, verboseMode, requestedStepMode, bootstrapDeps);
1074
+ const ready = await bootstrapAutoSession(s, ctx, pi, base, verboseMode, requestedStepMode, bootstrapDeps, freshStartAssessment);
996
1075
  if (!ready)
997
1076
  return;
1077
+ captureProjectRootEnv(s.originalBasePath || s.basePath);
998
1078
  try {
999
1079
  syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
1000
1080
  }
@@ -1074,24 +1154,6 @@ function ensurePreconditions(unitType, unitId, base, state) {
1074
1154
  }
1075
1155
  }
1076
1156
  }
1077
- // ─── Diagnostics ──────────────────────────────────────────────────────────────
1078
- /** Build recovery context from module state for recoverTimedOutUnit */
1079
- function buildRecoveryContext() {
1080
- return {
1081
- basePath: s.basePath,
1082
- verbose: s.verbose,
1083
- currentUnitStartedAt: s.currentUnit?.startedAt ?? Date.now(),
1084
- unitRecoveryCount: s.unitRecoveryCount,
1085
- };
1086
- }
1087
- /**
1088
- * Test-only: expose skip-loop state for unit tests.
1089
- * Not part of the public API.
1090
- */
1091
- /**
1092
- * Dispatch a hook unit directly, bypassing normal pre-dispatch hooks.
1093
- * Used for manual hook triggers via /gsd run-hook.
1094
- */
1095
1157
  export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, triggerUnitId, hookPrompt, hookModel, targetBasePath) {
1096
1158
  if (!s.active) {
1097
1159
  s.active = true;