@tacuchi/agent-workflow-cli 4.0.0

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 (423) hide show
  1. package/README.md +70 -0
  2. package/dist/adapters/git-cli.d.ts +13 -0
  3. package/dist/adapters/git-cli.d.ts.map +1 -0
  4. package/dist/adapters/git-cli.js +73 -0
  5. package/dist/adapters/git-cli.js.map +1 -0
  6. package/dist/adapters/node-env.d.ts +7 -0
  7. package/dist/adapters/node-env.d.ts.map +1 -0
  8. package/dist/adapters/node-env.js +13 -0
  9. package/dist/adapters/node-env.js.map +1 -0
  10. package/dist/adapters/node-file-system.d.ts +10 -0
  11. package/dist/adapters/node-file-system.d.ts.map +1 -0
  12. package/dist/adapters/node-file-system.js +35 -0
  13. package/dist/adapters/node-file-system.js.map +1 -0
  14. package/dist/adapters/node-process.d.ts +6 -0
  15. package/dist/adapters/node-process.d.ts.map +1 -0
  16. package/dist/adapters/node-process.js +53 -0
  17. package/dist/adapters/node-process.js.map +1 -0
  18. package/dist/application/artifacts-service.d.ts +58 -0
  19. package/dist/application/artifacts-service.d.ts.map +1 -0
  20. package/dist/application/artifacts-service.js +129 -0
  21. package/dist/application/artifacts-service.js.map +1 -0
  22. package/dist/application/auto-plan.d.ts +19 -0
  23. package/dist/application/auto-plan.d.ts.map +1 -0
  24. package/dist/application/auto-plan.js +190 -0
  25. package/dist/application/auto-plan.js.map +1 -0
  26. package/dist/application/check-branch-service.d.ts +31 -0
  27. package/dist/application/check-branch-service.d.ts.map +1 -0
  28. package/dist/application/check-branch-service.js +140 -0
  29. package/dist/application/check-branch-service.js.map +1 -0
  30. package/dist/application/checkpoint-service.d.ts +77 -0
  31. package/dist/application/checkpoint-service.d.ts.map +1 -0
  32. package/dist/application/checkpoint-service.js +259 -0
  33. package/dist/application/checkpoint-service.js.map +1 -0
  34. package/dist/application/checkpoint-write-service.d.ts +42 -0
  35. package/dist/application/checkpoint-write-service.d.ts.map +1 -0
  36. package/dist/application/checkpoint-write-service.js +354 -0
  37. package/dist/application/checkpoint-write-service.js.map +1 -0
  38. package/dist/application/code-scan-service.d.ts +44 -0
  39. package/dist/application/code-scan-service.d.ts.map +1 -0
  40. package/dist/application/code-scan-service.js +211 -0
  41. package/dist/application/code-scan-service.js.map +1 -0
  42. package/dist/application/decisiones-service.d.ts +22 -0
  43. package/dist/application/decisiones-service.d.ts.map +1 -0
  44. package/dist/application/decisiones-service.js +31 -0
  45. package/dist/application/decisiones-service.js.map +1 -0
  46. package/dist/application/dependencias-service.d.ts +21 -0
  47. package/dist/application/dependencias-service.d.ts.map +1 -0
  48. package/dist/application/dependencias-service.js +31 -0
  49. package/dist/application/dependencias-service.js.map +1 -0
  50. package/dist/application/dev-bootstrap-dsn-service.d.ts +16 -0
  51. package/dist/application/dev-bootstrap-dsn-service.d.ts.map +1 -0
  52. package/dist/application/dev-bootstrap-dsn-service.js +31 -0
  53. package/dist/application/dev-bootstrap-dsn-service.js.map +1 -0
  54. package/dist/application/dev-graduate-service.d.ts +33 -0
  55. package/dist/application/dev-graduate-service.d.ts.map +1 -0
  56. package/dist/application/dev-graduate-service.js +116 -0
  57. package/dist/application/dev-graduate-service.js.map +1 -0
  58. package/dist/application/dev-only-services.d.ts +50 -0
  59. package/dist/application/dev-only-services.d.ts.map +1 -0
  60. package/dist/application/dev-only-services.js +155 -0
  61. package/dist/application/dev-only-services.js.map +1 -0
  62. package/dist/application/handoff.d.ts +19 -0
  63. package/dist/application/handoff.d.ts.map +1 -0
  64. package/dist/application/handoff.js +98 -0
  65. package/dist/application/handoff.js.map +1 -0
  66. package/dist/application/history-data-service.d.ts +26 -0
  67. package/dist/application/history-data-service.d.ts.map +1 -0
  68. package/dist/application/history-data-service.js +61 -0
  69. package/dist/application/history-data-service.js.map +1 -0
  70. package/dist/application/history-table.d.ts +16 -0
  71. package/dist/application/history-table.d.ts.map +1 -0
  72. package/dist/application/history-table.js +49 -0
  73. package/dist/application/history-table.js.map +1 -0
  74. package/dist/application/history-update-service.d.ts +24 -0
  75. package/dist/application/history-update-service.d.ts.map +1 -0
  76. package/dist/application/history-update-service.js +47 -0
  77. package/dist/application/history-update-service.js.map +1 -0
  78. package/dist/application/hook-branch-check.d.ts +22 -0
  79. package/dist/application/hook-branch-check.d.ts.map +1 -0
  80. package/dist/application/hook-branch-check.js +152 -0
  81. package/dist/application/hook-branch-check.js.map +1 -0
  82. package/dist/application/hook-sql-mutation-guard.d.ts +13 -0
  83. package/dist/application/hook-sql-mutation-guard.d.ts.map +1 -0
  84. package/dist/application/hook-sql-mutation-guard.js +119 -0
  85. package/dist/application/hook-sql-mutation-guard.js.map +1 -0
  86. package/dist/application/markdown.d.ts +4 -0
  87. package/dist/application/markdown.d.ts.map +1 -0
  88. package/dist/application/markdown.js +53 -0
  89. package/dist/application/markdown.js.map +1 -0
  90. package/dist/application/mcp-dbhub-launcher.d.ts +31 -0
  91. package/dist/application/mcp-dbhub-launcher.d.ts.map +1 -0
  92. package/dist/application/mcp-dbhub-launcher.js +84 -0
  93. package/dist/application/mcp-dbhub-launcher.js.map +1 -0
  94. package/dist/application/multiroot-service.d.ts +83 -0
  95. package/dist/application/multiroot-service.d.ts.map +1 -0
  96. package/dist/application/multiroot-service.js +440 -0
  97. package/dist/application/multiroot-service.js.map +1 -0
  98. package/dist/application/objetivo-service.d.ts +23 -0
  99. package/dist/application/objetivo-service.d.ts.map +1 -0
  100. package/dist/application/objetivo-service.js +32 -0
  101. package/dist/application/objetivo-service.js.map +1 -0
  102. package/dist/application/orchestration.d.ts +29 -0
  103. package/dist/application/orchestration.d.ts.map +1 -0
  104. package/dist/application/orchestration.js +291 -0
  105. package/dist/application/orchestration.js.map +1 -0
  106. package/dist/application/parsers/decisiones.d.ts +9 -0
  107. package/dist/application/parsers/decisiones.d.ts.map +1 -0
  108. package/dist/application/parsers/decisiones.js +55 -0
  109. package/dist/application/parsers/decisiones.js.map +1 -0
  110. package/dist/application/parsers/dependencias.d.ts +7 -0
  111. package/dist/application/parsers/dependencias.d.ts.map +1 -0
  112. package/dist/application/parsers/dependencias.js +76 -0
  113. package/dist/application/parsers/dependencias.js.map +1 -0
  114. package/dist/application/parsers/objetivo.d.ts +11 -0
  115. package/dist/application/parsers/objetivo.d.ts.map +1 -0
  116. package/dist/application/parsers/objetivo.js +73 -0
  117. package/dist/application/parsers/objetivo.js.map +1 -0
  118. package/dist/application/parsers/project-block.d.ts +35 -0
  119. package/dist/application/parsers/project-block.d.ts.map +1 -0
  120. package/dist/application/parsers/project-block.js +188 -0
  121. package/dist/application/parsers/project-block.js.map +1 -0
  122. package/dist/application/parsers/tasks.d.ts +17 -0
  123. package/dist/application/parsers/tasks.d.ts.map +1 -0
  124. package/dist/application/parsers/tasks.js +40 -0
  125. package/dist/application/parsers/tasks.js.map +1 -0
  126. package/dist/application/paths-service.d.ts +28 -0
  127. package/dist/application/paths-service.d.ts.map +1 -0
  128. package/dist/application/paths-service.js +67 -0
  129. package/dist/application/paths-service.js.map +1 -0
  130. package/dist/application/paths.d.ts +2 -0
  131. package/dist/application/paths.d.ts.map +1 -0
  132. package/dist/application/paths.js +12 -0
  133. package/dist/application/paths.js.map +1 -0
  134. package/dist/application/phase-detect-service.d.ts +28 -0
  135. package/dist/application/phase-detect-service.d.ts.map +1 -0
  136. package/dist/application/phase-detect-service.js +141 -0
  137. package/dist/application/phase-detect-service.js.map +1 -0
  138. package/dist/application/phase-next-service.d.ts +20 -0
  139. package/dist/application/phase-next-service.d.ts.map +1 -0
  140. package/dist/application/phase-next-service.js +97 -0
  141. package/dist/application/phase-next-service.js.map +1 -0
  142. package/dist/application/plugin-doctor-service.d.ts +60 -0
  143. package/dist/application/plugin-doctor-service.d.ts.map +1 -0
  144. package/dist/application/plugin-doctor-service.js +651 -0
  145. package/dist/application/plugin-doctor-service.js.map +1 -0
  146. package/dist/application/project-md-service.d.ts +13 -0
  147. package/dist/application/project-md-service.d.ts.map +1 -0
  148. package/dist/application/project-md-service.js +27 -0
  149. package/dist/application/project-md-service.js.map +1 -0
  150. package/dist/application/project-md-upsert-service.d.ts +48 -0
  151. package/dist/application/project-md-upsert-service.d.ts.map +1 -0
  152. package/dist/application/project-md-upsert-service.js +182 -0
  153. package/dist/application/project-md-upsert-service.js.map +1 -0
  154. package/dist/application/release-data-service.d.ts +81 -0
  155. package/dist/application/release-data-service.d.ts.map +1 -0
  156. package/dist/application/release-data-service.js +305 -0
  157. package/dist/application/release-data-service.js.map +1 -0
  158. package/dist/application/render/history-row.d.ts +10 -0
  159. package/dist/application/render/history-row.d.ts.map +1 -0
  160. package/dist/application/render/history-row.js +47 -0
  161. package/dist/application/render/history-row.js.map +1 -0
  162. package/dist/application/render/project-block.d.ts +17 -0
  163. package/dist/application/render/project-block.d.ts.map +1 -0
  164. package/dist/application/render/project-block.js +129 -0
  165. package/dist/application/render/project-block.js.map +1 -0
  166. package/dist/application/self/doctor-self.d.ts +27 -0
  167. package/dist/application/self/doctor-self.d.ts.map +1 -0
  168. package/dist/application/self/doctor-self.js +44 -0
  169. package/dist/application/self/doctor-self.js.map +1 -0
  170. package/dist/application/self/install-skill.d.ts +25 -0
  171. package/dist/application/self/install-skill.d.ts.map +1 -0
  172. package/dist/application/self/install-skill.js +176 -0
  173. package/dist/application/self/install-skill.js.map +1 -0
  174. package/dist/application/self/namespace-info.d.ts +8 -0
  175. package/dist/application/self/namespace-info.d.ts.map +1 -0
  176. package/dist/application/self/namespace-info.js +11 -0
  177. package/dist/application/self/namespace-info.js.map +1 -0
  178. package/dist/application/self/update-self.d.ts +10 -0
  179. package/dist/application/self/update-self.d.ts.map +1 -0
  180. package/dist/application/self/update-self.js +31 -0
  181. package/dist/application/self/update-self.js.map +1 -0
  182. package/dist/application/session-close-service.d.ts +30 -0
  183. package/dist/application/session-close-service.d.ts.map +1 -0
  184. package/dist/application/session-close-service.js +64 -0
  185. package/dist/application/session-close-service.js.map +1 -0
  186. package/dist/application/session-create-service.d.ts +40 -0
  187. package/dist/application/session-create-service.d.ts.map +1 -0
  188. package/dist/application/session-create-service.js +197 -0
  189. package/dist/application/session-create-service.js.map +1 -0
  190. package/dist/application/session-resolver.d.ts +39 -0
  191. package/dist/application/session-resolver.d.ts.map +1 -0
  192. package/dist/application/session-resolver.js +192 -0
  193. package/dist/application/session-resolver.js.map +1 -0
  194. package/dist/application/session-resume-service.d.ts +23 -0
  195. package/dist/application/session-resume-service.d.ts.map +1 -0
  196. package/dist/application/session-resume-service.js +44 -0
  197. package/dist/application/session-resume-service.js.map +1 -0
  198. package/dist/application/sessions-service.d.ts +31 -0
  199. package/dist/application/sessions-service.d.ts.map +1 -0
  200. package/dist/application/sessions-service.js +74 -0
  201. package/dist/application/sessions-service.js.map +1 -0
  202. package/dist/application/skill-index-service.d.ts +27 -0
  203. package/dist/application/skill-index-service.d.ts.map +1 -0
  204. package/dist/application/skill-index-service.js +99 -0
  205. package/dist/application/skill-index-service.js.map +1 -0
  206. package/dist/application/sources-service.d.ts +43 -0
  207. package/dist/application/sources-service.d.ts.map +1 -0
  208. package/dist/application/sources-service.js +176 -0
  209. package/dist/application/sources-service.js.map +1 -0
  210. package/dist/application/stack-detect.d.ts +7 -0
  211. package/dist/application/stack-detect.d.ts.map +1 -0
  212. package/dist/application/stack-detect.js +52 -0
  213. package/dist/application/stack-detect.js.map +1 -0
  214. package/dist/application/stack-service.d.ts +14 -0
  215. package/dist/application/stack-service.d.ts.map +1 -0
  216. package/dist/application/stack-service.js +13 -0
  217. package/dist/application/stack-service.js.map +1 -0
  218. package/dist/application/tasks-service.d.ts +27 -0
  219. package/dist/application/tasks-service.d.ts.map +1 -0
  220. package/dist/application/tasks-service.js +45 -0
  221. package/dist/application/tasks-service.js.map +1 -0
  222. package/dist/application/templates/objetivo.d.ts +3 -0
  223. package/dist/application/templates/objetivo.d.ts.map +1 -0
  224. package/dist/application/templates/objetivo.js +77 -0
  225. package/dist/application/templates/objetivo.js.map +1 -0
  226. package/dist/application/upgrade-hub-mode-service.d.ts +27 -0
  227. package/dist/application/upgrade-hub-mode-service.d.ts.map +1 -0
  228. package/dist/application/upgrade-hub-mode-service.js +114 -0
  229. package/dist/application/upgrade-hub-mode-service.js.map +1 -0
  230. package/dist/application/workspace-mode-service.d.ts +17 -0
  231. package/dist/application/workspace-mode-service.d.ts.map +1 -0
  232. package/dist/application/workspace-mode-service.js +39 -0
  233. package/dist/application/workspace-mode-service.js.map +1 -0
  234. package/dist/cli/commands/checkpoint-write.d.ts +4 -0
  235. package/dist/cli/commands/checkpoint-write.d.ts.map +1 -0
  236. package/dist/cli/commands/checkpoint-write.js +25 -0
  237. package/dist/cli/commands/checkpoint-write.js.map +1 -0
  238. package/dist/cli/commands/decisiones-list.d.ts +3 -0
  239. package/dist/cli/commands/decisiones-list.d.ts.map +1 -0
  240. package/dist/cli/commands/decisiones-list.js +17 -0
  241. package/dist/cli/commands/decisiones-list.js.map +1 -0
  242. package/dist/cli/commands/dependencias-list.d.ts +3 -0
  243. package/dist/cli/commands/dependencias-list.d.ts.map +1 -0
  244. package/dist/cli/commands/dependencias-list.js +11 -0
  245. package/dist/cli/commands/dependencias-list.js.map +1 -0
  246. package/dist/cli/commands/dev-only.d.ts +6 -0
  247. package/dist/cli/commands/dev-only.d.ts.map +1 -0
  248. package/dist/cli/commands/dev-only.js +51 -0
  249. package/dist/cli/commands/dev-only.js.map +1 -0
  250. package/dist/cli/commands/history-data.d.ts +3 -0
  251. package/dist/cli/commands/history-data.d.ts.map +1 -0
  252. package/dist/cli/commands/history-data.js +17 -0
  253. package/dist/cli/commands/history-data.js.map +1 -0
  254. package/dist/cli/commands/history-update.d.ts +3 -0
  255. package/dist/cli/commands/history-update.d.ts.map +1 -0
  256. package/dist/cli/commands/history-update.js +37 -0
  257. package/dist/cli/commands/history-update.js.map +1 -0
  258. package/dist/cli/commands/hook.d.ts +3 -0
  259. package/dist/cli/commands/hook.d.ts.map +1 -0
  260. package/dist/cli/commands/hook.js +53 -0
  261. package/dist/cli/commands/hook.js.map +1 -0
  262. package/dist/cli/commands/mcp.d.ts +3 -0
  263. package/dist/cli/commands/mcp.d.ts.map +1 -0
  264. package/dist/cli/commands/mcp.js +56 -0
  265. package/dist/cli/commands/mcp.js.map +1 -0
  266. package/dist/cli/commands/multiroot.d.ts +4 -0
  267. package/dist/cli/commands/multiroot.d.ts.map +1 -0
  268. package/dist/cli/commands/multiroot.js +50 -0
  269. package/dist/cli/commands/multiroot.js.map +1 -0
  270. package/dist/cli/commands/objetivo-data.d.ts +3 -0
  271. package/dist/cli/commands/objetivo-data.d.ts.map +1 -0
  272. package/dist/cli/commands/objetivo-data.js +11 -0
  273. package/dist/cli/commands/objetivo-data.js.map +1 -0
  274. package/dist/cli/commands/orchestration.d.ts +5 -0
  275. package/dist/cli/commands/orchestration.d.ts.map +1 -0
  276. package/dist/cli/commands/orchestration.js +84 -0
  277. package/dist/cli/commands/orchestration.js.map +1 -0
  278. package/dist/cli/commands/plugin-doctor.d.ts +3 -0
  279. package/dist/cli/commands/plugin-doctor.d.ts.map +1 -0
  280. package/dist/cli/commands/plugin-doctor.js +29 -0
  281. package/dist/cli/commands/plugin-doctor.js.map +1 -0
  282. package/dist/cli/commands/project-md-upsert.d.ts +3 -0
  283. package/dist/cli/commands/project-md-upsert.d.ts.map +1 -0
  284. package/dist/cli/commands/project-md-upsert.js +132 -0
  285. package/dist/cli/commands/project-md-upsert.js.map +1 -0
  286. package/dist/cli/commands/release-data.d.ts +3 -0
  287. package/dist/cli/commands/release-data.d.ts.map +1 -0
  288. package/dist/cli/commands/release-data.js +27 -0
  289. package/dist/cli/commands/release-data.js.map +1 -0
  290. package/dist/cli/commands/self.d.ts +3 -0
  291. package/dist/cli/commands/self.d.ts.map +1 -0
  292. package/dist/cli/commands/self.js +41 -0
  293. package/dist/cli/commands/self.js.map +1 -0
  294. package/dist/cli/commands/session-artifacts.d.ts +3 -0
  295. package/dist/cli/commands/session-artifacts.d.ts.map +1 -0
  296. package/dist/cli/commands/session-artifacts.js +17 -0
  297. package/dist/cli/commands/session-artifacts.js.map +1 -0
  298. package/dist/cli/commands/session-close.d.ts +3 -0
  299. package/dist/cli/commands/session-close.d.ts.map +1 -0
  300. package/dist/cli/commands/session-close.js +43 -0
  301. package/dist/cli/commands/session-close.js.map +1 -0
  302. package/dist/cli/commands/session-create.d.ts +3 -0
  303. package/dist/cli/commands/session-create.d.ts.map +1 -0
  304. package/dist/cli/commands/session-create.js +42 -0
  305. package/dist/cli/commands/session-create.js.map +1 -0
  306. package/dist/cli/commands/session-resume.d.ts +3 -0
  307. package/dist/cli/commands/session-resume.d.ts.map +1 -0
  308. package/dist/cli/commands/session-resume.js +11 -0
  309. package/dist/cli/commands/session-resume.js.map +1 -0
  310. package/dist/cli/commands/sessions.d.ts +4 -0
  311. package/dist/cli/commands/sessions.d.ts.map +1 -0
  312. package/dist/cli/commands/sessions.js +26 -0
  313. package/dist/cli/commands/sessions.js.map +1 -0
  314. package/dist/cli/commands/tasks-data.d.ts +3 -0
  315. package/dist/cli/commands/tasks-data.d.ts.map +1 -0
  316. package/dist/cli/commands/tasks-data.js +20 -0
  317. package/dist/cli/commands/tasks-data.js.map +1 -0
  318. package/dist/cli/commands/wave2-extras.d.ts +7 -0
  319. package/dist/cli/commands/wave2-extras.d.ts.map +1 -0
  320. package/dist/cli/commands/wave2-extras.js +87 -0
  321. package/dist/cli/commands/wave2-extras.js.map +1 -0
  322. package/dist/cli/commands/wave2-final.d.ts +8 -0
  323. package/dist/cli/commands/wave2-final.d.ts.map +1 -0
  324. package/dist/cli/commands/wave2-final.js +134 -0
  325. package/dist/cli/commands/wave2-final.js.map +1 -0
  326. package/dist/cli/commands/wave4d-simple.d.ts +6 -0
  327. package/dist/cli/commands/wave4d-simple.d.ts.map +1 -0
  328. package/dist/cli/commands/wave4d-simple.js +133 -0
  329. package/dist/cli/commands/wave4d-simple.js.map +1 -0
  330. package/dist/cli/interactive-menu.d.ts +9 -0
  331. package/dist/cli/interactive-menu.d.ts.map +1 -0
  332. package/dist/cli/interactive-menu.js +17 -0
  333. package/dist/cli/interactive-menu.js.map +1 -0
  334. package/dist/cli/main.d.ts +3 -0
  335. package/dist/cli/main.d.ts.map +1 -0
  336. package/dist/cli/main.js +208 -0
  337. package/dist/cli/main.js.map +1 -0
  338. package/dist/cli/parser.d.ts +17 -0
  339. package/dist/cli/parser.d.ts.map +1 -0
  340. package/dist/cli/parser.js +125 -0
  341. package/dist/cli/parser.js.map +1 -0
  342. package/dist/cli/registry.d.ts +15 -0
  343. package/dist/cli/registry.d.ts.map +1 -0
  344. package/dist/cli/registry.js +16 -0
  345. package/dist/cli/registry.js.map +1 -0
  346. package/dist/cli/render.d.ts +6 -0
  347. package/dist/cli/render.d.ts.map +1 -0
  348. package/dist/cli/render.js +13 -0
  349. package/dist/cli/render.js.map +1 -0
  350. package/dist/cli/types.d.ts +17 -0
  351. package/dist/cli/types.d.ts.map +1 -0
  352. package/dist/cli/types.js +2 -0
  353. package/dist/cli/types.js.map +1 -0
  354. package/dist/domain/plugin.d.ts +21 -0
  355. package/dist/domain/plugin.d.ts.map +1 -0
  356. package/dist/domain/plugin.js +2 -0
  357. package/dist/domain/plugin.js.map +1 -0
  358. package/dist/domain/project.d.ts +22 -0
  359. package/dist/domain/project.d.ts.map +1 -0
  360. package/dist/domain/project.js +2 -0
  361. package/dist/domain/project.js.map +1 -0
  362. package/dist/domain/session.d.ts +39 -0
  363. package/dist/domain/session.d.ts.map +1 -0
  364. package/dist/domain/session.js +2 -0
  365. package/dist/domain/session.js.map +1 -0
  366. package/dist/domain/types.d.ts +16 -0
  367. package/dist/domain/types.d.ts.map +1 -0
  368. package/dist/domain/types.js +2 -0
  369. package/dist/domain/types.js.map +1 -0
  370. package/dist/index.d.ts +22 -0
  371. package/dist/index.d.ts.map +1 -0
  372. package/dist/index.js +12 -0
  373. package/dist/index.js.map +1 -0
  374. package/dist/ports/env.d.ts +6 -0
  375. package/dist/ports/env.d.ts.map +1 -0
  376. package/dist/ports/env.js +2 -0
  377. package/dist/ports/env.js.map +1 -0
  378. package/dist/ports/file-system.d.ts +20 -0
  379. package/dist/ports/file-system.d.ts.map +1 -0
  380. package/dist/ports/file-system.js +2 -0
  381. package/dist/ports/file-system.js.map +1 -0
  382. package/dist/ports/git.d.ts +15 -0
  383. package/dist/ports/git.d.ts.map +1 -0
  384. package/dist/ports/git.js +2 -0
  385. package/dist/ports/git.js.map +1 -0
  386. package/dist/ports/process.d.ts +16 -0
  387. package/dist/ports/process.d.ts.map +1 -0
  388. package/dist/ports/process.js +2 -0
  389. package/dist/ports/process.js.map +1 -0
  390. package/dist/runtime/config-service.d.ts +19 -0
  391. package/dist/runtime/config-service.d.ts.map +1 -0
  392. package/dist/runtime/config-service.js +145 -0
  393. package/dist/runtime/config-service.js.map +1 -0
  394. package/dist/runtime/namespace-resolver.d.ts +18 -0
  395. package/dist/runtime/namespace-resolver.d.ts.map +1 -0
  396. package/dist/runtime/namespace-resolver.js +58 -0
  397. package/dist/runtime/namespace-resolver.js.map +1 -0
  398. package/dist/runtime/namespace.d.ts +7 -0
  399. package/dist/runtime/namespace.d.ts.map +1 -0
  400. package/dist/runtime/namespace.js +12 -0
  401. package/dist/runtime/namespace.js.map +1 -0
  402. package/dist/runtime/types.d.ts +43 -0
  403. package/dist/runtime/types.d.ts.map +1 -0
  404. package/dist/runtime/types.js +8 -0
  405. package/dist/runtime/types.js.map +1 -0
  406. package/package.json +57 -0
  407. package/skills/agent-workflow/LICENSE +21 -0
  408. package/skills/agent-workflow/MANUAL-FUNCIONAL.md +298 -0
  409. package/skills/agent-workflow/MANUAL-TECNICO.md +271 -0
  410. package/skills/agent-workflow/README.md +74 -0
  411. package/skills/agent-workflow/SKILL.md +111 -0
  412. package/skills/agent-workflow/docs/TEST-PLAN.md +163 -0
  413. package/skills/agent-workflow/references/checkpoint.md +59 -0
  414. package/skills/agent-workflow/references/dev-only.md +50 -0
  415. package/skills/agent-workflow/references/doctor.md +61 -0
  416. package/skills/agent-workflow/references/history.md +40 -0
  417. package/skills/agent-workflow/references/hooks.md +35 -0
  418. package/skills/agent-workflow/references/mcp.md +31 -0
  419. package/skills/agent-workflow/references/objetivo-tasks.md +64 -0
  420. package/skills/agent-workflow/references/orchestration.md +86 -0
  421. package/skills/agent-workflow/references/self.md +68 -0
  422. package/skills/agent-workflow/references/session-mgmt.md +109 -0
  423. package/skills/agent-workflow/references/sources.md +102 -0
@@ -0,0 +1,651 @@
1
+ // Plugin doctor — health check del plugin (manifest, hooks, MCP, skills).
2
+ // Comportamiento dependiente de `qtcContractVersion` del manifest:
3
+ // - >= 6.3 (single-path post-session032): skip checks de Python (marker
4
+ // `<userRoot>/<flow>/.plugin-version`, core-lib version marker, scripts,
5
+ // version de python3). Estos artefactos ya no existen en plugins single-path.
6
+ // - < 6.3 (legacy dual-path): chequea presencia de marker como antes para
7
+ // detectar instalaciones rotas en versiones antiguas.
8
+ //
9
+ // Phase 3 agnostic CLI: los servidores MCP esperados se leen de
10
+ // `runtime.expectedMcpServers` (vacio = no expectations). El soporte de
11
+ // scripts Python se eliminó por completo (Python ya no es parte del runtime).
12
+ //
13
+ // `exported_skills` se lee de `.claude-plugin/plugin.json:exportedSkills` o
14
+ // de un --exports-file JSON.
15
+ import { spawnSync } from "node:child_process";
16
+ import { extname, join, relative, resolve, sep } from "node:path";
17
+ const SESSION_SPECIFIC_MARKERS = [
18
+ "session034",
19
+ "idNegocioFinanciero",
20
+ "usuario-editar.component",
21
+ "AuthUserServiceImpl",
22
+ "tb_acceso_usuario_rol",
23
+ ];
24
+ export async function runPluginDoctor(fs, env, paths, runtime, input) {
25
+ const cwd = env.cwd();
26
+ const pluginRoot = input.pluginRoot
27
+ ? resolve(input.pluginRoot.startsWith("/") ? input.pluginRoot : join(cwd, input.pluginRoot))
28
+ : cwd;
29
+ const flow = input.flow ?? "core";
30
+ const inputPluginVersion = input.pluginVersion ?? null;
31
+ const pluginName = input.pluginName ?? `${paths.namespace}-${flow}`;
32
+ const compatRange = input.compatRange ?? null;
33
+ const skillsDir = join(pluginRoot, "skills");
34
+ const readmePath = join(pluginRoot, "README.md");
35
+ const findings = [];
36
+ const skillsInfo = [];
37
+ // 1. Skills frontmatter.
38
+ const skillDirs = [];
39
+ if (await fs.exists(skillsDir)) {
40
+ const entries = await fs.list(skillsDir);
41
+ for (const entry of entries) {
42
+ if (entry.type !== "dir")
43
+ continue;
44
+ const skillMd = join(entry.path, "SKILL.md");
45
+ if (await fs.exists(skillMd))
46
+ skillDirs.push(entry.path);
47
+ }
48
+ skillDirs.sort((a, b) => a.localeCompare(b));
49
+ }
50
+ const skillsCount = skillDirs.length;
51
+ for (const sd of skillDirs) {
52
+ const skillMd = join(sd, "SKILL.md");
53
+ const dirName = sd.split(sep).pop() ?? "";
54
+ let content;
55
+ try {
56
+ content = await fs.readText(skillMd);
57
+ }
58
+ catch (e) {
59
+ findings.push({ level: "error", file: skillMd, msg: `cannot read: ${e.message}` });
60
+ skillsInfo.push({ dir: dirName, name: null, version: null });
61
+ continue;
62
+ }
63
+ const lines = content.split(/\r?\n/);
64
+ if (lines.length === 0 || (lines[0] ?? "").trim() !== "---") {
65
+ findings.push({ level: "error", file: skillMd, msg: "missing frontmatter opening ---" });
66
+ skillsInfo.push({ dir: dirName, name: null, version: null });
67
+ continue;
68
+ }
69
+ let endIdx = -1;
70
+ for (let i = 1; i < lines.length; i++) {
71
+ if ((lines[i] ?? "").trim() === "---") {
72
+ endIdx = i;
73
+ break;
74
+ }
75
+ }
76
+ if (endIdx === -1) {
77
+ findings.push({ level: "error", file: skillMd, msg: "missing frontmatter closing ---" });
78
+ skillsInfo.push({ dir: dirName, name: null, version: null });
79
+ continue;
80
+ }
81
+ const fm = {};
82
+ for (let i = 1; i < endIdx; i++) {
83
+ const m = (lines[i] ?? "").match(/^(\w+):\s*(.+)$/);
84
+ if (m?.[1] && m[2] !== undefined)
85
+ fm[m[1]] = m[2].trim();
86
+ }
87
+ const name = fm.name ?? null;
88
+ const version = fm.version ?? null;
89
+ const description = fm.description ?? null;
90
+ if (!name) {
91
+ findings.push({ level: "error", file: skillMd, msg: "missing 'name' in frontmatter" });
92
+ }
93
+ else if (name !== dirName) {
94
+ findings.push({
95
+ level: "warn",
96
+ file: skillMd,
97
+ msg: `frontmatter name '${name}' differs from directory '${dirName}'`,
98
+ });
99
+ }
100
+ if (!description) {
101
+ findings.push({ level: "error", file: skillMd, msg: "missing 'description' in frontmatter" });
102
+ }
103
+ if (!version) {
104
+ findings.push({ level: "warn", file: skillMd, msg: "missing 'version' in frontmatter" });
105
+ }
106
+ else if (!/^\d+\.\d+\.\d+$/.test(version)) {
107
+ findings.push({
108
+ level: "warn",
109
+ file: skillMd,
110
+ msg: `version '${version}' not semver-compatible`,
111
+ });
112
+ }
113
+ skillsInfo.push({ dir: dirName, name, version });
114
+ }
115
+ // 2. README sync check.
116
+ let readmeCountExpected = null;
117
+ let readmeCountMatch = null;
118
+ if (await fs.exists(readmePath)) {
119
+ try {
120
+ const readmeText = await fs.readText(readmePath);
121
+ const m = readmeText.match(/\*\*Skills\*\*\s*\((\d+)/);
122
+ if (m?.[1]) {
123
+ readmeCountExpected = Number.parseInt(m[1], 10);
124
+ readmeCountMatch = readmeCountExpected === skillsCount;
125
+ if (!readmeCountMatch) {
126
+ findings.push({
127
+ level: "warn",
128
+ file: "README.md",
129
+ msg: `Skills count mismatch: README claims ${readmeCountExpected}, actual ${skillsCount}`,
130
+ });
131
+ }
132
+ }
133
+ }
134
+ catch (e) {
135
+ findings.push({
136
+ level: "warn",
137
+ file: "README.md",
138
+ msg: `cannot read: ${e.message}`,
139
+ });
140
+ }
141
+ }
142
+ else {
143
+ findings.push({ level: "warn", file: "README.md", msg: "README.md not found at plugin root" });
144
+ }
145
+ // 3. frontend-design generalization.
146
+ const fdDir = join(skillsDir, "frontend-design");
147
+ if ((await fs.exists(skillsDir)) && (await fs.exists(fdDir))) {
148
+ const mdFiles = await collectMarkdownFiles(fs, fdDir);
149
+ mdFiles.sort((a, b) => a.localeCompare(b));
150
+ for (const mdFile of mdFiles) {
151
+ let text;
152
+ try {
153
+ text = await fs.readText(mdFile);
154
+ }
155
+ catch {
156
+ continue;
157
+ }
158
+ for (const marker of SESSION_SPECIFIC_MARKERS) {
159
+ if (text.includes(marker)) {
160
+ const rel = relative(pluginRoot, mdFile).split(sep).join("/");
161
+ findings.push({
162
+ level: "error",
163
+ file: rel,
164
+ msg: `contains session-specific name '${marker}' (frontend-design must stay generalized)`,
165
+ });
166
+ }
167
+ }
168
+ }
169
+ }
170
+ // 4. Manifest version drift + qtcContractVersion gate.
171
+ const manifestsInfo = {};
172
+ let manifestQtcContractVersion = null;
173
+ let canonicalVersion = inputPluginVersion;
174
+ for (const relPath of [".claude-plugin/plugin.json", ".codex-plugin/plugin.json"]) {
175
+ const manifestPath = join(pluginRoot, relPath);
176
+ if (!(await fs.exists(manifestPath))) {
177
+ findings.push({ level: "warn", file: relPath, msg: "manifest missing" });
178
+ manifestsInfo[relPath] = null;
179
+ continue;
180
+ }
181
+ let raw;
182
+ try {
183
+ raw = await fs.readText(manifestPath);
184
+ }
185
+ catch (e) {
186
+ findings.push({
187
+ level: "error",
188
+ file: relPath,
189
+ msg: `invalid JSON: ${e.message}`,
190
+ });
191
+ manifestsInfo[relPath] = null;
192
+ continue;
193
+ }
194
+ let data;
195
+ try {
196
+ data = JSON.parse(raw);
197
+ }
198
+ catch (e) {
199
+ findings.push({
200
+ level: "error",
201
+ file: relPath,
202
+ msg: `invalid JSON: ${e.message}`,
203
+ });
204
+ manifestsInfo[relPath] = null;
205
+ continue;
206
+ }
207
+ const manifestVersion = isRecord(data) && typeof data.version === "string" ? data.version : null;
208
+ manifestsInfo[relPath] = manifestVersion;
209
+ if (canonicalVersion === null && manifestVersion !== null) {
210
+ canonicalVersion = manifestVersion;
211
+ }
212
+ else if (canonicalVersion !== null && manifestVersion !== canonicalVersion) {
213
+ findings.push({
214
+ level: "error",
215
+ file: relPath,
216
+ msg: `version drift: manifest=${manifestVersion} vs declared=${canonicalVersion}`,
217
+ });
218
+ }
219
+ if (manifestQtcContractVersion === null &&
220
+ isRecord(data) &&
221
+ typeof data.qtcContractVersion === "string") {
222
+ manifestQtcContractVersion = data.qtcContractVersion;
223
+ }
224
+ }
225
+ const pluginVersion = canonicalVersion ?? "unknown";
226
+ // Si el manifest declara qtcContractVersion >= 6.3, el plugin opera en
227
+ // single-path y no debe chequearse la presencia de artefactos legacy.
228
+ const isSinglePathContract = isContractVersionAtLeast(manifestQtcContractVersion, 6, 3);
229
+ // 5/5b — checks legacy de era dual-path. Solo el marker de plugin version y
230
+ // el marker de core-lib se siguen revisando para detectar instalaciones rotas
231
+ // en plugins viejos. Los scripts Python se eliminaron por completo.
232
+ let installedMarker = null;
233
+ let qtcCoreInstalled = null;
234
+ let compatOk = null;
235
+ if (!isSinglePathContract) {
236
+ // 5. Marker file (~/.<ns>/<flow>/.plugin-version) — solo legacy.
237
+ const markerFile = paths.userPluginVersionFile(flow);
238
+ if (await fs.exists(markerFile)) {
239
+ try {
240
+ const raw = (await fs.readText(markerFile)).trim();
241
+ installedMarker = raw.length > 0 ? raw : null;
242
+ }
243
+ catch (e) {
244
+ findings.push({
245
+ level: "warn",
246
+ file: markerFile,
247
+ msg: `cannot read marker: ${e.message}`,
248
+ });
249
+ }
250
+ if (installedMarker && installedMarker !== pluginVersion) {
251
+ findings.push({
252
+ level: "warn",
253
+ file: markerFile,
254
+ msg: `installed plugin v${installedMarker} differs from declared v${pluginVersion} — reinstall/re-sync`,
255
+ });
256
+ }
257
+ }
258
+ // 5b. core lib install state + compat range — solo legacy.
259
+ const coreLibMarker = paths.userCoreLibMarker();
260
+ if (await fs.exists(coreLibMarker)) {
261
+ try {
262
+ const raw = (await fs.readText(coreLibMarker)).trim();
263
+ qtcCoreInstalled = raw.length > 0 ? raw : null;
264
+ }
265
+ catch {
266
+ // ignore
267
+ }
268
+ }
269
+ if (compatRange) {
270
+ compatOk = evaluateCompat(qtcCoreInstalled, compatRange, coreLibMarker, findings);
271
+ }
272
+ }
273
+ // 7. Hooks JSON.
274
+ const hooksInfo = {};
275
+ for (const relPath of ["hooks/hooks.json", "codex-hooks/hooks.json"]) {
276
+ const hookPath = join(pluginRoot, relPath);
277
+ if (!(await fs.exists(hookPath))) {
278
+ findings.push({ level: "warn", file: relPath, msg: "hooks file missing" });
279
+ hooksInfo[relPath] = null;
280
+ continue;
281
+ }
282
+ let raw;
283
+ try {
284
+ raw = await fs.readText(hookPath);
285
+ }
286
+ catch (e) {
287
+ findings.push({
288
+ level: "error",
289
+ file: relPath,
290
+ msg: `invalid JSON: ${e.message}`,
291
+ });
292
+ hooksInfo[relPath] = null;
293
+ continue;
294
+ }
295
+ let data;
296
+ try {
297
+ data = JSON.parse(raw);
298
+ }
299
+ catch (e) {
300
+ findings.push({
301
+ level: "error",
302
+ file: relPath,
303
+ msg: `invalid JSON: ${e.message}`,
304
+ });
305
+ hooksInfo[relPath] = null;
306
+ continue;
307
+ }
308
+ if (!isRecord(data) || !("hooks" in data) || !isRecord(data.hooks)) {
309
+ findings.push({
310
+ level: "warn",
311
+ file: relPath,
312
+ msg: "hooks JSON missing top-level 'hooks' key",
313
+ });
314
+ hooksInfo[relPath] = "invalid-structure";
315
+ }
316
+ else {
317
+ hooksInfo[relPath] = Object.keys(data.hooks).sort();
318
+ }
319
+ }
320
+ // 8. MCP — servidores esperados leídos del runtime config (Phase 3).
321
+ const mcpInfo = {};
322
+ const mcpPath = join(pluginRoot, ".mcp.json");
323
+ const expectedMcpServers = runtime.expectedMcpServers ?? [];
324
+ if (expectedMcpServers.length > 0 && (await fs.exists(mcpPath))) {
325
+ let mcpData = null;
326
+ try {
327
+ mcpData = JSON.parse(await fs.readText(mcpPath));
328
+ }
329
+ catch (e) {
330
+ findings.push({
331
+ level: "error",
332
+ file: ".mcp.json",
333
+ msg: `invalid JSON: ${e.message}`,
334
+ });
335
+ }
336
+ if (mcpData !== null && isRecord(mcpData)) {
337
+ const servers = isRecord(mcpData.mcpServers) ? mcpData.mcpServers : {};
338
+ for (const exp of expectedMcpServers) {
339
+ const server = servers[exp];
340
+ if (server === undefined) {
341
+ findings.push({
342
+ level: "warn",
343
+ file: ".mcp.json",
344
+ msg: `expected server '${exp}' not configured`,
345
+ });
346
+ mcpInfo[exp] = "missing";
347
+ continue;
348
+ }
349
+ const dsnRaw = isRecord(server) && isRecord(server.env) && typeof server.env.DSN === "string"
350
+ ? server.env.DSN
351
+ : "";
352
+ const m = dsnRaw.match(/^\$\{(\w+)\}$/);
353
+ if (m?.[1]) {
354
+ const envVar = m[1];
355
+ const envSet = Boolean(env.get(envVar));
356
+ mcpInfo[exp] = { dsn_env: envVar, env_set: envSet };
357
+ if (!envSet) {
358
+ findings.push({
359
+ level: "warn",
360
+ file: ".mcp.json",
361
+ msg: `env var ${envVar} not set (required by mcp server '${exp}')`,
362
+ });
363
+ }
364
+ }
365
+ else {
366
+ mcpInfo[exp] = { dsn_env: null, env_set: null };
367
+ }
368
+ }
369
+ }
370
+ }
371
+ // 9. Python version — solo legacy. En single-path no existe runtime Python.
372
+ let pythonVersion = null;
373
+ if (!isSinglePathContract) {
374
+ pythonVersion = detectPythonVersion();
375
+ if (pythonVersion) {
376
+ const m = pythonVersion.match(/^(\d+)\.(\d+)/);
377
+ if (m?.[1] && m[2]) {
378
+ const major = Number.parseInt(m[1], 10);
379
+ const minor = Number.parseInt(m[2], 10);
380
+ if (major < 3 || (major === 3 && minor < 8)) {
381
+ findings.push({
382
+ level: "warn",
383
+ file: "python",
384
+ msg: `python ${pythonVersion} is too old; recommend 3.8+`,
385
+ });
386
+ }
387
+ }
388
+ }
389
+ }
390
+ // 10. Exported skills.
391
+ const exportedInfo = [];
392
+ const exportedSkills = await loadExportedSkills(fs, pluginRoot, input.exportsFile, pluginName);
393
+ const skillsByName = new Map();
394
+ for (const s of skillsInfo) {
395
+ if (s.name)
396
+ skillsByName.set(s.dir, s);
397
+ }
398
+ for (const exp of exportedSkills) {
399
+ const expSkillName = exp.skill;
400
+ const record = {
401
+ namespace: exp.namespace,
402
+ version_declared: exp.version ?? null,
403
+ since: exp.since ?? null,
404
+ exists_in_disk: false,
405
+ frontmatter_ok: false,
406
+ };
407
+ if (await fs.exists(skillsDir)) {
408
+ const target = join(skillsDir, expSkillName);
409
+ const targetSkill = join(target, "SKILL.md");
410
+ if (await fs.exists(targetSkill)) {
411
+ record.exists_in_disk = true;
412
+ const diskSkill = skillsByName.get(expSkillName);
413
+ if (diskSkill?.name && diskSkill.version) {
414
+ record.frontmatter_ok = true;
415
+ record.version_in_skill = diskSkill.version;
416
+ if (diskSkill.version && exp.version && diskSkill.version !== exp.version) {
417
+ findings.push({
418
+ level: "warn",
419
+ file: `skills/${expSkillName}/SKILL.md`,
420
+ msg: `exported skill version drift: registry declares ${exp.version}, SKILL.md frontmatter declares ${diskSkill.version}`,
421
+ });
422
+ }
423
+ }
424
+ else {
425
+ findings.push({
426
+ level: "error",
427
+ file: `skills/${expSkillName}/SKILL.md`,
428
+ msg: "exported skill SKILL.md missing required frontmatter (name + version)",
429
+ });
430
+ }
431
+ }
432
+ else {
433
+ findings.push({
434
+ level: "error",
435
+ file: `skills/${expSkillName}/SKILL.md`,
436
+ msg: `exported skill '${exp.namespace}' registered but not found in plugin's skills/ directory — fix the register_exported_skill call or add the SKILL.md`,
437
+ });
438
+ }
439
+ }
440
+ else {
441
+ findings.push({
442
+ level: "error",
443
+ file: "skills/",
444
+ msg: `exported skill '${exp.namespace}' registered but plugin has no skills/ directory`,
445
+ });
446
+ }
447
+ exportedInfo.push(record);
448
+ }
449
+ const hasError = findings.some((f) => f.level === "error");
450
+ const hasWarn = findings.some((f) => f.level === "warn");
451
+ const status = hasError ? "error" : hasWarn ? "warn" : "ok";
452
+ return {
453
+ data: {
454
+ status,
455
+ plugin: pluginName,
456
+ plugin_root: pluginRoot,
457
+ plugin_version: pluginVersion,
458
+ qtc_core_installed: qtcCoreInstalled,
459
+ compat_range: compatRange,
460
+ compat_ok: compatOk,
461
+ python_version: pythonVersion,
462
+ skills_count: skillsCount,
463
+ readme_count_expected: readmeCountExpected,
464
+ readme_count_match: readmeCountMatch,
465
+ manifests: manifestsInfo,
466
+ installed_marker: installedMarker,
467
+ hooks: hooksInfo,
468
+ mcp: mcpInfo,
469
+ skills: skillsInfo,
470
+ exported_skills: exportedInfo,
471
+ findings,
472
+ },
473
+ hasError,
474
+ };
475
+ }
476
+ function evaluateCompat(qtcCoreInstalled, compatRange, coreLibMarker, findings) {
477
+ if (!qtcCoreInstalled) {
478
+ findings.push({
479
+ level: "error",
480
+ file: coreLibMarker,
481
+ msg: `plugin requiere core ${compatRange} pero ${coreLibMarker} no existe — instalá el core lib o reiniciá la sesión para que SessionStart hook lo copie`,
482
+ });
483
+ return false;
484
+ }
485
+ const compatOk = semverSatisfies(qtcCoreInstalled, compatRange);
486
+ if (compatOk === null) {
487
+ findings.push({
488
+ level: "warn",
489
+ file: "compat_range",
490
+ msg: `no pude parsear compat_range '${compatRange}' (esperado '~X.Y.Z', '^X.Y.Z' o 'X.Y.Z') — validación contra core lib skipped`,
491
+ });
492
+ }
493
+ else if (!compatOk) {
494
+ findings.push({
495
+ level: "error",
496
+ file: "compat_range",
497
+ msg: `core lib instalado v${qtcCoreInstalled} NO satisface compat_range del plugin (${compatRange}) — el plugin va a fallar en runtime`,
498
+ });
499
+ }
500
+ return compatOk;
501
+ }
502
+ async function loadExportedSkills(fs, pluginRoot, exportsFile, pluginName) {
503
+ const sources = [];
504
+ if (exportsFile) {
505
+ if (await fs.exists(exportsFile)) {
506
+ try {
507
+ sources.push(JSON.parse(await fs.readText(exportsFile)));
508
+ }
509
+ catch {
510
+ // ignore
511
+ }
512
+ }
513
+ }
514
+ else {
515
+ const claudeManifest = join(pluginRoot, ".claude-plugin", "plugin.json");
516
+ if (await fs.exists(claudeManifest)) {
517
+ try {
518
+ const data = JSON.parse(await fs.readText(claudeManifest));
519
+ if (isRecord(data) && Array.isArray(data.exportedSkills)) {
520
+ sources.push(data.exportedSkills);
521
+ }
522
+ }
523
+ catch {
524
+ // ignore
525
+ }
526
+ }
527
+ }
528
+ const out = [];
529
+ for (const src of sources) {
530
+ if (!Array.isArray(src))
531
+ continue;
532
+ for (const item of src) {
533
+ if (!isRecord(item))
534
+ continue;
535
+ const skill = typeof item.skill === "string" ? item.skill : null;
536
+ if (!skill)
537
+ continue;
538
+ const plugin = typeof item.plugin === "string" && item.plugin.length > 0 ? item.plugin : pluginName;
539
+ const namespace = typeof item.namespace === "string" && item.namespace.length > 0
540
+ ? item.namespace
541
+ : `${plugin}:${skill}`;
542
+ out.push({
543
+ plugin,
544
+ skill,
545
+ namespace,
546
+ version: typeof item.version === "string" ? item.version : null,
547
+ since: typeof item.since === "string" ? item.since : null,
548
+ });
549
+ }
550
+ }
551
+ return out;
552
+ }
553
+ async function collectMarkdownFiles(fs, dir) {
554
+ const out = [];
555
+ const stack = [dir];
556
+ while (stack.length > 0) {
557
+ const current = stack.pop();
558
+ if (!current)
559
+ break;
560
+ let entries;
561
+ try {
562
+ entries = await fs.list(current);
563
+ }
564
+ catch {
565
+ continue;
566
+ }
567
+ for (const e of entries) {
568
+ if (e.type === "dir")
569
+ stack.push(e.path);
570
+ else if (e.type === "file" && extname(e.name).toLowerCase() === ".md")
571
+ out.push(e.path);
572
+ }
573
+ }
574
+ return out;
575
+ }
576
+ function isContractVersionAtLeast(version, major, minor) {
577
+ if (!version)
578
+ return false;
579
+ const m = version.trim().match(/^(\d+)\.(\d+)/);
580
+ if (!m?.[1] || !m[2])
581
+ return false;
582
+ const x = Number.parseInt(m[1], 10);
583
+ const y = Number.parseInt(m[2], 10);
584
+ if (x > major)
585
+ return true;
586
+ if (x < major)
587
+ return false;
588
+ return y >= minor;
589
+ }
590
+ function semverSatisfies(installed, range) {
591
+ const inst = parseSemver(installed);
592
+ if (!inst)
593
+ return null;
594
+ const m = range.trim().match(/^([~^]?)(\d+)\.(\d+)\.(\d+)$/);
595
+ if (!m)
596
+ return null;
597
+ const op = m[1] ?? "";
598
+ const x = Number.parseInt(m[2] ?? "0", 10);
599
+ const y = Number.parseInt(m[3] ?? "0", 10);
600
+ const z = Number.parseInt(m[4] ?? "0", 10);
601
+ if (op === "~") {
602
+ return tupleGte(inst, [x, y, z]) && tupleLt(inst, [x, y + 1, 0]);
603
+ }
604
+ if (op === "^") {
605
+ return tupleGte(inst, [x, y, z]) && tupleLt(inst, [x + 1, 0, 0]);
606
+ }
607
+ return inst[0] === x && inst[1] === y && inst[2] === z;
608
+ }
609
+ function parseSemver(v) {
610
+ const m = v.trim().match(/^(\d+)\.(\d+)\.(\d+)$/);
611
+ if (!m)
612
+ return null;
613
+ return [
614
+ Number.parseInt(m[1] ?? "0", 10),
615
+ Number.parseInt(m[2] ?? "0", 10),
616
+ Number.parseInt(m[3] ?? "0", 10),
617
+ ];
618
+ }
619
+ function tupleGte(a, b) {
620
+ if (a[0] !== b[0])
621
+ return a[0] > b[0];
622
+ if (a[1] !== b[1])
623
+ return a[1] > b[1];
624
+ return a[2] >= b[2];
625
+ }
626
+ function tupleLt(a, b) {
627
+ if (a[0] !== b[0])
628
+ return a[0] < b[0];
629
+ if (a[1] !== b[1])
630
+ return a[1] < b[1];
631
+ return a[2] < b[2];
632
+ }
633
+ function detectPythonVersion() {
634
+ try {
635
+ const r = spawnSync("python3", ["--version"], { encoding: "utf-8" });
636
+ if (r.status === 0) {
637
+ const text = `${r.stdout ?? ""}${r.stderr ?? ""}`;
638
+ const m = text.match(/Python\s+(\d+\.\d+\.\d+)/);
639
+ if (m?.[1])
640
+ return m[1];
641
+ }
642
+ }
643
+ catch {
644
+ // ignore
645
+ }
646
+ return null;
647
+ }
648
+ function isRecord(v) {
649
+ return typeof v === "object" && v !== null && !Array.isArray(v);
650
+ }
651
+ //# sourceMappingURL=plugin-doctor-service.js.map