gsd-pi 2.76.0-dev.fe143342a → 2.77.0-dev.1d17f366c

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 (597) hide show
  1. package/README.md +17 -35
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +38 -2
  6. package/dist/extension-discovery.d.ts +6 -0
  7. package/dist/extension-discovery.js +37 -0
  8. package/dist/extension-registry.d.ts +3 -0
  9. package/dist/extension-sort.d.ts +18 -0
  10. package/dist/extension-sort.js +114 -0
  11. package/dist/extension-validator.d.ts +47 -0
  12. package/dist/extension-validator.js +127 -0
  13. package/dist/loader.js +35 -7
  14. package/dist/onboarding.js +45 -0
  15. package/dist/provider-migrations.d.ts +18 -0
  16. package/dist/provider-migrations.js +14 -0
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +78 -59
  19. package/dist/resources/extensions/cmux/index.js +20 -0
  20. package/dist/resources/extensions/github-sync/templates.js +103 -0
  21. package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
  22. package/dist/resources/extensions/google-search/index.js +3 -375
  23. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +90 -2
  25. package/dist/resources/extensions/gsd/auto/phases.js +95 -21
  26. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  27. package/dist/resources/extensions/gsd/auto/run-unit.js +48 -4
  28. package/dist/resources/extensions/gsd/auto/session.js +18 -1
  29. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  30. package/dist/resources/extensions/gsd/auto-dispatch.js +115 -17
  31. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -1
  33. package/dist/resources/extensions/gsd/auto-post-unit.js +90 -2
  34. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  35. package/dist/resources/extensions/gsd/auto-recovery.js +46 -1
  36. package/dist/resources/extensions/gsd/auto-start.js +45 -39
  37. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  38. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  39. package/dist/resources/extensions/gsd/auto-worktree.js +109 -61
  40. package/dist/resources/extensions/gsd/auto.js +97 -31
  41. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +27 -1
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
  43. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +11 -0
  44. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -6
  45. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -6
  46. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  47. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  49. package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
  50. package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
  51. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  52. package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
  53. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  54. package/dist/resources/extensions/gsd/git-service.js +1 -0
  55. package/dist/resources/extensions/gsd/gitignore.js +2 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +90 -30
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +212 -9
  59. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  60. package/dist/resources/extensions/gsd/journal.js +17 -2
  61. package/dist/resources/extensions/gsd/key-manager.js +22 -0
  62. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  63. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  64. package/dist/resources/extensions/gsd/model-router.js +36 -3
  65. package/dist/resources/extensions/gsd/notifications.js +30 -16
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +31 -6
  67. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  68. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  69. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  70. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  71. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  72. package/dist/resources/extensions/gsd/reports.js +5 -4
  73. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  74. package/dist/resources/extensions/gsd/safety/file-change-validator.js +12 -4
  75. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  76. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  77. package/dist/resources/extensions/gsd/state.js +25 -25
  78. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  79. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  80. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  81. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  82. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  83. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  84. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  85. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  86. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  87. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  88. package/dist/resources/extensions/gsd/uok/plan-v2.js +30 -7
  89. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  90. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  91. package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
  92. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  93. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  94. package/dist/resources/extensions/mcp-client/index.js +118 -9
  95. package/dist/resources/extensions/shared/cmux-events.js +12 -0
  96. package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
  97. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  98. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  99. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  100. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  101. package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
  102. package/dist/resources/skills/write-docs/SKILL.md +2 -1
  103. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  106. package/dist/web/standalone/.next/build-manifest.json +3 -3
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/index.html +1 -1
  190. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  191. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  193. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  194. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  197. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  198. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  199. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  201. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  206. package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
  207. package/dist/welcome-screen.js +6 -1
  208. package/dist/wizard.js +2 -0
  209. package/package.json +16 -14
  210. package/packages/daemon/package.json +2 -2
  211. package/packages/mcp-server/README.md +3 -3
  212. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  213. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  214. package/packages/mcp-server/dist/env-writer.js +74 -6
  215. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  216. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  217. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  218. package/packages/mcp-server/dist/remote-questions.js +732 -0
  219. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  220. package/packages/mcp-server/dist/server.d.ts +7 -0
  221. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/server.js +95 -10
  223. package/packages/mcp-server/dist/server.js.map +1 -1
  224. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  225. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/session-manager.js +49 -1
  227. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/package.json +9 -3
  232. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  233. package/packages/mcp-server/src/env-writer.ts +76 -6
  234. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  235. package/packages/mcp-server/src/readers/readers.test.ts +5 -1
  236. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  237. package/packages/mcp-server/src/remote-questions.ts +916 -0
  238. package/packages/mcp-server/src/server.ts +118 -16
  239. package/packages/mcp-server/src/session-manager.ts +43 -1
  240. package/packages/mcp-server/src/workflow-tools.test.ts +44 -0
  241. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  242. package/packages/mcp-server/tsconfig.test.json +19 -0
  243. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  244. package/packages/native/package.json +6 -1
  245. package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
  246. package/packages/native/tsconfig.tsbuildinfo +1 -1
  247. package/packages/pi-agent-core/package.json +6 -1
  248. package/packages/pi-agent-core/src/agent-loop.test.ts +220 -15
  249. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  250. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models/custom.js +41 -0
  252. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  254. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  255. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  257. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  258. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/providers/anthropic.js +8 -3
  260. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  261. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  262. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  263. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  264. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  265. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  266. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  268. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  269. package/packages/pi-ai/package.json +6 -1
  270. package/packages/pi-ai/src/models/custom.ts +42 -0
  271. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  272. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  273. package/packages/pi-ai/src/providers/anthropic.ts +9 -3
  274. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  275. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  276. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  278. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  280. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.js +7 -0
  282. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +25 -0
  284. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
  286. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
  288. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
  290. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
  292. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
  296. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  298. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  299. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  300. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  301. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
  302. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
  304. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
  306. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
  308. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
  310. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
  312. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
  313. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +3 -2
  314. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/extensions/loader.js +24 -8
  316. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  318. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +14 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +11 -0
  324. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -2
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  330. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/model-registry.js +14 -0
  333. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
  335. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  337. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  339. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  341. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/session-manager.js +1 -1
  343. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/session-manager.test.js +21 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/system-prompt.js +3 -3
  347. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
  349. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  351. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  354. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -0
  360. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  363. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  364. package/packages/pi-coding-agent/package.json +6 -1
  365. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  366. package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
  367. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
  368. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
  369. package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
  370. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  371. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
  372. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
  373. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
  374. package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
  375. package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
  376. package/packages/pi-coding-agent/src/core/extensions/loader.ts +24 -11
  377. package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
  378. package/packages/pi-coding-agent/src/core/extensions/types.ts +15 -0
  379. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +13 -0
  380. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -2
  381. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  382. package/packages/pi-coding-agent/src/core/model-registry.ts +16 -0
  383. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
  384. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  385. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  386. package/packages/pi-coding-agent/src/core/session-manager.test.ts +30 -1
  387. package/packages/pi-coding-agent/src/core/session-manager.ts +1 -1
  388. package/packages/pi-coding-agent/src/core/system-prompt.ts +3 -3
  389. package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
  390. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  391. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  392. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  393. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +14 -0
  394. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  395. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  396. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +12 -5
  397. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  398. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +21 -0
  399. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  400. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  401. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  403. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  404. package/packages/pi-tui/package.json +6 -1
  405. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -5
  406. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +27 -0
  407. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  408. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  409. package/packages/rpc-client/package.json +6 -1
  410. package/pkg/package.json +1 -1
  411. package/scripts/install.js +512 -0
  412. package/scripts/lib/workspace-manifest.cjs +86 -0
  413. package/scripts/link-workspace-packages.cjs +5 -17
  414. package/scripts/postinstall.js +9 -178
  415. package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
  416. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +91 -63
  417. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +114 -12
  418. package/src/resources/extensions/cmux/index.ts +35 -10
  419. package/src/resources/extensions/github-sync/templates.ts +151 -0
  420. package/src/resources/extensions/github-sync/tests/templates.test.ts +59 -0
  421. package/src/resources/extensions/google-search/extension-manifest.json +5 -4
  422. package/src/resources/extensions/google-search/index.ts +9 -470
  423. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  424. package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -1
  425. package/src/resources/extensions/gsd/auto/loop.ts +104 -2
  426. package/src/resources/extensions/gsd/auto/phases.ts +123 -21
  427. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  428. package/src/resources/extensions/gsd/auto/run-unit.ts +56 -4
  429. package/src/resources/extensions/gsd/auto/session.ts +28 -1
  430. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  431. package/src/resources/extensions/gsd/auto/types.ts +1 -1
  432. package/src/resources/extensions/gsd/auto-dispatch.ts +117 -16
  433. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  434. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -1
  435. package/src/resources/extensions/gsd/auto-post-unit.ts +92 -3
  436. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  437. package/src/resources/extensions/gsd/auto-recovery.ts +40 -1
  438. package/src/resources/extensions/gsd/auto-start.ts +48 -52
  439. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  440. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  441. package/src/resources/extensions/gsd/auto-worktree.ts +122 -68
  442. package/src/resources/extensions/gsd/auto.ts +105 -35
  443. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -1
  444. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
  445. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +11 -0
  446. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  447. package/src/resources/extensions/gsd/bootstrap/system-context.ts +13 -9
  448. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  449. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  450. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  451. package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
  452. package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
  453. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  454. package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
  455. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  456. package/src/resources/extensions/gsd/git-service.ts +1 -0
  457. package/src/resources/extensions/gsd/gitignore.ts +2 -1
  458. package/src/resources/extensions/gsd/gsd-db.ts +92 -32
  459. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  460. package/src/resources/extensions/gsd/guided-flow.ts +259 -10
  461. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  462. package/src/resources/extensions/gsd/journal.ts +29 -3
  463. package/src/resources/extensions/gsd/key-manager.ts +22 -0
  464. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  465. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  466. package/src/resources/extensions/gsd/model-router.ts +42 -1
  467. package/src/resources/extensions/gsd/notifications.ts +27 -15
  468. package/src/resources/extensions/gsd/pre-execution-checks.ts +33 -7
  469. package/src/resources/extensions/gsd/preferences-types.ts +8 -0
  470. package/src/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  471. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  472. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  473. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  474. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  475. package/src/resources/extensions/gsd/reports.ts +5 -4
  476. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  477. package/src/resources/extensions/gsd/safety/file-change-validator.ts +16 -3
  478. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  479. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  480. package/src/resources/extensions/gsd/state.ts +35 -30
  481. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +238 -4
  482. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  483. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  484. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +122 -0
  485. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  486. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +63 -0
  487. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  488. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  489. package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
  490. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +15 -0
  491. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  492. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  493. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  494. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +161 -0
  495. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  496. package/src/resources/extensions/gsd/tests/derive-state.test.ts +1 -2
  497. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
  498. package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
  499. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  500. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  501. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
  502. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  503. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -1
  504. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  505. package/src/resources/extensions/gsd/tests/exec-history.test.ts +113 -0
  506. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  507. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +38 -0
  508. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  509. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
  510. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +296 -1
  511. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  512. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  513. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +4 -2
  514. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  515. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  516. package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
  517. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  518. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +66 -0
  519. package/src/resources/extensions/gsd/tests/key-manager.test.ts +2 -0
  520. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
  521. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  522. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  523. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  524. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
  525. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  526. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
  527. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
  528. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  529. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
  530. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  531. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  532. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +337 -0
  533. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  534. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +39 -25
  535. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
  536. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  537. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  538. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  539. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  540. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  541. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  542. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  543. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  544. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  545. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  546. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  547. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +24 -0
  548. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  549. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  550. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  551. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  552. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  553. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  554. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  555. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  556. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  557. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  558. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +42 -2
  559. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  560. package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
  561. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +138 -5
  562. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
  563. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  564. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  566. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  567. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  568. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  569. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  570. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  571. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  572. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  573. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  574. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  575. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  576. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  577. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  578. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  579. package/src/resources/extensions/gsd/uok/plan-v2.ts +39 -8
  580. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  581. package/src/resources/extensions/gsd/workflow-logger.ts +23 -3
  582. package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
  583. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  584. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  585. package/src/resources/extensions/mcp-client/index.ts +129 -10
  586. package/src/resources/extensions/shared/cmux-events.ts +59 -0
  587. package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
  588. package/src/resources/skills/create-skill/SKILL.md +2 -2
  589. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  590. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  591. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  592. package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
  593. package/src/resources/skills/write-docs/SKILL.md +2 -1
  594. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  595. package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
  596. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_buildManifest.js +0 -0
  597. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_ssgManifest.js +0 -0
@@ -16,7 +16,11 @@ async function getEncoder() {
16
16
  try {
17
17
  // @ts-ignore — tiktoken may not have type declarations in extensions tsconfig
18
18
  const tiktoken = await import("tiktoken");
19
- encoder = tiktoken.encoding_for_model("gpt-4o");
19
+ // Use cl100k_base — the most conservative and broadly compatible BPE encoding.
20
+ // It is shared by GPT-3.5/GPT-4 and gives a safer (larger) estimate than
21
+ // gpt-4o's o200k_base encoding, which produces fewer tokens for the same text
22
+ // and would cause context windows for non-OpenAI providers to be under-counted.
23
+ encoder = tiktoken.get_encoding("cl100k_base");
20
24
  return encoder;
21
25
  }
22
26
  catch {
@@ -24,19 +28,32 @@ async function getEncoder() {
24
28
  return null;
25
29
  }
26
30
  }
27
- export async function countTokens(text) {
31
+ /**
32
+ * Count tokens in `text` using tiktoken (cl100k_base) when available.
33
+ *
34
+ * When tiktoken is not loaded, falls back to a provider-aware character-ratio
35
+ * estimate via `estimateTokensForProvider`. Passing `provider` is recommended
36
+ * so the heuristic fallback is as accurate as possible.
37
+ */
38
+ export async function countTokens(text, provider) {
28
39
  const enc = await getEncoder();
29
40
  if (enc) {
30
41
  const tokens = enc.encode(text);
31
42
  return tokens.length;
32
43
  }
33
- return Math.ceil(text.length / 4);
44
+ return estimateTokensForProvider(text, provider ?? "unknown");
34
45
  }
35
- export function countTokensSync(text) {
46
+ /**
47
+ * Synchronous token count — only accurate after `initTokenCounter()` resolves.
48
+ *
49
+ * Before init, or when tiktoken is unavailable, falls back to a provider-aware
50
+ * character-ratio estimate. Passing `provider` is recommended.
51
+ */
52
+ export function countTokensSync(text, provider) {
36
53
  if (encoder) {
37
54
  return encoder.encode(text).length;
38
55
  }
39
- return Math.ceil(text.length / 4);
56
+ return estimateTokensForProvider(text, provider ?? "unknown");
40
57
  }
41
58
  export async function initTokenCounter() {
42
59
  const enc = await getEncoder();
@@ -6,7 +6,7 @@
6
6
  * for recovery, and invalidates caches.
7
7
  */
8
8
  import { join } from "node:path";
9
- import { mkdirSync } from "node:fs";
9
+ import { mkdirSync, existsSync } from "node:fs";
10
10
  import { transaction, getMilestone, getMilestoneSlices, getSliceTasks, updateMilestoneStatus, } from "../gsd-db.js";
11
11
  import { resolveMilestonePath, clearPathCache } from "../paths.js";
12
12
  import { isClosedStatus } from "../status-guards.js";
@@ -141,15 +141,21 @@ export async function handleCompleteMilestone(params, basePath) {
141
141
  mkdirSync(manualDir, { recursive: true });
142
142
  summaryPath = join(manualDir, `${params.milestoneId}-SUMMARY.md`);
143
143
  }
144
- try {
145
- await saveFile(summaryPath, summaryMd);
146
- }
147
- catch (renderErr) {
148
- // Disk render failed — roll back DB status so state stays consistent
149
- logWarning("tool", `complete_milestone — disk render failed, rolling back DB status: ${renderErr.message}`);
150
- updateMilestoneStatus(params.milestoneId, 'active', null);
151
- invalidateStateCache();
152
- return { error: `disk render failed: ${renderErr.message}` };
144
+ // Guard (#4598): if SUMMARY.md already exists on disk, do not overwrite it.
145
+ // This handles re-dispatch scenarios (DB/disk state divergence) where a prior
146
+ // completion already wrote the file. Overwriting would silently destroy the
147
+ // richer content the agent produced during the original completion run.
148
+ if (!existsSync(summaryPath)) {
149
+ try {
150
+ await saveFile(summaryPath, summaryMd);
151
+ }
152
+ catch (renderErr) {
153
+ // Disk render failed — roll back DB status so state stays consistent
154
+ logWarning("tool", `complete_milestone — disk render failed, rolling back DB status: ${renderErr.message}`);
155
+ updateMilestoneStatus(params.milestoneId, 'active', null);
156
+ invalidateStateCache();
157
+ return { error: `disk render failed: ${renderErr.message}` };
158
+ }
153
159
  }
154
160
  // Invalidate all caches
155
161
  invalidateStateCache();
@@ -16,6 +16,7 @@ import { checkOwnership, sliceUnitKey } from "../unit-ownership.js";
16
16
  import { saveFile, clearParseCache } from "../files.js";
17
17
  import { invalidateStateCache } from "../state.js";
18
18
  import { renderRoadmapCheckboxes } from "../markdown-renderer.js";
19
+ import { isStaleWrite } from "../auto/turn-epoch.js";
19
20
  import { renderAllProjections } from "../workflow-projections.js";
20
21
  import { writeManifest } from "../workflow-manifest.js";
21
22
  import { appendEvent } from "../workflow-events.js";
@@ -228,6 +229,10 @@ export async function handleCompleteSlice(params, basePath) {
228
229
  }
229
230
  const slice = getSlice(params.milestoneId, params.sliceId);
230
231
  if (slice && isClosedStatus(slice.status)) {
232
+ if (isStaleWrite("complete-slice")) {
233
+ guardError = "__stale_duplicate__";
234
+ return;
235
+ }
231
236
  guardError = `slice ${params.sliceId} is already complete — use gsd_slice_reopen first if you need to redo it`;
232
237
  return;
233
238
  }
@@ -248,6 +253,22 @@ export async function handleCompleteSlice(params, basePath) {
248
253
  insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
249
254
  updateSliceStatus(params.milestoneId, params.sliceId, "complete", completedAt);
250
255
  });
256
+ if (guardError === "__stale_duplicate__") {
257
+ // Stale duplicate from a turn superseded by timeout recovery. Return a
258
+ // non-mutating success so the orphaned LLM tool call unwinds quietly.
259
+ const sliceDir = resolveSlicePath(basePath, params.milestoneId, params.sliceId);
260
+ const staleSummaryPath = sliceDir
261
+ ? join(sliceDir, `${params.sliceId}-SUMMARY.md`)
262
+ : join(basePath, ".gsd", "milestones", params.milestoneId, "slices", params.sliceId, `${params.sliceId}-SUMMARY.md`);
263
+ return {
264
+ sliceId: params.sliceId,
265
+ milestoneId: params.milestoneId,
266
+ summaryPath: staleSummaryPath,
267
+ uatPath: staleSummaryPath.replace(/-SUMMARY\.md$/, "-UAT.md"),
268
+ duplicate: true,
269
+ stale: true,
270
+ };
271
+ }
251
272
  if (guardError) {
252
273
  return { error: guardError };
253
274
  }
@@ -21,6 +21,7 @@ import { writeManifest } from "../workflow-manifest.js";
21
21
  import { appendEvent } from "../workflow-events.js";
22
22
  import { logWarning, logError } from "../workflow-logger.js";
23
23
  import { loadEffectiveGSDPreferences } from "../preferences.js";
24
+ import { isStaleWrite } from "../auto/turn-epoch.js";
24
25
  import { buildEscalationArtifact, writeEscalationArtifact } from "../escalation.js";
25
26
  /**
26
27
  * Map an execute-task-owned gate id to the CompleteTaskParams field whose
@@ -167,6 +168,18 @@ export async function handleCompleteTask(params, basePath) {
167
168
  }
168
169
  const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
169
170
  if (existingTask && isClosedStatus(existingTask.status)) {
171
+ // Stale-turn path: a timed-out turn that was superseded by recovery
172
+ // can still reach this code when its LLM call eventually returns and
173
+ // invokes gsd_complete_task. Returning an error would produce noisy
174
+ // "already complete — use reopen first" logs in the orphaned turn.
175
+ // Instead, signal the duplicate via a non-mutating success shape that
176
+ // callers can detect via `duplicate: true` / `stale: true`.
177
+ if (isStaleWrite("complete-task")) {
178
+ // Sentinel handled below — outside the transaction — so we don't
179
+ // render SUMMARY.md or flip plan checkboxes for a stale duplicate.
180
+ guardError = "__stale_duplicate__";
181
+ return;
182
+ }
170
183
  guardError = `task ${params.taskId} is already complete — use gsd_task_reopen first if you need to redo it`;
171
184
  return;
172
185
  }
@@ -201,6 +214,24 @@ export async function handleCompleteTask(params, basePath) {
201
214
  });
202
215
  }
203
216
  });
217
+ if (guardError === "__stale_duplicate__") {
218
+ // Orphaned-turn duplicate: the task is already complete from the
219
+ // superseded turn's earlier (real) call. Return a non-mutating success
220
+ // so the stale LLM tool call unwinds cleanly. summaryPath is synthesized
221
+ // from the existing on-disk layout; no file is written.
222
+ const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
223
+ const staleSummaryPath = tasksDir
224
+ ? join(tasksDir, `${params.taskId}-SUMMARY.md`)
225
+ : join(basePath, ".gsd", "milestones", params.milestoneId, "slices", params.sliceId, "tasks", `${params.taskId}-SUMMARY.md`);
226
+ return {
227
+ taskId: params.taskId,
228
+ sliceId: params.sliceId,
229
+ milestoneId: params.milestoneId,
230
+ summaryPath: staleSummaryPath,
231
+ duplicate: true,
232
+ stale: true,
233
+ };
234
+ }
204
235
  if (guardError) {
205
236
  return { error: guardError };
206
237
  }
@@ -1,6 +1,8 @@
1
- import { appendFileSync, mkdirSync } from "node:fs";
1
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { randomUUID } from "node:crypto";
4
+ import { isStaleWrite } from "../auto/turn-epoch.js";
5
+ import { withFileLockSync } from "../file-lock.js";
4
6
  import { gsdRoot } from "../paths.js";
5
7
  import { isDbAvailable, insertAuditEvent } from "../gsd-db.js";
6
8
  function auditLogPath(basePath) {
@@ -22,9 +24,23 @@ export function buildAuditEnvelope(args) {
22
24
  };
23
25
  }
24
26
  export function emitUokAuditEvent(basePath, event) {
27
+ // Drop writes from a turn superseded by timeout recovery / cancellation.
28
+ if (isStaleWrite("uok-audit"))
29
+ return;
25
30
  try {
26
31
  ensureAuditDir(basePath);
27
- appendFileSync(auditLogPath(basePath), `${JSON.stringify(event)}\n`, "utf-8");
32
+ const path = auditLogPath(basePath);
33
+ // proper-lockfile requires the target file to exist before locking.
34
+ // Touch it via open(O_APPEND|O_CREAT) so the first writer wins the race
35
+ // atomically at the kernel level.
36
+ if (!existsSync(path))
37
+ closeSync(openSync(path, "a"));
38
+ // onLocked: "skip" — audit writes are best-effort; under heavy contention
39
+ // POSIX O_APPEND atomicity still protects small line writes, so skipping
40
+ // the lock rather than stalling orchestration is the correct tradeoff.
41
+ withFileLockSync(path, () => {
42
+ appendFileSync(path, `${JSON.stringify(event)}\n`, "utf-8");
43
+ }, { onLocked: "skip" });
28
44
  }
29
45
  catch {
30
46
  // Best-effort: audit writes must never break orchestration.
@@ -0,0 +1,33 @@
1
+ export function buildDispatchEnvelope(input) {
2
+ return {
3
+ action: input.action,
4
+ nodeKind: input.node?.kind,
5
+ unitType: input.unitType,
6
+ unitId: input.unitId,
7
+ prompt: input.prompt,
8
+ reason: {
9
+ reasonCode: input.reasonCode,
10
+ summary: input.summary,
11
+ evidence: input.evidence,
12
+ blockedBy: input.blockedBy,
13
+ },
14
+ gateVerdict: input.gateVerdict,
15
+ constraints: input.node
16
+ ? {
17
+ reads: input.node.reads,
18
+ writes: input.node.writes,
19
+ dependsOn: input.node.dependsOn,
20
+ }
21
+ : undefined,
22
+ trace: input.trace,
23
+ };
24
+ }
25
+ export function explainDispatch(envelope) {
26
+ const subject = envelope.unitType && envelope.unitId
27
+ ? `${envelope.unitType} ${envelope.unitId}`
28
+ : envelope.nodeKind ?? envelope.action;
29
+ const blocked = envelope.reason.blockedBy && envelope.reason.blockedBy.length > 0
30
+ ? ` Blocked by: ${envelope.reason.blockedBy.map((b) => `${b.kind}:${b.id}`).join(", ")}.`
31
+ : "";
32
+ return `[${envelope.reason.reasonCode}] ${subject}: ${envelope.reason.summary}.${blocked}`;
33
+ }
@@ -68,6 +68,16 @@ export function buildSidecarQueueNodes(queue) {
68
68
  metadata: { index },
69
69
  }));
70
70
  }
71
+ export function buildExecutionGraphSnapshot(nodes, phase) {
72
+ const sorted = topologicalSort(nodes);
73
+ return {
74
+ capturedAt: new Date().toISOString(),
75
+ phase,
76
+ nodes: sorted,
77
+ order: sorted.map((node) => node.id),
78
+ conflicts: detectFileConflicts(nodes),
79
+ };
80
+ }
71
81
  export async function scheduleSidecarQueue(queue) {
72
82
  if (queue.length <= 1)
73
83
  return [...queue];
@@ -32,7 +32,7 @@ export function writeTurnGitTransaction(args) {
32
32
  },
33
33
  }));
34
34
  }
35
- export function writeTurnCloseoutGitRecord(basePath, record) {
35
+ export function writeTurnCloseoutGitRecord(basePath, record, metadata) {
36
36
  writeTurnGitTransaction({
37
37
  basePath,
38
38
  traceId: record.traceId,
@@ -45,6 +45,7 @@ export function writeTurnCloseoutGitRecord(basePath, record) {
45
45
  status: record.failureClass === "git" ? "failed" : "ok",
46
46
  error: record.failureClass === "git" ? "git closeout failure" : undefined,
47
47
  metadata: {
48
+ ...(metadata ?? {}),
48
49
  turnStatus: record.status,
49
50
  finishedAt: record.finishedAt,
50
51
  activityFile: record.activityFile,
@@ -1,12 +1,35 @@
1
1
  import { buildAuditEnvelope, emitUokAuditEvent } from "./audit.js";
2
2
  import { writeTurnCloseoutGitRecord, writeTurnGitTransaction } from "./gitops.js";
3
+ import { acquireWriterToken, nextWriteRecord, releaseWriterToken } from "./writer.js";
3
4
  export function createTurnObserver(options) {
4
5
  let current = null;
6
+ let writerToken = null;
5
7
  const phaseResults = [];
8
+ function nextSequenceMetadata(category, operation, metadata) {
9
+ if (!writerToken)
10
+ return metadata ?? {};
11
+ const record = nextWriteRecord({
12
+ basePath: options.basePath,
13
+ token: writerToken,
14
+ category,
15
+ operation,
16
+ metadata,
17
+ });
18
+ return {
19
+ ...(metadata ?? {}),
20
+ writeSequence: record.sequence.sequence,
21
+ writerTokenId: record.writerToken.tokenId,
22
+ };
23
+ }
6
24
  return {
7
25
  onTurnStart(contract) {
8
26
  current = contract;
9
27
  phaseResults.length = 0;
28
+ writerToken = acquireWriterToken({
29
+ basePath: options.basePath,
30
+ traceId: contract.traceId,
31
+ turnId: contract.turnId,
32
+ });
10
33
  if (options.enableGitops) {
11
34
  writeTurnGitTransaction({
12
35
  basePath: options.basePath,
@@ -18,10 +41,10 @@ export function createTurnObserver(options) {
18
41
  action: options.gitAction,
19
42
  push: options.gitPush,
20
43
  status: "ok",
21
- metadata: {
44
+ metadata: nextSequenceMetadata("gitops", "insert", {
22
45
  iteration: contract.iteration,
23
46
  sidecarKind: contract.sidecarKind,
24
- },
47
+ }),
25
48
  });
26
49
  }
27
50
  if (options.enableAudit) {
@@ -30,12 +53,12 @@ export function createTurnObserver(options) {
30
53
  turnId: contract.turnId,
31
54
  category: "orchestration",
32
55
  type: "turn-start",
33
- payload: {
56
+ payload: nextSequenceMetadata("audit", "append", {
34
57
  iteration: contract.iteration,
35
58
  unitType: contract.unitType,
36
59
  unitId: contract.unitId,
37
60
  sidecarKind: contract.sidecarKind,
38
- },
61
+ }),
39
62
  }));
40
63
  }
41
64
  },
@@ -59,7 +82,7 @@ export function createTurnObserver(options) {
59
82
  action: options.gitAction,
60
83
  push: options.gitPush,
61
84
  status: "ok",
62
- metadata: { action },
85
+ metadata: nextSequenceMetadata("gitops", "update", { action }),
63
86
  });
64
87
  }
65
88
  if (phase === "unit") {
@@ -73,7 +96,7 @@ export function createTurnObserver(options) {
73
96
  action: options.gitAction,
74
97
  push: options.gitPush,
75
98
  status: "ok",
76
- metadata: { action },
99
+ metadata: nextSequenceMetadata("gitops", "update", { action }),
77
100
  });
78
101
  }
79
102
  if (phase === "finalize") {
@@ -87,7 +110,7 @@ export function createTurnObserver(options) {
87
110
  action: options.gitAction,
88
111
  push: options.gitPush,
89
112
  status: "ok",
90
- metadata: { action },
113
+ metadata: nextSequenceMetadata("gitops", "update", { action }),
91
114
  });
92
115
  }
93
116
  },
@@ -102,14 +125,14 @@ export function createTurnObserver(options) {
102
125
  turnId: merged.turnId,
103
126
  category: "orchestration",
104
127
  type: "turn-result",
105
- payload: {
128
+ payload: nextSequenceMetadata("audit", "append", {
106
129
  unitType: merged.unitType,
107
130
  unitId: merged.unitId,
108
131
  status: merged.status,
109
132
  failureClass: merged.failureClass,
110
133
  error: merged.error,
111
134
  phaseCount: merged.phaseResults.length,
112
- },
135
+ }),
113
136
  }));
114
137
  }
115
138
  if (options.enableGitops) {
@@ -124,8 +147,12 @@ export function createTurnObserver(options) {
124
147
  gitPushed: options.gitPush,
125
148
  finishedAt: merged.finishedAt,
126
149
  };
127
- writeTurnCloseoutGitRecord(options.basePath, closeout);
150
+ writeTurnCloseoutGitRecord(options.basePath, closeout, nextSequenceMetadata("gitops", "update", { action: "record" }));
151
+ }
152
+ if (writerToken) {
153
+ releaseWriterToken(options.basePath, writerToken);
128
154
  }
155
+ writerToken = null;
129
156
  current = null;
130
157
  phaseResults.length = 0;
131
158
  },
@@ -0,0 +1,58 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { gsdRoot } from "../paths.js";
4
+ function parityLogPath(basePath) {
5
+ return join(gsdRoot(basePath), "runtime", "uok-parity.jsonl");
6
+ }
7
+ function reportPath(basePath) {
8
+ return join(gsdRoot(basePath), "runtime", "uok-parity-report.json");
9
+ }
10
+ function increment(bucket, key) {
11
+ const normalized = key && key.trim().length > 0 ? key : "unknown";
12
+ bucket[normalized] = (bucket[normalized] ?? 0) + 1;
13
+ }
14
+ export function parseParityEvents(raw) {
15
+ return raw
16
+ .split("\n")
17
+ .filter(Boolean)
18
+ .map((line) => {
19
+ try {
20
+ return JSON.parse(line);
21
+ }
22
+ catch {
23
+ return { status: "error", error: "invalid parity json line" };
24
+ }
25
+ });
26
+ }
27
+ export function buildParityReport(events, sourcePath) {
28
+ const paths = {};
29
+ const statuses = {};
30
+ const criticalMismatches = [];
31
+ let fallbackInvocations = 0;
32
+ for (const event of events) {
33
+ increment(paths, event.path);
34
+ increment(statuses, event.status);
35
+ if (event.path === "legacy-fallback")
36
+ fallbackInvocations += 1;
37
+ if (event.status === "error") {
38
+ criticalMismatches.push(event.error ?? "parity event reported error");
39
+ }
40
+ }
41
+ return {
42
+ generatedAt: new Date().toISOString(),
43
+ sourcePath,
44
+ totalEvents: events.length,
45
+ paths,
46
+ statuses,
47
+ criticalMismatches,
48
+ fallbackInvocations,
49
+ };
50
+ }
51
+ export function writeParityReport(basePath) {
52
+ const sourcePath = parityLogPath(basePath);
53
+ const raw = existsSync(sourcePath) ? readFileSync(sourcePath, "utf-8") : "";
54
+ const report = buildParityReport(parseParityEvents(raw), sourcePath);
55
+ mkdirSync(join(gsdRoot(basePath), "runtime"), { recursive: true });
56
+ writeFileSync(reportPath(basePath), JSON.stringify(report, null, 2) + "\n", "utf-8");
57
+ return report;
58
+ }
@@ -3,12 +3,15 @@ import { join } from "node:path";
3
3
  import { gsdRoot, resolveMilestoneFile, resolveSliceFile } from "../paths.js";
4
4
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "../gsd-db.js";
5
5
  const PLAN_V2_CLARIFY_ROUND_LIMIT = 3;
6
- const EXECUTION_ENTRY_PHASES = new Set([
6
+ export const EXECUTION_ENTRY_PHASES = new Set([
7
7
  "executing",
8
8
  "summarizing",
9
9
  "validating-milestone",
10
10
  "completing-milestone",
11
11
  ]);
12
+ export function isExecutionEntryPhase(phase) {
13
+ return EXECUTION_ENTRY_PHASES.has(phase);
14
+ }
12
15
  function graphOutputPath(basePath) {
13
16
  return join(gsdRoot(basePath), "runtime", "uok-plan-v2-graph.json");
14
17
  }
@@ -22,6 +25,29 @@ function hasFileContent(path) {
22
25
  return false;
23
26
  }
24
27
  }
28
+ function getArtifactLookupBases(basePath) {
29
+ const bases = [basePath];
30
+ const projectRoot = process.env.GSD_PROJECT_ROOT;
31
+ if (projectRoot && projectRoot.trim().length > 0 && projectRoot !== basePath) {
32
+ bases.push(projectRoot);
33
+ }
34
+ return bases;
35
+ }
36
+ function hasMilestoneFileContent(basePath, milestoneId, suffix) {
37
+ const bases = getArtifactLookupBases(basePath);
38
+ for (const candidateBase of bases) {
39
+ if (hasFileContent(resolveMilestoneFile(candidateBase, milestoneId, suffix))) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ export function hasFinalizedMilestoneContext(basePath, milestoneId) {
46
+ return hasMilestoneFileContent(basePath, milestoneId, "CONTEXT");
47
+ }
48
+ export function isMissingFinalizedContextResult(result) {
49
+ return !result.ok && result.finalizedContextIncluded === false;
50
+ }
25
51
  function countSliceResearchArtifacts(basePath, milestoneId, slices) {
26
52
  let count = 0;
27
53
  for (const slice of slices) {
@@ -31,9 +57,6 @@ function countSliceResearchArtifacts(basePath, milestoneId, slices) {
31
57
  }
32
58
  return count;
33
59
  }
34
- function isExecutionEntryPhase(phase) {
35
- return EXECUTION_ENTRY_PHASES.has(phase);
36
- }
37
60
  export function compileUnitGraphFromState(basePath, state) {
38
61
  const mid = state.activeMilestone?.id;
39
62
  if (!mid)
@@ -43,9 +66,9 @@ export function compileUnitGraphFromState(basePath, state) {
43
66
  const slices = getMilestoneSlices(mid).sort((a, b) => Number(a.sequence ?? 0) - Number(b.sequence ?? 0));
44
67
  const nodes = [];
45
68
  const clarifyRoundLimit = PLAN_V2_CLARIFY_ROUND_LIMIT;
46
- const draftContextIncluded = hasFileContent(resolveMilestoneFile(basePath, mid, "CONTEXT-DRAFT"));
47
- const finalizedContextIncluded = hasFileContent(resolveMilestoneFile(basePath, mid, "CONTEXT"));
48
- const researchSynthesized = hasFileContent(resolveMilestoneFile(basePath, mid, "RESEARCH"))
69
+ const draftContextIncluded = hasMilestoneFileContent(basePath, mid, "CONTEXT-DRAFT");
70
+ const finalizedContextIncluded = hasMilestoneFileContent(basePath, mid, "CONTEXT");
71
+ const researchSynthesized = hasMilestoneFileContent(basePath, mid, "RESEARCH")
49
72
  || countSliceResearchArtifacts(basePath, mid, slices) > 0;
50
73
  if (isExecutionEntryPhase(state.phase) && !finalizedContextIncluded) {
51
74
  const reason = draftContextIncluded
@@ -0,0 +1,82 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { atomicWriteSync } from "../atomic-write.js";
5
+ import { gsdRoot } from "../paths.js";
6
+ const activeTokens = new Map();
7
+ function tokenKey(basePath, turnId) {
8
+ return `${basePath}:${turnId}`;
9
+ }
10
+ function sequencePath(basePath) {
11
+ return join(gsdRoot(basePath), "runtime", "uok-writer-sequence.json");
12
+ }
13
+ function readSequenceState(basePath) {
14
+ const path = sequencePath(basePath);
15
+ if (!existsSync(path)) {
16
+ return { lastSequence: 0, updatedAt: new Date(0).toISOString() };
17
+ }
18
+ try {
19
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
20
+ return {
21
+ lastSequence: Number.isInteger(parsed.lastSequence) ? Number(parsed.lastSequence) : 0,
22
+ updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : new Date(0).toISOString(),
23
+ };
24
+ }
25
+ catch {
26
+ return { lastSequence: 0, updatedAt: new Date(0).toISOString() };
27
+ }
28
+ }
29
+ function writeSequenceState(basePath, state) {
30
+ atomicWriteSync(sequencePath(basePath), JSON.stringify(state, null, 2) + "\n", "utf-8");
31
+ }
32
+ export function acquireWriterToken(args) {
33
+ const key = tokenKey(args.basePath, args.turnId);
34
+ const existing = activeTokens.get(key);
35
+ if (existing) {
36
+ throw new Error(`Writer token already active for turn ${args.turnId}`);
37
+ }
38
+ const token = {
39
+ tokenId: randomUUID(),
40
+ traceId: args.traceId,
41
+ turnId: args.turnId,
42
+ acquiredAt: new Date().toISOString(),
43
+ owner: args.owner ?? "uok",
44
+ };
45
+ activeTokens.set(key, token);
46
+ return token;
47
+ }
48
+ export function releaseWriterToken(basePath, token) {
49
+ const key = tokenKey(basePath, token.turnId);
50
+ const current = activeTokens.get(key);
51
+ if (current?.tokenId === token.tokenId) {
52
+ activeTokens.delete(key);
53
+ }
54
+ }
55
+ export function hasActiveWriterToken(basePath, turnId) {
56
+ return activeTokens.has(tokenKey(basePath, turnId));
57
+ }
58
+ export function nextWriteRecord(args) {
59
+ if (!hasActiveWriterToken(args.basePath, args.token.turnId)) {
60
+ throw new Error(`Writer token is not active for turn ${args.token.turnId}`);
61
+ }
62
+ const state = readSequenceState(args.basePath);
63
+ const sequence = state.lastSequence + 1;
64
+ const updatedAt = new Date().toISOString();
65
+ writeSequenceState(args.basePath, { lastSequence: sequence, updatedAt });
66
+ return {
67
+ writerToken: args.token,
68
+ sequence: {
69
+ traceId: args.token.traceId,
70
+ turnId: args.token.turnId,
71
+ sequence,
72
+ },
73
+ category: args.category,
74
+ operation: args.operation,
75
+ path: args.path,
76
+ ts: updatedAt,
77
+ metadata: args.metadata,
78
+ };
79
+ }
80
+ export function resetWriterTokensForTests() {
81
+ activeTokens.clear();
82
+ }
@@ -15,8 +15,9 @@
15
15
  // a process. The auto-loop must call _resetLogs() (or drainAndSummarize()) at
16
16
  // the start of each unit to prevent log bleed between units running in the same
17
17
  // Node process.
18
- import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
18
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, } from "node:fs";
19
19
  import { join } from "node:path";
20
+ import { withFileLockSync } from "./file-lock.js";
20
21
  import { appendNotification } from "./notification-store.js";
21
22
  import { buildAuditEnvelope, emitUokAuditEvent } from "./uok/audit.js";
22
23
  import { isUnifiedAuditEnabled } from "./uok/audit-toggle.js";
@@ -231,8 +232,15 @@ function _push(severity, component, message, context) {
231
232
  try {
232
233
  const auditDir = join(_auditBasePath, ".gsd");
233
234
  mkdirSync(auditDir, { recursive: true });
235
+ const auditPath = join(auditDir, "audit-log.jsonl");
234
236
  const sanitized = _sanitizeForAudit(entry);
235
- appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(sanitized) + "\n", "utf-8");
237
+ // Ensure file exists so proper-lockfile can acquire a lock against it.
238
+ if (!existsSync(auditPath))
239
+ closeSync(openSync(auditPath, "a"));
240
+ // onLocked: "skip" — never block error logging on lock contention.
241
+ withFileLockSync(auditPath, () => {
242
+ appendFileSync(auditPath, JSON.stringify(sanitized) + "\n", "utf-8");
243
+ }, { onLocked: "skip" });
236
244
  }
237
245
  catch (auditErr) {
238
246
  // Best-effort — never let audit write failures bubble up
@@ -479,6 +479,7 @@ const SKIP_PATHS = [
479
479
  ".gsd/worktrees/",
480
480
  ".gsd/runtime/",
481
481
  ".gsd/activity/",
482
+ ".gsd/audit/",
482
483
  ".gsd/forensics/",
483
484
  ".gsd/parallel/",
484
485
  ".gsd/journal/",