@opengsd/gsd-pi 1.0.2-dev.e9a1b49 → 1.0.2-dev.fb7ddf1

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 (490) hide show
  1. package/README.md +63 -12
  2. package/dist/headless-answers.js +2 -1
  3. package/dist/headless-events.d.ts +1 -0
  4. package/dist/headless-events.js +8 -1
  5. package/dist/onboarding.js +22 -3
  6. package/dist/resource-loader.d.ts +7 -0
  7. package/dist/resource-loader.js +44 -9
  8. package/dist/resources/.managed-resources-content-hash +1 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
  10. package/dist/resources/extensions/context7/index.js +12 -2
  11. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  12. package/dist/resources/extensions/google-cli/index.js +30 -0
  13. package/dist/resources/extensions/google-cli/models.js +55 -0
  14. package/dist/resources/extensions/google-cli/package.json +11 -0
  15. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  16. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +81 -1
  18. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
  19. package/dist/resources/extensions/gsd/auto/phases.js +38 -1
  20. package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
  21. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  22. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
  23. package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
  24. package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
  25. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  26. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  27. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
  28. package/dist/resources/extensions/gsd/auto-verification.js +14 -2
  29. package/dist/resources/extensions/gsd/auto-worktree.js +36 -55
  30. package/dist/resources/extensions/gsd/auto.js +40 -2
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  32. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
  33. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
  36. package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
  37. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  38. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  39. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  40. package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
  41. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  42. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  43. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  44. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  45. package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
  46. package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
  47. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  48. package/dist/resources/extensions/gsd/doctor.js +7 -2
  49. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  50. package/dist/resources/extensions/gsd/guided-flow.js +5 -6
  51. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  52. package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
  53. package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
  54. package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
  55. package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
  56. package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
  57. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  58. package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
  59. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  60. package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
  61. package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
  62. package/dist/resources/extensions/gsd/preferences.js +14 -2
  63. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  64. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  65. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  67. package/dist/resources/extensions/gsd/prompts/system.md +3 -20
  68. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  69. package/dist/resources/extensions/gsd/repo-identity.js +36 -6
  70. package/dist/resources/extensions/gsd/repository-registry.js +3 -1
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
  72. package/dist/resources/extensions/gsd/skill-activation.js +233 -0
  73. package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
  74. package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
  75. package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
  76. package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
  77. package/dist/resources/extensions/gsd/skill-scope.js +52 -0
  78. package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
  79. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
  80. package/dist/resources/extensions/gsd/skills.js +60 -0
  81. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
  82. package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
  83. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  85. package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
  86. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
  87. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  88. package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
  89. package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
  90. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  91. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  92. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  93. package/dist/resources/extensions/gsd/worktree-post-create-hook.js +117 -0
  94. package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
  95. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  96. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  97. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  98. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  99. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  100. package/dist/resources/extensions/subagent/index.js +8 -15
  101. package/dist/resources/shared/package-manager-detection.js +36 -0
  102. package/dist/resources/skills/agent-browser/SKILL.md +1 -1
  103. package/dist/resources/skills/api-design/SKILL.md +1 -1
  104. package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
  105. package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
  106. package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
  107. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  108. package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
  109. package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
  110. package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
  111. package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
  112. package/dist/resources/skills/forensics/SKILL.md +2 -2
  113. package/dist/resources/skills/grill-me/SKILL.md +1 -1
  114. package/dist/resources/skills/handoff/SKILL.md +1 -1
  115. package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
  116. package/dist/resources/skills/observability/SKILL.md +1 -1
  117. package/dist/resources/skills/security-review/SKILL.md +1 -1
  118. package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
  119. package/dist/resources/skills/tdd/SKILL.md +1 -1
  120. package/dist/resources/skills/write-docs/SKILL.md +1 -1
  121. package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
  122. package/dist/update-check.d.ts +6 -2
  123. package/dist/update-check.js +7 -3
  124. package/dist/web/standalone/.next/BUILD_ID +1 -1
  125. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  126. package/dist/web/standalone/.next/build-manifest.json +2 -2
  127. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  128. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/index.html +1 -1
  146. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  153. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  154. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  156. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  157. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  158. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  159. package/dist/worktree-cli.d.ts +0 -2
  160. package/dist/worktree-cli.js +21 -9
  161. package/package.json +5 -2
  162. package/packages/cloud-mcp-gateway/bin/gsd-cloud-mcp-gateway.js +14 -0
  163. package/packages/cloud-mcp-gateway/package.json +4 -3
  164. package/packages/contracts/dist/rpc.test.js +5 -0
  165. package/packages/contracts/dist/rpc.test.js.map +1 -1
  166. package/packages/contracts/dist/workflow.d.ts +15 -0
  167. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  168. package/packages/contracts/dist/workflow.js +16 -0
  169. package/packages/contracts/dist/workflow.js.map +1 -1
  170. package/packages/contracts/dist/workflow.test.js +1 -0
  171. package/packages/contracts/dist/workflow.test.js.map +1 -1
  172. package/packages/contracts/package.json +1 -1
  173. package/packages/daemon/package.json +4 -4
  174. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
  175. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  176. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
  177. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  178. package/packages/gsd-agent-core/package.json +5 -5
  179. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  180. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  182. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  183. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  184. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  186. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  194. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  198. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  202. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  205. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  206. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  208. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
  209. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  210. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  211. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
  212. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  213. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
  214. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  215. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
  216. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  217. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  218. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
  219. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  220. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  221. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  222. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  223. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  224. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  225. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  226. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  227. package/packages/gsd-agent-modes/package.json +7 -7
  228. package/packages/mcp-server/bin/gsd-mcp-server.js +14 -0
  229. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  230. package/packages/mcp-server/dist/server.js +7 -1
  231. package/packages/mcp-server/dist/server.js.map +1 -1
  232. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  233. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  234. package/packages/mcp-server/dist/workflow-tools.js +47 -8
  235. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  236. package/packages/mcp-server/package.json +5 -4
  237. package/packages/native/package.json +1 -1
  238. package/packages/pi-agent-core/dist/agent-loop.js +16 -14
  239. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  240. package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  241. package/packages/pi-agent-core/dist/harness/skills.js +6 -0
  242. package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
  243. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
  244. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
  245. package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
  246. package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
  247. package/packages/pi-agent-core/package.json +1 -1
  248. package/packages/pi-ai/bin/pi-ai.js +14 -0
  249. package/packages/pi-ai/dist/models.generated.d.ts +48 -206
  250. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models.generated.js +73 -226
  252. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  255. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  256. package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  257. package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
  258. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  259. package/packages/pi-ai/dist/types.d.ts +2 -0
  260. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  261. package/packages/pi-ai/dist/types.js.map +1 -1
  262. package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js +29 -1
  263. package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
  264. package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
  265. package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
  266. package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
  267. package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
  268. package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
  269. package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
  270. package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
  271. package/packages/pi-ai/package.json +3 -2
  272. package/packages/pi-coding-agent/README.md +1 -1
  273. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
  274. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
  277. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  280. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
  282. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/skills.js +3 -0
  284. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
  287. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
  289. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
  291. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
  294. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  295. package/packages/pi-coding-agent/package.json +8 -8
  296. package/packages/pi-tui/package.json +1 -1
  297. package/packages/rpc-client/package.json +2 -2
  298. package/pkg/package.json +1 -1
  299. package/scripts/install/deps.js +10 -0
  300. package/scripts/install/detect-existing.js +17 -3
  301. package/scripts/install/npm-global.js +103 -33
  302. package/scripts/install.js +1 -0
  303. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
  304. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
  305. package/src/resources/extensions/context7/index.ts +15 -2
  306. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  307. package/src/resources/extensions/google-cli/index.ts +34 -0
  308. package/src/resources/extensions/google-cli/models.ts +57 -0
  309. package/src/resources/extensions/google-cli/package.json +11 -0
  310. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  311. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  312. package/src/resources/extensions/gsd/auto/loop.ts +96 -1
  313. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
  314. package/src/resources/extensions/gsd/auto/phases.ts +47 -1
  315. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
  316. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  317. package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
  318. package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
  319. package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
  320. package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
  321. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  322. package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
  323. package/src/resources/extensions/gsd/auto-verification.ts +18 -2
  324. package/src/resources/extensions/gsd/auto-worktree.ts +47 -57
  325. package/src/resources/extensions/gsd/auto.ts +50 -2
  326. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  327. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
  328. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
  329. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
  330. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
  331. package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
  332. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  333. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  334. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  335. package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
  336. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  337. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  338. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  339. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  340. package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
  341. package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
  342. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  343. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  344. package/src/resources/extensions/gsd/doctor.ts +7 -2
  345. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  346. package/src/resources/extensions/gsd/guided-flow.ts +5 -6
  347. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  348. package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
  349. package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
  350. package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
  351. package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
  352. package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
  353. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  354. package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
  355. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  356. package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
  357. package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
  358. package/src/resources/extensions/gsd/preferences.ts +17 -2
  359. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  360. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  361. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  362. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  363. package/src/resources/extensions/gsd/prompts/system.md +3 -20
  364. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  365. package/src/resources/extensions/gsd/repo-identity.ts +35 -7
  366. package/src/resources/extensions/gsd/repository-registry.ts +3 -1
  367. package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
  368. package/src/resources/extensions/gsd/skill-activation.ts +292 -0
  369. package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
  370. package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
  371. package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
  372. package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
  373. package/src/resources/extensions/gsd/skill-scope.ts +63 -0
  374. package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
  375. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
  376. package/src/resources/extensions/gsd/skills.ts +75 -0
  377. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
  378. package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
  379. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
  380. package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
  381. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
  382. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
  383. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
  384. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
  385. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
  386. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
  387. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  388. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
  389. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  390. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  391. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  392. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  393. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  394. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
  395. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  396. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
  397. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  398. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
  399. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  400. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
  401. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
  402. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  403. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
  404. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
  405. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  406. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
  407. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
  408. package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
  409. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  410. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
  411. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
  412. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
  413. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  414. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  415. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  416. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
  417. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
  418. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
  419. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
  420. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
  421. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  422. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
  423. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
  424. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
  425. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  426. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
  427. package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
  428. package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
  429. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  430. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
  431. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
  432. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  433. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  434. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  435. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
  436. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
  437. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  438. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  439. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
  440. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
  441. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  442. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  443. package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +141 -1
  444. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
  445. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
  446. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  447. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  448. package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
  449. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
  450. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  451. package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
  452. package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
  453. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  454. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  455. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  456. package/src/resources/extensions/gsd/worktree-post-create-hook.ts +127 -0
  457. package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
  458. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  459. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  460. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  461. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  462. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  463. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  464. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  465. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  466. package/src/resources/extensions/subagent/index.ts +8 -15
  467. package/src/resources/shared/package-manager-detection.ts +39 -0
  468. package/src/resources/skills/agent-browser/SKILL.md +1 -1
  469. package/src/resources/skills/api-design/SKILL.md +1 -1
  470. package/src/resources/skills/code-optimizer/SKILL.md +6 -11
  471. package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
  472. package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
  473. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  474. package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
  475. package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
  476. package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
  477. package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
  478. package/src/resources/skills/forensics/SKILL.md +2 -2
  479. package/src/resources/skills/grill-me/SKILL.md +1 -1
  480. package/src/resources/skills/handoff/SKILL.md +1 -1
  481. package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
  482. package/src/resources/skills/observability/SKILL.md +1 -1
  483. package/src/resources/skills/security-review/SKILL.md +1 -1
  484. package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
  485. package/src/resources/skills/tdd/SKILL.md +1 -1
  486. package/src/resources/skills/write-docs/SKILL.md +1 -1
  487. package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
  488. package/dist/tsconfig.extensions.tsbuildinfo +0 -1
  489. /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
  490. /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
@@ -0,0 +1,499 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Fail-closed reconciliation guards for DB/artifact and slice-id drift.
3
+
4
+ import {
5
+ existsSync,
6
+ lstatSync,
7
+ mkdirSync,
8
+ readdirSync,
9
+ renameSync,
10
+ rmSync,
11
+ } from "node:fs";
12
+ import { basename, join } from "node:path";
13
+
14
+ import {
15
+ _getAdapter,
16
+ getAllMilestones,
17
+ getMilestoneSlices,
18
+ getSliceTasks,
19
+ isDbAvailable,
20
+ } from "../../gsd-db.js";
21
+ import { clearParseCache } from "../../files.js";
22
+ import {
23
+ clearPathCache,
24
+ gsdProjectionRoot,
25
+ resolveMilestonePath,
26
+ resolveSliceFile,
27
+ resolveTaskFile,
28
+ } from "../../paths.js";
29
+ import { isClosedStatus } from "../../status-guards.js";
30
+ import { invalidateStateCache } from "../../state.js";
31
+ import type { GSDState } from "../../types.js";
32
+ import { isAfter, latestExplicitReopenAt } from "../../milestone-reopen-events.js";
33
+ import type { DriftContext, DriftHandler, DriftRecord } from "../types.js";
34
+
35
+ type DiskSliceIdDivergenceDrift = Extract<
36
+ DriftRecord,
37
+ { kind: "disk-slice-id-divergence" }
38
+ >;
39
+ type ArtifactDbStatusDivergenceDrift = Extract<
40
+ DriftRecord,
41
+ { kind: "artifact-db-status-divergence" }
42
+ >;
43
+ type CompletedMilestoneReopenedDrift = Extract<
44
+ DriftRecord,
45
+ { kind: "completed-milestone-reopened" }
46
+ >;
47
+
48
+ type ArtifactStatusRow = {
49
+ path: string;
50
+ artifact_type: string;
51
+ milestone_id: string | null;
52
+ slice_id: string | null;
53
+ task_id: string | null;
54
+ imported_at: string | null;
55
+ };
56
+
57
+ type CompletedDispatchRow = {
58
+ started_at: string | null;
59
+ ended_at: string | null;
60
+ };
61
+
62
+ function safeListArtifactRows(milestoneId: string): ArtifactStatusRow[] {
63
+ const adapter = _getAdapter();
64
+ if (!adapter) return [];
65
+ try {
66
+ return adapter
67
+ .prepare(
68
+ `SELECT path, artifact_type, milestone_id, slice_id, task_id, imported_at
69
+ FROM artifacts
70
+ WHERE milestone_id = :mid
71
+ ORDER BY imported_at, path`,
72
+ )
73
+ .all({ ":mid": milestoneId }) as ArtifactStatusRow[];
74
+ } catch {
75
+ return [];
76
+ }
77
+ }
78
+
79
+ function latestCompletedMilestoneDispatch(
80
+ milestoneId: string,
81
+ ): CompletedDispatchRow | null {
82
+ const adapter = _getAdapter();
83
+ if (!adapter) return null;
84
+ try {
85
+ const row = adapter
86
+ .prepare(
87
+ `SELECT started_at, ended_at
88
+ FROM unit_dispatches
89
+ WHERE milestone_id = :mid
90
+ AND unit_type = 'complete-milestone'
91
+ AND unit_id = :mid
92
+ AND status = 'completed'
93
+ ORDER BY COALESCE(ended_at, started_at) DESC, id DESC
94
+ LIMIT 1`,
95
+ )
96
+ .get({ ":mid": milestoneId }) as CompletedDispatchRow | undefined;
97
+ return row ?? null;
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
102
+
103
+ function hasExplicitReopenAfter(
104
+ basePath: string,
105
+ milestoneId: string,
106
+ completedDispatchAt: string | null | undefined,
107
+ ): boolean {
108
+ const reopenAt = latestExplicitReopenAt(basePath, milestoneId);
109
+ if (!reopenAt) return false;
110
+ if (!completedDispatchAt) return true;
111
+ return Date.parse(reopenAt) > Date.parse(completedDispatchAt);
112
+ }
113
+
114
+ function addUniqueDrift(
115
+ drifts: ArtifactDbStatusDivergenceDrift[],
116
+ seen: Set<string>,
117
+ drift: ArtifactDbStatusDivergenceDrift,
118
+ ): void {
119
+ const key = [
120
+ drift.milestoneId,
121
+ drift.sliceId ?? "",
122
+ drift.taskId ?? "",
123
+ drift.artifactType,
124
+ drift.artifactPath ?? "",
125
+ drift.reason,
126
+ ].join("|");
127
+ if (seen.has(key)) return;
128
+ seen.add(key);
129
+ drifts.push(drift);
130
+ }
131
+
132
+ function detectArtifactDbStatusDriftForMilestone(
133
+ basePath: string,
134
+ milestoneId: string,
135
+ ): ArtifactDbStatusDivergenceDrift[] {
136
+ const milestone = getAllMilestones().find((m) => m.id === milestoneId);
137
+ if (!milestone || isClosedStatus(milestone.status)) return [];
138
+
139
+ const latestReopen = latestExplicitReopenAt(basePath, milestoneId);
140
+ const artifacts = safeListArtifactRows(milestoneId).filter((row) =>
141
+ isAfter(row.imported_at, latestReopen),
142
+ );
143
+ const bySlice = new Map(getMilestoneSlices(milestoneId).map((slice) => [slice.id, slice]));
144
+ const drifts: ArtifactDbStatusDivergenceDrift[] = [];
145
+ const seen = new Set<string>();
146
+
147
+ for (const slice of bySlice.values()) {
148
+ if (!isClosedStatus(slice.status)) {
149
+ const diskSummary = resolveSliceFile(basePath, milestoneId, slice.id, "SUMMARY");
150
+ if (diskSummary && existsSync(diskSummary)) {
151
+ addUniqueDrift(drifts, seen, {
152
+ kind: "artifact-db-status-divergence",
153
+ milestoneId,
154
+ sliceId: slice.id,
155
+ artifactType: "SUMMARY",
156
+ artifactPath: diskSummary,
157
+ dbStatus: slice.status,
158
+ reason: `slice ${slice.id} has SUMMARY on disk while DB status is ${slice.status}`,
159
+ });
160
+ }
161
+ }
162
+
163
+ const tasks = getSliceTasks(milestoneId, slice.id);
164
+ const taskById = new Map(tasks.map((task) => [task.id, task]));
165
+ const summaryRows = artifacts.filter(
166
+ (row) =>
167
+ row.artifact_type === "SUMMARY" &&
168
+ row.slice_id === slice.id &&
169
+ row.task_id,
170
+ );
171
+
172
+ if (tasks.length === 0 && summaryRows.length > 0) {
173
+ addUniqueDrift(drifts, seen, {
174
+ kind: "artifact-db-status-divergence",
175
+ milestoneId,
176
+ sliceId: slice.id,
177
+ artifactType: "SUMMARY",
178
+ artifactPath: summaryRows[0]?.path,
179
+ dbStatus: "no-db-tasks",
180
+ reason: `slice ${slice.id} has task SUMMARY artifacts but no DB tasks`,
181
+ });
182
+ }
183
+
184
+ for (const row of summaryRows) {
185
+ const task = row.task_id ? taskById.get(row.task_id) : null;
186
+ if (!task) {
187
+ if (tasks.length > 0) {
188
+ addUniqueDrift(drifts, seen, {
189
+ kind: "artifact-db-status-divergence",
190
+ milestoneId,
191
+ sliceId: slice.id,
192
+ taskId: row.task_id ?? undefined,
193
+ artifactType: "SUMMARY",
194
+ artifactPath: row.path,
195
+ dbStatus: "missing-db-task",
196
+ reason: `task ${slice.id}/${row.task_id} has SUMMARY artifact but no DB task`,
197
+ });
198
+ }
199
+ continue;
200
+ }
201
+ if (isClosedStatus(task.status)) continue;
202
+ addUniqueDrift(drifts, seen, {
203
+ kind: "artifact-db-status-divergence",
204
+ milestoneId,
205
+ sliceId: slice.id,
206
+ taskId: row.task_id ?? undefined,
207
+ artifactType: "SUMMARY",
208
+ artifactPath: row.path,
209
+ dbStatus: task.status,
210
+ reason: `task ${slice.id}/${row.task_id} has SUMMARY artifact while DB status is ${task.status}`,
211
+ });
212
+ }
213
+
214
+ for (const task of tasks) {
215
+ if (isClosedStatus(task.status)) continue;
216
+ const diskTaskSummary = resolveTaskFile(
217
+ basePath,
218
+ milestoneId,
219
+ slice.id,
220
+ task.id,
221
+ "SUMMARY",
222
+ );
223
+ if (!diskTaskSummary || !existsSync(diskTaskSummary)) continue;
224
+ addUniqueDrift(drifts, seen, {
225
+ kind: "artifact-db-status-divergence",
226
+ milestoneId,
227
+ sliceId: slice.id,
228
+ taskId: task.id,
229
+ artifactType: "SUMMARY",
230
+ artifactPath: diskTaskSummary,
231
+ dbStatus: task.status,
232
+ reason: `task ${slice.id}/${task.id} has SUMMARY on disk while DB status is ${task.status}`,
233
+ });
234
+ }
235
+ }
236
+
237
+ for (const row of artifacts) {
238
+ if (row.artifact_type !== "SUMMARY" || !row.slice_id || row.task_id) continue;
239
+ const slice = bySlice.get(row.slice_id);
240
+ if (!slice || isClosedStatus(slice.status)) continue;
241
+ addUniqueDrift(drifts, seen, {
242
+ kind: "artifact-db-status-divergence",
243
+ milestoneId,
244
+ sliceId: row.slice_id,
245
+ artifactType: "SUMMARY",
246
+ artifactPath: row.path,
247
+ dbStatus: slice.status,
248
+ reason: `slice ${row.slice_id} has SUMMARY artifact while DB status is ${slice.status}`,
249
+ });
250
+ }
251
+
252
+ return drifts;
253
+ }
254
+
255
+ function classifyDiskOnlySliceDir(
256
+ sliceDir: string,
257
+ ): DiskSliceIdDivergenceDrift["disposition"] {
258
+ let sawScaffold = false;
259
+ const stack = [sliceDir];
260
+
261
+ while (stack.length > 0) {
262
+ const dir = stack.pop()!;
263
+ let entries: string[];
264
+ try {
265
+ entries = readdirSync(dir);
266
+ } catch {
267
+ return "block-meaningful";
268
+ }
269
+ if (entries.length === 0 && dir !== sliceDir) {
270
+ sawScaffold = true;
271
+ continue;
272
+ }
273
+ for (const entry of entries) {
274
+ if (entry === ".DS_Store") continue;
275
+ const full = join(dir, entry);
276
+ let stat;
277
+ try {
278
+ stat = lstatSync(full);
279
+ } catch {
280
+ return "block-meaningful";
281
+ }
282
+ if (stat.isDirectory()) {
283
+ sawScaffold = true;
284
+ stack.push(full);
285
+ continue;
286
+ }
287
+ if (stat.isFile() && stat.size === 0) {
288
+ sawScaffold = true;
289
+ continue;
290
+ }
291
+ return "block-meaningful";
292
+ }
293
+ }
294
+
295
+ return sawScaffold ? "quarantine-scaffold" : "delete-empty";
296
+ }
297
+
298
+ function detectDiskSliceIdDivergenceForMilestone(
299
+ basePath: string,
300
+ milestoneId: string,
301
+ ): DiskSliceIdDivergenceDrift[] {
302
+ const milestonePath = resolveMilestonePath(basePath, milestoneId);
303
+ if (!milestonePath) return [];
304
+
305
+ const slicesDir = join(milestonePath, "slices");
306
+ if (!existsSync(slicesDir)) return [];
307
+
308
+ const knownSliceIds = new Set(getMilestoneSlices(milestoneId).map((slice) => slice.id));
309
+ const drifts: DiskSliceIdDivergenceDrift[] = [];
310
+
311
+ for (const entry of readdirSync(slicesDir)) {
312
+ const sliceDir = join(slicesDir, entry);
313
+ try {
314
+ if (!lstatSync(sliceDir).isDirectory()) continue;
315
+ } catch {
316
+ continue;
317
+ }
318
+ if (entry === "parallel-research") continue;
319
+ if (knownSliceIds.has(entry)) continue;
320
+
321
+ const disposition = classifyDiskOnlySliceDir(sliceDir);
322
+ drifts.push({
323
+ kind: "disk-slice-id-divergence",
324
+ milestoneId,
325
+ sliceId: entry,
326
+ sliceDir,
327
+ disposition,
328
+ reason:
329
+ disposition === "block-meaningful"
330
+ ? `disk-only slice directory ${entry} contains meaningful files and is not in the DB`
331
+ : `disk-only slice directory ${entry} is not in the DB`,
332
+ });
333
+ }
334
+
335
+ return drifts;
336
+ }
337
+
338
+ export function detectArtifactDbDrift(
339
+ _state: GSDState,
340
+ ctx: DriftContext,
341
+ ): Array<
342
+ | DiskSliceIdDivergenceDrift
343
+ | ArtifactDbStatusDivergenceDrift
344
+ | CompletedMilestoneReopenedDrift
345
+ > {
346
+ if (!isDbAvailable()) return [];
347
+
348
+ const drifts: Array<
349
+ | DiskSliceIdDivergenceDrift
350
+ | ArtifactDbStatusDivergenceDrift
351
+ | CompletedMilestoneReopenedDrift
352
+ > = [];
353
+
354
+ for (const milestone of getAllMilestones()) {
355
+ if (isClosedStatus(milestone.status)) continue;
356
+
357
+ const completedDispatch = latestCompletedMilestoneDispatch(milestone.id);
358
+ const completedAt = completedDispatch?.ended_at ?? completedDispatch?.started_at ?? null;
359
+ if (
360
+ completedDispatch &&
361
+ !hasExplicitReopenAfter(ctx.basePath, milestone.id, completedAt)
362
+ ) {
363
+ drifts.push({
364
+ kind: "completed-milestone-reopened",
365
+ milestoneId: milestone.id,
366
+ dbStatus: milestone.status,
367
+ completedDispatchAt: completedAt,
368
+ });
369
+ }
370
+
371
+ drifts.push(...detectArtifactDbStatusDriftForMilestone(ctx.basePath, milestone.id));
372
+ drifts.push(...detectDiskSliceIdDivergenceForMilestone(ctx.basePath, milestone.id));
373
+ }
374
+
375
+ return drifts;
376
+ }
377
+
378
+ function quarantineSliceDir(record: DiskSliceIdDivergenceDrift, basePath: string): void {
379
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
380
+ const quarantineDir = join(
381
+ gsdProjectionRoot(basePath),
382
+ "quarantine",
383
+ "milestones",
384
+ record.milestoneId,
385
+ "slices",
386
+ );
387
+ mkdirSync(quarantineDir, { recursive: true });
388
+ const target = join(quarantineDir, `${basename(record.sliceDir)}-${stamp}`);
389
+ renameSync(record.sliceDir, target);
390
+ }
391
+
392
+ function diskSliceIdDivergenceGuidance(record: DiskSliceIdDivergenceDrift): string {
393
+ const quarantineExample = `.gsd/quarantine/milestones/${record.milestoneId}/slices/${record.sliceId}-manual-review`;
394
+ return (
395
+ `Slice ID drift in ${record.milestoneId}: ${record.reason}. ` +
396
+ "Runtime will not import disk-only slice IDs into the DB. " +
397
+ `Review ${record.sliceDir}. ` +
398
+ `If ${record.sliceId} is stale, move or delete that directory; to preserve it, move it under ${quarantineExample}. ` +
399
+ "If it contains work to keep, copy or merge that content into a DB-backed slice, or explicitly recreate the slice through GSD planning, then remove the disk-only directory. " +
400
+ `After repair, run /gsd doctor ${record.milestoneId}, then resume with /gsd next or /gsd auto.`
401
+ );
402
+ }
403
+
404
+ export function repairArtifactDbDrift(
405
+ record:
406
+ | DiskSliceIdDivergenceDrift
407
+ | ArtifactDbStatusDivergenceDrift
408
+ | CompletedMilestoneReopenedDrift,
409
+ ctx: DriftContext,
410
+ ): void {
411
+ if (record.kind === "disk-slice-id-divergence") {
412
+ if (record.disposition === "delete-empty") {
413
+ rmSync(record.sliceDir, { recursive: true, force: true });
414
+ } else if (record.disposition === "quarantine-scaffold") {
415
+ quarantineSliceDir(record, ctx.basePath);
416
+ } else {
417
+ throw new Error(diskSliceIdDivergenceGuidance(record));
418
+ }
419
+ clearPathCache();
420
+ clearParseCache();
421
+ invalidateStateCache();
422
+ return;
423
+ }
424
+
425
+ if (record.kind === "completed-milestone-reopened") {
426
+ throw new Error(
427
+ `Milestone ${record.milestoneId} has completed complete-milestone dispatch history` +
428
+ ` (${record.completedDispatchAt ?? "time unknown"}) but the DB status is ${record.dbStatus}. ` +
429
+ "Refusing to plan it again without an explicit reopen or recovery.",
430
+ );
431
+ }
432
+
433
+ throw new Error(
434
+ `Artifact/DB status drift in ${record.milestoneId}` +
435
+ `${record.sliceId ? `/${record.sliceId}` : ""}` +
436
+ `${record.taskId ? `/${record.taskId}` : ""}: ${record.reason}. ` +
437
+ "Runtime will not silently import completion artifacts into DB state; run explicit recovery/repair after review.",
438
+ );
439
+ }
440
+
441
+ export function describeArtifactDbDriftBlocker(
442
+ record:
443
+ | DiskSliceIdDivergenceDrift
444
+ | ArtifactDbStatusDivergenceDrift
445
+ | CompletedMilestoneReopenedDrift,
446
+ ): string | null {
447
+ if (record.kind === "disk-slice-id-divergence") {
448
+ if (record.disposition !== "block-meaningful") return null;
449
+ return diskSliceIdDivergenceGuidance(record);
450
+ }
451
+
452
+ if (record.kind === "completed-milestone-reopened") {
453
+ return (
454
+ `Milestone ${record.milestoneId} has completed complete-milestone dispatch history` +
455
+ ` (${record.completedDispatchAt ?? "time unknown"}) but the DB status is ${record.dbStatus}. ` +
456
+ "Refusing to plan it again without an explicit reopen or recovery."
457
+ );
458
+ }
459
+
460
+ return (
461
+ `Artifact/DB status drift in ${record.milestoneId}` +
462
+ `${record.sliceId ? `/${record.sliceId}` : ""}` +
463
+ `${record.taskId ? `/${record.taskId}` : ""}: ${record.reason}. ` +
464
+ "Runtime will not silently import completion artifacts into DB state; run explicit recovery/repair after review."
465
+ );
466
+ }
467
+
468
+ export const diskSliceIdDivergenceHandler: DriftHandler<DiskSliceIdDivergenceDrift> = {
469
+ kind: "disk-slice-id-divergence",
470
+ detect: (state, ctx) =>
471
+ detectArtifactDbDrift(state, ctx).filter(
472
+ (record): record is DiskSliceIdDivergenceDrift =>
473
+ record.kind === "disk-slice-id-divergence",
474
+ ),
475
+ blocker: describeArtifactDbDriftBlocker,
476
+ repair: repairArtifactDbDrift,
477
+ };
478
+
479
+ export const artifactDbStatusDivergenceHandler: DriftHandler<ArtifactDbStatusDivergenceDrift> = {
480
+ kind: "artifact-db-status-divergence",
481
+ detect: (state, ctx) =>
482
+ detectArtifactDbDrift(state, ctx).filter(
483
+ (record): record is ArtifactDbStatusDivergenceDrift =>
484
+ record.kind === "artifact-db-status-divergence",
485
+ ),
486
+ blocker: describeArtifactDbDriftBlocker,
487
+ repair: repairArtifactDbDrift,
488
+ };
489
+
490
+ export const completedMilestoneReopenedHandler: DriftHandler<CompletedMilestoneReopenedDrift> = {
491
+ kind: "completed-milestone-reopened",
492
+ detect: (state, ctx) =>
493
+ detectArtifactDbDrift(state, ctx).filter(
494
+ (record): record is CompletedMilestoneReopenedDrift =>
495
+ record.kind === "completed-milestone-reopened",
496
+ ),
497
+ blocker: describeArtifactDbDriftBlocker,
498
+ repair: repairArtifactDbDrift,
499
+ };
@@ -76,6 +76,8 @@ export async function reconcileBeforeDispatch(
76
76
  }
77
77
 
78
78
  const failures: ReconciliationFailureDetail[] = [];
79
+ const blockers: string[] = [];
80
+ let repairedThisPass = false;
79
81
  for (const record of drift) {
80
82
  const handler = registry.find((h) => h.kind === record.kind);
81
83
  if (!handler) {
@@ -87,14 +89,33 @@ export async function reconcileBeforeDispatch(
87
89
  });
88
90
  continue;
89
91
  }
92
+ const blocker = handler.blocker ? await handler.blocker(record, ctx) : null;
93
+ if (blocker) {
94
+ blockers.push(blocker);
95
+ continue;
96
+ }
90
97
  try {
91
98
  await handler.repair(record, ctx);
92
99
  repaired.push(record);
100
+ repairedThisPass = true;
93
101
  } catch (cause) {
94
102
  failures.push({ drift: record, cause });
95
103
  }
96
104
  }
97
105
 
106
+ if (blockers.length > 0) {
107
+ let blockerState = stateSnapshot;
108
+ if (repairedThisPass) {
109
+ deps.invalidateStateCache();
110
+ blockerState = await deps.deriveState(basePath, deps.deriveStateOptions);
111
+ }
112
+ return {
113
+ ok: true,
114
+ stateSnapshot: blockerState,
115
+ repaired,
116
+ blockers: [...new Set([...(blockerState.blockers ?? []), ...blockers])],
117
+ };
118
+ }
98
119
  if (failures.length > 0) {
99
120
  throw new ReconciliationFailedError({ failures, pass });
100
121
  }
@@ -108,6 +129,25 @@ export async function reconcileBeforeDispatch(
108
129
  const persistent = await detectAllDrift(finalState, finalCtx, registry);
109
130
 
110
131
  if (persistent.length > 0) {
132
+ const blockers: string[] = [];
133
+ const unblockedPersistent: DriftRecord[] = [];
134
+ for (const record of persistent) {
135
+ const handler = registry.find((h) => h.kind === record.kind);
136
+ const blocker = handler?.blocker ? await handler.blocker(record, finalCtx) : null;
137
+ if (blocker) {
138
+ blockers.push(blocker);
139
+ } else {
140
+ unblockedPersistent.push(record);
141
+ }
142
+ }
143
+ if (blockers.length > 0 && unblockedPersistent.length === 0) {
144
+ return {
145
+ ok: true,
146
+ stateSnapshot: finalState,
147
+ repaired,
148
+ blockers: [...new Set([...(finalState.blockers ?? []), ...blockers])],
149
+ };
150
+ }
111
151
  throw new ReconciliationFailedError({ persistentDrift: persistent });
112
152
  }
113
153
 
@@ -3,6 +3,11 @@
3
3
  // the catalog. Tests can override per-call via ReconciliationDeps.registry.
4
4
 
5
5
  import { completionTimestampHandler } from "./drift/completion.js";
6
+ import {
7
+ artifactDbStatusDivergenceHandler,
8
+ completedMilestoneReopenedHandler,
9
+ diskSliceIdDivergenceHandler,
10
+ } from "./drift/artifact-db.js";
6
11
  import { mergeStateHandler } from "./drift/merge-state.js";
7
12
  import { unregisteredMilestoneHandler } from "./drift/project-md.js";
8
13
  import { roadmapDivergenceHandler } from "./drift/roadmap.js";
@@ -22,6 +27,9 @@ export const DRIFT_REGISTRY: ReadonlyArray<DriftHandler<any>> = [
22
27
  staleRenderHandler,
23
28
  staleWorkerHandler,
24
29
  unregisteredMilestoneHandler,
30
+ diskSliceIdDivergenceHandler,
25
31
  roadmapDivergenceHandler,
32
+ completedMilestoneReopenedHandler,
33
+ artifactDbStatusDivergenceHandler,
26
34
  completionTimestampHandler,
27
35
  ];
@@ -15,6 +15,30 @@ export type DriftRecord =
15
15
  | { kind: "stale-worker"; lockPath: string; pid: number }
16
16
  | { kind: "unregistered-milestone"; milestoneId: string }
17
17
  | { kind: "roadmap-divergence"; milestoneId: string; sliceId?: string }
18
+ | {
19
+ kind: "disk-slice-id-divergence";
20
+ milestoneId: string;
21
+ sliceId: string;
22
+ sliceDir: string;
23
+ disposition: "delete-empty" | "quarantine-scaffold" | "block-meaningful";
24
+ reason: string;
25
+ }
26
+ | {
27
+ kind: "artifact-db-status-divergence";
28
+ milestoneId: string;
29
+ sliceId?: string;
30
+ taskId?: string;
31
+ artifactType: string;
32
+ artifactPath?: string;
33
+ dbStatus?: string;
34
+ reason: string;
35
+ }
36
+ | {
37
+ kind: "completed-milestone-reopened";
38
+ milestoneId: string;
39
+ dbStatus: string;
40
+ completedDispatchAt?: string | null;
41
+ }
18
42
  | {
19
43
  kind: "missing-completion-timestamp";
20
44
  entity: "task" | "slice" | "milestone";
@@ -40,6 +64,12 @@ export interface DriftContext {
40
64
  export interface DriftHandler<T extends DriftRecord = DriftRecord> {
41
65
  kind: T["kind"];
42
66
  detect: (state: GSDState, ctx: DriftContext) => T[] | Promise<T[]>;
67
+ /**
68
+ * Return a terminal blocker message for drift that is intentionally
69
+ * non-repairable in runtime. This lets callers stop cleanly without
70
+ * classifying the condition as a repair exception.
71
+ */
72
+ blocker?: (record: T, ctx: DriftContext) => string | null | Promise<string | null>;
43
73
  repair: (record: T, ctx: DriftContext) => Promise<void> | void;
44
74
  }
45
75