@opengsd/gsd-pi 1.0.2-dev.867e002 → 1.0.2-dev.cce3612

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 (318) hide show
  1. package/dist/onboarding.js +22 -3
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/context7/index.js +12 -2
  4. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  5. package/dist/resources/extensions/google-cli/index.js +30 -0
  6. package/dist/resources/extensions/google-cli/models.js +55 -0
  7. package/dist/resources/extensions/google-cli/package.json +11 -0
  8. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  9. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +62 -1
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
  12. package/dist/resources/extensions/gsd/auto/phases.js +37 -0
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +18 -2
  17. package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
  18. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  19. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  20. package/dist/resources/extensions/gsd/auto.js +6 -1
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  22. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -7
  24. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
  25. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  26. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  27. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  28. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  29. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  30. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  31. package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
  32. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  33. package/dist/resources/extensions/gsd/doctor.js +6 -1
  34. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  35. package/dist/resources/extensions/gsd/guided-flow.js +5 -6
  36. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  37. package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
  38. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  39. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  40. package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
  41. package/dist/resources/extensions/gsd/preferences.js +14 -2
  42. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  43. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  44. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  45. package/dist/resources/extensions/gsd/prompts/system.md +1 -3
  46. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  47. package/dist/resources/extensions/gsd/repository-registry.js +3 -1
  48. package/dist/resources/extensions/gsd/skill-activation.js +233 -0
  49. package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
  50. package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
  51. package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
  52. package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
  53. package/dist/resources/extensions/gsd/skill-scope.js +52 -0
  54. package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
  55. package/dist/resources/extensions/gsd/skills.js +60 -0
  56. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
  57. package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
  58. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
  59. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  60. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
  61. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  62. package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
  63. package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
  64. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  65. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  66. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  67. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  68. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  69. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  70. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  71. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  72. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  73. package/dist/web/standalone/.next/BUILD_ID +1 -1
  74. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  75. package/dist/web/standalone/.next/build-manifest.json +2 -2
  76. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  77. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.html +1 -1
  94. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  101. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  102. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  104. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  105. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  106. package/package.json +1 -1
  107. package/packages/cloud-mcp-gateway/package.json +2 -2
  108. package/packages/contracts/package.json +1 -1
  109. package/packages/daemon/package.json +4 -4
  110. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
  111. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  112. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
  113. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  114. package/packages/gsd-agent-core/package.json +5 -5
  115. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  116. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  117. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  118. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  119. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  120. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  121. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  122. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  123. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  124. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  125. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  126. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  127. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  128. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  129. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  130. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  131. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  132. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  133. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  134. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  135. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  136. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  137. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  138. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  139. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  140. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  141. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  142. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  143. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  144. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
  145. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  146. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  147. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  148. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  149. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  150. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  151. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  152. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  153. package/packages/gsd-agent-modes/package.json +7 -7
  154. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  155. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  156. package/packages/mcp-server/package.json +3 -3
  157. package/packages/native/package.json +1 -1
  158. package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  159. package/packages/pi-agent-core/dist/harness/skills.js +6 -0
  160. package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
  161. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
  162. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
  163. package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
  164. package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
  165. package/packages/pi-agent-core/package.json +1 -1
  166. package/packages/pi-ai/dist/models.generated.d.ts +8 -59
  167. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  168. package/packages/pi-ai/dist/models.generated.js +21 -72
  169. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  170. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  171. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  172. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  173. package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  174. package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
  175. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  176. package/packages/pi-ai/dist/types.d.ts +2 -0
  177. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  178. package/packages/pi-ai/dist/types.js.map +1 -1
  179. package/packages/pi-ai/package.json +1 -1
  180. package/packages/pi-coding-agent/README.md +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
  182. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
  185. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  188. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
  190. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/skills.js +3 -0
  192. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  193. package/packages/pi-coding-agent/package.json +7 -7
  194. package/packages/pi-tui/package.json +1 -1
  195. package/packages/rpc-client/package.json +2 -2
  196. package/pkg/package.json +1 -1
  197. package/src/resources/extensions/context7/index.ts +15 -2
  198. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  199. package/src/resources/extensions/google-cli/index.ts +34 -0
  200. package/src/resources/extensions/google-cli/models.ts +57 -0
  201. package/src/resources/extensions/google-cli/package.json +11 -0
  202. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  203. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  204. package/src/resources/extensions/gsd/auto/loop.ts +74 -1
  205. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
  206. package/src/resources/extensions/gsd/auto/phases.ts +46 -0
  207. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
  208. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  209. package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
  210. package/src/resources/extensions/gsd/auto-post-unit.ts +37 -2
  211. package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
  212. package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
  213. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  214. package/src/resources/extensions/gsd/auto.ts +6 -1
  215. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  216. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
  217. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  218. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
  219. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  220. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  221. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  222. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  223. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  224. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  225. package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
  226. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  227. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  228. package/src/resources/extensions/gsd/doctor.ts +6 -1
  229. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  230. package/src/resources/extensions/gsd/guided-flow.ts +5 -6
  231. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  232. package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
  233. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  234. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  235. package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
  236. package/src/resources/extensions/gsd/preferences.ts +17 -2
  237. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  238. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  239. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  240. package/src/resources/extensions/gsd/prompts/system.md +1 -3
  241. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  242. package/src/resources/extensions/gsd/repository-registry.ts +3 -1
  243. package/src/resources/extensions/gsd/skill-activation.ts +292 -0
  244. package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
  245. package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
  246. package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
  247. package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
  248. package/src/resources/extensions/gsd/skill-scope.ts +63 -0
  249. package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
  250. package/src/resources/extensions/gsd/skills.ts +75 -0
  251. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
  252. package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
  253. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
  254. package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
  255. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
  256. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +21 -0
  257. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
  258. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
  259. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  260. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  261. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  262. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  263. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  264. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  265. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  266. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  267. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
  268. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  269. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
  270. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  271. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
  272. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  273. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  274. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  275. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  276. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  277. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
  278. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  279. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
  280. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
  281. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  282. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
  283. package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
  284. package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
  285. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  286. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
  287. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +19 -0
  288. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  289. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  290. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  291. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
  292. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
  293. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  294. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  295. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +74 -1
  296. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
  297. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  298. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  299. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  300. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  301. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
  302. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  303. package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
  304. package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
  305. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  306. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  307. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  308. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  309. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  310. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  311. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  312. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  313. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  314. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  315. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  316. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  317. /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → orfEoZqDIo6Be_Z9ZFipD}/_buildManifest.js +0 -0
  318. /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → orfEoZqDIo6Be_Z9ZFipD}/_ssgManifest.js +0 -0
@@ -7,6 +7,7 @@ import { logWarning } from "../workflow-logger.js";
7
7
  import { resolveAutoSupervisorConfig } from "../preferences.js";
8
8
  import { readUnitRuntimeRecord } from "../unit-runtime.js";
9
9
  import { consumeAutoWakeup } from "./schedule-wakeup.js";
10
+ import { applyUnitSkillVisibility } from "../skill-scope.js";
10
11
  const UNIT_FAILSAFE_BUFFER_MS = 30_000;
11
12
  const UNIT_FAILSAFE_RECHECK_MS = 30_000;
12
13
  const WAKEUP_SLEEP_CHUNK_MS = 1_000;
@@ -123,6 +124,10 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
123
124
  };
124
125
  }
125
126
  }
127
+ const setVisibleSkills = typeof pi.setVisibleSkills === "function" ? pi.setVisibleSkills.bind(pi) : undefined;
128
+ if (setVisibleSkills) {
129
+ applyUnitSkillVisibility({ setVisibleSkills }, unitType);
130
+ }
126
131
  // ── Create the agent_end promise (per-unit one-shot) ──
127
132
  // This happens after newSession completes so session-switch agent_end events
128
133
  // from the previous session cannot resolve the new unit.
@@ -134,6 +139,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
134
139
  const pendingSwitchCancellation = _consumePendingSwitchCancellation();
135
140
  if (pendingSwitchCancellation) {
136
141
  _clearCurrentResolve();
142
+ setVisibleSkills?.(undefined);
137
143
  return {
138
144
  status: "cancelled",
139
145
  ...(pendingSwitchCancellation.errorContext ? { errorContext: pendingSwitchCancellation.errorContext } : {}),
@@ -156,6 +162,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
156
162
  }
157
163
  if (!ready) {
158
164
  _clearCurrentResolve();
165
+ setVisibleSkills?.(undefined);
159
166
  return {
160
167
  status: "cancelled",
161
168
  errorContext: {
@@ -290,6 +297,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
290
297
  if (unitTimeoutHandle)
291
298
  clearTimeout(unitTimeoutHandle);
292
299
  ctx.ui.setWorkingMessage?.(undefined);
300
+ setVisibleSkills?.(undefined);
293
301
  }
294
302
  debugLog("runUnit", {
295
303
  phase: "agent-end-received",
@@ -132,6 +132,8 @@ export class AutoSession {
132
132
  // ── Isolation degradation ────────────────────────────────────────────
133
133
  /** Set to true when worktree creation fails; prevents merge of nonexistent branch. */
134
134
  isolationDegraded = false;
135
+ /** Temporary recovery mode for stranded work adopted from physical git evidence. */
136
+ strandedRecoveryIsolationMode = null;
135
137
  /** Project-root dirty snapshot captured before an isolated worktree unit runs. */
136
138
  rootWriteBaseline = null;
137
139
  // ── Merge guard ──────────────────────────────────────────────────────
@@ -285,6 +287,7 @@ export class AutoSession {
285
287
  this.lastGitActionFailure = null;
286
288
  this.lastGitActionStatus = null;
287
289
  this.isolationDegraded = false;
290
+ this.strandedRecoveryIsolationMode = null;
288
291
  this.rootWriteBaseline = null;
289
292
  this.milestoneMergedInPhases = false;
290
293
  this.milestoneStartShas = new Map();
@@ -33,6 +33,11 @@ import { resolveWorktreeProjectRoot } from "./worktree-root.js";
33
33
  import { probeGitConflictState } from "./git-conflict-state.js";
34
34
  import { runTurnGitAction } from "./git-service.js";
35
35
  import { parseUnitId } from "./unit-id.js";
36
+ import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
37
+ function resolveExistingExpectedArtifact(unitType, unitId, basePath) {
38
+ const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
39
+ return artifactPath && existsSync(artifactPath) ? artifactPath : null;
40
+ }
36
41
  let reassessmentChecker = checkNeedsReassessment;
37
42
  let researchProjectPromptBuilder = buildResearchProjectPrompt;
38
43
  function shouldBypassMilestoneDepthGateInAuto(prefs) {
@@ -808,13 +813,15 @@ export const DISPATCH_RULES = [
808
813
  if (await getMilestonePipelineVariant(mid) === "trivial")
809
814
  return null;
810
815
  // Load roadmap to find all slices
811
- const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
816
+ const roadmapFile = resolveExistingExpectedArtifact("plan-milestone", mid, basePath) ??
817
+ resolveMilestoneFile(basePath, mid, "ROADMAP");
812
818
  const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
813
819
  if (!roadmapContent)
814
820
  return null;
815
821
  const roadmap = parseRoadmap(roadmapContent);
816
822
  // Find slices that need research (no RESEARCH file, dependencies done)
817
- const milestoneResearchFile = resolveMilestoneFile(basePath, mid, "RESEARCH");
823
+ const milestoneResearchFile = resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
824
+ resolveMilestoneFile(basePath, mid, "RESEARCH");
818
825
  const researchReadySlices = [];
819
826
  for (const slice of roadmap.slices) {
820
827
  if (slice.done)
@@ -823,10 +830,10 @@ export const DISPATCH_RULES = [
823
830
  if (milestoneResearchFile && slice.id === "S01")
824
831
  continue;
825
832
  // Skip if already has research
826
- if (resolveSliceFile(basePath, mid, slice.id, "RESEARCH"))
833
+ if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath))
827
834
  continue;
828
835
  // Skip if dependencies aren't done (check for SUMMARY files)
829
- const depsComplete = (slice.depends ?? []).every((depId) => !!resolveSliceFile(basePath, mid, depId, "SUMMARY"));
836
+ const depsComplete = (slice.depends ?? []).every((depId) => !!resolveExistingExpectedArtifact("complete-slice", `${mid}/${depId}`, basePath));
830
837
  if (!depsComplete)
831
838
  continue;
832
839
  researchReadySlices.push({ id: slice.id, title: slice.title });
@@ -837,7 +844,8 @@ export const DISPATCH_RULES = [
837
844
  // #4414: If a previous parallel-research attempt escalated to a blocker
838
845
  // placeholder, skip this rule and fall through to per-slice research
839
846
  // (or other rules) rather than re-dispatching the same failing unit.
840
- const parallelBlocker = resolveMilestoneFile(basePath, mid, "PARALLEL-BLOCKER");
847
+ const parallelBlocker = resolveExistingExpectedArtifact("research-slice", `${mid}/parallel-research`, basePath) ??
848
+ resolveMilestoneFile(basePath, mid, "PARALLEL-BLOCKER");
841
849
  if (parallelBlocker)
842
850
  return null;
843
851
  return {
@@ -863,12 +871,14 @@ export const DISPATCH_RULES = [
863
871
  return missingSliceStop(mid, state.phase);
864
872
  const sid = state.activeSlice.id;
865
873
  const sTitle = state.activeSlice.title;
866
- const researchFile = resolveSliceFile(basePath, mid, sid, "RESEARCH");
874
+ const researchFile = resolveExistingExpectedArtifact("research-slice", `${mid}/${sid}`, basePath) ??
875
+ resolveSliceFile(basePath, mid, sid, "RESEARCH");
867
876
  if (researchFile)
868
877
  return null; // has research, fall through
869
878
  // Skip slice research for S01 when milestone research already exists —
870
879
  // the milestone research already covers the same ground for the first slice.
871
- const milestoneResearchFile = resolveMilestoneFile(basePath, mid, "RESEARCH");
880
+ const milestoneResearchFile = resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
881
+ resolveMilestoneFile(basePath, mid, "RESEARCH");
872
882
  if (milestoneResearchFile && sid === "S01")
873
883
  return null; // fall through to plan-slice
874
884
  return {
@@ -74,6 +74,15 @@ const MAX_VERIFICATION_RETRIES = 3;
74
74
  /** Keep failure toasts short while still showing concrete examples. */
75
75
  const MAX_NOTIFICATION_DETAILS = 3;
76
76
  const NOTIFICATION_BULLET = "•";
77
+ function isParallelResearchUnit(unitType, unitId) {
78
+ return unitType === "research-slice" && unitId.endsWith("/parallel-research");
79
+ }
80
+ export function maybeWriteParallelResearchCostSpikeBlocker(unitType, unitId, basePath, unitCostUsd, rollingAvgUsd) {
81
+ if (!isParallelResearchUnit(unitType, unitId))
82
+ return null;
83
+ return writeBlockerPlaceholder(unitType, unitId, basePath, `Parallel slice research cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}). ` +
84
+ "Skipping the aggregate sentinel so dispatch can fall back to per-slice research.");
85
+ }
77
86
  export function resolveCloseoutGitAction(uokFlags) {
78
87
  return uokFlags.gitops ? uokFlags.gitopsTurnAction : null;
79
88
  }
@@ -1360,7 +1369,7 @@ export async function postUnitPreVerification(pctx, opts) {
1360
1369
  if (!triggerArtifactVerified) {
1361
1370
  try {
1362
1371
  const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
1363
- if (mid && sid) {
1372
+ if (mid && sid && !isParallelResearchUnit(s.currentUnit.type, s.currentUnit.id)) {
1364
1373
  // Phase C: write to the canonical project root (#5236 scope)
1365
1374
  // so non-symlinked worktrees no longer maintain a separate
1366
1375
  // local .gsd/ projection. copyPlanningArtifacts has been
@@ -1582,7 +1591,10 @@ export async function postUnitPreVerification(pctx, opts) {
1582
1591
  ctx.ui.notify(`Unit ${s.currentUnit.id} cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}) after state advanced; continuing closeout.`, "warning");
1583
1592
  return "continue";
1584
1593
  }
1585
- ctx.ui.notify(`Unit ${s.currentUnit.id} cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}) — pausing auto-mode.`, "error");
1594
+ const parallelBlocker = maybeWriteParallelResearchCostSpikeBlocker(s.currentUnit.type, s.currentUnit.id, verificationBasePath, unitCostUsd, rollingAvgUsd);
1595
+ ctx.ui.notify(parallelBlocker
1596
+ ? `Unit ${s.currentUnit.id} cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}) — wrote parallel blocker and pausing auto-mode.`
1597
+ : `Unit ${s.currentUnit.id} cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}) — pausing auto-mode.`, "error");
1586
1598
  await pauseAuto(ctx, pi);
1587
1599
  return "dispatched";
1588
1600
  }
@@ -1712,6 +1724,10 @@ export async function postUnitPostVerification(pctx) {
1712
1724
  const trigger = consumeRetryTrigger();
1713
1725
  if (trigger) {
1714
1726
  ctx.ui.notify(`Hook requested retry of ${trigger.unitType} ${trigger.unitId} — resetting task state.`, "info");
1727
+ await s.orchestration?.retryActiveUnit({
1728
+ unitType: trigger.unitType,
1729
+ unitId: trigger.unitId,
1730
+ });
1715
1731
  // ── State reset: undo the completion so deriveState re-derives the unit ──
1716
1732
  try {
1717
1733
  const { milestone: mid, slice: sid, task: tid } = parseUnitId(trigger.unitId);
@@ -7,15 +7,14 @@
7
7
  * state, no globals — every dependency is passed as a parameter or imported as a
8
8
  * utility.
9
9
  */
10
- import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection, parseTaskPlanFile } from "./files.js";
10
+ import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection } from "./files.js";
11
11
  import { hasVerdict, getUatType, extractVerdict } from "./verdict-parser.js";
12
12
  import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
13
13
  import { resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile, } from "./paths.js";
14
- import { resolveSkillDiscoveryMode, resolveInlineLevel, loadEffectiveGSDPreferences, resolveAllSkillReferences } from "./preferences.js";
14
+ import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
15
15
  import { isContextModeEnabled } from "./preferences-types.js";
16
16
  import { parseRoadmap } from "./parsers-legacy.js";
17
- import { getLoadedSkills } from "@gsd/pi-coding-agent";
18
- import { join, basename } from "node:path";
17
+ import { join } from "node:path";
19
18
  import { existsSync } from "node:fs";
20
19
  import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary } from "./context-budget.js";
21
20
  import { getPendingGatesForTurn } from "./gsd-db.js";
@@ -27,10 +26,11 @@ import { readCompactionSnapshot } from "./compaction-snapshot.js";
27
26
  import { logWarning } from "./workflow-logger.js";
28
27
  import { inlineGraphSubgraph } from "./graph-context.js";
29
28
  import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
30
- import { resolveSkillManifest, warnIfManifestHasMissingSkills } from "./skill-manifest.js";
31
29
  import { classifyProject } from "./detection.js";
32
30
  import { hasBrowserRequiredText } from "./browser-evidence.js";
33
31
  import { debugLog } from "./debug-logger.js";
32
+ import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
33
+ export { buildSkillActivationBlock, buildSkillDiscoveryVars };
34
34
  // ─── Preamble Cap ─────────────────────────────────────────────────────────────
35
35
  /**
36
36
  * Static ceiling for the preamble cap. Kept as an upper bound even
@@ -1033,237 +1033,6 @@ export async function inlineRoadmapExcerpt(base, mid, sid) {
1033
1033
  return null;
1034
1034
  return `### Milestone Roadmap (excerpt)\nSource: \`${roadmapRel}\`\n\n${excerpt}`;
1035
1035
  }
1036
- // ─── Skill Activation & Discovery ─────────────────────────────────────────
1037
- function normalizeSkillReference(ref) {
1038
- const normalized = ref.replace(/\\/g, "/").trim();
1039
- const base = basename(normalized).replace(/\.md$/i, "");
1040
- const name = /^SKILL$/i.test(base)
1041
- ? basename(normalized.replace(/\/SKILL(?:\.md)?$/i, ""))
1042
- : base;
1043
- return name.trim().toLowerCase();
1044
- }
1045
- function tokenizeSkillContext(...parts) {
1046
- const tokens = new Set();
1047
- const addVariants = (raw) => {
1048
- const value = raw.trim().toLowerCase();
1049
- if (!value || value.length < 2)
1050
- return;
1051
- tokens.add(value);
1052
- tokens.add(value.replace(/[-_]+/g, " "));
1053
- tokens.add(value.replace(/\s+/g, "-"));
1054
- tokens.add(value.replace(/\s+/g, ""));
1055
- };
1056
- for (const part of parts) {
1057
- if (!part)
1058
- continue;
1059
- const text = part.toLowerCase();
1060
- const phraseMatches = text.match(/[a-z0-9][a-z0-9+.#/_-]{1,}/g) ?? [];
1061
- for (const match of phraseMatches) {
1062
- addVariants(match);
1063
- for (const piece of match.split(/[^a-z0-9+.#]+/g)) {
1064
- if (piece.length >= 3)
1065
- addVariants(piece);
1066
- }
1067
- }
1068
- }
1069
- return tokens;
1070
- }
1071
- function skillMatchesContext(skill, contextTokens) {
1072
- const haystacks = [
1073
- skill.name.toLowerCase(),
1074
- skill.name.toLowerCase().replace(/[-_]+/g, " "),
1075
- skill.description.toLowerCase(),
1076
- ];
1077
- return [...contextTokens].some(token => token.length >= 3 && haystacks.some(haystack => haystack.includes(token)));
1078
- }
1079
- function resolvePreferenceSkillNames(refs, base) {
1080
- if (refs.length === 0)
1081
- return [];
1082
- const prefs = { always_use_skills: refs };
1083
- const report = resolveAllSkillReferences(prefs, base);
1084
- return refs.map(ref => {
1085
- const resolution = report.resolutions.get(ref);
1086
- return normalizeSkillReference(resolution?.resolvedPath ?? ref);
1087
- }).filter(Boolean);
1088
- }
1089
- function ruleMatchesContext(when, contextTokens) {
1090
- const whenTokens = tokenizeSkillContext(when);
1091
- return [...whenTokens].some(token => contextTokens.has(token) || [...contextTokens].some(ctx => ctx.includes(token) || token.includes(ctx)));
1092
- }
1093
- function resolveSkillRuleMatches(prefs, contextTokens, base) {
1094
- if (!prefs?.skill_rules?.length)
1095
- return { include: [], avoid: [] };
1096
- const include = [];
1097
- const avoid = [];
1098
- for (const rule of prefs.skill_rules) {
1099
- if (!ruleMatchesContext(rule.when, contextTokens))
1100
- continue;
1101
- include.push(...resolvePreferenceSkillNames([...(rule.use ?? []), ...(rule.prefer ?? [])], base));
1102
- avoid.push(...resolvePreferenceSkillNames(rule.avoid ?? [], base));
1103
- }
1104
- return { include, avoid };
1105
- }
1106
- function resolvePreferredSkillNames(prefs, visibleSkills, contextTokens, base) {
1107
- if (!prefs?.prefer_skills?.length)
1108
- return [];
1109
- const preferred = new Set(resolvePreferenceSkillNames(prefs.prefer_skills, base));
1110
- return visibleSkills
1111
- .filter(skill => preferred.has(normalizeSkillReference(skill.name)) && skillMatchesContext(skill, contextTokens))
1112
- .map(skill => normalizeSkillReference(skill.name));
1113
- }
1114
- /** Skill names must be lowercase alphanumeric with hyphens — reject anything else
1115
- * to prevent prompt injection via crafted directory names. */
1116
- const SAFE_SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
1117
- function formatSkillActivationBlock(skillNames) {
1118
- const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
1119
- if (safe.length === 0)
1120
- return "";
1121
- // Use explicit parameter syntax so LLMs pass { skill: "..." } instead of { name: "..." }.
1122
- // The function-call-like syntax `Skill('name')` led LLMs to infer a positional
1123
- // parameter name, causing tool validation failures — see #2224.
1124
- const calls = safe.map(name => `Call Skill({ skill: '${name}' })`).join('. ');
1125
- return `<skill_activation>${calls}.</skill_activation>`;
1126
- }
1127
- /**
1128
- * Manifest-driven recommendations block — informational only, does NOT
1129
- * auto-invoke. Lists per-unit-type skills that are installed but not already
1130
- * activated by explicit user intent (always_use_skills / prefer_skills /
1131
- * skill_rules / task-plan skills_used). Surfaces relevant skills to the
1132
- * model so they can be invoked when the model judges them useful.
1133
- *
1134
- * This is the additive complement to the existing activation directive:
1135
- * activation force-invokes (explicit intent), recommendations remind
1136
- * (manifest defaults). User intent is preserved as the stronger signal
1137
- * (RFC #4779 design principle); this block only adds visibility.
1138
- */
1139
- function formatSkillRecommendationsBlock(unitType, skillNames) {
1140
- if (!unitType)
1141
- return "";
1142
- const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
1143
- if (safe.length === 0)
1144
- return "";
1145
- return `<skill_recommendations unit="${unitType}">For this unit type, also consider invoking: ${safe.join(", ")}. Use Skill({ skill: 'name' }) when relevant — these are recommendations, not requirements.</skill_recommendations>`;
1146
- }
1147
- export function buildSkillActivationBlock(params) {
1148
- const prefs = params.preferences ?? loadEffectiveGSDPreferences(params.base)?.preferences;
1149
- const contextTokens = tokenizeSkillContext(params.milestoneId, params.milestoneTitle, params.sliceId, params.sliceTitle, params.taskId, params.taskTitle);
1150
- const loaded = (typeof getLoadedSkills === 'function' ? getLoadedSkills() : []).filter(skill => !skill.disableModelInvocation);
1151
- // Skill activation here is driven entirely by explicit sources
1152
- // (always_use_skills, prefer_skills, skill_rules, task-plan skills_used).
1153
- // Every match is an explicit user/project intent and must not be dropped
1154
- // by the unit-type manifest — user intent is stronger signal than
1155
- // defaults. The manifest's real home is the skill catalog rendering
1156
- // layer (pi-coding-agent `formatSkillsForPrompt`); that wiring is tracked
1157
- // as the "load-time short-circuit" follow-up to RFC #4779.
1158
- //
1159
- // `unitType` stays plumbed so the strict-mode warning can surface
1160
- // manifest entries that reference uninstalled skills, and so the
1161
- // activation-block site is ready to opt in once PR B lands.
1162
- const visibleSkills = loaded;
1163
- const installedNames = new Set(visibleSkills.map(skill => normalizeSkillReference(skill.name)));
1164
- warnIfManifestHasMissingSkills(params.unitType, installedNames);
1165
- const avoided = new Set(resolvePreferenceSkillNames(prefs?.avoid_skills ?? [], params.base));
1166
- const matched = new Set();
1167
- for (const name of resolvePreferenceSkillNames(prefs?.always_use_skills ?? [], params.base)) {
1168
- matched.add(name);
1169
- }
1170
- const ruleMatches = resolveSkillRuleMatches(prefs, contextTokens, params.base);
1171
- for (const name of ruleMatches.include)
1172
- matched.add(name);
1173
- for (const name of ruleMatches.avoid)
1174
- avoided.add(name);
1175
- for (const name of resolvePreferredSkillNames(prefs, visibleSkills, contextTokens, params.base)) {
1176
- matched.add(name);
1177
- }
1178
- if (params.taskPlanContent) {
1179
- try {
1180
- const taskPlan = parseTaskPlanFile(params.taskPlanContent);
1181
- for (const skillName of taskPlan.frontmatter.skills_used) {
1182
- matched.add(normalizeSkillReference(skillName));
1183
- }
1184
- }
1185
- catch (err) {
1186
- logWarning("prompt", `parseTaskPlanFile failed: ${err instanceof Error ? err.message : String(err)}`);
1187
- }
1188
- }
1189
- // Heuristic auto-match (gated on skill_discovery: "auto").
1190
- // For each installed skill, check if its name or description appears in the
1191
- // unit's context tokens (milestone/slice/task titles). Only consider skills
1192
- // already on the unit-type manifest allowlist — this keeps the heuristic
1193
- // narrow and avoids wildly off-topic activations.
1194
- // Users who set `skill_discovery: "off"` or "suggest" do not get
1195
- // auto-matched skills (the recommendations block still surfaces manifest
1196
- // skills passively); only "auto" actually adds them to the activation
1197
- // directive set. Default `skill_discovery` is "suggest", so this is opt-in.
1198
- if ((prefs?.skill_discovery ?? "suggest") === "auto") {
1199
- const manifestAllow = resolveSkillManifest(params.unitType);
1200
- const allowSet = manifestAllow ? new Set(manifestAllow) : null;
1201
- for (const skill of visibleSkills) {
1202
- const normalized = normalizeSkillReference(skill.name);
1203
- if (matched.has(normalized) || avoided.has(normalized))
1204
- continue;
1205
- // Respect the manifest allowlist when present; wildcard (null) lets all
1206
- // installed skills compete for keyword match.
1207
- if (allowSet && !allowSet.has(normalized))
1208
- continue;
1209
- if (skillMatchesContext(skill, contextTokens)) {
1210
- matched.add(normalized);
1211
- }
1212
- }
1213
- }
1214
- const ordered = [...matched]
1215
- .filter(name => installedNames.has(name) && !avoided.has(name))
1216
- .sort();
1217
- const activationBlock = formatSkillActivationBlock(ordered);
1218
- // Manifest-driven recommendations (additive, does not override explicit intent).
1219
- // Only surface skills the manifest declares for this unit type that are
1220
- // installed and not already in matched/avoided.
1221
- const matchedSet = new Set(ordered);
1222
- const manifestList = resolveSkillManifest(params.unitType);
1223
- const recommendations = (manifestList ?? [])
1224
- .filter(name => installedNames.has(name) && !avoided.has(name) && !matchedSet.has(name))
1225
- .sort();
1226
- const recommendationsBlock = formatSkillRecommendationsBlock(params.unitType, recommendations);
1227
- if (!activationBlock && !recommendationsBlock)
1228
- return "";
1229
- if (!activationBlock)
1230
- return recommendationsBlock;
1231
- if (!recommendationsBlock)
1232
- return activationBlock;
1233
- return `${activationBlock}\n${recommendationsBlock}`;
1234
- }
1235
- /**
1236
- * Build the skill discovery template variables for research prompts.
1237
- * Returns { skillDiscoveryMode, skillDiscoveryInstructions } for template substitution.
1238
- */
1239
- export function buildSkillDiscoveryVars() {
1240
- const mode = resolveSkillDiscoveryMode();
1241
- if (mode === "off") {
1242
- return {
1243
- skillDiscoveryMode: "off",
1244
- skillDiscoveryInstructions: " Skill discovery is disabled. Skip this step.",
1245
- };
1246
- }
1247
- const autoInstall = mode === "auto";
1248
- const instructions = `
1249
- Identify the key technologies, frameworks, and services this work depends on (e.g. Stripe, Clerk, Supabase, JUCE, SwiftUI).
1250
- For each, check if a professional agent skill already exists:
1251
- - First check \`<available_skills>\` in your system prompt — a skill may already be installed.
1252
- - For technologies without an installed skill, run: \`npx skills find "<technology>"\`
1253
- - Only consider skills that are **directly relevant** to core technologies — not tangentially related.
1254
- - Evaluate results by install count and relevance to the actual work.${autoInstall
1255
- ? `
1256
- - Install relevant skills: \`npx skills add <owner/repo@skill> -g -y\`
1257
- - Record installed skills in the "Skills Discovered" section of your research output.
1258
- - Installed skills will automatically appear in subsequent units' system prompts — no manual steps needed.`
1259
- : `
1260
- - Note promising skills in your research output with their install commands, but do NOT install them.
1261
- - The user will decide which to install.`}`;
1262
- return {
1263
- skillDiscoveryMode: mode,
1264
- skillDiscoveryInstructions: instructions,
1265
- };
1266
- }
1267
1036
  // ─── Text Helpers ──────────────────────────────────────────────────────────
1268
1037
  export function extractMarkdownSection(content, heading) {
1269
1038
  const match = new RegExp(`^## ${escapeRegExp(heading)}\\s*$`, "m").exec(content);
@@ -352,23 +352,28 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
352
352
  if (blockerPath && existsSync(blockerPath)) {
353
353
  return true;
354
354
  }
355
- const roadmapFile = resolveMilestoneFile(base, mid, "ROADMAP");
355
+ const roadmapFile = resolveExpectedArtifactPath("plan-milestone", mid, base);
356
356
  if (!roadmapFile || !existsSync(roadmapFile)) {
357
357
  logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
358
358
  return false;
359
359
  }
360
360
  try {
361
361
  const roadmap = parseLegacyRoadmap(readFileSync(roadmapFile, "utf-8"));
362
- const milestoneResearchFile = resolveMilestoneFile(base, mid, "RESEARCH");
362
+ const milestoneResearchFile = resolveExpectedArtifactPath("research-milestone", mid, base);
363
+ const hasMilestoneResearch = !!milestoneResearchFile && existsSync(milestoneResearchFile);
363
364
  for (const slice of roadmap.slices) {
364
365
  if (slice.done)
365
366
  continue;
366
- if (milestoneResearchFile && slice.id === "S01")
367
+ if (hasMilestoneResearch && slice.id === "S01")
367
368
  continue;
368
- const depsComplete = (slice.depends ?? []).every((depId) => !!resolveSliceFile(base, mid, depId, "SUMMARY"));
369
+ const depsComplete = (slice.depends ?? []).every((depId) => {
370
+ const summaryPath = resolveExpectedArtifactPath("complete-slice", `${mid}/${depId}`, base);
371
+ return !!summaryPath && existsSync(summaryPath);
372
+ });
369
373
  if (!depsComplete)
370
374
  continue;
371
- if (!resolveSliceFile(base, mid, slice.id, "RESEARCH")) {
375
+ const researchPath = resolveExpectedArtifactPath("research-slice", `${mid}/${slice.id}`, base);
376
+ if (!researchPath || !existsSync(researchPath)) {
372
377
  logWarning("recovery", `verify-fail ${unitType} ${unitId}: slice ${slice.id} missing RESEARCH`);
373
378
  return false;
374
379
  }