gsd-pi 2.49.0 → 2.50.0-dev.d210a87

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 (679) hide show
  1. package/README.md +2 -0
  2. package/dist/cli.js +26 -0
  3. package/dist/headless-ui.js +12 -2
  4. package/dist/headless.js +29 -13
  5. package/dist/loader.js +4 -0
  6. package/dist/resource-loader.d.ts +4 -1
  7. package/dist/resource-loader.js +138 -3
  8. package/dist/resources/extensions/async-jobs/async-bash-tool.js +3 -1
  9. package/dist/resources/extensions/bg-shell/interaction.js +3 -1
  10. package/dist/resources/extensions/bg-shell/process-manager.js +4 -1
  11. package/dist/resources/extensions/claude-code-cli/partial-builder.js +5 -0
  12. package/dist/resources/extensions/gsd/auto/infra-errors.js +1 -0
  13. package/dist/resources/extensions/gsd/auto/phases.js +27 -12
  14. package/dist/resources/extensions/gsd/auto/resolve.js +2 -2
  15. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -2
  16. package/dist/resources/extensions/gsd/auto/session.js +9 -0
  17. package/dist/resources/extensions/gsd/auto-artifact-paths.js +8 -10
  18. package/dist/resources/extensions/gsd/auto-dashboard.js +28 -6
  19. package/dist/resources/extensions/gsd/auto-dispatch.js +113 -74
  20. package/dist/resources/extensions/gsd/auto-observability.js +54 -0
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +53 -99
  22. package/dist/resources/extensions/gsd/auto-prompts.js +155 -17
  23. package/dist/resources/extensions/gsd/auto-recovery.js +79 -205
  24. package/dist/resources/extensions/gsd/auto-start.js +4 -31
  25. package/dist/resources/extensions/gsd/auto-timers.js +2 -2
  26. package/dist/resources/extensions/gsd/auto-utils.js +20 -0
  27. package/dist/resources/extensions/gsd/auto-verification.js +4 -7
  28. package/dist/resources/extensions/gsd/auto-worktree.js +257 -113
  29. package/dist/resources/extensions/gsd/auto.js +22 -10
  30. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -0
  31. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +24 -1
  32. package/dist/resources/extensions/gsd/branch-patterns.js +13 -0
  33. package/dist/resources/extensions/gsd/crash-recovery.js +6 -2
  34. package/dist/resources/extensions/gsd/custom-execution-policy.js +3 -2
  35. package/dist/resources/extensions/gsd/custom-verification.js +3 -1
  36. package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -2
  37. package/dist/resources/extensions/gsd/dashboard-overlay.js +4 -0
  38. package/dist/resources/extensions/gsd/detection.js +589 -3
  39. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  40. package/dist/resources/extensions/gsd/docs/preferences-reference.md +15 -0
  41. package/dist/resources/extensions/gsd/doctor-checks.js +5 -1234
  42. package/dist/resources/extensions/gsd/doctor-engine-checks.js +168 -0
  43. package/dist/resources/extensions/gsd/doctor-environment.js +28 -7
  44. package/dist/resources/extensions/gsd/doctor-git-checks.js +405 -0
  45. package/dist/resources/extensions/gsd/doctor-global-checks.js +74 -0
  46. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +600 -0
  47. package/dist/resources/extensions/gsd/doctor.js +9 -1
  48. package/dist/resources/extensions/gsd/extension-manifest.json +1 -1
  49. package/dist/resources/extensions/gsd/files.js +5 -1
  50. package/dist/resources/extensions/gsd/git-service.js +9 -10
  51. package/dist/resources/extensions/gsd/gsd-db.js +124 -1
  52. package/dist/resources/extensions/gsd/guided-flow-queue.js +10 -11
  53. package/dist/resources/extensions/gsd/guided-flow.js +10 -0
  54. package/dist/resources/extensions/gsd/init-wizard.js +9 -1
  55. package/dist/resources/extensions/gsd/markdown-renderer.js +33 -5
  56. package/dist/resources/extensions/gsd/model-router.js +25 -0
  57. package/dist/resources/extensions/gsd/notifications.js +23 -0
  58. package/dist/resources/extensions/gsd/observability-validator.js +422 -0
  59. package/dist/resources/extensions/gsd/preferences-skills.js +11 -5
  60. package/dist/resources/extensions/gsd/preferences-types.js +3 -1
  61. package/dist/resources/extensions/gsd/preferences-validation.js +64 -0
  62. package/dist/resources/extensions/gsd/preferences.js +3 -0
  63. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
  64. package/dist/resources/extensions/gsd/prompts/complete-slice.md +9 -8
  65. package/dist/resources/extensions/gsd/prompts/execute-task.md +16 -13
  66. package/dist/resources/extensions/gsd/prompts/forensics.md +19 -8
  67. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  68. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  73. package/dist/resources/extensions/gsd/prompts/plan-slice.md +8 -3
  74. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
  75. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +6 -1
  77. package/dist/resources/extensions/gsd/provider-error-pause.js +8 -0
  78. package/dist/resources/extensions/gsd/repo-identity.js +29 -0
  79. package/dist/resources/extensions/gsd/roadmap-mutations.js +110 -0
  80. package/dist/resources/extensions/gsd/roadmap-slices.js +2 -2
  81. package/dist/resources/extensions/gsd/rtk-status.js +43 -0
  82. package/dist/resources/extensions/gsd/rule-registry.js +10 -11
  83. package/dist/resources/extensions/gsd/session-forensics.js +13 -14
  84. package/dist/resources/extensions/gsd/session-lock.js +67 -56
  85. package/dist/resources/extensions/gsd/skill-catalog.js +1026 -0
  86. package/dist/resources/extensions/gsd/skill-discovery.js +3 -2
  87. package/dist/resources/extensions/gsd/skill-health.js +2 -2
  88. package/dist/resources/extensions/gsd/skill-telemetry.js +15 -5
  89. package/dist/resources/extensions/gsd/state.js +51 -12
  90. package/dist/resources/extensions/gsd/templates/milestone-summary.md +8 -0
  91. package/dist/resources/extensions/gsd/templates/milestone-validation.md +12 -0
  92. package/dist/resources/extensions/gsd/templates/plan.md +16 -0
  93. package/dist/resources/extensions/gsd/templates/preferences.md +2 -0
  94. package/dist/resources/extensions/gsd/templates/roadmap.md +13 -0
  95. package/dist/resources/extensions/gsd/templates/slice-summary.md +9 -0
  96. package/dist/resources/extensions/gsd/templates/task-plan.md +24 -0
  97. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +28 -9
  98. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -1
  99. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -3
  100. package/dist/resources/extensions/gsd/undo.js +8 -7
  101. package/dist/resources/extensions/gsd/unit-runtime.js +2 -1
  102. package/dist/resources/extensions/gsd/verdict-parser.js +84 -0
  103. package/dist/resources/extensions/gsd/verification-gate.js +3 -1
  104. package/dist/resources/extensions/gsd/worktree-resolver.js +24 -0
  105. package/dist/resources/extensions/gsd/worktree.js +3 -2
  106. package/dist/resources/extensions/remote-questions/config.js +3 -5
  107. package/dist/resources/extensions/search-the-web/native-search.js +8 -3
  108. package/dist/resources/extensions/search-the-web/tool-search.js +19 -2
  109. package/dist/resources/extensions/shared/rtk-session-stats.js +189 -0
  110. package/dist/resources/extensions/shared/rtk.js +100 -0
  111. package/dist/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
  112. package/dist/rtk.d.ts +52 -0
  113. package/dist/rtk.js +332 -0
  114. package/dist/web/standalone/.next/BUILD_ID +1 -1
  115. package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -19
  116. package/dist/web/standalone/.next/build-manifest.json +4 -4
  117. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  118. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  119. package/dist/web/standalone/.next/required-server-files.json +3 -3
  120. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  121. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  122. package/dist/web/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  125. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  143. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  153. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  160. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/experimental/route.js +3 -0
  171. package/dist/web/standalone/.next/server/app/api/experimental/route.js.nft.json +1 -0
  172. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -0
  173. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  202. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  204. package/dist/web/standalone/.next/server/app/api/preferences/route.js.nft.json +1 -1
  205. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  208. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  211. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -26
  213. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js.nft.json +1 -1
  214. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  217. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  218. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  219. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  220. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  221. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  222. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  223. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  224. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  225. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  226. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  227. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  228. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  229. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  230. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  231. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  232. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  233. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  234. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  235. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  236. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  237. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  238. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  239. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  240. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  241. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  242. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  243. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js.nft.json +1 -1
  244. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  245. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  246. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js.nft.json +1 -1
  247. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  248. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  249. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  250. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  251. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  252. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  253. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  254. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  255. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js.nft.json +1 -1
  256. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  257. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  258. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  259. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  260. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  261. package/dist/web/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  262. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  263. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  264. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  265. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  266. package/dist/web/standalone/.next/server/app/index.html +1 -1
  267. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  268. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  269. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  270. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  271. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  272. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  273. package/dist/web/standalone/.next/server/app/page.js +2 -2
  274. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  275. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  276. package/dist/web/standalone/.next/server/app-paths-manifest.json +20 -19
  277. package/dist/web/standalone/.next/server/chunks/2229.js +12 -0
  278. package/dist/web/standalone/.next/server/chunks/2331.js +25 -0
  279. package/dist/web/standalone/.next/server/chunks/{741.js → 4741.js} +1 -1
  280. package/dist/web/standalone/.next/server/chunks/5822.js +2 -0
  281. package/dist/web/standalone/.next/server/chunks/7471.js +13 -0
  282. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  283. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  284. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  285. package/dist/web/standalone/.next/server/middleware.js +3 -3
  286. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  287. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  288. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  289. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  290. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  291. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  292. package/dist/web/standalone/.next/static/chunks/{485.243af25f0cdf50d6.js → 2008.817d0885545aaea9.js} +6 -6
  293. package/dist/web/standalone/.next/static/chunks/4024.9ad5def014d90ce4.js +9 -0
  294. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +1 -0
  295. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  296. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +1 -0
  297. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +1 -0
  298. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +1 -0
  299. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +1 -0
  300. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +1 -0
  301. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +1 -0
  302. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +1 -0
  303. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +1 -0
  304. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +1 -0
  305. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +1 -0
  306. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +1 -0
  307. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +1 -0
  308. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +1 -0
  309. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +1 -0
  310. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +1 -0
  311. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +1 -0
  312. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +1 -0
  313. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +1 -0
  314. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +1 -0
  315. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +1 -0
  316. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +1 -0
  317. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +1 -0
  318. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +1 -0
  319. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +1 -0
  320. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +1 -0
  321. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +1 -0
  322. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +1 -0
  323. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +1 -0
  324. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +1 -0
  325. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +1 -0
  326. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +1 -0
  327. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +1 -0
  328. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +1 -0
  329. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +1 -0
  330. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +1 -0
  331. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +1 -0
  332. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +1 -0
  333. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +1 -0
  334. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +1 -0
  335. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +1 -0
  336. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +1 -0
  337. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  338. package/dist/web/standalone/.next/static/chunks/app/page-b950e4e384cc62b3.js +1 -0
  339. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  340. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +1 -0
  341. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +1 -0
  342. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  343. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +1 -0
  344. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +1 -0
  345. package/dist/web/standalone/.next/static/chunks/webpack-cfc9a116e6450a6b.js +1 -0
  346. package/dist/web/standalone/.next/static/css/de141508b083f922.css +1 -0
  347. package/dist/web/standalone/.next/static/yJIyd5cXPNpmXTv18ZlyC/_buildManifest.js +1 -0
  348. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  349. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  350. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  351. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  352. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  353. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  354. package/dist/web/standalone/server.js +1 -1
  355. package/package.json +1 -1
  356. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  357. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  358. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  359. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  360. package/packages/pi-ai/dist/providers/openai-codex-responses.js +39 -10
  361. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  362. package/packages/pi-ai/dist/types.d.ts +1 -0
  363. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  364. package/packages/pi-ai/dist/types.js.map +1 -1
  365. package/packages/pi-ai/src/providers/openai-codex-responses.ts +39 -8
  366. package/packages/pi-ai/src/types.ts +1 -1
  367. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +1 -0
  368. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -0
  370. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/bash-executor.d.ts +3 -1
  372. package/packages/pi-coding-agent/dist/core/bash-executor.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/bash-executor.js +10 -1
  374. package/packages/pi-coding-agent/dist/core/bash-executor.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/blob-store.d.ts.map +1 -1
  376. package/packages/pi-coding-agent/dist/core/blob-store.js +8 -3
  377. package/packages/pi-coding-agent/dist/core/blob-store.js.map +1 -1
  378. package/packages/pi-coding-agent/dist/core/discovery-cache.d.ts.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/discovery-cache.js +9 -2
  380. package/packages/pi-coding-agent/dist/core/discovery-cache.js.map +1 -1
  381. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
  382. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  383. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -0
  385. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/extensions/runner.js +13 -0
  387. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +19 -1
  389. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  390. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  391. package/packages/pi-coding-agent/dist/core/extensions/wrapper.d.ts.map +1 -1
  392. package/packages/pi-coding-agent/dist/core/extensions/wrapper.js +8 -0
  393. package/packages/pi-coding-agent/dist/core/extensions/wrapper.js.map +1 -1
  394. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  395. package/packages/pi-coding-agent/dist/core/package-manager.js +8 -1
  396. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  397. package/packages/pi-coding-agent/dist/core/retry-handler.js +1 -1
  398. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  399. package/packages/pi-coding-agent/dist/core/skills.d.ts +11 -1
  400. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  401. package/packages/pi-coding-agent/dist/core/skills.js +30 -8
  402. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  403. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  404. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  405. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  406. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  407. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  408. package/packages/pi-coding-agent/dist/index.js +1 -1
  409. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  410. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  411. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +3 -2
  412. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  413. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  414. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -36
  415. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  416. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts +5 -0
  417. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  418. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +12 -0
  419. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  420. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  421. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +2 -1
  422. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  423. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.d.ts.map +1 -1
  424. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js +5 -0
  425. package/packages/pi-coding-agent/dist/modes/rpc/jsonl.js.map +1 -1
  426. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  427. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +0 -1
  428. package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
  429. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  430. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  431. package/packages/pi-coding-agent/package.json +1 -1
  432. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  433. package/packages/pi-coding-agent/src/core/bash-executor.ts +10 -2
  434. package/packages/pi-coding-agent/src/core/blob-store.ts +6 -3
  435. package/packages/pi-coding-agent/src/core/discovery-cache.ts +9 -2
  436. package/packages/pi-coding-agent/src/core/extensions/index.ts +2 -0
  437. package/packages/pi-coding-agent/src/core/extensions/runner.ts +18 -0
  438. package/packages/pi-coding-agent/src/core/extensions/types.ts +21 -0
  439. package/packages/pi-coding-agent/src/core/extensions/wrapper.ts +9 -0
  440. package/packages/pi-coding-agent/src/core/package-manager.ts +10 -1
  441. package/packages/pi-coding-agent/src/core/retry-handler.ts +1 -1
  442. package/packages/pi-coding-agent/src/core/skills.ts +35 -10
  443. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  444. package/packages/pi-coding-agent/src/index.ts +4 -0
  445. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +3 -2
  446. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -36
  447. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +15 -0
  448. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +2 -1
  449. package/packages/pi-coding-agent/src/modes/rpc/jsonl.ts +6 -0
  450. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +0 -2
  451. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -2
  452. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  453. package/pkg/dist/modes/interactive/theme/themes.js +2 -1
  454. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  455. package/pkg/package.json +1 -1
  456. package/scripts/postinstall.js +163 -6
  457. package/src/resources/extensions/async-jobs/async-bash-tool.ts +3 -1
  458. package/src/resources/extensions/bg-shell/interaction.ts +3 -1
  459. package/src/resources/extensions/bg-shell/process-manager.ts +4 -1
  460. package/src/resources/extensions/claude-code-cli/partial-builder.ts +5 -0
  461. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +105 -0
  462. package/src/resources/extensions/gsd/auto/infra-errors.ts +1 -0
  463. package/src/resources/extensions/gsd/auto/phases.ts +25 -12
  464. package/src/resources/extensions/gsd/auto/resolve.ts +3 -3
  465. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -2
  466. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  467. package/src/resources/extensions/gsd/auto/types.ts +13 -0
  468. package/src/resources/extensions/gsd/auto-artifact-paths.ts +19 -21
  469. package/src/resources/extensions/gsd/auto-dashboard.ts +36 -5
  470. package/src/resources/extensions/gsd/auto-dispatch.ts +122 -71
  471. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  472. package/src/resources/extensions/gsd/auto-observability.ts +72 -0
  473. package/src/resources/extensions/gsd/auto-post-unit.ts +73 -110
  474. package/src/resources/extensions/gsd/auto-prompts.ts +159 -17
  475. package/src/resources/extensions/gsd/auto-recovery.ts +80 -221
  476. package/src/resources/extensions/gsd/auto-start.ts +7 -27
  477. package/src/resources/extensions/gsd/auto-timers.ts +2 -2
  478. package/src/resources/extensions/gsd/auto-utils.ts +25 -0
  479. package/src/resources/extensions/gsd/auto-verification.ts +4 -7
  480. package/src/resources/extensions/gsd/auto-worktree.ts +305 -108
  481. package/src/resources/extensions/gsd/auto.ts +26 -15
  482. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +93 -0
  483. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -0
  484. package/src/resources/extensions/gsd/branch-patterns.ts +16 -0
  485. package/src/resources/extensions/gsd/crash-recovery.ts +6 -2
  486. package/src/resources/extensions/gsd/custom-execution-policy.ts +3 -2
  487. package/src/resources/extensions/gsd/custom-verification.ts +3 -1
  488. package/src/resources/extensions/gsd/custom-workflow-engine.ts +3 -2
  489. package/src/resources/extensions/gsd/dashboard-overlay.ts +7 -0
  490. package/src/resources/extensions/gsd/detection.ts +662 -3
  491. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  492. package/src/resources/extensions/gsd/docs/preferences-reference.md +15 -0
  493. package/src/resources/extensions/gsd/doctor-checks.ts +5 -1291
  494. package/src/resources/extensions/gsd/doctor-engine-checks.ts +182 -0
  495. package/src/resources/extensions/gsd/doctor-environment.ts +30 -7
  496. package/src/resources/extensions/gsd/doctor-git-checks.ts +415 -0
  497. package/src/resources/extensions/gsd/doctor-global-checks.ts +84 -0
  498. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +626 -0
  499. package/src/resources/extensions/gsd/doctor.ts +9 -1
  500. package/src/resources/extensions/gsd/extension-manifest.json +1 -1
  501. package/src/resources/extensions/gsd/files.ts +6 -1
  502. package/src/resources/extensions/gsd/git-service.ts +7 -15
  503. package/src/resources/extensions/gsd/gsd-db.ts +150 -2
  504. package/src/resources/extensions/gsd/guided-flow-queue.ts +11 -12
  505. package/src/resources/extensions/gsd/guided-flow.ts +11 -0
  506. package/src/resources/extensions/gsd/init-wizard.ts +9 -1
  507. package/src/resources/extensions/gsd/markdown-renderer.ts +37 -4
  508. package/src/resources/extensions/gsd/model-router.ts +25 -0
  509. package/src/resources/extensions/gsd/notifications.ts +23 -0
  510. package/src/resources/extensions/gsd/observability-validator.ts +456 -0
  511. package/src/resources/extensions/gsd/preferences-skills.ts +11 -5
  512. package/src/resources/extensions/gsd/preferences-types.ts +25 -1
  513. package/src/resources/extensions/gsd/preferences-validation.ts +63 -0
  514. package/src/resources/extensions/gsd/preferences.ts +3 -0
  515. package/src/resources/extensions/gsd/prompts/complete-milestone.md +27 -8
  516. package/src/resources/extensions/gsd/prompts/complete-slice.md +9 -8
  517. package/src/resources/extensions/gsd/prompts/execute-task.md +16 -13
  518. package/src/resources/extensions/gsd/prompts/forensics.md +19 -8
  519. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  520. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  521. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  522. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  523. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  524. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  525. package/src/resources/extensions/gsd/prompts/plan-slice.md +8 -3
  526. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +3 -0
  527. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  528. package/src/resources/extensions/gsd/prompts/validate-milestone.md +6 -1
  529. package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
  530. package/src/resources/extensions/gsd/repo-identity.ts +28 -0
  531. package/src/resources/extensions/gsd/roadmap-mutations.ts +134 -0
  532. package/src/resources/extensions/gsd/roadmap-slices.ts +2 -2
  533. package/src/resources/extensions/gsd/rtk-status.ts +53 -0
  534. package/src/resources/extensions/gsd/rule-registry.ts +10 -11
  535. package/src/resources/extensions/gsd/session-forensics.ts +13 -14
  536. package/src/resources/extensions/gsd/session-lock.ts +92 -64
  537. package/src/resources/extensions/gsd/skill-catalog.ts +1085 -0
  538. package/src/resources/extensions/gsd/skill-discovery.ts +3 -2
  539. package/src/resources/extensions/gsd/skill-health.ts +2 -2
  540. package/src/resources/extensions/gsd/skill-telemetry.ts +15 -5
  541. package/src/resources/extensions/gsd/state.ts +54 -10
  542. package/src/resources/extensions/gsd/templates/milestone-summary.md +8 -0
  543. package/src/resources/extensions/gsd/templates/milestone-validation.md +12 -0
  544. package/src/resources/extensions/gsd/templates/plan.md +16 -0
  545. package/src/resources/extensions/gsd/templates/preferences.md +2 -0
  546. package/src/resources/extensions/gsd/templates/roadmap.md +13 -0
  547. package/src/resources/extensions/gsd/templates/slice-summary.md +9 -0
  548. package/src/resources/extensions/gsd/templates/task-plan.md +24 -0
  549. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +2 -2
  550. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +16 -0
  551. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +2 -2
  552. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -0
  553. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +1 -81
  554. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +2 -2
  555. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  556. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  557. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +9 -12
  558. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +5 -3
  559. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +33 -0
  560. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  561. package/src/resources/extensions/gsd/tests/detection.test.ts +838 -0
  562. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +28 -9
  563. package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +115 -1
  564. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +65 -1
  565. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +50 -0
  566. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +97 -0
  567. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +189 -0
  568. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +156 -0
  569. package/src/resources/extensions/gsd/tests/git-service.test.ts +49 -0
  570. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
  571. package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +63 -0
  572. package/src/resources/extensions/gsd/tests/infra-error.test.ts +12 -2
  573. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +39 -0
  574. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  575. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  576. package/src/resources/extensions/gsd/tests/model-router.test.ts +40 -0
  577. package/src/resources/extensions/gsd/tests/notifications.test.ts +28 -6
  578. package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +474 -0
  579. package/src/resources/extensions/gsd/tests/preferences.test.ts +50 -0
  580. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +347 -0
  581. package/src/resources/extensions/gsd/tests/queue-completed-milestone-perf.test.ts +155 -0
  582. package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +40 -0
  583. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +6 -6
  584. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +2 -1
  585. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +32 -0
  586. package/src/resources/extensions/gsd/tests/retry-diagnostic-reasoning.test.ts +161 -0
  587. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +4 -5
  588. package/src/resources/extensions/gsd/tests/rewrite-count-persist.test.ts +82 -0
  589. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +26 -0
  590. package/src/resources/extensions/gsd/tests/run-uat.test.ts +166 -16
  591. package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +223 -0
  592. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +12 -12
  593. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +44 -4
  594. package/src/resources/extensions/gsd/tests/skill-catalog.test.ts +193 -0
  595. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +24 -0
  596. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -1
  597. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +2 -2
  598. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +2 -1
  599. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +0 -16
  600. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +67 -0
  601. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +1 -1
  602. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +204 -0
  603. package/src/resources/extensions/gsd/tools/plan-slice.ts +16 -0
  604. package/src/resources/extensions/gsd/tools/validate-milestone.ts +3 -3
  605. package/src/resources/extensions/gsd/types.ts +32 -0
  606. package/src/resources/extensions/gsd/undo.ts +8 -7
  607. package/src/resources/extensions/gsd/unit-runtime.ts +2 -1
  608. package/src/resources/extensions/gsd/verdict-parser.ts +95 -0
  609. package/src/resources/extensions/gsd/verification-gate.ts +3 -3
  610. package/src/resources/extensions/gsd/worktree-resolver.ts +31 -0
  611. package/src/resources/extensions/gsd/worktree.ts +3 -2
  612. package/src/resources/extensions/remote-questions/config.ts +3 -5
  613. package/src/resources/extensions/search-the-web/native-search.ts +8 -3
  614. package/src/resources/extensions/search-the-web/tool-search.ts +22 -2
  615. package/src/resources/extensions/shared/rtk-session-stats.ts +249 -0
  616. package/src/resources/extensions/shared/rtk.ts +120 -0
  617. package/src/resources/skills/github-workflows/references/gh/SKILL.md +22 -1
  618. package/dist/resources/extensions/gsd/auto-worktree-sync.js +0 -191
  619. package/dist/resources/extensions/gsd/resource-version.js +0 -97
  620. package/dist/web/standalone/.next/server/chunks/229.js +0 -12
  621. package/dist/web/standalone/.next/server/chunks/441.js +0 -2
  622. package/dist/web/standalone/.next/server/chunks/471.js +0 -13
  623. package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +0 -9
  624. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-d83ba70a25a85472.js +0 -1
  625. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-d83ba70a25a85472.js +0 -1
  626. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-d83ba70a25a85472.js +0 -1
  627. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-d83ba70a25a85472.js +0 -1
  628. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +0 -1
  629. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +0 -1
  630. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +0 -1
  631. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +0 -1
  632. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +0 -1
  633. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +0 -1
  634. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +0 -1
  635. package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +0 -1
  636. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +0 -1
  637. package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +0 -1
  638. package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +0 -1
  639. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +0 -1
  640. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +0 -1
  641. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +0 -1
  642. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +0 -1
  643. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +0 -1
  644. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +0 -1
  645. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +0 -1
  646. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +0 -1
  647. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +0 -1
  648. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +0 -1
  649. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +0 -1
  650. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +0 -1
  651. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +0 -1
  652. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +0 -1
  653. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +0 -1
  654. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +0 -1
  655. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +0 -1
  656. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +0 -1
  657. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +0 -1
  658. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +0 -1
  659. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +0 -1
  660. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +0 -1
  661. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +0 -1
  662. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +0 -1
  663. package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +0 -1
  664. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.js +0 -1
  665. package/dist/web/standalone/.next/static/chunks/app/page-12dd5ece0df4badc.js +0 -1
  666. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  667. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-d83ba70a25a85472.js +0 -1
  668. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +0 -1
  669. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  670. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +0 -1
  671. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +0 -1
  672. package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +0 -1
  673. package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +0 -1
  674. package/dist/web/standalone/.next/static/gj-y5hikmhS--NT8Web6M/_buildManifest.js +0 -1
  675. package/packages/pi-ai/pnpm-lock.yaml +0 -2022
  676. package/packages/pi-coding-agent/pnpm-lock.yaml +0 -454
  677. package/src/resources/extensions/gsd/auto-worktree-sync.ts +0 -234
  678. package/src/resources/extensions/gsd/resource-version.ts +0 -101
  679. /package/dist/web/standalone/.next/static/{gj-y5hikmhS--NT8Web6M → yJIyd5cXPNpmXTv18ZlyC}/_ssgManifest.js +0 -0
@@ -350,3 +350,841 @@ test("detectProjectSignals: Makefile with test target", (t) => {
350
350
  assert.ok(signals.detectedFiles.includes("Makefile"));
351
351
  assert.ok(signals.verificationCommands.includes("make test"));
352
352
  });
353
+
354
+ test("detectProjectSignals: SQLite file detection via extensions", () => {
355
+ const dir = makeTempDir("signals-sqlite");
356
+ try {
357
+ writeFileSync(join(dir, "app.sqlite3"), "", "utf-8");
358
+ const signals = detectProjectSignals(dir);
359
+ assert.ok(signals.detectedFiles.includes("*.sqlite"), "should add synthetic *.sqlite marker");
360
+ } finally {
361
+ cleanup(dir);
362
+ }
363
+ });
364
+
365
+ test("detectProjectSignals: SQL file detection", () => {
366
+ const dir = makeTempDir("signals-sql");
367
+ try {
368
+ writeFileSync(join(dir, "migrations.sql"), "", "utf-8");
369
+ const signals = detectProjectSignals(dir);
370
+ assert.ok(signals.detectedFiles.includes("*.sql"), "should add synthetic *.sql marker");
371
+ } finally {
372
+ cleanup(dir);
373
+ }
374
+ });
375
+
376
+ test("detectProjectSignals: nested SQL file detection", () => {
377
+ const dir = makeTempDir("signals-sql-nested");
378
+ try {
379
+ mkdirSync(join(dir, "db", "migrations"), { recursive: true });
380
+ writeFileSync(join(dir, "db", "migrations", "001_init.sql"), "", "utf-8");
381
+ const signals = detectProjectSignals(dir);
382
+ assert.ok(signals.detectedFiles.includes("*.sql"), "should detect nested SQL files");
383
+ } finally {
384
+ cleanup(dir);
385
+ }
386
+ });
387
+
388
+ test("detectProjectSignals: .db file triggers SQLite detection", () => {
389
+ const dir = makeTempDir("signals-db");
390
+ try {
391
+ writeFileSync(join(dir, "data.db"), "", "utf-8");
392
+ const signals = detectProjectSignals(dir);
393
+ assert.ok(signals.detectedFiles.includes("*.sqlite"), "should add synthetic *.sqlite marker for .db files");
394
+ } finally {
395
+ cleanup(dir);
396
+ }
397
+ });
398
+
399
+ test("detectProjectSignals: no SQLite markers without matching files", () => {
400
+ const dir = makeTempDir("signals-no-sqlite");
401
+ try {
402
+ writeFileSync(join(dir, "package.json"), "{}", "utf-8");
403
+ const signals = detectProjectSignals(dir);
404
+ assert.ok(!signals.detectedFiles.includes("*.sqlite"), "should not have *.sqlite marker");
405
+ assert.ok(!signals.detectedFiles.includes("*.sql"), "should not have *.sql marker");
406
+ } finally {
407
+ cleanup(dir);
408
+ }
409
+ });
410
+
411
+ test("detectProjectSignals: .NET project via .csproj extension", () => {
412
+ const dir = makeTempDir("signals-dotnet");
413
+ try {
414
+ writeFileSync(join(dir, "MyApp.csproj"), "<Project></Project>", "utf-8");
415
+ const signals = detectProjectSignals(dir);
416
+ assert.ok(signals.detectedFiles.includes("*.csproj"), "should add synthetic *.csproj marker");
417
+ assert.equal(signals.primaryLanguage, "csharp");
418
+ } finally {
419
+ cleanup(dir);
420
+ }
421
+ });
422
+
423
+ test("detectProjectSignals: nested .csproj detection", () => {
424
+ const dir = makeTempDir("signals-dotnet-nested");
425
+ try {
426
+ mkdirSync(join(dir, "src", "App"), { recursive: true });
427
+ writeFileSync(join(dir, "src", "App", "App.csproj"), "<Project></Project>", "utf-8");
428
+ const signals = detectProjectSignals(dir);
429
+ assert.ok(signals.detectedFiles.includes("*.csproj"), "should detect nested .csproj files");
430
+ assert.equal(signals.primaryLanguage, "csharp");
431
+ } finally {
432
+ cleanup(dir);
433
+ }
434
+ });
435
+
436
+ test("detectProjectSignals: .NET project via .sln extension", () => {
437
+ const dir = makeTempDir("signals-sln");
438
+ try {
439
+ writeFileSync(join(dir, "MyApp.sln"), "", "utf-8");
440
+ const signals = detectProjectSignals(dir);
441
+ assert.ok(signals.detectedFiles.includes("*.sln"), "should add synthetic *.sln marker for .sln files");
442
+ assert.equal(signals.primaryLanguage, "dotnet");
443
+ } finally {
444
+ cleanup(dir);
445
+ }
446
+ });
447
+
448
+ test("detectProjectSignals: F# project via .fsproj extension", () => {
449
+ const dir = makeTempDir("signals-fsharp");
450
+ try {
451
+ writeFileSync(join(dir, "MyApp.fsproj"), "<Project></Project>", "utf-8");
452
+ const signals = detectProjectSignals(dir);
453
+ assert.ok(signals.detectedFiles.includes("*.fsproj"), "should add synthetic *.fsproj marker");
454
+ assert.equal(signals.primaryLanguage, "fsharp");
455
+ } finally {
456
+ cleanup(dir);
457
+ }
458
+ });
459
+
460
+ test("detectProjectSignals: Angular project via angular.json", () => {
461
+ const dir = makeTempDir("signals-angular");
462
+ try {
463
+ writeFileSync(join(dir, "angular.json"), "{}", "utf-8");
464
+ writeFileSync(join(dir, "package.json"), "{}", "utf-8");
465
+ const signals = detectProjectSignals(dir);
466
+ assert.ok(signals.detectedFiles.includes("angular.json"));
467
+ assert.equal(signals.primaryLanguage, "javascript/typescript");
468
+ } finally {
469
+ cleanup(dir);
470
+ }
471
+ });
472
+
473
+ test("detectProjectSignals: Next.js project via next.config.ts", () => {
474
+ const dir = makeTempDir("signals-nextjs");
475
+ try {
476
+ writeFileSync(join(dir, "next.config.ts"), "export default {}", "utf-8");
477
+ writeFileSync(join(dir, "package.json"), "{}", "utf-8");
478
+ const signals = detectProjectSignals(dir);
479
+ assert.ok(signals.detectedFiles.includes("next.config.ts"));
480
+ } finally {
481
+ cleanup(dir);
482
+ }
483
+ });
484
+
485
+ test("detectProjectSignals: nested Next.js config via packages/web/next.config.ts", () => {
486
+ const dir = makeTempDir("signals-nextjs-nested");
487
+ try {
488
+ mkdirSync(join(dir, "packages", "web"), { recursive: true });
489
+ writeFileSync(join(dir, "packages", "web", "next.config.ts"), "export default {}", "utf-8");
490
+ const signals = detectProjectSignals(dir);
491
+ assert.ok(signals.detectedFiles.includes("next.config.ts"), "should detect nested Next.js config");
492
+ } finally {
493
+ cleanup(dir);
494
+ }
495
+ });
496
+
497
+ test("detectProjectSignals: Flutter project via pubspec.yaml", () => {
498
+ const dir = makeTempDir("signals-flutter");
499
+ try {
500
+ writeFileSync(join(dir, "pubspec.yaml"), "name: my_app", "utf-8");
501
+ const signals = detectProjectSignals(dir);
502
+ assert.ok(signals.detectedFiles.includes("pubspec.yaml"));
503
+ assert.equal(signals.primaryLanguage, "dart/flutter");
504
+ } finally {
505
+ cleanup(dir);
506
+ }
507
+ });
508
+
509
+ test("detectProjectSignals: Django project via manage.py", () => {
510
+ const dir = makeTempDir("signals-django");
511
+ try {
512
+ writeFileSync(join(dir, "manage.py"), "#!/usr/bin/env python", "utf-8");
513
+ const signals = detectProjectSignals(dir);
514
+ assert.ok(signals.detectedFiles.includes("manage.py"));
515
+ assert.equal(signals.primaryLanguage, "python");
516
+ } finally {
517
+ cleanup(dir);
518
+ }
519
+ });
520
+
521
+ test("detectProjectSignals: nested Django manage.py", () => {
522
+ const dir = makeTempDir("signals-django-nested");
523
+ try {
524
+ mkdirSync(join(dir, "services", "api"), { recursive: true });
525
+ writeFileSync(join(dir, "services", "api", "manage.py"), "#!/usr/bin/env python", "utf-8");
526
+ const signals = detectProjectSignals(dir);
527
+ assert.ok(signals.detectedFiles.includes("manage.py"), "should detect nested manage.py");
528
+ assert.equal(signals.primaryLanguage, "python");
529
+ } finally {
530
+ cleanup(dir);
531
+ }
532
+ });
533
+
534
+ test("detectProjectSignals: Docker project via Dockerfile", () => {
535
+ const dir = makeTempDir("signals-docker");
536
+ try {
537
+ writeFileSync(join(dir, "Dockerfile"), "FROM node:18", "utf-8");
538
+ const signals = detectProjectSignals(dir);
539
+ assert.ok(signals.detectedFiles.includes("Dockerfile"));
540
+ } finally {
541
+ cleanup(dir);
542
+ }
543
+ });
544
+
545
+ test("detectProjectSignals: Terraform project via main.tf", () => {
546
+ const dir = makeTempDir("signals-terraform");
547
+ try {
548
+ writeFileSync(join(dir, "main.tf"), 'provider "aws" {}', "utf-8");
549
+ const signals = detectProjectSignals(dir);
550
+ assert.ok(signals.detectedFiles.includes("main.tf"));
551
+ } finally {
552
+ cleanup(dir);
553
+ }
554
+ });
555
+
556
+ // ── QA4/QA5 — new detection tests ──────────────────────────────────────────
557
+
558
+ test("detectProjectSignals: Vue.js via .vue files in src/", () => {
559
+ const dir = makeTempDir("signals-vue");
560
+ try {
561
+ writeFileSync(join(dir, "package.json"), '{"name":"vue-app"}', "utf-8");
562
+ mkdirSync(join(dir, "src"), { recursive: true });
563
+ writeFileSync(join(dir, "src", "App.vue"), "<template></template>", "utf-8");
564
+ const signals = detectProjectSignals(dir);
565
+ assert.ok(signals.detectedFiles.includes("*.vue"), "should add *.vue synthetic marker");
566
+ } finally {
567
+ cleanup(dir);
568
+ }
569
+ });
570
+
571
+ test("detectProjectSignals: Vue.js via nested .vue file in src/components/", () => {
572
+ const dir = makeTempDir("signals-vue-nested");
573
+ try {
574
+ writeFileSync(join(dir, "package.json"), '{"name":"vue-app"}', "utf-8");
575
+ mkdirSync(join(dir, "src", "components"), { recursive: true });
576
+ writeFileSync(join(dir, "src", "components", "Card.vue"), "<template></template>", "utf-8");
577
+ const signals = detectProjectSignals(dir);
578
+ assert.ok(signals.detectedFiles.includes("*.vue"), "should detect nested .vue files");
579
+ } finally {
580
+ cleanup(dir);
581
+ }
582
+ });
583
+
584
+ test("detectProjectSignals: Vue CLI via vue.config.js", () => {
585
+ const dir = makeTempDir("signals-vue-cli");
586
+ try {
587
+ writeFileSync(join(dir, "package.json"), '{"name":"vue-cli-app"}', "utf-8");
588
+ writeFileSync(join(dir, "vue.config.js"), "module.exports = {};", "utf-8");
589
+ const signals = detectProjectSignals(dir);
590
+ assert.ok(signals.detectedFiles.includes("vue.config.js"));
591
+ } finally {
592
+ cleanup(dir);
593
+ }
594
+ });
595
+
596
+ test("detectProjectSignals: requirements.txt sets Python language", () => {
597
+ const dir = makeTempDir("signals-requirements");
598
+ try {
599
+ writeFileSync(join(dir, "requirements.txt"), "flask==3.0\n", "utf-8");
600
+ const signals = detectProjectSignals(dir);
601
+ assert.ok(signals.detectedFiles.includes("requirements.txt"));
602
+ assert.equal(signals.primaryLanguage, "python");
603
+ assert.ok(signals.verificationCommands.includes("pytest"), "should suggest pytest for requirements.txt projects");
604
+ } finally {
605
+ cleanup(dir);
606
+ }
607
+ });
608
+
609
+ test("detectProjectSignals: Android project via app/build.gradle", () => {
610
+ const dir = makeTempDir("signals-android");
611
+ try {
612
+ mkdirSync(join(dir, "app"), { recursive: true });
613
+ writeFileSync(join(dir, "app", "build.gradle"), "apply plugin: 'com.android.application'", "utf-8");
614
+ const signals = detectProjectSignals(dir);
615
+ assert.ok(signals.detectedFiles.includes("app/build.gradle"));
616
+ assert.equal(signals.primaryLanguage, "java/kotlin");
617
+ assert.ok(!signals.detectedFiles.includes("build.gradle"), "should not collapse Android app/build.gradle into generic build.gradle");
618
+ } finally {
619
+ cleanup(dir);
620
+ }
621
+ });
622
+
623
+ test("detectProjectSignals: nested app/build.gradle normalizes to Android marker", () => {
624
+ const dir = makeTempDir("signals-android-nested");
625
+ try {
626
+ mkdirSync(join(dir, "apps", "mobile", "app"), { recursive: true });
627
+ writeFileSync(join(dir, "apps", "mobile", "app", "build.gradle"), "apply plugin: 'com.android.application'", "utf-8");
628
+ const signals = detectProjectSignals(dir);
629
+ assert.ok(signals.detectedFiles.includes("app/build.gradle"), "should detect nested Android app/build.gradle");
630
+ assert.ok(!signals.detectedFiles.includes("build.gradle"), "should not emit generic build.gradle marker for nested Android modules");
631
+ assert.equal(signals.primaryLanguage, "java/kotlin");
632
+ } finally {
633
+ cleanup(dir);
634
+ }
635
+ });
636
+
637
+ test("detectProjectSignals: Unity project via ProjectSettings/ProjectVersion.txt", () => {
638
+ const dir = makeTempDir("signals-unity");
639
+ try {
640
+ mkdirSync(join(dir, "ProjectSettings"), { recursive: true });
641
+ writeFileSync(join(dir, "ProjectSettings", "ProjectVersion.txt"), "m_EditorVersion: 2022.3", "utf-8");
642
+ const signals = detectProjectSignals(dir);
643
+ assert.ok(signals.detectedFiles.includes("ProjectSettings/ProjectVersion.txt"));
644
+ } finally {
645
+ cleanup(dir);
646
+ }
647
+ });
648
+
649
+ test("detectProjectSignals: Godot project via project.godot", () => {
650
+ const dir = makeTempDir("signals-godot");
651
+ try {
652
+ writeFileSync(join(dir, "project.godot"), "[application]", "utf-8");
653
+ const signals = detectProjectSignals(dir);
654
+ assert.ok(signals.detectedFiles.includes("project.godot"));
655
+ } finally {
656
+ cleanup(dir);
657
+ }
658
+ });
659
+
660
+ test("detectProjectSignals: Airflow via airflow.cfg", () => {
661
+ const dir = makeTempDir("signals-airflow");
662
+ try {
663
+ writeFileSync(join(dir, "airflow.cfg"), "[core]\ndags_folder = ./dags", "utf-8");
664
+ const signals = detectProjectSignals(dir);
665
+ assert.ok(signals.detectedFiles.includes("airflow.cfg"));
666
+ } finally {
667
+ cleanup(dir);
668
+ }
669
+ });
670
+
671
+ test("detectProjectSignals: Kubernetes via Chart.yaml (Helm)", () => {
672
+ const dir = makeTempDir("signals-k8s");
673
+ try {
674
+ writeFileSync(join(dir, "Chart.yaml"), "apiVersion: v2\nname: my-chart", "utf-8");
675
+ const signals = detectProjectSignals(dir);
676
+ assert.ok(signals.detectedFiles.includes("Chart.yaml"));
677
+ } finally {
678
+ cleanup(dir);
679
+ }
680
+ });
681
+
682
+ test("detectProjectSignals: Blockchain via hardhat.config.ts", () => {
683
+ const dir = makeTempDir("signals-blockchain");
684
+ try {
685
+ writeFileSync(join(dir, "hardhat.config.ts"), 'import "@nomiclabs/hardhat-ethers"', "utf-8");
686
+ const signals = detectProjectSignals(dir);
687
+ assert.ok(signals.detectedFiles.includes("hardhat.config.ts"));
688
+ } finally {
689
+ cleanup(dir);
690
+ }
691
+ });
692
+
693
+ test("detectProjectSignals: CI/CD via .github/workflows", () => {
694
+ const dir = makeTempDir("signals-cicd");
695
+ try {
696
+ mkdirSync(join(dir, ".github", "workflows"), { recursive: true });
697
+ const signals = detectProjectSignals(dir);
698
+ assert.ok(signals.detectedFiles.includes(".github/workflows"));
699
+ } finally {
700
+ cleanup(dir);
701
+ }
702
+ });
703
+
704
+ test("detectProjectSignals: Tailwind via tailwind.config.ts", () => {
705
+ const dir = makeTempDir("signals-tailwind");
706
+ try {
707
+ writeFileSync(join(dir, "package.json"), '{"name":"tw-app"}', "utf-8");
708
+ writeFileSync(join(dir, "tailwind.config.ts"), "export default {};", "utf-8");
709
+ const signals = detectProjectSignals(dir);
710
+ assert.ok(signals.detectedFiles.includes("tailwind.config.ts"));
711
+ } finally {
712
+ cleanup(dir);
713
+ }
714
+ });
715
+
716
+ test("detectProjectSignals: FastAPI detected via requirements.txt dependency", () => {
717
+ const dir = makeTempDir("signals-fastapi-req");
718
+ try {
719
+ writeFileSync(join(dir, "requirements.txt"), "fastapi==0.115.0\nuvicorn[standard]\n", "utf-8");
720
+ const signals = detectProjectSignals(dir);
721
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "should add dep:fastapi marker");
722
+ assert.equal(signals.primaryLanguage, "python");
723
+ } finally {
724
+ cleanup(dir);
725
+ }
726
+ });
727
+
728
+ test("detectProjectSignals: FastAPI detected via pyproject.toml dependency", () => {
729
+ const dir = makeTempDir("signals-fastapi-pyproject");
730
+ try {
731
+ writeFileSync(join(dir, "pyproject.toml"), '[project]\ndependencies = ["fastapi>=0.100"]\n', "utf-8");
732
+ const signals = detectProjectSignals(dir);
733
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "should add dep:fastapi marker");
734
+ } finally {
735
+ cleanup(dir);
736
+ }
737
+ });
738
+
739
+ test("detectProjectSignals: FastAPI detected with PEP 508 ~= operator", () => {
740
+ const dir = makeTempDir("signals-fastapi-compatible-release");
741
+ try {
742
+ writeFileSync(join(dir, "requirements.txt"), "fastapi~=0.115\n", "utf-8");
743
+ const signals = detectProjectSignals(dir);
744
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "~= should count as a FastAPI dependency");
745
+ } finally {
746
+ cleanup(dir);
747
+ }
748
+ });
749
+
750
+ test("detectProjectSignals: pyproject metadata mention does not trigger dep:fastapi", () => {
751
+ const dir = makeTempDir("signals-fastapi-pyproject-metadata");
752
+ try {
753
+ writeFileSync(
754
+ join(dir, "pyproject.toml"),
755
+ '[project]\nname = "example"\nkeywords = ["fastapi"]\ndependencies = ["flask>=3.0"]\n',
756
+ "utf-8",
757
+ );
758
+ const signals = detectProjectSignals(dir);
759
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "metadata-only mentions should not trigger FastAPI detection");
760
+ } finally {
761
+ cleanup(dir);
762
+ }
763
+ });
764
+
765
+ test("detectProjectSignals: pyproject dependency table extras do not trigger dep:fastapi", () => {
766
+ const dir = makeTempDir("signals-fastapi-pyproject-table-extra");
767
+ try {
768
+ writeFileSync(
769
+ join(dir, "pyproject.toml"),
770
+ '[tool.poetry.dependencies]\npython = "^3.12"\nmy-sdk = { version = "^1.0", extras = ["fastapi"] }\n',
771
+ "utf-8",
772
+ );
773
+ const signals = detectProjectSignals(dir);
774
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "dependency table extras should not imply FastAPI framework usage");
775
+ } finally {
776
+ cleanup(dir);
777
+ }
778
+ });
779
+
780
+ test("detectProjectSignals: Poetry group FastAPI dependency does not imply app framework usage", () => {
781
+ const dir = makeTempDir("signals-fastapi-poetry-group");
782
+ try {
783
+ writeFileSync(
784
+ join(dir, "pyproject.toml"),
785
+ '[tool.poetry.dependencies]\npython = "^3.12"\nflask = "^3.0"\n\n[tool.poetry.group.dev.dependencies]\nfastapi = "^0.115"\n',
786
+ "utf-8",
787
+ );
788
+ const signals = detectProjectSignals(dir);
789
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "Poetry dev-group dependencies should not imply FastAPI app usage");
790
+ } finally {
791
+ cleanup(dir);
792
+ }
793
+ });
794
+
795
+ test("detectProjectSignals: pyproject optional-dependency group name does not trigger dep:fastapi", () => {
796
+ const dir = makeTempDir("signals-fastapi-pyproject-extra-name");
797
+ try {
798
+ writeFileSync(
799
+ join(dir, "pyproject.toml"),
800
+ '[project]\ndependencies = ["flask>=3.0"]\n\n[project.optional-dependencies]\nfastapi = ["orjson>=3"]\n',
801
+ "utf-8",
802
+ );
803
+ const signals = detectProjectSignals(dir);
804
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "optional-dependency extra names should not trigger FastAPI detection");
805
+ } finally {
806
+ cleanup(dir);
807
+ }
808
+ });
809
+
810
+ test("detectProjectSignals: pyproject multiline optional dependency emits dep:fastapi", () => {
811
+ const dir = makeTempDir("signals-fastapi-pyproject-optional-multiline");
812
+ try {
813
+ writeFileSync(
814
+ join(dir, "pyproject.toml"),
815
+ '[project]\ndependencies = ["flask>=3.0"]\n\n[project.optional-dependencies]\napi = [\n "fastapi>=0.115",\n "uvicorn>=0.30",\n]\n',
816
+ "utf-8",
817
+ );
818
+ const signals = detectProjectSignals(dir);
819
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "multiline optional dependency arrays should trigger FastAPI detection");
820
+ } finally {
821
+ cleanup(dir);
822
+ }
823
+ });
824
+
825
+ test("detectProjectSignals: FastAPI direct reference with @ emits dep:fastapi", () => {
826
+ const dir = makeTempDir("signals-fastapi-direct-reference");
827
+ try {
828
+ writeFileSync(join(dir, "requirements.txt"), "fastapi @ https://example.com/fastapi.whl\n", "utf-8");
829
+ const signals = detectProjectSignals(dir);
830
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "direct-reference dependencies should trigger FastAPI detection");
831
+ } finally {
832
+ cleanup(dir);
833
+ }
834
+ });
835
+
836
+ test("detectProjectSignals: FastAPI detected via requirements.in", () => {
837
+ const dir = makeTempDir("signals-fastapi-requirements-in");
838
+ try {
839
+ writeFileSync(join(dir, "requirements.in"), "fastapi>=0.115\n", "utf-8");
840
+ const signals = detectProjectSignals(dir);
841
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "requirements.in should trigger FastAPI detection");
842
+ assert.ok(signals.detectedFiles.includes("requirements.txt"), "requirements.in should normalize to requirements.txt marker");
843
+ } finally {
844
+ cleanup(dir);
845
+ }
846
+ });
847
+
848
+ test("detectProjectSignals: FastAPI detected via nested requirements/base.in", () => {
849
+ const dir = makeTempDir("signals-fastapi-requirements-dir-in");
850
+ try {
851
+ mkdirSync(join(dir, "requirements"), { recursive: true });
852
+ writeFileSync(join(dir, "requirements", "base.in"), "fastapi>=0.115\n", "utf-8");
853
+ const signals = detectProjectSignals(dir);
854
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "requirements/base.in should trigger FastAPI detection");
855
+ assert.ok(signals.detectedFiles.includes("requirements.txt"), "requirements/base.in should normalize to requirements.txt marker");
856
+ } finally {
857
+ cleanup(dir);
858
+ }
859
+ });
860
+
861
+ test("detectProjectSignals: FastAPI comments do not trigger dep:fastapi", () => {
862
+ const dir = makeTempDir("signals-fastapi-comment");
863
+ try {
864
+ writeFileSync(join(dir, "requirements.txt"), "# maybe evaluate fastapi later\nflask==3.0\n", "utf-8");
865
+ const signals = detectProjectSignals(dir);
866
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "comments should not trigger FastAPI detection");
867
+ } finally {
868
+ cleanup(dir);
869
+ }
870
+ });
871
+
872
+ test("detectProjectSignals: FastAPI inline comments do not trigger dep:fastapi", () => {
873
+ const dir = makeTempDir("signals-fastapi-inline-comment");
874
+ try {
875
+ writeFileSync(join(dir, "requirements.txt"), "flask==3.0 # maybe fastapi later\n", "utf-8");
876
+ const signals = detectProjectSignals(dir);
877
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "inline comments should not trigger FastAPI detection");
878
+ } finally {
879
+ cleanup(dir);
880
+ }
881
+ });
882
+
883
+ test("detectProjectSignals: fastapi-* packages do not trigger dep:fastapi without fastapi itself", () => {
884
+ const dir = makeTempDir("signals-fastapi-suffix-only");
885
+ try {
886
+ writeFileSync(join(dir, "requirements.txt"), "fastapi-users==13.0\n", "utf-8");
887
+ const signals = detectProjectSignals(dir);
888
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "fastapi-* packages alone should not imply FastAPI framework usage");
889
+ } finally {
890
+ cleanup(dir);
891
+ }
892
+ });
893
+
894
+ test("detectProjectSignals: dependency extras mentioning fastapi do not trigger dep:fastapi", () => {
895
+ const dir = makeTempDir("signals-fastapi-extra-only");
896
+ try {
897
+ writeFileSync(join(dir, "requirements.txt"), "my-sdk[fastapi]>=1.0\n", "utf-8");
898
+ const signals = detectProjectSignals(dir);
899
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "dependency extras should not imply FastAPI framework usage");
900
+ } finally {
901
+ cleanup(dir);
902
+ }
903
+ });
904
+
905
+ test("detectProjectSignals: Django project does NOT get dep:fastapi marker", () => {
906
+ const dir = makeTempDir("signals-django-no-fastapi");
907
+ try {
908
+ writeFileSync(join(dir, "requirements.txt"), "django==5.0\ncelery\n", "utf-8");
909
+ writeFileSync(join(dir, "manage.py"), "#!/usr/bin/env python", "utf-8");
910
+ const signals = detectProjectSignals(dir);
911
+ assert.ok(!signals.detectedFiles.includes("dep:fastapi"), "should NOT add dep:fastapi for Django");
912
+ } finally {
913
+ cleanup(dir);
914
+ }
915
+ });
916
+
917
+ test("detectProjectSignals: FastAPI detected case-insensitively (PyPI canonical name)", () => {
918
+ const dir = makeTempDir("signals-fastapi-case");
919
+ try {
920
+ writeFileSync(join(dir, "pyproject.toml"), '[project]\ndependencies = ["FastAPI>=0.100"]\n', "utf-8");
921
+ const signals = detectProjectSignals(dir);
922
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "should detect FastAPI (mixed case)");
923
+ } finally {
924
+ cleanup(dir);
925
+ }
926
+ });
927
+
928
+ test("detectProjectSignals: FastAPI detected via nested service requirements.txt", () => {
929
+ const dir = makeTempDir("signals-fastapi-nested");
930
+ try {
931
+ mkdirSync(join(dir, "services", "api"), { recursive: true });
932
+ writeFileSync(join(dir, "services", "api", "requirements.txt"), "fastapi==0.115.0\n", "utf-8");
933
+ const signals = detectProjectSignals(dir);
934
+ assert.ok(signals.detectedFiles.includes("dep:fastapi"), "should detect FastAPI in nested service requirements.txt");
935
+ assert.ok(signals.detectedFiles.includes("requirements.txt"), "should normalize nested requirements.txt marker");
936
+ assert.equal(signals.primaryLanguage, "python");
937
+ } finally {
938
+ cleanup(dir);
939
+ }
940
+ });
941
+
942
+ test("detectProjectSignals: nested Prisma schema normalizes to prisma/schema.prisma", () => {
943
+ const dir = makeTempDir("signals-prisma-nested");
944
+ try {
945
+ mkdirSync(join(dir, "services", "api", "prisma"), { recursive: true });
946
+ writeFileSync(join(dir, "services", "api", "prisma", "schema.prisma"), "datasource db { provider = \"sqlite\" }", "utf-8");
947
+ const signals = detectProjectSignals(dir);
948
+ assert.ok(signals.detectedFiles.includes("prisma/schema.prisma"), "should detect nested Prisma schema");
949
+ } finally {
950
+ cleanup(dir);
951
+ }
952
+ });
953
+
954
+ test("detectProjectSignals: nested Spring Boot Gradle service emits dep:spring-boot", () => {
955
+ const dir = makeTempDir("signals-spring-gradle-nested");
956
+ try {
957
+ mkdirSync(join(dir, "services", "api"), { recursive: true });
958
+ writeFileSync(
959
+ join(dir, "services", "api", "build.gradle"),
960
+ "plugins { id 'org.springframework.boot' version '3.2.0' }",
961
+ "utf-8",
962
+ );
963
+ const signals = detectProjectSignals(dir);
964
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "should detect nested Spring Boot Gradle service");
965
+ assert.equal(signals.primaryLanguage, "java/kotlin");
966
+ } finally {
967
+ cleanup(dir);
968
+ }
969
+ });
970
+
971
+ test("detectProjectSignals: legacy apply plugin syntax emits dep:spring-boot", () => {
972
+ const dir = makeTempDir("signals-spring-apply-plugin");
973
+ try {
974
+ writeFileSync(join(dir, "build.gradle"), "apply plugin: 'org.springframework.boot'", "utf-8");
975
+ const signals = detectProjectSignals(dir);
976
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "apply plugin syntax should trigger Spring Boot detection");
977
+ } finally {
978
+ cleanup(dir);
979
+ }
980
+ });
981
+
982
+ test("detectProjectSignals: nested Spring Boot Kotlin DSL service still uses neutral java/kotlin language hint", () => {
983
+ const dir = makeTempDir("signals-spring-gradle-kts-nested");
984
+ try {
985
+ mkdirSync(join(dir, "services", "api"), { recursive: true });
986
+ writeFileSync(
987
+ join(dir, "services", "api", "build.gradle.kts"),
988
+ "plugins { id(\"org.springframework.boot\") version \"3.2.0\" }",
989
+ "utf-8",
990
+ );
991
+ const signals = detectProjectSignals(dir);
992
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"));
993
+ assert.equal(signals.primaryLanguage, "java/kotlin");
994
+ } finally {
995
+ cleanup(dir);
996
+ }
997
+ });
998
+
999
+ test("detectProjectSignals: Android Gradle project does not emit dep:spring-boot", () => {
1000
+ const dir = makeTempDir("signals-android-no-spring");
1001
+ try {
1002
+ writeFileSync(join(dir, "build.gradle"), "plugins { id 'com.android.application' }", "utf-8");
1003
+ mkdirSync(join(dir, "app"), { recursive: true });
1004
+ writeFileSync(join(dir, "app", "build.gradle"), "plugins { id 'com.android.application' }", "utf-8");
1005
+ const signals = detectProjectSignals(dir);
1006
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "Android Gradle files should not trigger Spring Boot detection");
1007
+ } finally {
1008
+ cleanup(dir);
1009
+ }
1010
+ });
1011
+
1012
+ test("detectProjectSignals: Android inline comments do not emit dep:spring-boot", () => {
1013
+ const dir = makeTempDir("signals-android-inline-comment");
1014
+ try {
1015
+ writeFileSync(join(dir, "build.gradle"), "plugins { id 'com.android.application' } // spring-boot maybe later", "utf-8");
1016
+ mkdirSync(join(dir, "app"), { recursive: true });
1017
+ writeFileSync(join(dir, "app", "build.gradle"), "plugins { id 'com.android.application' }", "utf-8");
1018
+ const signals = detectProjectSignals(dir);
1019
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "inline comments should not trigger Spring Boot detection");
1020
+ } finally {
1021
+ cleanup(dir);
1022
+ }
1023
+ });
1024
+
1025
+ test("detectProjectSignals: build metadata mentioning spring-boot does not emit dep:spring-boot", () => {
1026
+ const dir = makeTempDir("signals-spring-metadata-only");
1027
+ try {
1028
+ writeFileSync(join(dir, "build.gradle"), 'def notes = "spring-boot migration planned later"', "utf-8");
1029
+ const signals = detectProjectSignals(dir);
1030
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "arbitrary metadata text should not trigger Spring Boot detection");
1031
+ } finally {
1032
+ cleanup(dir);
1033
+ }
1034
+ });
1035
+
1036
+ test("detectProjectSignals: Maven artifactId alone does not emit dep:spring-boot", () => {
1037
+ const dir = makeTempDir("signals-spring-maven-artifact-only");
1038
+ try {
1039
+ writeFileSync(
1040
+ join(dir, "pom.xml"),
1041
+ '<project><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>spring-boot-tools</artifactId></project>',
1042
+ "utf-8",
1043
+ );
1044
+ const signals = detectProjectSignals(dir);
1045
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "artifactId alone should not imply Spring Boot");
1046
+ } finally {
1047
+ cleanup(dir);
1048
+ }
1049
+ });
1050
+
1051
+ test("detectProjectSignals: Spring Boot version-catalog alias emits dep:spring-boot", () => {
1052
+ const dir = makeTempDir("signals-spring-version-catalog");
1053
+ try {
1054
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1055
+ writeFileSync(join(dir, "build.gradle.kts"), "plugins { alias(libs.plugins.backend.web) }", "utf-8");
1056
+ writeFileSync(
1057
+ join(dir, "gradle", "libs.versions.toml"),
1058
+ "[plugins]\nbackend-web = { id = 'org.springframework.boot', version = '3.2.0' }\n",
1059
+ "utf-8",
1060
+ );
1061
+ const signals = detectProjectSignals(dir);
1062
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "should detect Spring Boot via version-catalog alias");
1063
+ } finally {
1064
+ cleanup(dir);
1065
+ }
1066
+ });
1067
+
1068
+ test("detectProjectSignals: commented Spring Boot alias in libs.versions.toml does not emit dep:spring-boot", () => {
1069
+ const dir = makeTempDir("signals-spring-version-catalog-comment");
1070
+ try {
1071
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1072
+ writeFileSync(join(dir, "build.gradle.kts"), "plugins { alias(libs.plugins.backend.web) }", "utf-8");
1073
+ writeFileSync(
1074
+ join(dir, "gradle", "libs.versions.toml"),
1075
+ "[plugins]\n# backend-web = { id = 'org.springframework.boot', version = '3.2.0' }\n",
1076
+ "utf-8",
1077
+ );
1078
+ const signals = detectProjectSignals(dir);
1079
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "commented aliases should not trigger Spring Boot detection");
1080
+ } finally {
1081
+ cleanup(dir);
1082
+ }
1083
+ });
1084
+
1085
+ test("detectProjectSignals: unused Spring Boot alias in libs.versions.toml does not emit dep:spring-boot", () => {
1086
+ const dir = makeTempDir("signals-spring-version-catalog-unused");
1087
+ try {
1088
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1089
+ writeFileSync(join(dir, "build.gradle.kts"), "plugins { alias(libs.plugins.backend.web) }", "utf-8");
1090
+ writeFileSync(
1091
+ join(dir, "gradle", "libs.versions.toml"),
1092
+ "[plugins]\nother-plugin = { id = 'org.springframework.boot', version = '3.2.0' }\n",
1093
+ "utf-8",
1094
+ );
1095
+ const signals = detectProjectSignals(dir);
1096
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "unused Spring Boot aliases should not trigger detection");
1097
+ } finally {
1098
+ cleanup(dir);
1099
+ }
1100
+ });
1101
+
1102
+ test("detectProjectSignals: spring-like alias name without Spring Boot id does not emit dep:spring-boot", () => {
1103
+ const dir = makeTempDir("signals-spring-version-catalog-false-alias");
1104
+ try {
1105
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1106
+ writeFileSync(join(dir, "build.gradle.kts"), "plugins { alias(libs.plugins.spring.boot.conventions) }", "utf-8");
1107
+ writeFileSync(
1108
+ join(dir, "gradle", "libs.versions.toml"),
1109
+ "[plugins]\nspring-boot-conventions = { id = 'com.example.conventions', version = '1.0.0' }\n",
1110
+ "utf-8",
1111
+ );
1112
+ const signals = detectProjectSignals(dir);
1113
+ assert.ok(!signals.detectedFiles.includes("dep:spring-boot"), "spring-looking alias names should not imply Spring Boot without matching id");
1114
+ } finally {
1115
+ cleanup(dir);
1116
+ }
1117
+ });
1118
+
1119
+ test("detectProjectSignals: Spring Boot version-catalog library alias emits dep:spring-boot", () => {
1120
+ const dir = makeTempDir("signals-spring-version-catalog-library");
1121
+ try {
1122
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1123
+ writeFileSync(join(dir, "build.gradle.kts"), "dependencies { implementation(libs.backend.web) }", "utf-8");
1124
+ writeFileSync(
1125
+ join(dir, "gradle", "libs.versions.toml"),
1126
+ "[libraries]\nbackend-web = { module = 'org.springframework.boot:spring-boot-starter-web', version = '3.2.0' }\n",
1127
+ "utf-8",
1128
+ );
1129
+ const signals = detectProjectSignals(dir);
1130
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "Spring Boot library aliases should trigger detection");
1131
+ } finally {
1132
+ cleanup(dir);
1133
+ }
1134
+ });
1135
+
1136
+ test("detectProjectSignals: Spring Boot version-catalog bundle alias emits dep:spring-boot", () => {
1137
+ const dir = makeTempDir("signals-spring-version-catalog-bundle");
1138
+ try {
1139
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1140
+ writeFileSync(join(dir, "build.gradle.kts"), "dependencies { implementation(libs.bundles.backend.web) }", "utf-8");
1141
+ writeFileSync(
1142
+ join(dir, "gradle", "libs.versions.toml"),
1143
+ "[libraries]\nspring-boot-starter-web = { module = 'org.springframework.boot:spring-boot-starter-web', version = '3.2.0' }\n\n[bundles]\nbackend-web = ['spring-boot-starter-web']\n",
1144
+ "utf-8",
1145
+ );
1146
+ const signals = detectProjectSignals(dir);
1147
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "Spring Boot bundle aliases should trigger detection");
1148
+ } finally {
1149
+ cleanup(dir);
1150
+ }
1151
+ });
1152
+
1153
+ test("detectProjectSignals: Spring Boot custom version-catalog accessor emits dep:spring-boot", () => {
1154
+ const dir = makeTempDir("signals-spring-version-catalog-custom-accessor");
1155
+ try {
1156
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1157
+ writeFileSync(join(dir, "build.gradle.kts"), "plugins { alias(backend.plugins.web) }", "utf-8");
1158
+ writeFileSync(
1159
+ join(dir, "gradle", "backend.versions.toml"),
1160
+ "[plugins]\nweb = { id = 'org.springframework.boot', version = '3.2.0' }\n",
1161
+ "utf-8",
1162
+ );
1163
+ const signals = detectProjectSignals(dir);
1164
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "custom version-catalog accessors should trigger Spring Boot detection");
1165
+ } finally {
1166
+ cleanup(dir);
1167
+ }
1168
+ });
1169
+
1170
+ test("detectProjectSignals: Spring Boot settings-defined catalog accessor emits dep:spring-boot", () => {
1171
+ const dir = makeTempDir("signals-spring-version-catalog-settings-accessor");
1172
+ try {
1173
+ mkdirSync(join(dir, "gradle"), { recursive: true });
1174
+ writeFileSync(
1175
+ join(dir, "settings.gradle.kts"),
1176
+ 'dependencyResolutionManagement { versionCatalogs { create("backendLibs") { from(files("./gradle/backend.versions.toml")) } } }',
1177
+ "utf-8",
1178
+ );
1179
+ writeFileSync(join(dir, "build.gradle.kts"), "plugins { alias(backendLibs.plugins.web) }", "utf-8");
1180
+ writeFileSync(
1181
+ join(dir, "gradle", "backend.versions.toml"),
1182
+ "[plugins]\nweb = { id = 'org.springframework.boot', version = '3.2.0' }\n",
1183
+ "utf-8",
1184
+ );
1185
+ const signals = detectProjectSignals(dir);
1186
+ assert.ok(signals.detectedFiles.includes("dep:spring-boot"), "settings-defined catalog accessors should trigger Spring Boot detection");
1187
+ } finally {
1188
+ cleanup(dir);
1189
+ }
1190
+ });