gsd-pi 2.49.0-dev.de3d9f6 → 2.50.0-dev.9476db8

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 (249) hide show
  1. package/dist/headless-ui.js +12 -2
  2. package/dist/headless.js +29 -13
  3. package/dist/resources/extensions/gsd/auto/infra-errors.js +1 -0
  4. package/dist/resources/extensions/gsd/auto/phases.js +11 -11
  5. package/dist/resources/extensions/gsd/auto/resolve.js +2 -2
  6. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -2
  7. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  8. package/dist/resources/extensions/gsd/auto-artifact-paths.js +8 -10
  9. package/dist/resources/extensions/gsd/auto-dashboard.js +6 -3
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +33 -21
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +17 -24
  12. package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
  13. package/dist/resources/extensions/gsd/auto-recovery.js +62 -184
  14. package/dist/resources/extensions/gsd/auto-start.js +4 -31
  15. package/dist/resources/extensions/gsd/auto-timers.js +2 -2
  16. package/dist/resources/extensions/gsd/auto-verification.js +4 -7
  17. package/dist/resources/extensions/gsd/auto-worktree.js +257 -113
  18. package/dist/resources/extensions/gsd/auto.js +7 -5
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -0
  20. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -1
  21. package/dist/resources/extensions/gsd/branch-patterns.js +13 -0
  22. package/dist/resources/extensions/gsd/doctor-checks.js +5 -1234
  23. package/dist/resources/extensions/gsd/doctor-engine-checks.js +168 -0
  24. package/dist/resources/extensions/gsd/doctor-environment.js +28 -7
  25. package/dist/resources/extensions/gsd/doctor-git-checks.js +405 -0
  26. package/dist/resources/extensions/gsd/doctor-global-checks.js +74 -0
  27. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +600 -0
  28. package/dist/resources/extensions/gsd/doctor.js +9 -1
  29. package/dist/resources/extensions/gsd/extension-manifest.json +1 -1
  30. package/dist/resources/extensions/gsd/git-service.js +9 -10
  31. package/dist/resources/extensions/gsd/gsd-db.js +124 -1
  32. package/dist/resources/extensions/gsd/guided-flow-queue.js +10 -11
  33. package/dist/resources/extensions/gsd/markdown-renderer.js +33 -5
  34. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  35. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  36. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
  37. package/dist/resources/extensions/gsd/prompts/complete-slice.md +9 -8
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +16 -13
  39. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  40. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  41. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  42. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  43. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  44. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/plan-slice.md +8 -3
  47. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
  48. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  49. package/dist/resources/extensions/gsd/repo-identity.js +29 -0
  50. package/dist/resources/extensions/gsd/roadmap-slices.js +2 -2
  51. package/dist/resources/extensions/gsd/session-forensics.js +6 -11
  52. package/dist/resources/extensions/gsd/session-lock.js +67 -56
  53. package/dist/resources/extensions/gsd/state.js +34 -7
  54. package/dist/resources/extensions/gsd/templates/milestone-summary.md +8 -0
  55. package/dist/resources/extensions/gsd/templates/plan.md +16 -0
  56. package/dist/resources/extensions/gsd/templates/roadmap.md +13 -0
  57. package/dist/resources/extensions/gsd/templates/slice-summary.md +9 -0
  58. package/dist/resources/extensions/gsd/templates/task-plan.md +24 -0
  59. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -1
  60. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -3
  61. package/dist/resources/extensions/gsd/verdict-parser.js +84 -0
  62. package/dist/resources/extensions/gsd/worktree-resolver.js +24 -0
  63. package/dist/resources/extensions/gsd/worktree.js +3 -2
  64. package/dist/resources/extensions/remote-questions/config.js +3 -5
  65. package/dist/resources/extensions/search-the-web/native-search.js +8 -3
  66. package/dist/resources/extensions/search-the-web/tool-search.js +19 -2
  67. package/dist/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
  68. package/dist/web/standalone/.next/BUILD_ID +1 -1
  69. package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
  70. package/dist/web/standalone/.next/build-manifest.json +3 -3
  71. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  72. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  73. package/dist/web/standalone/.next/required-server-files.json +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  75. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/index.html +1 -1
  91. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
  98. package/dist/web/standalone/.next/server/chunks/229.js +2 -2
  99. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  102. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  103. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  104. package/dist/web/standalone/.next/static/chunks/4024.7c75ac378de0f2b5.js +9 -0
  105. package/dist/web/standalone/.next/static/chunks/{webpack-0a4cd455ec4197d2.js → webpack-2473ce2c3879fff4.js} +1 -1
  106. package/dist/web/standalone/server.js +1 -1
  107. package/package.json +1 -1
  108. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  109. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  110. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  111. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  112. package/packages/pi-ai/dist/providers/openai-codex-responses.js +39 -10
  113. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  114. package/packages/pi-ai/src/providers/openai-codex-responses.ts +39 -8
  115. package/packages/pi-coding-agent/dist/core/blob-store.d.ts.map +1 -1
  116. package/packages/pi-coding-agent/dist/core/blob-store.js +8 -3
  117. package/packages/pi-coding-agent/dist/core/blob-store.js.map +1 -1
  118. package/packages/pi-coding-agent/dist/core/discovery-cache.d.ts.map +1 -1
  119. package/packages/pi-coding-agent/dist/core/discovery-cache.js +9 -2
  120. package/packages/pi-coding-agent/dist/core/discovery-cache.js.map +1 -1
  121. package/packages/pi-coding-agent/dist/core/retry-handler.js +1 -1
  122. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  123. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  124. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -32
  125. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.d.ts.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js +5 -0
  128. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js.map +1 -1
  129. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  130. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +0 -1
  131. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  132. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  133. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  134. package/packages/pi-coding-agent/package.json +1 -1
  135. package/packages/pi-coding-agent/src/core/blob-store.ts +6 -3
  136. package/packages/pi-coding-agent/src/core/discovery-cache.ts +9 -2
  137. package/packages/pi-coding-agent/src/core/retry-handler.ts +1 -1
  138. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +7 -32
  139. package/packages/pi-coding-agent/src/modes/rpc/jsonl.ts +6 -0
  140. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +0 -2
  141. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -2
  142. package/pkg/package.json +1 -1
  143. package/src/resources/extensions/gsd/auto/infra-errors.ts +1 -0
  144. package/src/resources/extensions/gsd/auto/phases.ts +10 -11
  145. package/src/resources/extensions/gsd/auto/resolve.ts +3 -3
  146. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -2
  147. package/src/resources/extensions/gsd/auto/session.ts +5 -0
  148. package/src/resources/extensions/gsd/auto/types.ts +13 -0
  149. package/src/resources/extensions/gsd/auto-artifact-paths.ts +19 -21
  150. package/src/resources/extensions/gsd/auto-dashboard.ts +5 -2
  151. package/src/resources/extensions/gsd/auto-dispatch.ts +39 -21
  152. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  153. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -28
  154. package/src/resources/extensions/gsd/auto-prompts.ts +113 -19
  155. package/src/resources/extensions/gsd/auto-recovery.ts +65 -199
  156. package/src/resources/extensions/gsd/auto-start.ts +7 -27
  157. package/src/resources/extensions/gsd/auto-timers.ts +2 -2
  158. package/src/resources/extensions/gsd/auto-verification.ts +4 -7
  159. package/src/resources/extensions/gsd/auto-worktree.ts +305 -108
  160. package/src/resources/extensions/gsd/auto.ts +11 -10
  161. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +93 -0
  162. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -0
  163. package/src/resources/extensions/gsd/branch-patterns.ts +16 -0
  164. package/src/resources/extensions/gsd/doctor-checks.ts +5 -1291
  165. package/src/resources/extensions/gsd/doctor-engine-checks.ts +182 -0
  166. package/src/resources/extensions/gsd/doctor-environment.ts +30 -7
  167. package/src/resources/extensions/gsd/doctor-git-checks.ts +415 -0
  168. package/src/resources/extensions/gsd/doctor-global-checks.ts +84 -0
  169. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +626 -0
  170. package/src/resources/extensions/gsd/doctor.ts +9 -1
  171. package/src/resources/extensions/gsd/extension-manifest.json +1 -1
  172. package/src/resources/extensions/gsd/git-service.ts +7 -15
  173. package/src/resources/extensions/gsd/gsd-db.ts +150 -2
  174. package/src/resources/extensions/gsd/guided-flow-queue.ts +11 -12
  175. package/src/resources/extensions/gsd/markdown-renderer.ts +37 -4
  176. package/src/resources/extensions/gsd/preferences-types.ts +5 -1
  177. package/src/resources/extensions/gsd/preferences-validation.ts +37 -0
  178. package/src/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
  179. package/src/resources/extensions/gsd/prompts/complete-slice.md +9 -8
  180. package/src/resources/extensions/gsd/prompts/execute-task.md +16 -13
  181. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  182. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  183. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  184. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  185. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  186. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  187. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  188. package/src/resources/extensions/gsd/prompts/plan-slice.md +8 -3
  189. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
  190. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  191. package/src/resources/extensions/gsd/repo-identity.ts +28 -0
  192. package/src/resources/extensions/gsd/roadmap-slices.ts +2 -2
  193. package/src/resources/extensions/gsd/session-forensics.ts +6 -11
  194. package/src/resources/extensions/gsd/session-lock.ts +92 -64
  195. package/src/resources/extensions/gsd/state.ts +38 -5
  196. package/src/resources/extensions/gsd/templates/milestone-summary.md +8 -0
  197. package/src/resources/extensions/gsd/templates/plan.md +16 -0
  198. package/src/resources/extensions/gsd/templates/roadmap.md +13 -0
  199. package/src/resources/extensions/gsd/templates/slice-summary.md +9 -0
  200. package/src/resources/extensions/gsd/templates/task-plan.md +24 -0
  201. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +2 -2
  202. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +35 -0
  203. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +1 -81
  204. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  205. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  206. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +9 -12
  207. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +115 -1
  208. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +65 -1
  209. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +50 -0
  210. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +189 -0
  211. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +156 -0
  212. package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
  213. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  214. package/src/resources/extensions/gsd/tests/infra-error.test.ts +12 -2
  215. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +39 -0
  216. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  217. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  218. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +347 -0
  219. package/src/resources/extensions/gsd/tests/queue-completed-milestone-perf.test.ts +155 -0
  220. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +2 -1
  221. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +32 -0
  222. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +26 -0
  223. package/src/resources/extensions/gsd/tests/run-uat.test.ts +20 -16
  224. package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +223 -0
  225. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +44 -4
  226. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
  227. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +2 -1
  228. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +0 -16
  229. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +67 -0
  230. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +1 -1
  231. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +204 -0
  232. package/src/resources/extensions/gsd/tools/plan-slice.ts +16 -0
  233. package/src/resources/extensions/gsd/tools/validate-milestone.ts +3 -3
  234. package/src/resources/extensions/gsd/types.ts +30 -0
  235. package/src/resources/extensions/gsd/verdict-parser.ts +95 -0
  236. package/src/resources/extensions/gsd/verification-gate.ts +0 -2
  237. package/src/resources/extensions/gsd/worktree-resolver.ts +31 -0
  238. package/src/resources/extensions/gsd/worktree.ts +3 -2
  239. package/src/resources/extensions/remote-questions/config.ts +3 -5
  240. package/src/resources/extensions/search-the-web/native-search.ts +8 -3
  241. package/src/resources/extensions/search-the-web/tool-search.ts +22 -2
  242. package/src/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
  243. package/dist/resources/extensions/gsd/auto-worktree-sync.js +0 -191
  244. package/dist/resources/extensions/gsd/resource-version.js +0 -97
  245. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +0 -9
  246. package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -234
  247. package/src/resources/extensions/gsd/resource-version.ts +0 -101
  248. /package/dist/web/standalone/.next/static/{ceckLbAMjhzHaQ3RPtJnT → MkE9kzqUGny3-cSE0GNnm}/_buildManifest.js +0 -0
  249. /package/dist/web/standalone/.next/static/{ceckLbAMjhzHaQ3RPtJnT → MkE9kzqUGny3-cSE0GNnm}/_ssgManifest.js +0 -0
@@ -1,234 +0,0 @@
1
- /**
2
- * Worktree ↔ project root state synchronization for auto-mode.
3
- *
4
- * When auto-mode runs inside a worktree, dispatch-critical state files
5
- * (.gsd/ metadata) diverge between the worktree (where work happens)
6
- * and the project root (where startAutoMode reads initial state on restart).
7
- * Without syncing, restarting auto-mode reads stale state from the project
8
- * root and re-dispatches already-completed units.
9
- *
10
- * Also contains resource staleness detection and stale worktree escape.
11
- */
12
-
13
- import {
14
- existsSync,
15
- mkdirSync,
16
- readFileSync,
17
- cpSync,
18
- unlinkSync,
19
- readdirSync,
20
- } from "node:fs";
21
- import { join, sep as pathSep } from "node:path";
22
- import { homedir } from "node:os";
23
- import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
24
-
25
- const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
26
-
27
- // ─── Project Root → Worktree Sync ─────────────────────────────────────────
28
-
29
- /**
30
- * Sync milestone artifacts from project root INTO worktree before deriveState.
31
- * Covers the case where the LLM wrote artifacts to the main repo filesystem
32
- * (e.g. via absolute paths) but the worktree has stale data. Also deletes
33
- * gsd.db in the worktree so it rebuilds from fresh disk state (#853).
34
- * Non-fatal — sync failure should never block dispatch.
35
- */
36
- export function syncProjectRootToWorktree(
37
- projectRoot: string,
38
- worktreePath: string,
39
- milestoneId: string | null,
40
- ): void {
41
- if (!worktreePath || !projectRoot || worktreePath === projectRoot) return;
42
- if (!milestoneId) return;
43
-
44
- const prGsd = join(projectRoot, ".gsd");
45
- const wtGsd = join(worktreePath, ".gsd");
46
-
47
- // Copy milestone directory from project root to worktree if the project root
48
- // has newer artifacts (e.g. slices that don't exist in the worktree yet)
49
- safeCopyRecursive(
50
- join(prGsd, "milestones", milestoneId),
51
- join(wtGsd, "milestones", milestoneId),
52
- );
53
-
54
- // Delete worktree gsd.db so it rebuilds from the freshly synced files.
55
- // Stale DB rows are the root cause of the infinite skip loop (#853).
56
- try {
57
- const wtDb = join(wtGsd, "gsd.db");
58
- if (existsSync(wtDb)) {
59
- unlinkSync(wtDb);
60
- }
61
- } catch {
62
- /* non-fatal */
63
- }
64
- }
65
-
66
- // ─── Worktree → Project Root Sync ─────────────────────────────────────────
67
-
68
- /**
69
- * Sync dispatch-critical .gsd/ state files from worktree to project root.
70
- * Only runs when inside an auto-worktree (worktreePath differs from projectRoot).
71
- * Copies: STATE.md + active milestone directory (roadmap, slice plans, task summaries).
72
- * Non-fatal — sync failure should never block dispatch.
73
- */
74
- export function syncStateToProjectRoot(
75
- worktreePath: string,
76
- projectRoot: string,
77
- milestoneId: string | null,
78
- ): void {
79
- if (!worktreePath || !projectRoot || worktreePath === projectRoot) return;
80
- if (!milestoneId) return;
81
-
82
- const wtGsd = join(worktreePath, ".gsd");
83
- const prGsd = join(projectRoot, ".gsd");
84
-
85
- // 1. STATE.md — the quick-glance status used by initial deriveState()
86
- safeCopy(join(wtGsd, "STATE.md"), join(prGsd, "STATE.md"), { force: true });
87
-
88
- // 2. Milestone directory — ROADMAP, slice PLANs, task summaries
89
- // Copy the entire milestone .gsd subtree so deriveState reads current checkboxes
90
- safeCopyRecursive(
91
- join(wtGsd, "milestones", milestoneId),
92
- join(prGsd, "milestones", milestoneId),
93
- { force: true },
94
- );
95
-
96
- // 3. metrics.json — session cost/token tracking (#2313).
97
- // Without this, metrics accumulated in the worktree are invisible from the
98
- // project root and never appear in the dashboard or skill-health reports.
99
- safeCopy(join(wtGsd, "metrics.json"), join(prGsd, "metrics.json"), { force: true });
100
-
101
- // 4. Runtime records — unit dispatch state used by selfHealRuntimeRecords().
102
- // Without this, a crash during a unit leaves the runtime record only in the
103
- // worktree. If the next session resolves basePath before worktree re-entry,
104
- // selfHeal can't find or clear the stale record (#769).
105
- safeCopyRecursive(
106
- join(wtGsd, "runtime", "units"),
107
- join(prGsd, "runtime", "units"),
108
- { force: true },
109
- );
110
- }
111
-
112
- // ─── Resource Staleness ───────────────────────────────────────────────────
113
-
114
- /**
115
- * Read the resource version (semver) from the managed-resources manifest.
116
- * Uses gsdVersion instead of syncedAt so that launching a second session
117
- * doesn't falsely trigger staleness (#804).
118
- */
119
- export function readResourceVersion(): string | null {
120
- const agentDir =
121
- process.env.GSD_CODING_AGENT_DIR || join(gsdHome, "agent");
122
- const manifestPath = join(agentDir, "managed-resources.json");
123
- try {
124
- const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
125
- return typeof manifest?.gsdVersion === "string"
126
- ? manifest.gsdVersion
127
- : null;
128
- } catch {
129
- return null;
130
- }
131
- }
132
-
133
- /**
134
- * Check if managed resources have been updated since session start.
135
- * Returns a warning message if stale, null otherwise.
136
- */
137
- export function checkResourcesStale(
138
- versionOnStart: string | null,
139
- ): string | null {
140
- if (versionOnStart === null) return null;
141
- const current = readResourceVersion();
142
- if (current === null) return null;
143
- if (current !== versionOnStart) {
144
- return "GSD resources were updated since this session started. Restart gsd to load the new code.";
145
- }
146
- return null;
147
- }
148
-
149
- // ─── Stale Worktree Escape ────────────────────────────────────────────────
150
-
151
- /**
152
- * Detect and escape a stale worktree cwd (#608).
153
- *
154
- * After milestone completion + merge, the worktree directory is removed but
155
- * the process cwd may still point inside `.gsd/worktrees/<MID>/`.
156
- * When a new session starts, `process.cwd()` is passed as `base` to startAuto
157
- * and all subsequent writes land in the wrong directory. This function detects
158
- * that scenario and chdir back to the project root.
159
- *
160
- * Returns the corrected base path.
161
- */
162
- export function escapeStaleWorktree(base: string): string {
163
- // Direct layout: /.gsd/worktrees/
164
- const directMarker = `${pathSep}.gsd${pathSep}worktrees${pathSep}`;
165
- let idx = base.indexOf(directMarker);
166
- if (idx === -1) {
167
- // Symlink-resolved layout: /.gsd/projects/<hash>/worktrees/
168
- const symlinkRe = new RegExp(
169
- `\\${pathSep}\\.gsd\\${pathSep}projects\\${pathSep}[a-f0-9]+\\${pathSep}worktrees\\${pathSep}`,
170
- );
171
- const match = base.match(symlinkRe);
172
- if (!match || match.index === undefined) return base;
173
- idx = match.index;
174
- }
175
-
176
- // base is inside .gsd/worktrees/<something> — extract the project root
177
- const projectRoot = base.slice(0, idx);
178
-
179
- // Guard: If the candidate project root's .gsd IS the user-level ~/.gsd,
180
- // the string-slice heuristic matched the wrong /.gsd/ boundary. This happens
181
- // when .gsd is a symlink into ~/.gsd/projects/<hash> and process.cwd()
182
- // resolved through the symlink. Returning ~ would be catastrophic (#1676).
183
- const candidateGsd = join(projectRoot, ".gsd").replaceAll("\\", "/");
184
- const gsdHomePath = gsdHome.replaceAll("\\", "/");
185
- if (candidateGsd === gsdHomePath || candidateGsd.startsWith(gsdHomePath + "/")) {
186
- // Don't chdir to home — return base unchanged.
187
- // resolveProjectRoot() in worktree.ts has the full git-file-based recovery
188
- // and will be called by the caller (startAuto → projectRoot()).
189
- return base;
190
- }
191
-
192
- try {
193
- process.chdir(projectRoot);
194
- } catch {
195
- // If chdir fails, return the original — caller will handle errors downstream
196
- return base;
197
- }
198
- return projectRoot;
199
- }
200
-
201
- /**
202
- * Clean stale runtime unit files for completed milestones.
203
- *
204
- * After restart, stale runtime/units/*.json from prior milestones can
205
- * cause deriveState to resume the wrong milestone (#887). Removes files
206
- * for milestones that have a SUMMARY (fully complete).
207
- */
208
- export function cleanStaleRuntimeUnits(
209
- gsdRootPath: string,
210
- hasMilestoneSummary: (mid: string) => boolean,
211
- ): number {
212
- const runtimeUnitsDir = join(gsdRootPath, "runtime", "units");
213
- if (!existsSync(runtimeUnitsDir)) return 0;
214
-
215
- let cleaned = 0;
216
- try {
217
- for (const file of readdirSync(runtimeUnitsDir)) {
218
- if (!file.endsWith(".json")) continue;
219
- const midMatch = file.match(/(M\d+(?:-[a-z0-9]{6})?)/);
220
- if (!midMatch) continue;
221
- if (hasMilestoneSummary(midMatch[1])) {
222
- try {
223
- unlinkSync(join(runtimeUnitsDir, file));
224
- cleaned++;
225
- } catch {
226
- /* non-fatal */
227
- }
228
- }
229
- }
230
- } catch {
231
- /* non-fatal */
232
- }
233
- return cleaned;
234
- }
@@ -1,101 +0,0 @@
1
- /**
2
- * Resource version tracking and stale worktree detection.
3
- *
4
- * Staleness detection for managed GSD resources and utilities
5
- * for escaping stale worktree cwd after milestone teardown.
6
- */
7
-
8
- import { existsSync, readdirSync, unlinkSync } from "node:fs";
9
- import { loadJsonFileOrNull } from "./json-persistence.js";
10
- import { join } from "node:path";
11
- import { homedir } from "node:os";
12
- import { resolveProjectRoot } from "./worktree.js";
13
-
14
- const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
15
-
16
- // ─── Resource Staleness ───────────────────────────────────────────────────
17
-
18
- /**
19
- * Read the resource version (semver) from the managed-resources manifest.
20
- * Uses gsdVersion instead of syncedAt so that launching a second session
21
- * doesn't falsely trigger staleness (#804).
22
- */
23
- function isManifestWithVersion(data: unknown): data is { gsdVersion: string } {
24
- return data !== null && typeof data === "object" && "gsdVersion" in data! && typeof (data as Record<string, unknown>).gsdVersion === "string";
25
- }
26
-
27
- export function readResourceVersion(): string | null {
28
- const agentDir = process.env.GSD_CODING_AGENT_DIR || join(gsdHome, "agent");
29
- const manifestPath = join(agentDir, "managed-resources.json");
30
- const manifest = loadJsonFileOrNull(manifestPath, isManifestWithVersion);
31
- return manifest?.gsdVersion ?? null;
32
- }
33
-
34
- /**
35
- * Check if managed resources have been updated since session start.
36
- * Returns a warning message if stale, null otherwise.
37
- */
38
- export function checkResourcesStale(versionOnStart: string | null): string | null {
39
- if (versionOnStart === null) return null;
40
- const current = readResourceVersion();
41
- if (current === null) return null;
42
- if (current !== versionOnStart) {
43
- return "GSD resources were updated since this session started. Restart gsd to load the new code.";
44
- }
45
- return null;
46
- }
47
-
48
- // ─── Stale Worktree Escape ────────────────────────────────────────────────
49
-
50
- /**
51
- * Detect and escape a stale worktree cwd (#608).
52
- *
53
- * After milestone completion + merge, the worktree directory is removed but
54
- * the process cwd may still point inside `.gsd/worktrees/<MID>/`.
55
- * When a new session starts, `process.cwd()` is passed as `base` to startAuto
56
- * and all subsequent writes land in the wrong directory. This function detects
57
- * that scenario and chdir back to the project root.
58
- *
59
- * Returns the corrected base path.
60
- */
61
- export function escapeStaleWorktree(base: string): string {
62
- const projectRoot = resolveProjectRoot(base);
63
- if (projectRoot === base) return base;
64
- try {
65
- process.chdir(projectRoot);
66
- } catch {
67
- return base;
68
- }
69
- return projectRoot;
70
- }
71
-
72
- /**
73
- * Clean stale runtime unit files for completed milestones.
74
- *
75
- * After restart, stale runtime/units/*.json from prior milestones can
76
- * cause deriveState to resume the wrong milestone (#887). Removes files
77
- * for milestones that have a SUMMARY (fully complete).
78
- */
79
- export function cleanStaleRuntimeUnits(
80
- gsdRootPath: string,
81
- hasMilestoneSummary: (mid: string) => boolean,
82
- ): number {
83
- const runtimeUnitsDir = join(gsdRootPath, "runtime", "units");
84
- if (!existsSync(runtimeUnitsDir)) return 0;
85
-
86
- let cleaned = 0;
87
- try {
88
- for (const file of readdirSync(runtimeUnitsDir)) {
89
- if (!file.endsWith(".json")) continue;
90
- const midMatch = file.match(/(M\d+(?:-[a-z0-9]{6})?)/);
91
- if (!midMatch) continue;
92
- if (hasMilestoneSummary(midMatch[1])) {
93
- try {
94
- unlinkSync(join(runtimeUnitsDir, file));
95
- cleaned++;
96
- } catch { /* non-fatal */ }
97
- }
98
- }
99
- } catch { /* non-fatal */ }
100
- return cleaned;
101
- }