gsd-pi 2.28.0-dev.e19bf89 → 2.29.0-dev.2ccf3fb

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 (256) hide show
  1. package/README.md +24 -17
  2. package/dist/cli.js +15 -9
  3. package/dist/resource-loader.js +80 -8
  4. package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
  5. package/dist/resources/extensions/gsd/auto-dashboard.ts +186 -65
  6. package/dist/resources/extensions/gsd/auto-post-unit.ts +14 -6
  7. package/dist/resources/extensions/gsd/auto-recovery.ts +33 -23
  8. package/dist/resources/extensions/gsd/auto-start.ts +25 -10
  9. package/dist/resources/extensions/gsd/auto-verification.ts +41 -7
  10. package/dist/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
  11. package/dist/resources/extensions/gsd/auto.ts +67 -22
  12. package/dist/resources/extensions/gsd/commands-handlers.ts +3 -11
  13. package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
  14. package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
  15. package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  16. package/dist/resources/extensions/gsd/commands.ts +75 -29
  17. package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  18. package/dist/resources/extensions/gsd/doctor-types.ts +13 -0
  19. package/dist/resources/extensions/gsd/doctor.ts +2 -6
  20. package/dist/resources/extensions/gsd/export.ts +28 -2
  21. package/dist/resources/extensions/gsd/gsd-db.ts +19 -0
  22. package/dist/resources/extensions/gsd/index.ts +2 -1
  23. package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
  24. package/dist/resources/extensions/gsd/metrics.ts +17 -31
  25. package/dist/resources/extensions/gsd/paths.ts +0 -8
  26. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  27. package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  28. package/dist/resources/extensions/gsd/queue-order.ts +10 -11
  29. package/dist/resources/extensions/gsd/routing-history.ts +13 -17
  30. package/dist/resources/extensions/gsd/session-lock.ts +284 -0
  31. package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
  32. package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  33. package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  34. package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  35. package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  36. package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  37. package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  38. package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  39. package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  40. package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  41. package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
  42. package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  43. package/dist/resources/extensions/gsd/types.ts +1 -0
  44. package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
  45. package/dist/resources/extensions/gsd/verification-evidence.ts +2 -0
  46. package/dist/resources/extensions/gsd/verification-gate.ts +13 -2
  47. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  48. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  49. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  50. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  51. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  52. package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  53. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  54. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  55. package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  56. package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
  57. package/dist/resources/extensions/mcp-client/index.ts +459 -0
  58. package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  59. package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
  60. package/dist/resources/extensions/remote-questions/notify.ts +1 -2
  61. package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  62. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  63. package/dist/resources/extensions/remote-questions/types.ts +3 -0
  64. package/dist/resources/extensions/shared/mod.ts +3 -0
  65. package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
  66. package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  67. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  68. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  69. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  70. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  71. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  72. package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  73. package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  74. package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  75. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  76. package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  77. package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  78. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  79. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  80. package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  81. package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  82. package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  83. package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  84. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  85. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  86. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  87. package/dist/resources/skills/create-skill/SKILL.md +184 -0
  88. package/dist/resources/skills/create-skill/references/api-security.md +226 -0
  89. package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  90. package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
  91. package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
  92. package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
  93. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  94. package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  95. package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
  96. package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
  97. package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  98. package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
  99. package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
  100. package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  101. package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
  102. package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
  103. package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
  104. package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
  105. package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
  106. package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  107. package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  108. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  109. package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  110. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  111. package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  112. package/package.json +6 -3
  113. package/packages/native/dist/native.d.ts +2 -0
  114. package/packages/native/dist/native.js +19 -5
  115. package/packages/native/src/native.ts +23 -9
  116. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  117. package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
  118. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  119. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  120. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  121. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  122. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  124. package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
  125. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -1
  128. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  129. package/packages/pi-coding-agent/package.json +1 -1
  130. package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
  131. package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
  132. package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
  133. package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
  134. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -1
  135. package/packages/pi-tui/dist/autocomplete.d.ts +3 -0
  136. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  137. package/packages/pi-tui/dist/autocomplete.js +14 -0
  138. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  139. package/packages/pi-tui/src/autocomplete.ts +19 -1
  140. package/pkg/package.json +1 -1
  141. package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
  142. package/src/resources/extensions/gsd/auto-dashboard.ts +186 -65
  143. package/src/resources/extensions/gsd/auto-post-unit.ts +14 -6
  144. package/src/resources/extensions/gsd/auto-recovery.ts +33 -23
  145. package/src/resources/extensions/gsd/auto-start.ts +25 -10
  146. package/src/resources/extensions/gsd/auto-verification.ts +41 -7
  147. package/src/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
  148. package/src/resources/extensions/gsd/auto.ts +67 -22
  149. package/src/resources/extensions/gsd/commands-handlers.ts +3 -11
  150. package/src/resources/extensions/gsd/commands-logs.ts +536 -0
  151. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
  152. package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  153. package/src/resources/extensions/gsd/commands.ts +75 -29
  154. package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  155. package/src/resources/extensions/gsd/doctor-types.ts +13 -0
  156. package/src/resources/extensions/gsd/doctor.ts +2 -6
  157. package/src/resources/extensions/gsd/export.ts +28 -2
  158. package/src/resources/extensions/gsd/gsd-db.ts +19 -0
  159. package/src/resources/extensions/gsd/index.ts +2 -1
  160. package/src/resources/extensions/gsd/json-persistence.ts +67 -0
  161. package/src/resources/extensions/gsd/metrics.ts +17 -31
  162. package/src/resources/extensions/gsd/paths.ts +0 -8
  163. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  164. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  165. package/src/resources/extensions/gsd/queue-order.ts +10 -11
  166. package/src/resources/extensions/gsd/routing-history.ts +13 -17
  167. package/src/resources/extensions/gsd/session-lock.ts +284 -0
  168. package/src/resources/extensions/gsd/session-status-io.ts +23 -41
  169. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  170. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  171. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  172. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  173. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  174. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  175. package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  176. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  177. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  178. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
  179. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  180. package/src/resources/extensions/gsd/types.ts +1 -0
  181. package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
  182. package/src/resources/extensions/gsd/verification-evidence.ts +2 -0
  183. package/src/resources/extensions/gsd/verification-gate.ts +13 -2
  184. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  185. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  186. package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  187. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  188. package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  189. package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  190. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  191. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  192. package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  193. package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
  194. package/src/resources/extensions/mcp-client/index.ts +459 -0
  195. package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  196. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  197. package/src/resources/extensions/remote-questions/notify.ts +1 -2
  198. package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  199. package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  200. package/src/resources/extensions/remote-questions/types.ts +3 -0
  201. package/src/resources/extensions/shared/mod.ts +3 -0
  202. package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
  203. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  204. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  205. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  206. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  207. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  208. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  209. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  210. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  211. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  212. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  213. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  214. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  215. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  216. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  217. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  218. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  219. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  220. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  221. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  222. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  223. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  224. package/src/resources/skills/create-skill/SKILL.md +184 -0
  225. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  226. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  227. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  228. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  229. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  230. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  231. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  232. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  233. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  234. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  235. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  236. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  237. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  238. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  239. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  240. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  241. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  242. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  243. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  244. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  245. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  246. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  247. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  248. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  249. package/dist/resources/extensions/gsd/preferences-hooks.ts +0 -10
  250. package/dist/resources/extensions/mcporter/index.ts +0 -525
  251. package/dist/resources/extensions/shared/progress-widget.ts +0 -282
  252. package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
  253. package/src/resources/extensions/gsd/preferences-hooks.ts +0 -10
  254. package/src/resources/extensions/mcporter/index.ts +0 -525
  255. package/src/resources/extensions/shared/progress-widget.ts +0 -282
  256. package/src/resources/extensions/shared/thinking-widget.ts +0 -107
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import { existsSync, mkdirSync, readFileSync, cpSync, unlinkSync, readdirSync } from "node:fs";
14
+ import { loadJsonFileOrNull } from "./json-persistence.js";
14
15
  import { join, sep as pathSep } from "node:path";
15
16
  import { homedir } from "node:os";
16
17
  import { safeCopy, safeCopyRecursive } from "./safe-fs.js";
@@ -36,6 +37,12 @@ export function syncProjectRootToWorktree(projectRoot: string, worktreePath: str
36
37
  // has newer artifacts (e.g. slices that don't exist in the worktree yet)
37
38
  safeCopyRecursive(join(prGsd, "milestones", milestoneId), join(wtGsd, "milestones", milestoneId))
38
39
 
40
+ // Copy living documents from project root to worktree so agents have the
41
+ // latest decisions, requirements, project state, and knowledge.
42
+ for (const doc of ["DECISIONS.md", "REQUIREMENTS.md", "PROJECT.md", "KNOWLEDGE.md"]) {
43
+ safeCopy(join(prGsd, doc), join(wtGsd, doc), { force: true });
44
+ }
45
+
39
46
  // Delete worktree gsd.db so it rebuilds from the freshly synced files.
40
47
  // Stale DB rows are the root cause of the infinite skip loop (#853).
41
48
  try {
@@ -89,6 +96,14 @@ export function syncStateToProjectRoot(worktreePath: string, projectRoot: string
89
96
  // worktree. If the next session resolves basePath before worktree re-entry,
90
97
  // selfHeal can't find or clear the stale record (#769).
91
98
  safeCopyRecursive(join(wtGsd, "runtime", "units"), join(prGsd, "runtime", "units"), { force: true })
99
+
100
+ // 5. Living documents — decisions, requirements, project description, knowledge.
101
+ // Agents update these during slice execution. Without syncing, a new session
102
+ // reads stale copies from the project root, losing architectural decisions,
103
+ // requirement status updates, and accumulated knowledge (#1168).
104
+ for (const doc of ["DECISIONS.md", "REQUIREMENTS.md", "PROJECT.md", "KNOWLEDGE.md"]) {
105
+ safeCopy(join(wtGsd, doc), join(prGsd, doc), { force: true });
106
+ }
92
107
  }
93
108
 
94
109
  // ─── Resource Staleness ───────────────────────────────────────────────────
@@ -98,15 +113,15 @@ export function syncStateToProjectRoot(worktreePath: string, projectRoot: string
98
113
  * Uses gsdVersion instead of syncedAt so that launching a second session
99
114
  * doesn't falsely trigger staleness (#804).
100
115
  */
116
+ function isManifestWithVersion(data: unknown): data is { gsdVersion: string } {
117
+ return data !== null && typeof data === "object" && "gsdVersion" in data! && typeof (data as Record<string, unknown>).gsdVersion === "string";
118
+ }
119
+
101
120
  export function readResourceVersion(): string | null {
102
121
  const agentDir = process.env.GSD_CODING_AGENT_DIR || join(homedir(), ".gsd", "agent");
103
122
  const manifestPath = join(agentDir, "managed-resources.json");
104
- try {
105
- const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
106
- return typeof manifest?.gsdVersion === "string" ? manifest.gsdVersion : null;
107
- } catch {
108
- return null;
109
- }
123
+ const manifest = loadJsonFileOrNull(manifestPath, isManifestWithVersion);
124
+ return manifest?.gsdVersion ?? null;
110
125
  }
111
126
 
112
127
  /**
@@ -22,7 +22,6 @@ import { loadFile, getManifestStatus, resolveAllOverrides, parsePlan, parseSumma
22
22
  import { loadPrompt } from "./prompt-loader.js";
23
23
  import { runVerificationGate, formatFailureContext, captureRuntimeErrors, runDependencyAudit } from "./verification-gate.js";
24
24
  import { writeVerificationJSON } from "./verification-evidence.js";
25
- export { inlinePriorMilestoneSummary } from "./files.js";
26
25
  import { collectSecretsFromManifest } from "../get-secrets-from-user.js";
27
26
  import {
28
27
  gsdRoot, resolveMilestoneFile, resolveSliceFile, resolveSlicePath,
@@ -33,6 +32,12 @@ import { invalidateAllCaches } from "./cache.js";
33
32
  import { saveActivityLog, clearActivityLogState } from "./activity-log.js";
34
33
  import { synthesizeCrashRecovery, getDeepDiagnostic } from "./session-forensics.js";
35
34
  import { writeLock, clearLock, readCrashLock, formatCrashInfo, isLockProcessAlive } from "./crash-recovery.js";
35
+ import {
36
+ acquireSessionLock,
37
+ validateSessionLock,
38
+ releaseSessionLock,
39
+ updateSessionLock,
40
+ } from "./session-lock.js";
36
41
  import {
37
42
  clearUnitRuntimeRecord,
38
43
  inspectExecuteTaskDurability,
@@ -186,12 +191,6 @@ import {
186
191
  NEW_SESSION_TIMEOUT_MS, DISPATCH_HANG_TIMEOUT_MS,
187
192
  } from "./auto/session.js";
188
193
  import type { CompletedUnit, CurrentUnit, UnitRouting, StartModel, PendingVerificationRetry } from "./auto/session.js";
189
- export {
190
- MAX_UNIT_DISPATCHES, STUB_RECOVERY_THRESHOLD, MAX_LIFETIME_DISPATCHES,
191
- MAX_CONSECUTIVE_SKIPS, DISPATCH_GAP_TIMEOUT_MS, MAX_SKIP_DEPTH,
192
- NEW_SESSION_TIMEOUT_MS, DISPATCH_HANG_TIMEOUT_MS,
193
- } from "./auto/session.js";
194
- export type { CompletedUnit, CurrentUnit, UnitRouting, StartModel } from "./auto/session.js";
195
194
 
196
195
  // ── ENCAPSULATION INVARIANT ─────────────────────────────────────────────────
197
196
  // ALL mutable auto-mode state lives in the AutoSession class (auto/session.ts).
@@ -262,8 +261,6 @@ export function shouldUseWorktreeIsolation(): boolean {
262
261
  * Maps toolCallId → start timestamp (ms) so the idle watchdog can detect tools that have been
263
262
  * running suspiciously long (e.g., a Bash command hung because `&` kept stdout open).
264
263
  */
265
- // Re-export budget utilities for external consumers
266
- export { getBudgetAlertLevel, getNewBudgetAlertLevel, getBudgetEnforcementAction } from "./auto-budget.js";
267
264
 
268
265
  /** Wrapper: register SIGTERM handler and store reference. */
269
266
  function registerSigtermHandler(currentBasePath: string): void {
@@ -276,8 +273,6 @@ function deregisterSigtermHandler(): void {
276
273
  s.sigtermHandler = null;
277
274
  }
278
275
 
279
- export { type AutoDashboardData } from "./auto-dashboard.js";
280
-
281
276
  export function getAutoDashboardData(): AutoDashboardData {
282
277
  const ledger = getLedger();
283
278
  const totals = ledger ? getProjectTotals(ledger.units) : null;
@@ -451,7 +446,10 @@ export async function stopAuto(ctx?: ExtensionContext, pi?: ExtensionAPI, reason
451
446
  if (!s.active && !s.paused) return;
452
447
  const reasonSuffix = reason ? ` — ${reason}` : "";
453
448
  clearUnitTimeout();
454
- if (lockBase()) clearLock(lockBase());
449
+ if (lockBase()) {
450
+ releaseSessionLock(lockBase());
451
+ clearLock(lockBase());
452
+ }
455
453
  clearSkillSnapshot();
456
454
  resetSkillTelemetry();
457
455
  s.dispatching = false;
@@ -565,7 +563,10 @@ export async function pauseAuto(ctx?: ExtensionContext, _pi?: ExtensionAPI): Pro
565
563
 
566
564
  s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
567
565
 
568
- if (lockBase()) clearLock(lockBase());
566
+ if (lockBase()) {
567
+ releaseSessionLock(lockBase());
568
+ clearLock(lockBase());
569
+ }
569
570
 
570
571
  deregisterSigtermHandler();
571
572
 
@@ -598,6 +599,16 @@ export async function startAuto(
598
599
 
599
600
  // If resuming from paused state, just re-activate and dispatch next unit.
600
601
  if (s.paused) {
602
+ // Re-acquire session lock before resuming
603
+ const resumeLock = acquireSessionLock(base);
604
+ if (!resumeLock.acquired) {
605
+ ctx.ui.notify(
606
+ `Cannot resume: ${resumeLock.reason}`,
607
+ "error",
608
+ );
609
+ return;
610
+ }
611
+
601
612
  s.paused = false;
602
613
  s.active = true;
603
614
  s.verbose = verboseMode;
@@ -699,6 +710,7 @@ export async function startAuto(
699
710
  s.pausedForSecrets = false;
700
711
  }
701
712
 
713
+ updateSessionLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown", s.completedUnits.length);
702
714
  writeLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown", s.completedUnits.length);
703
715
 
704
716
  await dispatchNextUnit(ctx, pi);
@@ -854,7 +866,7 @@ async function showStepWizard(
854
866
  : "previous unit";
855
867
 
856
868
  if (!mid || state.phase === "complete") {
857
- const incomplete = state.registry.filter(m => m.status !== "complete" && m.status !== "parked");
869
+ const incomplete = (state.registry ?? []).filter(m => m.status !== "complete" && m.status !== "parked");
858
870
  if (incomplete.length > 0 && state.phase !== "complete" && state.phase !== "blocked" && state.phase !== "pre-planning") {
859
871
  const ids = incomplete.map(m => m.id).join(", ");
860
872
  const diag = `basePath=${s.basePath}, milestones=[${state.registry.map(m => `${m.id}:${m.status}`).join(", ")}], phase=${state.phase}`;
@@ -911,8 +923,6 @@ async function showStepWizard(
911
923
  }
912
924
  }
913
925
 
914
- // describeNextUnit is imported from auto-dashboard.ts and re-exported
915
- export { describeNextUnit } from "./auto-dashboard.js";
916
926
 
917
927
  /** Thin wrapper: delegates to auto-dashboard.ts, passing state accessors. */
918
928
  function updateProgressWidget(
@@ -950,6 +960,24 @@ async function dispatchNextUnit(
950
960
  return;
951
961
  }
952
962
 
963
+ // ── Session lock validation: detect if another process has taken over ──
964
+ if (lockBase() && !validateSessionLock(lockBase())) {
965
+ debugLog("dispatchNextUnit session-lock-lost — another process may have taken over");
966
+ ctx.ui.notify(
967
+ "Session lock lost — another GSD process appears to have taken over. Stopping gracefully.",
968
+ "error",
969
+ );
970
+ // Don't call stopAuto here to avoid releasing the lock we don't own
971
+ s.active = false;
972
+ s.paused = false;
973
+ clearUnitTimeout();
974
+ deregisterSigtermHandler();
975
+ ctx.ui.setStatus("gsd-auto", undefined);
976
+ ctx.ui.setWidget("gsd-progress", undefined);
977
+ ctx.ui.setFooter(undefined);
978
+ return;
979
+ }
980
+
953
981
  // Reentrancy guard
954
982
  if (s.dispatching && s.skipDepth === 0) {
955
983
  debugLog("dispatchNextUnit reentrancy guard — another dispatch in progress, bailing");
@@ -1130,7 +1158,7 @@ async function dispatchNextUnit(
1130
1158
  }
1131
1159
  }
1132
1160
 
1133
- const pendingIds = state.registry
1161
+ const pendingIds = (state.registry ?? [])
1134
1162
  .filter(m => m.status !== "complete")
1135
1163
  .map(m => m.id);
1136
1164
  pruneQueueOrder(s.basePath, pendingIds);
@@ -1145,7 +1173,7 @@ async function dispatchNextUnit(
1145
1173
  await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
1146
1174
  }
1147
1175
 
1148
- const incomplete = state.registry.filter(m => m.status !== "complete" && m.status !== "parked");
1176
+ const incomplete = (state.registry ?? []).filter(m => m.status !== "complete" && m.status !== "parked");
1149
1177
  if (incomplete.length === 0) {
1150
1178
  // Genuinely all complete (parked milestones excluded) — merge milestone branch to main before stopping (#962)
1151
1179
  if (s.currentMilestoneId && isInAutoWorktree(s.basePath) && s.originalBasePath) {
@@ -1171,7 +1199,7 @@ async function dispatchNextUnit(
1171
1199
  try { process.chdir(s.basePath); } catch { /* best-effort */ }
1172
1200
  }
1173
1201
  }
1174
- } else if (s.currentMilestoneId && !isInAutoWorktree(s.basePath) && getIsolationMode() !== "none") {
1202
+ } else if (s.currentMilestoneId && !isInAutoWorktree(s.basePath) && getIsolationMode() === "branch") {
1175
1203
  try {
1176
1204
  const currentBranch = getCurrentBranch(s.basePath);
1177
1205
  const milestoneBranch = autoWorktreeBranch(s.currentMilestoneId);
@@ -1273,7 +1301,7 @@ async function dispatchNextUnit(
1273
1301
  try { process.chdir(s.basePath); } catch { /* best-effort */ }
1274
1302
  }
1275
1303
  }
1276
- } else if (s.currentMilestoneId && !isInAutoWorktree(s.basePath) && getIsolationMode() !== "none") {
1304
+ } else if (s.currentMilestoneId && !isInAutoWorktree(s.basePath) && getIsolationMode() === "branch") {
1277
1305
  try {
1278
1306
  const currentBranch = getCurrentBranch(s.basePath);
1279
1307
  const milestoneBranch = autoWorktreeBranch(s.currentMilestoneId);
@@ -1398,6 +1426,23 @@ async function dispatchNextUnit(
1398
1426
 
1399
1427
  await runSecretsGate();
1400
1428
 
1429
+ // ── Interactive discussion gate ──
1430
+ // If the active milestone needs discussion (has CONTEXT-DRAFT.md but no roadmap),
1431
+ // stop auto-mode and route to the interactive discussion flow. The guided-flow
1432
+ // handles needs-discussion correctly — it just needs to be called instead of
1433
+ // letting the dispatch table fire "needs-discussion → stop" (#1170).
1434
+ if (state.phase === "needs-discussion") {
1435
+ if (s.currentUnit) {
1436
+ await closeoutUnit(ctx, s.basePath, s.currentUnit.type, s.currentUnit.id, s.currentUnit.startedAt, buildSnapshotOpts(s.currentUnit.type, s.currentUnit.id));
1437
+ }
1438
+ const cmdCtx = s.cmdCtx!;
1439
+ const basePath = s.basePath;
1440
+ await stopAuto(ctx, pi, `${mid}: ${midTitle} needs discussion before planning.`);
1441
+ const { showSmartEntry } = await import("./guided-flow.js");
1442
+ await showSmartEntry(cmdCtx, pi, basePath);
1443
+ return;
1444
+ }
1445
+
1401
1446
  // ── Dispatch table ──
1402
1447
  const dispatchResult = await resolveDispatch({ basePath: s.basePath, mid, midTitle: midTitle!, state, prefs,
1403
1448
  });
@@ -1583,6 +1628,7 @@ async function dispatchNextUnit(
1583
1628
  }
1584
1629
 
1585
1630
  const sessionFile = ctx.sessionManager.getSessionFile();
1631
+ updateSessionLock(lockBase(), unitType, unitId, s.completedUnits.length, sessionFile);
1586
1632
  writeLock(lockBase(), unitType, unitId, s.completedUnits.length, sessionFile);
1587
1633
 
1588
1634
  // Prompt injection
@@ -1809,6 +1855,7 @@ export async function dispatchHookUnit(
1809
1855
  }
1810
1856
 
1811
1857
  const sessionFile = ctx.sessionManager.getSessionFile();
1858
+ updateSessionLock(lockBase(), hookUnitType, triggerUnitId, s.completedUnits.length, sessionFile);
1812
1859
  writeLock(lockBase(), hookUnitType, triggerUnitId, s.completedUnits.length, sessionFile);
1813
1860
 
1814
1861
  clearUnitTimeout();
@@ -1845,5 +1892,3 @@ export async function dispatchHookUnit(
1845
1892
  }
1846
1893
 
1847
1894
 
1848
- // Direct phase dispatch → auto-direct-dispatch.ts
1849
- export { dispatchDirectPhase } from "./auto-direct-dispatch.js";
@@ -18,19 +18,11 @@ import {
18
18
  selectDoctorScope,
19
19
  filterDoctorIssues,
20
20
  } from "./doctor.js";
21
- import { loadPrompt } from "./prompt-loader.js";
22
21
  import { isAutoActive } from "./auto.js";
23
- import { resolveProjectRoot } from "./worktree.js";
24
- import { assertSafeDirectory } from "./validate-directory.js";
25
-
26
- /** Resolve the effective project root, accounting for worktree paths. */
27
- function projectRoot(): string {
28
- const root = resolveProjectRoot(process.cwd());
29
- assertSafeDirectory(root);
30
- return root;
31
- }
22
+ import { projectRoot } from "./commands.js";
23
+ import { loadPrompt } from "./prompt-loader.js";
32
24
 
33
- function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportText: string, structuredIssues: string): void {
25
+ export function dispatchDoctorHeal(pi: ExtensionAPI, scope: string | undefined, reportText: string, structuredIssues: string): void {
34
26
  const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md");
35
27
  const workflow = readFileSync(workflowPath, "utf-8");
36
28
  const prompt = loadPrompt("doctor-heal", {