@jaimevalasek/aioson 1.3.0 → 1.5.1

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 (330) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/LICENSE +661 -21
  3. package/README.md +22 -3
  4. package/docs/en/squad-dashboard.md +372 -0
  5. package/docs/openclaw-bridge.md +308 -0
  6. package/docs/pt/README.md +62 -2
  7. package/docs/pt/advisor-spec.md +5 -5
  8. package/docs/pt/agentes-customizados.md +670 -0
  9. package/docs/pt/agentes.md +235 -23
  10. package/docs/pt/automacao-squads.md +407 -0
  11. package/docs/pt/cenarios.md +49 -5
  12. package/docs/pt/clientes-ai.md +62 -0
  13. package/docs/pt/comandos-cli.md +226 -17
  14. package/docs/pt/deyvin.md +115 -0
  15. package/docs/pt/genome-3.0-spec.md +11 -11
  16. package/docs/pt/inicio-rapido.md +63 -2
  17. package/docs/pt/memoria-contexto.md +255 -0
  18. package/docs/pt/output-strategy-delivery.md +655 -0
  19. package/docs/pt/profiler-system.md +17 -17
  20. package/docs/pt/runtime-observability.md +5 -1
  21. package/docs/pt/skills.md +175 -0
  22. package/docs/pt/squad-dashboard.md +373 -0
  23. package/docs/pt/{squad-genoma.md → squad-genome.md} +81 -75
  24. package/docs/testing/genome-2.0-matrix.md +5 -5
  25. package/docs/testing/genome-2.0-rollout.md +10 -10
  26. package/package.json +4 -4
  27. package/src/agents.js +21 -5
  28. package/src/backup-local.js +74 -0
  29. package/src/backup-provider.js +303 -0
  30. package/src/cli.js +276 -2
  31. package/src/commands/agents.js +22 -4
  32. package/src/commands/backup-local-cmd.js +25 -0
  33. package/src/commands/backup.js +533 -0
  34. package/src/commands/cloud.js +17 -17
  35. package/src/commands/context-pack.js +45 -0
  36. package/src/commands/implementation-plan.js +340 -0
  37. package/src/commands/learning.js +134 -0
  38. package/src/commands/live.js +1583 -0
  39. package/src/commands/runtime.js +1075 -2
  40. package/src/commands/scan-project.js +288 -24
  41. package/src/commands/setup-context.js +30 -2
  42. package/src/commands/skill.js +558 -0
  43. package/src/commands/squad-agent-create.js +788 -0
  44. package/src/commands/squad-daemon.js +209 -0
  45. package/src/commands/squad-dashboard.js +39 -0
  46. package/src/commands/squad-deploy.js +64 -0
  47. package/src/commands/squad-doctor.js +103 -1
  48. package/src/commands/squad-investigate.js +261 -0
  49. package/src/commands/squad-learning.js +209 -0
  50. package/src/commands/squad-mcp.js +270 -0
  51. package/src/commands/squad-pipeline.js +247 -1
  52. package/src/commands/squad-plan.js +329 -0
  53. package/src/commands/squad-processes.js +56 -0
  54. package/src/commands/squad-recovery.js +42 -0
  55. package/src/commands/squad-roi.js +291 -0
  56. package/src/commands/squad-score.js +250 -0
  57. package/src/commands/squad-status.js +38 -2
  58. package/src/commands/squad-validate.js +118 -1
  59. package/src/commands/squad-webhook.js +160 -0
  60. package/src/commands/squad-worker.js +191 -0
  61. package/src/commands/squad-worktrees.js +75 -0
  62. package/src/commands/test-agents.js +6 -1
  63. package/src/commands/web-map.js +70 -0
  64. package/src/commands/web-scrape.js +71 -0
  65. package/src/commands/workflow-next.js +8 -1
  66. package/src/commands/workflow-status.js +250 -0
  67. package/src/constants.js +88 -16
  68. package/src/context-memory.js +837 -0
  69. package/src/context-writer.js +47 -1
  70. package/src/delivery-runner.js +319 -0
  71. package/src/genome-files.js +1 -1
  72. package/src/genome-format.js +1 -1
  73. package/src/i18n/messages/en.js +333 -8
  74. package/src/i18n/messages/es.js +240 -6
  75. package/src/i18n/messages/fr.js +239 -5
  76. package/src/i18n/messages/pt-BR.js +330 -12
  77. package/src/installer.js +30 -2
  78. package/src/lib/genomes/compat.js +1 -1
  79. package/src/lib/webhook-server.js +328 -0
  80. package/src/mcp-connectors/registry.js +602 -0
  81. package/src/runtime-store.js +1037 -42
  82. package/src/session-handoff.js +77 -0
  83. package/src/squad/external-session.js +180 -0
  84. package/src/squad/inter-squad.js +74 -0
  85. package/src/squad/recovery-context.js +201 -0
  86. package/src/squad/worktree-manager.js +114 -0
  87. package/src/squad-daemon.js +490 -0
  88. package/src/squad-dashboard/api.js +223 -0
  89. package/src/squad-dashboard/attachment-handler.js +93 -0
  90. package/src/squad-dashboard/context-monitor.js +157 -0
  91. package/src/squad-dashboard/execution-logs.js +115 -0
  92. package/src/squad-dashboard/hunk-review.js +209 -0
  93. package/src/squad-dashboard/metrics.js +133 -0
  94. package/src/squad-dashboard/process-monitor.js +125 -0
  95. package/src/squad-dashboard/renderer.js +858 -0
  96. package/src/squad-dashboard/server.js +232 -0
  97. package/src/squad-dashboard/styles.js +525 -0
  98. package/src/squad-dashboard/token-tracker.js +99 -0
  99. package/src/web.js +284 -0
  100. package/src/worker-runner.js +339 -0
  101. package/template/.aioson/agents/analyst.md +40 -9
  102. package/template/.aioson/agents/architect.md +24 -5
  103. package/template/.aioson/agents/dev.md +254 -25
  104. package/template/.aioson/agents/deyvin.md +174 -0
  105. package/template/.aioson/agents/discovery-design-doc.md +25 -1
  106. package/template/.aioson/agents/{genoma.md → genome.md} +20 -20
  107. package/template/.aioson/agents/neo.md +152 -0
  108. package/template/.aioson/agents/orache.md +388 -0
  109. package/template/.aioson/agents/orchestrator.md +63 -2
  110. package/template/.aioson/agents/pair.md +5 -0
  111. package/template/.aioson/agents/pm.md +17 -5
  112. package/template/.aioson/agents/product.md +113 -29
  113. package/template/.aioson/agents/profiler-enricher.md +1 -1
  114. package/template/.aioson/agents/profiler-forge.md +9 -9
  115. package/template/.aioson/agents/profiler-researcher.md +1 -1
  116. package/template/.aioson/agents/qa.md +18 -5
  117. package/template/.aioson/agents/setup.md +138 -18
  118. package/template/.aioson/agents/sheldon.md +603 -0
  119. package/template/.aioson/agents/squad.md +866 -28
  120. package/template/.aioson/agents/tester.md +254 -0
  121. package/template/.aioson/agents/ux-ui.md +289 -34
  122. package/template/.aioson/config.md +181 -0
  123. package/template/.aioson/context/spec.md.template +17 -0
  124. package/template/.aioson/genomes/.gitkeep +0 -0
  125. package/template/.aioson/installed-skills/.gitkeep +0 -0
  126. package/template/.aioson/locales/en/agents/analyst.md +34 -4
  127. package/template/.aioson/locales/en/agents/architect.md +18 -0
  128. package/template/.aioson/locales/en/agents/dev.md +155 -11
  129. package/template/.aioson/locales/en/agents/deyvin.md +137 -0
  130. package/template/.aioson/locales/en/agents/{genoma.md → genome.md} +14 -14
  131. package/template/.aioson/locales/en/agents/neo.md +8 -0
  132. package/template/.aioson/locales/en/agents/orchestrator.md +62 -2
  133. package/template/.aioson/locales/en/agents/pair.md +5 -0
  134. package/template/.aioson/locales/en/agents/pm.md +7 -0
  135. package/template/.aioson/locales/en/agents/product.md +35 -17
  136. package/template/.aioson/locales/en/agents/qa.md +56 -0
  137. package/template/.aioson/locales/en/agents/setup.md +53 -6
  138. package/template/.aioson/locales/en/agents/sheldon.md +340 -0
  139. package/template/.aioson/locales/en/agents/squad.md +203 -15
  140. package/template/.aioson/locales/en/agents/ux-ui.md +383 -35
  141. package/template/.aioson/locales/es/agents/analyst.md +24 -4
  142. package/template/.aioson/locales/es/agents/architect.md +18 -0
  143. package/template/.aioson/locales/es/agents/dev.md +136 -9
  144. package/template/.aioson/locales/es/agents/deyvin.md +97 -0
  145. package/template/.aioson/locales/es/agents/{genoma.md → genome.md} +13 -13
  146. package/template/.aioson/locales/es/agents/neo.md +48 -0
  147. package/template/.aioson/locales/es/agents/orache.md +103 -0
  148. package/template/.aioson/locales/es/agents/orchestrator.md +62 -2
  149. package/template/.aioson/locales/es/agents/pair.md +5 -0
  150. package/template/.aioson/locales/es/agents/pm.md +7 -0
  151. package/template/.aioson/locales/es/agents/product.md +13 -3
  152. package/template/.aioson/locales/es/agents/qa.md +33 -0
  153. package/template/.aioson/locales/es/agents/setup.md +30 -6
  154. package/template/.aioson/locales/es/agents/sheldon.md +192 -0
  155. package/template/.aioson/locales/es/agents/squad.md +284 -15
  156. package/template/.aioson/locales/es/agents/ux-ui.md +34 -25
  157. package/template/.aioson/locales/fr/agents/analyst.md +24 -4
  158. package/template/.aioson/locales/fr/agents/architect.md +18 -0
  159. package/template/.aioson/locales/fr/agents/dev.md +136 -9
  160. package/template/.aioson/locales/fr/agents/deyvin.md +97 -0
  161. package/template/.aioson/locales/fr/agents/{genoma.md → genome.md} +7 -7
  162. package/template/.aioson/locales/fr/agents/neo.md +48 -0
  163. package/template/.aioson/locales/fr/agents/orache.md +104 -0
  164. package/template/.aioson/locales/fr/agents/orchestrator.md +62 -2
  165. package/template/.aioson/locales/fr/agents/pair.md +5 -0
  166. package/template/.aioson/locales/fr/agents/pm.md +7 -0
  167. package/template/.aioson/locales/fr/agents/product.md +13 -3
  168. package/template/.aioson/locales/fr/agents/qa.md +33 -0
  169. package/template/.aioson/locales/fr/agents/setup.md +30 -6
  170. package/template/.aioson/locales/fr/agents/sheldon.md +192 -0
  171. package/template/.aioson/locales/fr/agents/squad.md +279 -10
  172. package/template/.aioson/locales/fr/agents/ux-ui.md +34 -25
  173. package/template/.aioson/locales/pt-BR/agents/analyst.md +45 -4
  174. package/template/.aioson/locales/pt-BR/agents/architect.md +29 -0
  175. package/template/.aioson/locales/pt-BR/agents/dev.md +167 -15
  176. package/template/.aioson/locales/pt-BR/agents/deyvin.md +137 -0
  177. package/template/.aioson/locales/pt-BR/agents/{genoma.md → genome.md} +49 -49
  178. package/template/.aioson/locales/pt-BR/agents/neo.md +147 -0
  179. package/template/.aioson/locales/pt-BR/agents/orache.md +137 -0
  180. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +62 -2
  181. package/template/.aioson/locales/pt-BR/agents/pair.md +5 -0
  182. package/template/.aioson/locales/pt-BR/agents/pm.md +7 -0
  183. package/template/.aioson/locales/pt-BR/agents/product.md +43 -20
  184. package/template/.aioson/locales/pt-BR/agents/qa.md +67 -0
  185. package/template/.aioson/locales/pt-BR/agents/setup.md +53 -6
  186. package/template/.aioson/locales/pt-BR/agents/sheldon.md +192 -0
  187. package/template/.aioson/locales/pt-BR/agents/squad.md +591 -47
  188. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +369 -22
  189. package/template/.aioson/my-agents/.gitkeep +0 -0
  190. package/template/.aioson/rules/.gitkeep +0 -0
  191. package/template/.aioson/rules/squad/.gitkeep +0 -0
  192. package/template/.aioson/rules/squad/README.md +50 -0
  193. package/template/.aioson/schemas/genome-meta.schema.json +1 -1
  194. package/template/.aioson/schemas/genome.schema.json +1 -1
  195. package/template/.aioson/schemas/squad-blueprint.schema.json +32 -0
  196. package/template/.aioson/schemas/squad-manifest.schema.json +434 -1
  197. package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +205 -0
  198. package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -0
  199. package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -0
  200. package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -0
  201. package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -0
  202. package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -0
  203. package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -0
  204. package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -0
  205. package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +210 -0
  206. package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -0
  207. package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -0
  208. package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -0
  209. package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -0
  210. package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -0
  211. package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -0
  212. package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -0
  213. package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +203 -0
  214. package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -0
  215. package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +407 -0
  216. package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +272 -0
  217. package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +524 -0
  218. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +277 -0
  219. package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +289 -0
  220. package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +437 -0
  221. package/template/.aioson/skills/design/interface-design/SKILL.md +47 -0
  222. package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -0
  223. package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -0
  224. package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +71 -0
  225. package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -0
  226. package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -0
  227. package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +62 -0
  228. package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -0
  229. package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -0
  230. package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -0
  231. package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -0
  232. package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +209 -0
  233. package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -0
  234. package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -0
  235. package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -0
  236. package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -0
  237. package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -0
  238. package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -0
  239. package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -0
  240. package/template/.aioson/skills/design-system/SKILL.md +92 -0
  241. package/template/.aioson/skills/design-system/cognitive-core-ui.skill +0 -0
  242. package/template/.aioson/skills/design-system/components/SKILL.md +274 -0
  243. package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
  244. package/template/.aioson/skills/design-system/dashboards/SKILL.md +184 -0
  245. package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
  246. package/template/.aioson/skills/design-system/foundations/SKILL.md +250 -0
  247. package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
  248. package/template/.aioson/skills/design-system/motion/SKILL.md +197 -0
  249. package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
  250. package/template/.aioson/skills/design-system/patterns/SKILL.md +231 -0
  251. package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
  252. package/template/.aioson/skills/premium-visual-design/SKILL.md +83 -0
  253. package/template/.aioson/skills/premium-visual-design/components/agent-badge.md +92 -0
  254. package/template/.aioson/skills/premium-visual-design/components/dependency-node.md +102 -0
  255. package/template/.aioson/skills/premium-visual-design/components/mention-autocomplete.md +136 -0
  256. package/template/.aioson/skills/premium-visual-design/components/notification-center.md +136 -0
  257. package/template/.aioson/skills/premium-visual-design/components/review-action-bar.md +188 -0
  258. package/template/.aioson/skills/premium-visual-design/components/team-switcher.md +131 -0
  259. package/template/.aioson/skills/premium-visual-design/patterns/agent-message-thread.md +198 -0
  260. package/template/.aioson/skills/premium-visual-design/patterns/notification-panel.md +275 -0
  261. package/template/.aioson/skills/premium-visual-design/patterns/review-workflow-ui.md +234 -0
  262. package/template/.aioson/skills/premium-visual-design/patterns/task-dependency-graph.md +147 -0
  263. package/template/.aioson/skills/premium-visual-design/tokens/status-extended.md +142 -0
  264. package/template/.aioson/skills/squad/SKILL.md +58 -0
  265. package/template/.aioson/skills/squad/domains/.gitkeep +0 -0
  266. package/template/.aioson/skills/squad/formats/.gitkeep +0 -0
  267. package/template/.aioson/skills/squad/formats/catalog.json +15 -0
  268. package/template/.aioson/skills/squad/formats/content/blog-post.md +47 -0
  269. package/template/.aioson/skills/squad/formats/content/newsletter.md +47 -0
  270. package/template/.aioson/skills/squad/formats/creative/podcast-script.md +43 -0
  271. package/template/.aioson/skills/squad/formats/creative/video-script.md +41 -0
  272. package/template/.aioson/skills/squad/formats/social/instagram-feed.md +42 -0
  273. package/template/.aioson/skills/squad/formats/social/linkedin-post.md +42 -0
  274. package/template/.aioson/skills/squad/formats/social/tiktok.md +39 -0
  275. package/template/.aioson/skills/squad/formats/social/twitter-thread.md +39 -0
  276. package/template/.aioson/skills/squad/formats/social/youtube-long.md +47 -0
  277. package/template/.aioson/skills/squad/formats/social/youtube-shorts.md +39 -0
  278. package/template/.aioson/skills/squad/patterns/.gitkeep +0 -0
  279. package/template/.aioson/skills/squad/patterns/multi-platform-pattern.md +108 -0
  280. package/template/.aioson/skills/squad/patterns/persona-based-pattern.md +98 -0
  281. package/template/.aioson/skills/squad/patterns/pipeline-pattern.md +106 -0
  282. package/template/.aioson/skills/squad/patterns/review-loop-pattern.md +81 -0
  283. package/template/.aioson/skills/squad/references/.gitkeep +0 -0
  284. package/template/.aioson/skills/squad/references/checklist-templates.md +122 -0
  285. package/template/.aioson/skills/squad/references/executor-archetypes.md +123 -0
  286. package/template/.aioson/skills/squad/references/workflow-templates.md +169 -0
  287. package/template/.aioson/skills/static/debugging-protocol.md +42 -0
  288. package/template/.aioson/skills/static/git-worktrees.md +36 -0
  289. package/template/.aioson/tasks/implementation-plan.md +307 -0
  290. package/template/.aioson/tasks/squad-create.md +1 -1
  291. package/template/.aioson/tasks/squad-design.md +28 -0
  292. package/template/.aioson/tasks/squad-execution-plan.md +279 -0
  293. package/template/.aioson/tasks/squad-export.md +1 -1
  294. package/template/.aioson/tasks/squad-investigate.md +44 -0
  295. package/template/.aioson/tasks/squad-learning-review.md +44 -0
  296. package/template/.aioson/tasks/squad-output-config.md +177 -0
  297. package/template/.aioson/tasks/squad-profile.md +48 -0
  298. package/template/.aioson/tasks/squad-review.md +61 -0
  299. package/template/.aioson/tasks/squad-task-decompose.md +66 -0
  300. package/template/.aioson/tasks/squad-validate.md +1 -1
  301. package/template/.claude/commands/aioson/agent/deyvin.md +5 -0
  302. package/template/.claude/commands/aioson/agent/discovery-design-doc.md +5 -0
  303. package/template/.claude/commands/aioson/agent/genome.md +5 -0
  304. package/template/.claude/commands/aioson/agent/neo.md +5 -0
  305. package/template/.claude/commands/aioson/agent/product.md +5 -0
  306. package/template/.claude/commands/aioson/agent/profiler-enricher.md +5 -0
  307. package/template/.claude/commands/aioson/agent/profiler-forge.md +5 -0
  308. package/template/.claude/commands/aioson/agent/profiler-researcher.md +5 -0
  309. package/template/.claude/commands/aioson/agent/squad.md +5 -0
  310. package/template/.claude/commands/aioson/agent/tester.md +5 -0
  311. package/template/.gemini/GEMINI.md +3 -0
  312. package/template/.gemini/commands/aios-deyvin.toml +6 -0
  313. package/template/.gemini/commands/aios-neo.toml +4 -0
  314. package/template/.gemini/commands/aios-pair.toml +6 -0
  315. package/template/.gemini/commands/aios-tester.toml +6 -0
  316. package/template/AGENTS.md +37 -6
  317. package/template/CLAUDE.md +34 -4
  318. package/template/OPENCODE.md +8 -2
  319. package/template/squad-searches/.gitkeep +0 -0
  320. package/template/.aioson/skills/static/interface-design.md +0 -372
  321. package/template/.aioson/skills/static/premium-command-center-ui.md +0 -190
  322. /package/template/.aioson/{genomas → docs}/.gitkeep +0 -0
  323. /package/template/.claude/commands/aioson/{analyst.md → agent/analyst.md} +0 -0
  324. /package/template/.claude/commands/aioson/{architect.md → agent/architect.md} +0 -0
  325. /package/template/.claude/commands/aioson/{dev.md → agent/dev.md} +0 -0
  326. /package/template/.claude/commands/aioson/{orchestrator.md → agent/orchestrator.md} +0 -0
  327. /package/template/.claude/commands/aioson/{pm.md → agent/pm.md} +0 -0
  328. /package/template/.claude/commands/aioson/{qa.md → agent/qa.md} +0 -0
  329. /package/template/.claude/commands/aioson/{setup.md → agent/setup.md} +0 -0
  330. /package/template/.claude/commands/aioson/{ux-ui.md → agent/ux-ui.md} +0 -0
@@ -0,0 +1,558 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { execFile } = require('node:child_process');
6
+ const { exists, ensureDir } = require('../utils');
7
+
8
+ const INSTALLED_SKILLS_DIR = '.aioson/installed-skills';
9
+ const TOOL_TARGETS = [
10
+ '.claude/skills',
11
+ '.cursor/skills',
12
+ '.windsurf/skills'
13
+ ];
14
+
15
+ function resolveTargetDir(args) {
16
+ return path.resolve(process.cwd(), args[0] || '.');
17
+ }
18
+
19
+ /**
20
+ * Parse YAML frontmatter from a SKILL.md file.
21
+ */
22
+ function parseSkillFrontmatter(content) {
23
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
24
+ if (!match) return {};
25
+ const result = {};
26
+ for (const line of match[1].split('\n')) {
27
+ const idx = line.indexOf(':');
28
+ if (idx === -1) continue;
29
+ const key = line.slice(0, idx).trim();
30
+ let val = line.slice(idx + 1).trim();
31
+ if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
32
+ val = val.slice(1, -1);
33
+ }
34
+ result[key] = val;
35
+ }
36
+ return result;
37
+ }
38
+
39
+ /**
40
+ * Copy a skill to a tool-specific directory (Claude Code, Cursor, Windsurf).
41
+ */
42
+ async function distributeToTool(targetDir, slug, skillDir) {
43
+ const results = [];
44
+ for (const toolPath of TOOL_TARGETS) {
45
+ const toolSkillDir = path.join(targetDir, toolPath, slug);
46
+ try {
47
+ await ensureDir(toolSkillDir);
48
+ // Copy all files from the installed skill dir
49
+ const entries = await fs.readdir(skillDir);
50
+ for (const entry of entries) {
51
+ const src = path.join(skillDir, entry);
52
+ const dest = path.join(toolSkillDir, entry);
53
+ const stat = await fs.stat(src);
54
+ if (stat.isFile()) {
55
+ await fs.copyFile(src, dest);
56
+ }
57
+ }
58
+ results.push({ tool: toolPath, ok: true });
59
+ } catch (err) {
60
+ results.push({ tool: toolPath, ok: false, error: err.message });
61
+ }
62
+ }
63
+ return results;
64
+ }
65
+
66
+ /**
67
+ * Remove a skill from tool-specific directories.
68
+ */
69
+ async function removeFromTools(targetDir, slug) {
70
+ for (const toolPath of TOOL_TARGETS) {
71
+ const toolSkillDir = path.join(targetDir, toolPath, slug);
72
+ try {
73
+ await fs.rm(toolSkillDir, { recursive: true, force: true });
74
+ } catch {
75
+ // Ignore — may not exist
76
+ }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Update the AGENTS.md installed-skills section.
82
+ */
83
+ async function updateAgentsMdSkills(targetDir) {
84
+ const agentsPath = path.join(targetDir, 'AGENTS.md');
85
+ if (!(await exists(agentsPath))) return;
86
+
87
+ let content = await fs.readFile(agentsPath, 'utf8');
88
+
89
+ // List installed skills
90
+ const skillsDir = path.join(targetDir, INSTALLED_SKILLS_DIR);
91
+ let skills = [];
92
+ try {
93
+ const entries = await fs.readdir(skillsDir);
94
+ for (const slug of entries) {
95
+ const skillMdPath = path.join(skillsDir, slug, 'SKILL.md');
96
+ if (await exists(skillMdPath)) {
97
+ const raw = await fs.readFile(skillMdPath, 'utf8');
98
+ const fm = parseSkillFrontmatter(raw);
99
+ skills.push({
100
+ slug,
101
+ name: fm.name || slug,
102
+ description: fm.description || ''
103
+ });
104
+ }
105
+ }
106
+ } catch {
107
+ // No installed skills
108
+ }
109
+
110
+ // Build the section
111
+ const marker = '## Installed skills';
112
+ const endMarker = '## '; // Next section starts with ##
113
+ const startIdx = content.indexOf(marker);
114
+
115
+ let skillsSection = '';
116
+ if (skills.length > 0) {
117
+ skillsSection = `${marker}\n\n`;
118
+ skillsSection += 'These skills are available in the project. Load them on-demand when the task matches their description.\n\n';
119
+ skillsSection += '| Skill | File | Description |\n';
120
+ skillsSection += '|-------|------|-------------|\n';
121
+ for (const s of skills) {
122
+ const shortDesc = s.description.length > 100 ? s.description.slice(0, 100) + '...' : s.description;
123
+ skillsSection += `| @${s.slug} | \`.aioson/installed-skills/${s.slug}/SKILL.md\` | ${shortDesc} |\n`;
124
+ }
125
+ skillsSection += '\n';
126
+ }
127
+
128
+ if (startIdx !== -1) {
129
+ // Replace existing section
130
+ const afterMarker = content.slice(startIdx + marker.length);
131
+ const nextSectionIdx = afterMarker.indexOf('\n## ');
132
+ if (nextSectionIdx !== -1) {
133
+ const before = content.slice(0, startIdx);
134
+ const after = afterMarker.slice(nextSectionIdx + 1);
135
+ content = before + (skills.length > 0 ? skillsSection : '') + after;
136
+ } else {
137
+ // Section is at the end
138
+ content = content.slice(0, startIdx) + skillsSection;
139
+ }
140
+ } else if (skills.length > 0) {
141
+ // Insert before "## Golden rule" or at the end
142
+ const goldenIdx = content.indexOf('## Golden rule');
143
+ if (goldenIdx !== -1) {
144
+ content = content.slice(0, goldenIdx) + skillsSection + content.slice(goldenIdx);
145
+ } else {
146
+ content = content.trimEnd() + '\n\n' + skillsSection;
147
+ }
148
+ }
149
+
150
+ await fs.writeFile(agentsPath, content, 'utf8');
151
+ }
152
+
153
+ /**
154
+ * Install from npm using @tech-leads-club/agent-skills
155
+ * Runs the npm CLI, then moves the resulting files to .aioson/installed-skills/
156
+ */
157
+ async function installFromNpm(targetDir, slug, options, logger) {
158
+ return new Promise((resolve, reject) => {
159
+ const args = ['@tech-leads-club/agent-skills', 'install', '--skill', slug];
160
+ if (options.force) args.push('--force');
161
+
162
+ logger.log(` Running: npx ${args.join(' ')}`);
163
+ execFile('npx', args, {
164
+ cwd: targetDir,
165
+ timeout: 60000,
166
+ env: { ...process.env }
167
+ }, async (error, stdout, stderr) => {
168
+ if (error) {
169
+ logger.error(` npm install failed: ${error.message}`);
170
+ return resolve({ ok: false, error: error.message });
171
+ }
172
+
173
+ // The npm tool installs to .claude/skills/{slug}/, .cursor/skills/{slug}/, .windsurf/skills/{slug}/
174
+ // Find the SKILL.md in any of these and copy to .aioson/installed-skills/
175
+ const sources = TOOL_TARGETS.map(t => path.join(targetDir, t, slug));
176
+ let sourceDir = null;
177
+ for (const src of sources) {
178
+ if (await exists(path.join(src, 'SKILL.md'))) {
179
+ sourceDir = src;
180
+ break;
181
+ }
182
+ }
183
+
184
+ if (!sourceDir) {
185
+ return resolve({ ok: false, error: `Skill "${slug}" installed by npm but SKILL.md not found in tool directories` });
186
+ }
187
+
188
+ // Copy to .aioson/installed-skills/{slug}/
189
+ const destDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
190
+ await ensureDir(destDir);
191
+
192
+ const entries = await fs.readdir(sourceDir);
193
+ for (const entry of entries) {
194
+ await fs.copyFile(path.join(sourceDir, entry), path.join(destDir, entry));
195
+ }
196
+
197
+ resolve({ ok: true, sourceDir, destDir });
198
+ });
199
+ });
200
+ }
201
+
202
+ /**
203
+ * Install from aioson.com cloud registry
204
+ */
205
+ async function installFromCloud(targetDir, slug, options, logger) {
206
+ // Read cloud config
207
+ let cloudUrl, cloudToken;
208
+ try {
209
+ const raw = await fs.readFile(path.join(targetDir, '.aioson/install.json'), 'utf8');
210
+ const meta = JSON.parse(raw);
211
+ cloudUrl = options.url || meta.cloudBaseUrl;
212
+ cloudToken = options.token || meta.cloudApiToken;
213
+ } catch {
214
+ cloudUrl = options.url;
215
+ cloudToken = options.token;
216
+ }
217
+
218
+ if (!cloudUrl) {
219
+ return { ok: false, error: 'Cloud URL not configured. Use --url or set cloudBaseUrl.' };
220
+ }
221
+
222
+ const endpoint = `${cloudUrl.replace(/\/+$/, '')}/api/registry/skills/${encodeURIComponent(slug)}`;
223
+ logger.log(` Fetching: ${endpoint}`);
224
+
225
+ const headers = { accept: 'application/json' };
226
+ if (cloudToken) headers.authorization = `Bearer ${cloudToken}`;
227
+
228
+ const response = await fetch(endpoint, { headers, signal: AbortSignal.timeout(15000) });
229
+ if (!response.ok) {
230
+ return { ok: false, error: `Cloud returned ${response.status}` };
231
+ }
232
+
233
+ const snapshot = await response.json();
234
+ if (!snapshot.skill || !snapshot.contentMarkdown) {
235
+ return { ok: false, error: 'Invalid skill snapshot from cloud' };
236
+ }
237
+
238
+ // Build SKILL.md with frontmatter
239
+ const fm = [
240
+ '---',
241
+ `name: ${snapshot.skill.slug}`,
242
+ `description: ${snapshot.skill.summary || snapshot.skill.title || slug}`,
243
+ `source: cloud`,
244
+ `domain: ${snapshot.skill.domain || 'general'}`,
245
+ '---',
246
+ '',
247
+ snapshot.contentMarkdown
248
+ ].join('\n');
249
+
250
+ const destDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
251
+ await ensureDir(destDir);
252
+ await fs.writeFile(path.join(destDir, 'SKILL.md'), fm, 'utf8');
253
+
254
+ // Write meta
255
+ await fs.writeFile(path.join(destDir, '.skill-meta.json'), JSON.stringify({
256
+ source: 'cloud',
257
+ cloudSlug: snapshot.skill.slug,
258
+ installedAt: new Date().toISOString()
259
+ }, null, 2), 'utf8');
260
+
261
+ return { ok: true, destDir };
262
+ }
263
+
264
+ /**
265
+ * Install from a local file path
266
+ */
267
+ async function installFromLocal(targetDir, slug, filePath, logger) {
268
+ const absPath = path.resolve(targetDir, filePath);
269
+ if (!(await exists(absPath))) {
270
+ return { ok: false, error: `File not found: ${absPath}` };
271
+ }
272
+
273
+ const destDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
274
+ await ensureDir(destDir);
275
+
276
+ const stat = await fs.stat(absPath);
277
+ if (stat.isDirectory()) {
278
+ // Copy entire directory
279
+ const entries = await fs.readdir(absPath);
280
+ for (const entry of entries) {
281
+ const src = path.join(absPath, entry);
282
+ const srcStat = await fs.stat(src);
283
+ if (srcStat.isFile()) {
284
+ await fs.copyFile(src, path.join(destDir, entry));
285
+ }
286
+ }
287
+ } else {
288
+ // Single file — copy as SKILL.md
289
+ await fs.copyFile(absPath, path.join(destDir, 'SKILL.md'));
290
+ }
291
+
292
+ // Write meta
293
+ await fs.writeFile(path.join(destDir, '.skill-meta.json'), JSON.stringify({
294
+ source: 'local',
295
+ sourcePath: filePath,
296
+ installedAt: new Date().toISOString()
297
+ }, null, 2), 'utf8');
298
+
299
+ return { ok: true, destDir };
300
+ }
301
+
302
+ // ── Main commands ──
303
+
304
+ async function runSkillInstall({ args, options = {}, logger, t }) {
305
+ const targetDir = resolveTargetDir(args);
306
+ const slug = options.slug || options.skill;
307
+ const from = options.from || 'npm';
308
+
309
+ if (!slug) {
310
+ logger.error('Usage: aioson skill:install --slug=<name> [--from=npm|cloud|./path]');
311
+ return { ok: false, error: 'Missing --slug' };
312
+ }
313
+
314
+ logger.log(`Installing skill "${slug}" from ${from}...`);
315
+
316
+ let result;
317
+ if (from === 'npm') {
318
+ result = await installFromNpm(targetDir, slug, options, logger);
319
+ } else if (from === 'cloud') {
320
+ result = await installFromCloud(targetDir, slug, options, logger);
321
+ } else {
322
+ // Treat as local path
323
+ result = await installFromLocal(targetDir, slug, from, logger);
324
+ }
325
+
326
+ if (!result.ok) {
327
+ logger.error(` Installation failed: ${result.error}`);
328
+ return { ok: false, error: result.error, slug };
329
+ }
330
+
331
+ // Distribute to tool directories
332
+ const skillDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
333
+ const distributed = await distributeToTool(targetDir, slug, skillDir);
334
+
335
+ for (const d of distributed) {
336
+ const status = d.ok ? 'OK' : `FAIL: ${d.error}`;
337
+ logger.log(` ${d.tool}: ${status}`);
338
+ }
339
+
340
+ // Update AGENTS.md
341
+ await updateAgentsMdSkills(targetDir);
342
+ logger.log(` AGENTS.md updated`);
343
+
344
+ const skillMdPath = path.join(skillDir, 'SKILL.md');
345
+ if (await exists(skillMdPath)) {
346
+ const raw = await fs.readFile(skillMdPath, 'utf8');
347
+ const fm = parseSkillFrontmatter(raw);
348
+ logger.log(`\nInstalled: ${fm.name || slug}`);
349
+ if (fm.description) {
350
+ logger.log(` ${fm.description.slice(0, 120)}`);
351
+ }
352
+ }
353
+
354
+ logger.log(`\nSkill available at: .aioson/installed-skills/${slug}/SKILL.md`);
355
+
356
+ return {
357
+ ok: true,
358
+ slug,
359
+ from,
360
+ installed: path.join(INSTALLED_SKILLS_DIR, slug),
361
+ distributed: distributed.filter(d => d.ok).map(d => d.tool)
362
+ };
363
+ }
364
+
365
+ /**
366
+ * Scan a directory for .md files with SKILL.md or frontmatter descriptions.
367
+ * Returns array of { slug, name, description, type, path }.
368
+ */
369
+ async function scanSourceSkillDir(baseDir, type) {
370
+ const results = [];
371
+ if (!(await exists(baseDir))) return results;
372
+
373
+ try {
374
+ const entries = await fs.readdir(baseDir, { withFileTypes: true });
375
+ for (const entry of entries) {
376
+ if (entry.name.startsWith('.')) continue;
377
+
378
+ if (entry.isDirectory()) {
379
+ // Look for SKILL.md inside the directory
380
+ const skillMdPath = path.join(baseDir, entry.name, 'SKILL.md');
381
+ if (await exists(skillMdPath)) {
382
+ const raw = await fs.readFile(skillMdPath, 'utf8');
383
+ const fm = parseSkillFrontmatter(raw);
384
+ results.push({
385
+ slug: entry.name,
386
+ name: fm.name || entry.name,
387
+ description: fm.description || '',
388
+ type,
389
+ path: path.relative(process.cwd(), path.join(baseDir, entry.name))
390
+ });
391
+ }
392
+ } else if (entry.isFile() && entry.name.endsWith('.md') && entry.name !== 'README.md') {
393
+ // Read frontmatter from .md file directly
394
+ const filePath = path.join(baseDir, entry.name);
395
+ const raw = await fs.readFile(filePath, 'utf8');
396
+ const fm = parseSkillFrontmatter(raw);
397
+ const slug = entry.name.replace(/\.md$/, '');
398
+ results.push({
399
+ slug,
400
+ name: fm.name || slug,
401
+ description: fm.description || '',
402
+ type,
403
+ path: path.relative(process.cwd(), filePath)
404
+ });
405
+ }
406
+ }
407
+ } catch {
408
+ // Directory not readable
409
+ }
410
+
411
+ return results;
412
+ }
413
+
414
+ async function runSkillList({ args, options = {}, logger, t }) {
415
+ const targetDir = resolveTargetDir(args);
416
+ const skillsDir = path.join(targetDir, INSTALLED_SKILLS_DIR);
417
+ const showAll = options.all !== undefined;
418
+
419
+ const installed = [];
420
+
421
+ // Installed skills
422
+ try {
423
+ const entries = await fs.readdir(skillsDir);
424
+ for (const slug of entries) {
425
+ const skillMdPath = path.join(skillsDir, slug, 'SKILL.md');
426
+ if (!(await exists(skillMdPath))) continue;
427
+
428
+ const raw = await fs.readFile(skillMdPath, 'utf8');
429
+ const fm = parseSkillFrontmatter(raw);
430
+
431
+ let source = 'unknown';
432
+ try {
433
+ const metaRaw = await fs.readFile(path.join(skillsDir, slug, '.skill-meta.json'), 'utf8');
434
+ const meta = JSON.parse(metaRaw);
435
+ source = meta.source || 'unknown';
436
+ } catch { /* no meta */ }
437
+
438
+ installed.push({
439
+ slug,
440
+ name: fm.name || slug,
441
+ description: fm.description || '',
442
+ source,
443
+ path: path.relative(targetDir, path.join(skillsDir, slug))
444
+ });
445
+ }
446
+ } catch {
447
+ // Dir may not exist
448
+ }
449
+
450
+ // Source skills (design, static, dynamic)
451
+ const sourceBase = path.join(targetDir, '.aioson/skills');
452
+ const designSkills = await scanSourceSkillDir(path.join(sourceBase, 'design'), 'design');
453
+ const designSystemSkills = await scanSourceSkillDir(sourceBase, 'design-system')
454
+ .then(r => r.filter(s => s.slug === 'design-system'));
455
+ const staticSkills = await scanSourceSkillDir(path.join(sourceBase, 'static'), 'static');
456
+ const dynamicSkills = await scanSourceSkillDir(path.join(sourceBase, 'dynamic'), 'dynamic');
457
+
458
+ // Check active design skill
459
+ let activeDesignSkill = null;
460
+ try {
461
+ const contextPath = path.join(targetDir, '.aioson/context/project.context.md');
462
+ const contextRaw = await fs.readFile(contextPath, 'utf8');
463
+ const match = contextRaw.match(/design_skill:\s*(.+)/);
464
+ if (match) activeDesignSkill = match[1].trim();
465
+ } catch { /* no context */ }
466
+
467
+ // Output
468
+ if (installed.length > 0) {
469
+ logger.log(`Installed skills (${installed.length}):\n`);
470
+ for (const s of installed) {
471
+ logger.log(` ${s.slug} (${s.source})`);
472
+ if (s.description) {
473
+ logger.log(` ${s.description.slice(0, 100)}`);
474
+ }
475
+ logger.log(` ${s.path}/SKILL.md`);
476
+ logger.log('');
477
+ }
478
+ } else {
479
+ logger.log('No installed skills.\n');
480
+ }
481
+
482
+ // Always show source skills summary
483
+ const allSource = [...designSkills, ...staticSkills, ...dynamicSkills];
484
+
485
+ if (designSkills.length > 0) {
486
+ logger.log(`Design skills (${designSkills.length}) — ONE active per project:`);
487
+ for (const s of designSkills) {
488
+ const active = activeDesignSkill === s.slug ? ' [active]' : '';
489
+ logger.log(` ${s.slug}${active}`);
490
+ if (s.description) logger.log(` ${s.description.slice(0, 100)}`);
491
+ }
492
+ logger.log('');
493
+ }
494
+
495
+ if (staticSkills.length > 0) {
496
+ logger.log(`Static skills (${staticSkills.length}) — loaded by framework match:`);
497
+ for (const s of staticSkills) {
498
+ logger.log(` ${s.slug}`);
499
+ if (showAll && s.description) logger.log(` ${s.description.slice(0, 100)}`);
500
+ }
501
+ logger.log('');
502
+ }
503
+
504
+ if (dynamicSkills.length > 0) {
505
+ logger.log(`Dynamic skills (${dynamicSkills.length}) — loaded by task context:`);
506
+ for (const s of dynamicSkills) {
507
+ logger.log(` ${s.slug}`);
508
+ if (showAll && s.description) logger.log(` ${s.description.slice(0, 100)}`);
509
+ }
510
+ logger.log('');
511
+ }
512
+
513
+ if (installed.length === 0 && allSource.length === 0) {
514
+ logger.log('Use `aioson skill:install --slug=<name>` to add a skill.');
515
+ } else {
516
+ logger.log('Source skills are loaded automatically by agents — no installation needed.');
517
+ logger.log('Use --all for full descriptions. Use `aioson skill:install` for third-party skills.');
518
+ }
519
+
520
+ return { ok: true, installed, source: { design: designSkills, static: staticSkills, dynamic: dynamicSkills } };
521
+ }
522
+
523
+ async function runSkillRemove({ args, options = {}, logger, t }) {
524
+ const targetDir = resolveTargetDir(args);
525
+ const slug = options.slug || options.skill;
526
+
527
+ if (!slug) {
528
+ logger.error('Usage: aioson skill:remove --slug=<name>');
529
+ return { ok: false, error: 'Missing --slug' };
530
+ }
531
+
532
+ const skillDir = path.join(targetDir, INSTALLED_SKILLS_DIR, slug);
533
+ if (!(await exists(skillDir))) {
534
+ logger.error(`Skill "${slug}" not found in .aioson/installed-skills/`);
535
+ return { ok: false, error: 'not_found', slug };
536
+ }
537
+
538
+ // Remove from installed-skills
539
+ await fs.rm(skillDir, { recursive: true, force: true });
540
+ logger.log(` Removed .aioson/installed-skills/${slug}/`);
541
+
542
+ // Remove from tool directories
543
+ await removeFromTools(targetDir, slug);
544
+ logger.log(` Removed from .claude/skills/, .cursor/skills/, .windsurf/skills/`);
545
+
546
+ // Update AGENTS.md
547
+ await updateAgentsMdSkills(targetDir);
548
+ logger.log(` AGENTS.md updated`);
549
+
550
+ logger.log(`\nSkill "${slug}" removed.`);
551
+ return { ok: true, slug };
552
+ }
553
+
554
+ module.exports = {
555
+ runSkillInstall,
556
+ runSkillList,
557
+ runSkillRemove
558
+ };