@jaimevalasek/aioson 1.7.0 → 1.8.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 (383) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +153 -10
  3. package/docs/en/cli-reference.md +56 -1
  4. package/docs/en/i18n.md +18 -18
  5. package/docs/en/schemas/index.json +10 -0
  6. package/docs/en/schemas/parallel-assign.schema.json +9 -0
  7. package/docs/en/schemas/parallel-doctor.schema.json +36 -0
  8. package/docs/en/schemas/parallel-guard.schema.json +63 -0
  9. package/docs/en/schemas/parallel-merge.schema.json +84 -0
  10. package/docs/en/schemas/parallel-status.schema.json +91 -1
  11. package/docs/integrations/apps-publish-marketplace.md +94 -0
  12. package/docs/pt/README.md +9 -0
  13. package/docs/pt/agentes.md +324 -3
  14. package/docs/pt/clientes-ai.md +7 -3
  15. package/docs/pt/comandos-cli.md +160 -13
  16. package/docs/pt/compress-agents.md +304 -0
  17. package/docs/pt/design-docs-governance.md +59 -0
  18. package/docs/pt/feature-archive.md +191 -0
  19. package/docs/pt/genome-3.0-spec.md +115 -4
  20. package/docs/pt/genome-distribution.md +232 -0
  21. package/docs/pt/inicio-rapido.md +1 -0
  22. package/docs/pt/motor-hardening.md +492 -0
  23. package/docs/pt/runner-system.md +113 -0
  24. package/package.json +2 -1
  25. package/src/agent-manifests.js +66 -0
  26. package/src/agents.js +27 -7
  27. package/src/autonomy-policy.js +139 -0
  28. package/src/brain-query.js +161 -0
  29. package/src/cli.js +1377 -1099
  30. package/src/commands/agents.js +102 -7
  31. package/src/commands/artifact-validate.js +33 -4
  32. package/src/commands/auth.js +272 -0
  33. package/src/commands/brain-query.js +44 -0
  34. package/src/commands/briefing.js +344 -0
  35. package/src/commands/commit-prepare.js +547 -0
  36. package/src/commands/compress-agents.js +416 -0
  37. package/src/commands/context-health.js +4 -2
  38. package/src/commands/context-trim.js +17 -11
  39. package/src/commands/design-hybrid-options.js +3 -3
  40. package/src/commands/devlog-process.js +6 -4
  41. package/src/commands/dossier.js +423 -0
  42. package/src/commands/feature-archive.js +513 -0
  43. package/src/commands/feature-close.js +123 -18
  44. package/src/commands/gate-approve.js +198 -0
  45. package/src/commands/gate-check.js +24 -5
  46. package/src/commands/genome-doctor.js +166 -9
  47. package/src/commands/git-guard.js +170 -0
  48. package/src/commands/harness.js +121 -0
  49. package/src/commands/implementation-plan.js +47 -20
  50. package/src/commands/init.js +6 -2
  51. package/src/commands/install.js +6 -2
  52. package/src/commands/live.js +497 -56
  53. package/src/commands/locale-apply.js +9 -6
  54. package/src/commands/locale-diff.js +11 -112
  55. package/src/commands/mcp-doctor.js +2 -1
  56. package/src/commands/mcp-init.js +4 -10
  57. package/src/commands/memory.js +234 -0
  58. package/src/commands/parallel-assign.js +107 -27
  59. package/src/commands/parallel-doctor.js +416 -3
  60. package/src/commands/parallel-guard.js +241 -0
  61. package/src/commands/parallel-init.js +66 -4
  62. package/src/commands/parallel-merge.js +299 -0
  63. package/src/commands/parallel-status.js +147 -3
  64. package/src/commands/preflight.js +63 -4
  65. package/src/commands/qa-init.js +10 -5
  66. package/src/commands/revision.js +235 -0
  67. package/src/commands/scaffold-complete.js +188 -0
  68. package/src/commands/security-audit.js +275 -0
  69. package/src/commands/security-scan.js +376 -0
  70. package/src/commands/self-implement-loop.js +46 -2
  71. package/src/commands/setup-context.js +11 -10
  72. package/src/commands/squad-agent-create.js +51 -9
  73. package/src/commands/squad-investigate.js +53 -0
  74. package/src/commands/squad-plan.js +33 -1
  75. package/src/commands/squad-scaffold.js +4 -3
  76. package/src/commands/squad-score.js +71 -14
  77. package/src/commands/squad-status.js +22 -1
  78. package/src/commands/squad-validate.js +93 -2
  79. package/src/commands/store-genome.js +304 -0
  80. package/src/commands/store-skill.js +247 -0
  81. package/src/commands/store-squad.js +431 -0
  82. package/src/commands/store-system.js +392 -0
  83. package/src/commands/tool-capabilities.js +63 -0
  84. package/src/commands/update.js +3 -3
  85. package/src/commands/verify-gate.js +40 -0
  86. package/src/commands/workflow-execute.js +644 -155
  87. package/src/commands/workflow-harden.js +231 -0
  88. package/src/commands/workflow-heal.js +136 -0
  89. package/src/commands/workflow-next.js +460 -22
  90. package/src/commands/workflow-status.js +328 -138
  91. package/src/commands/workspace.js +144 -0
  92. package/src/constants.js +55 -75
  93. package/src/context-memory.js +133 -4
  94. package/src/context-writer.js +2 -1
  95. package/src/context.js +32 -2
  96. package/src/doctor.js +46 -6
  97. package/src/dossier/codemap-store.js +267 -0
  98. package/src/dossier/dossier-bootstrap.js +222 -0
  99. package/src/dossier/dossier-compact.js +159 -0
  100. package/src/dossier/lock.js +128 -0
  101. package/src/dossier/revision-store.js +313 -0
  102. package/src/dossier/schema.js +155 -0
  103. package/src/dossier/store.js +400 -0
  104. package/src/execution-gateway.js +3 -0
  105. package/src/friction-scanner.js +202 -0
  106. package/src/genome-schema.js +24 -1
  107. package/src/genomes.js +33 -0
  108. package/src/handoff-contract.js +363 -0
  109. package/src/handoff-validator.js +45 -0
  110. package/src/harness/circuit-breaker.js +135 -0
  111. package/src/i18n/messages/en.js +317 -22
  112. package/src/i18n/messages/es.js +259 -18
  113. package/src/i18n/messages/fr.js +260 -18
  114. package/src/i18n/messages/pt-BR.js +313 -22
  115. package/src/install-profile.js +0 -16
  116. package/src/installer.js +70 -6
  117. package/src/lib/git-commit-guard.js +691 -0
  118. package/src/lib/security/artifact-reader.js +167 -0
  119. package/src/lib/security/exit-codes.js +51 -0
  120. package/src/lib/security/findings-writer.js +176 -0
  121. package/src/lib/security/runtime-events.js +77 -0
  122. package/src/lib/security/secrets-regex.js +115 -0
  123. package/src/lib/store/security-scan.js +173 -0
  124. package/src/lib/terminal-checkbox.js +130 -0
  125. package/src/lib/tmux-launcher.js +163 -0
  126. package/src/lib/tool-capabilities.js +102 -0
  127. package/src/locales.js +12 -8
  128. package/src/parallel-workspace.js +756 -0
  129. package/src/parser.js +8 -1
  130. package/src/path-guard.js +47 -0
  131. package/src/preflight-engine.js +237 -26
  132. package/src/self-healing.js +142 -0
  133. package/src/session-handoff.js +111 -1
  134. package/src/squad/squad-scaffold.js +183 -19
  135. package/src/test-briefing.js +226 -0
  136. package/src/updater.js +1 -1
  137. package/src/utils.js +3 -0
  138. package/src/workflow-gates.js +185 -0
  139. package/template/.aioson/agents/analyst.md +76 -130
  140. package/template/.aioson/agents/architect.md +53 -86
  141. package/template/.aioson/agents/committer.md +161 -0
  142. package/template/.aioson/agents/copywriter.md +463 -0
  143. package/template/.aioson/agents/cypher.md +252 -0
  144. package/template/.aioson/agents/dev.md +112 -600
  145. package/template/.aioson/agents/deyvin.md +33 -235
  146. package/template/.aioson/agents/discover.md +235 -0
  147. package/template/.aioson/agents/discovery-design-doc.md +17 -252
  148. package/template/.aioson/agents/genome.md +76 -26
  149. package/template/.aioson/agents/manifests/analyst.manifest.json +26 -0
  150. package/template/.aioson/agents/manifests/architect.manifest.json +23 -0
  151. package/template/.aioson/agents/manifests/committer.manifest.json +23 -0
  152. package/template/.aioson/agents/manifests/dev.manifest.json +37 -0
  153. package/template/.aioson/agents/manifests/orchestrator.manifest.json +30 -0
  154. package/template/.aioson/agents/manifests/pentester.manifest.json +39 -0
  155. package/template/.aioson/agents/manifests/pm.manifest.json +26 -0
  156. package/template/.aioson/agents/manifests/product.manifest.json +23 -0
  157. package/template/.aioson/agents/manifests/qa.manifest.json +25 -0
  158. package/template/.aioson/agents/manifests/setup.manifest.json +20 -0
  159. package/template/.aioson/agents/manifests/ux-ui.manifest.json +24 -0
  160. package/template/.aioson/agents/neo.md +10 -8
  161. package/template/.aioson/agents/orache.md +2 -6
  162. package/template/.aioson/agents/orchestrator.md +81 -182
  163. package/template/.aioson/agents/pentester.md +235 -0
  164. package/template/.aioson/agents/pm.md +40 -104
  165. package/template/.aioson/agents/product.md +99 -344
  166. package/template/.aioson/agents/profiler-enricher.md +57 -6
  167. package/template/.aioson/agents/profiler-forge.md +17 -7
  168. package/template/.aioson/agents/profiler-researcher.md +29 -6
  169. package/template/.aioson/agents/qa.md +165 -410
  170. package/template/.aioson/agents/setup.md +52 -262
  171. package/template/.aioson/agents/sheldon.md +122 -754
  172. package/template/.aioson/agents/site-forge.md +111 -1583
  173. package/template/.aioson/agents/squad.md +139 -1820
  174. package/template/.aioson/agents/tester.md +10 -0
  175. package/template/.aioson/agents/ux-ui.md +103 -645
  176. package/template/.aioson/agents/validator.md +69 -0
  177. package/template/.aioson/brains/scripts/query.js +5 -1
  178. package/template/.aioson/config/autonomy-protocol.json +43 -0
  179. package/template/.aioson/config.md +43 -15
  180. package/template/.aioson/constitution.md +36 -33
  181. package/template/.aioson/context/design-doc.md +136 -0
  182. package/template/.aioson/context/project-map.md +57 -0
  183. package/template/.aioson/design-docs/code-reuse.md +48 -0
  184. package/template/.aioson/design-docs/componentization.md +47 -0
  185. package/template/.aioson/design-docs/file-size.md +52 -0
  186. package/template/.aioson/design-docs/folder-structure.md +51 -0
  187. package/template/.aioson/design-docs/naming.md +54 -0
  188. package/template/.aioson/docs/LAYERS.md +12 -2
  189. package/template/.aioson/docs/dev/execution-discipline.md +106 -0
  190. package/template/.aioson/docs/dev/stack-conventions.md +83 -0
  191. package/template/.aioson/docs/deyvin/continuity-recovery.md +57 -0
  192. package/template/.aioson/docs/deyvin/debugging-escalation.md +30 -0
  193. package/template/.aioson/docs/deyvin/pair-execution.md +44 -0
  194. package/template/.aioson/docs/deyvin/runtime-handoffs.md +36 -0
  195. package/template/.aioson/docs/product/conversation-playbook.md +116 -0
  196. package/template/.aioson/docs/product/prd-contract.md +107 -0
  197. package/template/.aioson/docs/product/quality-lens.md +57 -0
  198. package/template/.aioson/docs/product/research-loop.md +65 -0
  199. package/template/.aioson/docs/sheldon/enrichment-paths.md +134 -0
  200. package/template/.aioson/docs/sheldon/quality-lens.md +57 -0
  201. package/template/.aioson/docs/sheldon/research-loop.md +56 -0
  202. package/template/.aioson/docs/sheldon/web-intelligence.md +75 -0
  203. package/template/.aioson/docs/site-forge-build.md +195 -0
  204. package/template/.aioson/docs/site-forge-extraction.md +135 -0
  205. package/template/.aioson/docs/site-forge-qa.md +155 -0
  206. package/template/.aioson/docs/site-forge-recon.md +434 -0
  207. package/template/.aioson/docs/site-forge-transform.md +249 -0
  208. package/template/.aioson/docs/squad/content-output.md +91 -0
  209. package/template/.aioson/docs/squad/creation-flow.md +135 -0
  210. package/template/.aioson/docs/squad/domain-classification.md +117 -0
  211. package/template/.aioson/docs/squad/genome-bindings.md +47 -0
  212. package/template/.aioson/docs/squad/package-contract.md +234 -0
  213. package/template/.aioson/docs/squad/quality-lens.md +56 -0
  214. package/template/.aioson/docs/squad/research-loop.md +59 -0
  215. package/template/.aioson/docs/squad/session-operations.md +117 -0
  216. package/template/.aioson/docs/squad/workflow-quality.md +165 -0
  217. package/template/.aioson/docs/ux-ui/accessibility-audit.md +55 -0
  218. package/template/.aioson/docs/ux-ui/audit-mode.md +86 -0
  219. package/template/.aioson/docs/ux-ui/component-map.md +35 -0
  220. package/template/.aioson/docs/ux-ui/design-execution.md +111 -0
  221. package/template/.aioson/docs/ux-ui/design-gate.md +27 -0
  222. package/template/.aioson/docs/ux-ui/research-mode.md +39 -0
  223. package/template/.aioson/docs/ux-ui/site-delivery.md +156 -0
  224. package/template/.aioson/docs/ux-ui/token-contract.md +57 -0
  225. package/template/.aioson/genomes/copywriting.md +204 -0
  226. package/template/.aioson/genomes/copywriting.meta.json +48 -0
  227. package/template/.aioson/git-guard.json +11 -0
  228. package/template/.aioson/mcp/servers.md +0 -1
  229. package/template/.aioson/rules/agent-language-policy.md +93 -0
  230. package/template/.aioson/rules/aioson-context-boundary.md +63 -0
  231. package/template/.aioson/rules/canonical-path-contract.md +47 -0
  232. package/template/.aioson/rules/data-format-convention.md +24 -86
  233. package/template/.aioson/rules/disk-first-artifacts.md +44 -0
  234. package/template/.aioson/rules/output-brevity.md +44 -0
  235. package/template/.aioson/rules/prd-section-ownership.md +49 -0
  236. package/template/.aioson/rules/security-baseline.md +139 -0
  237. package/template/.aioson/rules/spec-level-ownership.md +61 -0
  238. package/template/.aioson/rules/squad-driver-pattern.md +81 -0
  239. package/template/.aioson/schemas/squad-blueprint.schema.json +24 -0
  240. package/template/.aioson/schemas/squad-manifest.schema.json +44 -0
  241. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +2 -0
  242. package/template/.aioson/skills/marketing/references/anti-patterns.md +254 -0
  243. package/template/.aioson/skills/marketing/references/fascinations.md +192 -0
  244. package/template/.aioson/skills/marketing/references/five-acts.md +248 -0
  245. package/template/.aioson/skills/marketing/references/market-intelligence.md +198 -0
  246. package/template/.aioson/skills/marketing/references/offer-structure.md +203 -0
  247. package/template/.aioson/skills/marketing/references/one-belief.md +149 -0
  248. package/template/.aioson/skills/marketing/references/patterns.md +218 -0
  249. package/template/.aioson/skills/marketing/references/pms-research.md +193 -0
  250. package/template/.aioson/skills/marketing/vsl-craft.md +385 -0
  251. package/template/.aioson/skills/process/aioson-spec-driven/references/pm.md +30 -0
  252. package/template/.aioson/skills/process/secure-tdd/SKILL.md +97 -0
  253. package/template/.aioson/skills/process/secure-tdd/references/nextjs.md +81 -0
  254. package/template/.aioson/skills/process/secure-tdd/references/node-express.md +91 -0
  255. package/template/.aioson/skills/process/secure-tdd/references/planned-stacks.md +33 -0
  256. package/template/.aioson/skills/static/harness-validate/SKILL.md +46 -0
  257. package/template/.aioson/skills/static/landing-page-deploy.md +192 -0
  258. package/template/.aioson/skills/static/landing-page-forge.md +730 -0
  259. package/template/.aioson/skills/static/ui-ux-modern.md +1 -0
  260. package/template/.aioson/skills/static/web-research-cache.md +3 -0
  261. package/template/.aioson/tasks/squad-create.md +56 -7
  262. package/template/.aioson/tasks/squad-design.md +80 -2
  263. package/template/.aioson/tasks/squad-investigate.md +14 -1
  264. package/template/.aioson/templates/squads/digital-marketing-agency/template.json +96 -0
  265. package/template/.claude/commands/aioson/agent/committer.md +5 -0
  266. package/template/.claude/commands/aioson/agent/copywriter.md +5 -0
  267. package/template/.claude/commands/aioson/agent/cypher.md +5 -0
  268. package/template/.claude/commands/aioson/agent/pair.md +5 -0
  269. package/template/.claude/commands/aioson/agent/validator.md +5 -0
  270. package/template/.gemini/commands/aios-analyst.toml +6 -3
  271. package/template/.gemini/commands/aios-architect.toml +7 -6
  272. package/template/.gemini/commands/aios-committer.toml +7 -0
  273. package/template/.gemini/commands/aios-copywriter.toml +7 -0
  274. package/template/.gemini/commands/aios-cypher.toml +7 -0
  275. package/template/.gemini/commands/aios-dev.toml +8 -7
  276. package/template/.gemini/commands/aios-deyvin.toml +6 -5
  277. package/template/.gemini/commands/aios-discovery-design-doc.toml +6 -3
  278. package/template/.gemini/commands/aios-genome.toml +7 -0
  279. package/template/.gemini/commands/aios-neo.toml +5 -3
  280. package/template/.gemini/commands/aios-orache.toml +7 -0
  281. package/template/.gemini/commands/aios-orchestrator.toml +8 -7
  282. package/template/.gemini/commands/aios-pair.toml +6 -5
  283. package/template/.gemini/commands/aios-pm.toml +8 -7
  284. package/template/.gemini/commands/aios-product.toml +5 -3
  285. package/template/.gemini/commands/aios-qa.toml +6 -5
  286. package/template/.gemini/commands/aios-setup.toml +5 -2
  287. package/template/.gemini/commands/aios-sheldon.toml +7 -0
  288. package/template/.gemini/commands/aios-site-forge.toml +7 -0
  289. package/template/.gemini/commands/aios-squad.toml +7 -0
  290. package/template/.gemini/commands/aios-tester.toml +6 -5
  291. package/template/.gemini/commands/aios-ux-ui.toml +8 -7
  292. package/template/.gemini/commands/aios-validator.toml +7 -0
  293. package/template/AGENTS.md +12 -1
  294. package/template/CLAUDE.md +6 -1
  295. package/template/.aioson/locales/en/agents/analyst.md +0 -244
  296. package/template/.aioson/locales/en/agents/architect.md +0 -245
  297. package/template/.aioson/locales/en/agents/dev.md +0 -397
  298. package/template/.aioson/locales/en/agents/deyvin.md +0 -137
  299. package/template/.aioson/locales/en/agents/discovery-design-doc.md +0 -27
  300. package/template/.aioson/locales/en/agents/genome.md +0 -212
  301. package/template/.aioson/locales/en/agents/neo.md +0 -8
  302. package/template/.aioson/locales/en/agents/orache.md +0 -6
  303. package/template/.aioson/locales/en/agents/orchestrator.md +0 -189
  304. package/template/.aioson/locales/en/agents/pair.md +0 -5
  305. package/template/.aioson/locales/en/agents/pm.md +0 -84
  306. package/template/.aioson/locales/en/agents/product.md +0 -378
  307. package/template/.aioson/locales/en/agents/profiler-enricher.md +0 -5
  308. package/template/.aioson/locales/en/agents/profiler-forge.md +0 -5
  309. package/template/.aioson/locales/en/agents/profiler-researcher.md +0 -5
  310. package/template/.aioson/locales/en/agents/qa.md +0 -270
  311. package/template/.aioson/locales/en/agents/setup.md +0 -421
  312. package/template/.aioson/locales/en/agents/sheldon.md +0 -455
  313. package/template/.aioson/locales/en/agents/squad.md +0 -449
  314. package/template/.aioson/locales/en/agents/tester.md +0 -6
  315. package/template/.aioson/locales/en/agents/ux-ui.md +0 -668
  316. package/template/.aioson/locales/es/agents/analyst.md +0 -225
  317. package/template/.aioson/locales/es/agents/architect.md +0 -245
  318. package/template/.aioson/locales/es/agents/dev.md +0 -370
  319. package/template/.aioson/locales/es/agents/deyvin.md +0 -99
  320. package/template/.aioson/locales/es/agents/discovery-design-doc.md +0 -21
  321. package/template/.aioson/locales/es/agents/genome.md +0 -104
  322. package/template/.aioson/locales/es/agents/neo.md +0 -50
  323. package/template/.aioson/locales/es/agents/orache.md +0 -105
  324. package/template/.aioson/locales/es/agents/orchestrator.md +0 -194
  325. package/template/.aioson/locales/es/agents/pair.md +0 -7
  326. package/template/.aioson/locales/es/agents/pm.md +0 -90
  327. package/template/.aioson/locales/es/agents/product.md +0 -372
  328. package/template/.aioson/locales/es/agents/profiler-enricher.md +0 -7
  329. package/template/.aioson/locales/es/agents/profiler-forge.md +0 -7
  330. package/template/.aioson/locales/es/agents/profiler-researcher.md +0 -7
  331. package/template/.aioson/locales/es/agents/qa.md +0 -198
  332. package/template/.aioson/locales/es/agents/setup.md +0 -405
  333. package/template/.aioson/locales/es/agents/sheldon.md +0 -309
  334. package/template/.aioson/locales/es/agents/squad.md +0 -532
  335. package/template/.aioson/locales/es/agents/tester.md +0 -9
  336. package/template/.aioson/locales/es/agents/ux-ui.md +0 -212
  337. package/template/.aioson/locales/fr/agents/analyst.md +0 -225
  338. package/template/.aioson/locales/fr/agents/architect.md +0 -245
  339. package/template/.aioson/locales/fr/agents/dev.md +0 -370
  340. package/template/.aioson/locales/fr/agents/deyvin.md +0 -99
  341. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +0 -21
  342. package/template/.aioson/locales/fr/agents/genome.md +0 -104
  343. package/template/.aioson/locales/fr/agents/neo.md +0 -50
  344. package/template/.aioson/locales/fr/agents/orache.md +0 -106
  345. package/template/.aioson/locales/fr/agents/orchestrator.md +0 -194
  346. package/template/.aioson/locales/fr/agents/pair.md +0 -7
  347. package/template/.aioson/locales/fr/agents/pm.md +0 -90
  348. package/template/.aioson/locales/fr/agents/product.md +0 -372
  349. package/template/.aioson/locales/fr/agents/profiler-enricher.md +0 -7
  350. package/template/.aioson/locales/fr/agents/profiler-forge.md +0 -7
  351. package/template/.aioson/locales/fr/agents/profiler-researcher.md +0 -7
  352. package/template/.aioson/locales/fr/agents/qa.md +0 -198
  353. package/template/.aioson/locales/fr/agents/setup.md +0 -405
  354. package/template/.aioson/locales/fr/agents/sheldon.md +0 -309
  355. package/template/.aioson/locales/fr/agents/squad.md +0 -532
  356. package/template/.aioson/locales/fr/agents/tester.md +0 -9
  357. package/template/.aioson/locales/fr/agents/ux-ui.md +0 -212
  358. package/template/.aioson/locales/pt-BR/agents/analyst.md +0 -319
  359. package/template/.aioson/locales/pt-BR/agents/architect.md +0 -284
  360. package/template/.aioson/locales/pt-BR/agents/dev.md +0 -483
  361. package/template/.aioson/locales/pt-BR/agents/deyvin.md +0 -184
  362. package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +0 -198
  363. package/template/.aioson/locales/pt-BR/agents/genome.md +0 -297
  364. package/template/.aioson/locales/pt-BR/agents/neo.md +0 -208
  365. package/template/.aioson/locales/pt-BR/agents/orache.md +0 -137
  366. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +0 -324
  367. package/template/.aioson/locales/pt-BR/agents/pair.md +0 -5
  368. package/template/.aioson/locales/pt-BR/agents/pm.md +0 -182
  369. package/template/.aioson/locales/pt-BR/agents/product.md +0 -466
  370. package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +0 -5
  371. package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +0 -5
  372. package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +0 -5
  373. package/template/.aioson/locales/pt-BR/agents/qa.md +0 -300
  374. package/template/.aioson/locales/pt-BR/agents/setup.md +0 -533
  375. package/template/.aioson/locales/pt-BR/agents/sheldon.md +0 -323
  376. package/template/.aioson/locales/pt-BR/agents/squad.md +0 -1330
  377. package/template/.aioson/locales/pt-BR/agents/tester.md +0 -449
  378. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +0 -669
  379. package/template/.aioson/skills/design-system/components/SKILL.md:Zone.Identifier +0 -0
  380. package/template/.aioson/skills/design-system/dashboards/SKILL.md:Zone.Identifier +0 -0
  381. package/template/.aioson/skills/design-system/foundations/SKILL.md:Zone.Identifier +0 -0
  382. package/template/.aioson/skills/design-system/motion/SKILL.md:Zone.Identifier +0 -0
  383. package/template/.aioson/skills/design-system/patterns/SKILL.md:Zone.Identifier +0 -0
@@ -0,0 +1,304 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { exists } = require('../utils');
6
+ const { readConfig } = require('./config');
7
+ const { readWorkspace, findProjectRoot } = require('./workspace');
8
+ const { scanPackage, formatScanReport } = require('../lib/store/security-scan');
9
+
10
+ const DEFAULT_BASE_URL = 'https://aioson.com';
11
+ const GENOMES_DIR = '.aioson/genomes';
12
+
13
+ function resolveBaseUrl(config) {
14
+ return String(config.aiosonBaseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
15
+ }
16
+
17
+ function requireToken(config, t) {
18
+ const token = config.aiosonToken;
19
+ if (!token) throw new Error(t('store.error_not_authenticated'));
20
+ return token;
21
+ }
22
+
23
+ async function storeGet(url, token) {
24
+ const response = await fetch(url, {
25
+ headers: {
26
+ authorization: `Bearer ${token}`,
27
+ accept: 'application/json'
28
+ },
29
+ signal: AbortSignal.timeout(15000)
30
+ });
31
+ const text = await response.text();
32
+ let parsed = null;
33
+ try { parsed = JSON.parse(text); } catch { /* */ }
34
+ if (!response.ok) {
35
+ const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
36
+ throw new Error(`HTTP ${response.status}: ${detail}`);
37
+ }
38
+ return parsed;
39
+ }
40
+
41
+ async function storePost(url, payload, token) {
42
+ const response = await fetch(url, {
43
+ method: 'POST',
44
+ headers: {
45
+ authorization: `Bearer ${token}`,
46
+ 'content-type': 'application/json',
47
+ accept: 'application/json'
48
+ },
49
+ body: JSON.stringify(payload),
50
+ signal: AbortSignal.timeout(30000)
51
+ });
52
+
53
+ const text = await response.text();
54
+ let parsed = null;
55
+ try { parsed = JSON.parse(text); } catch { /* */ }
56
+
57
+ if (!response.ok) {
58
+ const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
59
+ throw new Error(`HTTP ${response.status}: ${detail}`);
60
+ }
61
+
62
+ return parsed;
63
+ }
64
+
65
+ async function collectRefs(refsDir) {
66
+ const refs = {};
67
+ if (!(await exists(refsDir))) return refs;
68
+ const entries = await fs.readdir(refsDir);
69
+ for (const entry of entries) {
70
+ try {
71
+ refs[entry] = await fs.readFile(path.join(refsDir, entry), 'utf8');
72
+ } catch { /* */ }
73
+ }
74
+ return refs;
75
+ }
76
+
77
+ // ── genome:publish ──────────────────────────────────────────────────────────
78
+
79
+ async function runGenomePublish({ args, options, logger, t }) {
80
+ const config = await readConfig();
81
+ const token = requireToken(config, t);
82
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
83
+ const slug = String(options.slug || '').trim();
84
+ if (!slug) throw new Error(t('store.error_missing_slug'));
85
+
86
+ const genomePath = path.join(projectDir, GENOMES_DIR, `${slug}.md`);
87
+ const metaPath = path.join(projectDir, GENOMES_DIR, `${slug}.meta.json`);
88
+ const refsDir = path.join(projectDir, GENOMES_DIR, `${slug}.refs`);
89
+
90
+ if (!(await exists(genomePath))) {
91
+ throw new Error(t('store.error_genome_not_found', { slug, path: genomePath }));
92
+ }
93
+
94
+ logger.log(t('store.publish_genome_validating'));
95
+ const content = await fs.readFile(genomePath, 'utf8');
96
+
97
+ let meta = {};
98
+ if (await exists(metaPath)) {
99
+ try { meta = JSON.parse(await fs.readFile(metaPath, 'utf8')); } catch { /* */ }
100
+ }
101
+
102
+ const refs = await collectRefs(refsDir);
103
+
104
+ // Security scan
105
+ const allFiles = { [`${slug}.md`]: content };
106
+ if (meta) allFiles[`${slug}.meta.json`] = JSON.stringify(meta);
107
+ for (const [k, v] of Object.entries(refs)) allFiles[`refs/${k}`] = v;
108
+
109
+ const scan = scanPackage(allFiles, 'genome');
110
+ formatScanReport(scan, logger);
111
+ if (!scan.ok) throw new Error(t('store.error_scan_failed'));
112
+ if (scan.warnings.length > 0 && !options.force) {
113
+ throw new Error(t('store.error_scan_warnings', { count: scan.warnings.length }));
114
+ }
115
+
116
+ const ws = await readWorkspace(projectDir);
117
+ const visibility = options.private ? 'private' : 'public';
118
+ const paid = Boolean(options.paid);
119
+
120
+ if (options['dry-run']) {
121
+ logger.log(t('store.publish_dry_run', { type: 'genome', slug, visibility }));
122
+ logger.log(t('store.publish_scan_ok', { hash: scan.hash.slice(0, 12) }));
123
+ return { ok: true, dryRun: true, slug, visibility, paid, hash: scan.hash };
124
+ }
125
+
126
+ logger.log(t('store.publish_scan_ok', { hash: scan.hash.slice(0, 12) }));
127
+ logger.log(t('store.publish_genome_sending'));
128
+ const baseUrl = resolveBaseUrl(config);
129
+ const response = await storePost(`${baseUrl}/api/store/genomes/publish`, {
130
+ kind: 'aioson.store.genome',
131
+ slug,
132
+ content,
133
+ meta,
134
+ refs,
135
+ visibility,
136
+ paid,
137
+ hash: scan.hash,
138
+ workspaceSlug: ws?.slug || null
139
+ }, token);
140
+
141
+ logger.log(t('store.publish_genome_done', { slug, url: `${baseUrl}/store/genomes/${slug}` }));
142
+ return { ok: true, slug, visibility, paid, response };
143
+ }
144
+
145
+ // ── genome:install (store) ──────────────────────────────────────────────────
146
+
147
+ async function runGenomeInstallStore({ args, options, logger, t }) {
148
+ const config = await readConfig();
149
+ const token = requireToken(config, t);
150
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
151
+ const baseUrl = resolveBaseUrl(config);
152
+
153
+ // Accept: --slug=X or positional code/slug
154
+ const ref = String(options.slug || options.code || args[1] || args[0] || '').trim();
155
+ if (!ref) throw new Error(t('store.error_missing_code_or_slug'));
156
+
157
+ const ws = await readWorkspace(projectDir);
158
+ logger.log(t('store.install_genome_fetching', { ref }));
159
+
160
+ const response = await storePost(`${baseUrl}/api/store/genomes/install`, {
161
+ ref,
162
+ workspaceSlug: ws?.slug || null
163
+ }, token);
164
+
165
+ const slug = response.slug;
166
+ if (!slug || !response.content) {
167
+ throw new Error(t('store.error_invalid_response'));
168
+ }
169
+
170
+ const destPath = path.join(projectDir, GENOMES_DIR, `${slug}.md`);
171
+ const metaDestPath = path.join(projectDir, GENOMES_DIR, `${slug}.meta.json`);
172
+
173
+ // Backup existing version if present
174
+ if ((await exists(destPath)) && !options.force) {
175
+ const backupPath = path.join(projectDir, GENOMES_DIR, `${slug}.backup.md`);
176
+ logger.log(t('store.install_backing_up', { path: backupPath }));
177
+ await fs.copyFile(destPath, backupPath);
178
+ }
179
+
180
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
181
+ await fs.writeFile(destPath, response.content, 'utf8');
182
+
183
+ if (response.meta) {
184
+ await fs.writeFile(metaDestPath, `${JSON.stringify(response.meta, null, 2)}\n`, 'utf8');
185
+ }
186
+
187
+ // Write refs if present
188
+ if (response.refs && typeof response.refs === 'object') {
189
+ const refsDir = path.join(projectDir, GENOMES_DIR, `${slug}.refs`);
190
+ await fs.mkdir(refsDir, { recursive: true });
191
+ for (const [name, content] of Object.entries(response.refs)) {
192
+ await fs.writeFile(path.join(refsDir, name), content, 'utf8');
193
+ }
194
+ }
195
+
196
+ logger.log(t('store.install_genome_done', { slug, path: destPath }));
197
+ return { ok: true, slug, path: destPath };
198
+ }
199
+
200
+ // ── genome:install (user-facing alias for genome:install:store) ─────────────
201
+
202
+ async function runGenomeInstall({ args, options, logger, t }) {
203
+ // Accept: aioson genome:install <code-or-slug> or --slug=X or --code=X
204
+ const ref = String(options.slug || options.code || args[0] || '').trim();
205
+ if (!ref) throw new Error(t('store.error_missing_code_or_slug'));
206
+ return runGenomeInstallStore({ args, options: { ...options, slug: ref }, logger, t });
207
+ }
208
+
209
+ // ── genome:list ─────────────────────────────────────────────────────────────
210
+
211
+ async function runGenomeList({ args, options, logger, t }) {
212
+ // --remote: list published genomes on aioson.com
213
+ if (options.remote) {
214
+ const config = await readConfig();
215
+ const token = requireToken(config, t);
216
+ const baseUrl = resolveBaseUrl(config);
217
+ logger.log(t('store.list_remote_fetching', { type: 'genomes' }));
218
+ const response = await storeGet(`${baseUrl}/api/store/genomes`, token);
219
+ const genomes = response.genomes || [];
220
+ if (genomes.length === 0) {
221
+ logger.log(t('store.list_remote_empty', { type: 'genomes' }));
222
+ } else {
223
+ logger.log(t('store.list_remote_header', { count: genomes.length, type: 'genomes' }));
224
+ for (const g of genomes) {
225
+ logger.log(t('store.list_remote_item', { slug: g.slug, name: g.name || g.slug, visibility: g.visibility || '?' }));
226
+ }
227
+ }
228
+ return { ok: true, genomes, remote: true };
229
+ }
230
+
231
+ // local list
232
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
233
+ const genomesDir = path.join(projectDir, GENOMES_DIR);
234
+
235
+ if (!(await exists(genomesDir))) {
236
+ logger.log(t('store.list_genome_empty'));
237
+ return { ok: true, genomes: [] };
238
+ }
239
+
240
+ const entries = await fs.readdir(genomesDir);
241
+ const genomes = [];
242
+
243
+ for (const entry of entries) {
244
+ if (!entry.endsWith('.md') || entry.endsWith('.backup.md')) continue;
245
+ const slug = entry.replace(/\.md$/, '');
246
+ const metaPath = path.join(genomesDir, `${slug}.meta.json`);
247
+ let meta = {};
248
+ try {
249
+ if (await exists(metaPath)) {
250
+ meta = JSON.parse(await fs.readFile(metaPath, 'utf8'));
251
+ }
252
+ } catch { /* */ }
253
+ genomes.push({ slug, version: meta.version || null, name: meta.name || slug });
254
+ }
255
+
256
+ if (genomes.length === 0) {
257
+ logger.log(t('store.list_genome_empty'));
258
+ } else {
259
+ logger.log(t('store.list_genome_header', { count: genomes.length }));
260
+ for (const g of genomes) {
261
+ const ver = g.version ? ` (v${g.version})` : '';
262
+ logger.log(t('store.list_genome_item', { slug: g.slug, name: g.name, version: ver }));
263
+ }
264
+ }
265
+
266
+ return { ok: true, genomes };
267
+ }
268
+
269
+ // ── genome:remove ────────────────────────────────────────────────────────────
270
+
271
+ async function runGenomeRemove({ args, options, logger, t }) {
272
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
273
+ const slug = String(options.slug || args[0] || '').trim();
274
+ if (!slug) throw new Error(t('store.error_missing_slug'));
275
+
276
+ const genomesDir = path.join(projectDir, GENOMES_DIR);
277
+ const genomePath = path.join(genomesDir, `${slug}.md`);
278
+ const metaPath = path.join(genomesDir, `${slug}.meta.json`);
279
+ const refsDir = path.join(genomesDir, `${slug}.refs`);
280
+
281
+ if (!(await exists(genomePath))) {
282
+ throw new Error(t('store.error_genome_not_found', { slug, path: genomePath }));
283
+ }
284
+
285
+ if (!options.force) {
286
+ // Backup before removing
287
+ const backupPath = path.join(genomesDir, `${slug}.backup.md`);
288
+ await fs.copyFile(genomePath, backupPath);
289
+ logger.log(t('store.install_backing_up', { path: backupPath }));
290
+ }
291
+
292
+ await fs.unlink(genomePath);
293
+ if (await exists(metaPath)) await fs.unlink(metaPath);
294
+ if (await exists(refsDir)) {
295
+ const refs = await fs.readdir(refsDir);
296
+ for (const r of refs) await fs.unlink(path.join(refsDir, r));
297
+ await fs.rmdir(refsDir);
298
+ }
299
+
300
+ logger.log(t('store.remove_genome_done', { slug }));
301
+ return { ok: true, slug };
302
+ }
303
+
304
+ module.exports = { runGenomePublish, runGenomeInstallStore, runGenomeInstall, runGenomeList, runGenomeRemove };
@@ -0,0 +1,247 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs/promises');
4
+ const path = require('node:path');
5
+ const { exists } = require('../utils');
6
+ const { readConfig } = require('./config');
7
+ const { readWorkspace, findProjectRoot } = require('./workspace');
8
+ const { scanPackage, formatScanReport } = require('../lib/store/security-scan');
9
+
10
+ const DEFAULT_BASE_URL = 'https://aioson.com';
11
+ const SKILLS_DIRS = ['.aioson/skills', '.aioson/installed-skills'];
12
+
13
+ function resolveBaseUrl(config) {
14
+ return String(config.aiosonBaseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
15
+ }
16
+
17
+ function requireToken(config, t) {
18
+ const token = config.aiosonToken;
19
+ if (!token) throw new Error(t('store.error_not_authenticated'));
20
+ return token;
21
+ }
22
+
23
+ async function storeGet(url, token) {
24
+ const response = await fetch(url, {
25
+ headers: { authorization: `Bearer ${token}`, accept: 'application/json' },
26
+ signal: AbortSignal.timeout(15000)
27
+ });
28
+ const text = await response.text();
29
+ let parsed = null;
30
+ try { parsed = JSON.parse(text); } catch { /* */ }
31
+ if (!response.ok) {
32
+ const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
33
+ throw new Error(`HTTP ${response.status}: ${detail}`);
34
+ }
35
+ return parsed;
36
+ }
37
+
38
+ async function storePost(url, payload, token) {
39
+ const response = await fetch(url, {
40
+ method: 'POST',
41
+ headers: {
42
+ authorization: `Bearer ${token}`,
43
+ 'content-type': 'application/json',
44
+ accept: 'application/json'
45
+ },
46
+ body: JSON.stringify(payload),
47
+ signal: AbortSignal.timeout(30000)
48
+ });
49
+
50
+ const text = await response.text();
51
+ let parsed = null;
52
+ try { parsed = JSON.parse(text); } catch { /* */ }
53
+
54
+ if (!response.ok) {
55
+ const detail = (parsed && parsed.error) ? String(parsed.error) : `${response.status} ${response.statusText}`;
56
+ throw new Error(`HTTP ${response.status}: ${detail}`);
57
+ }
58
+
59
+ return parsed;
60
+ }
61
+
62
+ /**
63
+ * Collect all files in a skill directory recursively.
64
+ * Returns { relativePath: fileContent } for text files.
65
+ */
66
+ async function collectSkillFiles(skillDir) {
67
+ const files = {};
68
+
69
+ async function walk(dir, base) {
70
+ const entries = await fs.readdir(dir, { withFileTypes: true });
71
+ for (const entry of entries) {
72
+ const fullPath = path.join(dir, entry.name);
73
+ const relPath = base ? `${base}/${entry.name}` : entry.name;
74
+ if (entry.isDirectory()) {
75
+ await walk(fullPath, relPath);
76
+ } else {
77
+ try {
78
+ files[relPath] = await fs.readFile(fullPath, 'utf8');
79
+ } catch { /* binary files skipped */ }
80
+ }
81
+ }
82
+ }
83
+
84
+ await walk(skillDir, '');
85
+ return files;
86
+ }
87
+
88
+ async function findSkillDir(projectDir, slug) {
89
+ for (const base of SKILLS_DIRS) {
90
+ const skillDir = path.join(projectDir, base, slug);
91
+ if (await exists(path.join(skillDir, 'SKILL.md'))) {
92
+ return skillDir;
93
+ }
94
+ }
95
+ return null;
96
+ }
97
+
98
+ // ── skill:publish ───────────────────────────────────────────────────────────
99
+
100
+ async function runSkillPublish({ args, options, logger, t }) {
101
+ const config = await readConfig();
102
+ const token = requireToken(config, t);
103
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
104
+ const slug = String(options.slug || '').trim();
105
+ if (!slug) throw new Error(t('store.error_missing_slug'));
106
+
107
+ const skillDir = await findSkillDir(projectDir, slug);
108
+ if (!skillDir) {
109
+ throw new Error(t('store.error_skill_not_found', { slug }));
110
+ }
111
+
112
+ logger.log(t('store.publish_skill_collecting'));
113
+ const files = await collectSkillFiles(skillDir);
114
+ const fileCount = Object.keys(files).length;
115
+
116
+ if (!files['SKILL.md']) {
117
+ throw new Error(t('store.error_skill_missing_skillmd', { slug }));
118
+ }
119
+
120
+ // Security scan
121
+ const scan = scanPackage(files, 'skill');
122
+ formatScanReport(scan, logger);
123
+ if (!scan.ok) throw new Error(t('store.error_scan_failed'));
124
+ if (scan.warnings.length > 0 && !options.force) {
125
+ throw new Error(t('store.error_scan_warnings', { count: scan.warnings.length }));
126
+ }
127
+
128
+ const ws = await readWorkspace(projectDir);
129
+ const visibility = options.private ? 'private' : 'public';
130
+ const paid = Boolean(options.paid);
131
+
132
+ if (options['dry-run']) {
133
+ logger.log(t('store.publish_dry_run', { type: 'skill', slug, visibility }));
134
+ logger.log(t('store.publish_skill_files', { count: fileCount }));
135
+ logger.log(t('store.publish_scan_ok', { hash: scan.hash.slice(0, 12) }));
136
+ return { ok: true, dryRun: true, slug, visibility, paid, fileCount, hash: scan.hash };
137
+ }
138
+
139
+ logger.log(t('store.publish_scan_ok', { hash: scan.hash.slice(0, 12) }));
140
+ logger.log(t('store.publish_skill_sending', { count: fileCount }));
141
+ const baseUrl = resolveBaseUrl(config);
142
+ const response = await storePost(`${baseUrl}/api/store/skills/publish`, {
143
+ kind: 'aioson.store.skill',
144
+ slug,
145
+ files,
146
+ visibility,
147
+ paid,
148
+ hash: scan.hash,
149
+ workspaceSlug: ws?.slug || null
150
+ }, token);
151
+
152
+ logger.log(t('store.publish_skill_done', { slug, url: `${baseUrl}/store/skills/${slug}` }));
153
+ return { ok: true, slug, visibility, paid, fileCount, response };
154
+ }
155
+
156
+ // ── skill:install:store ─────────────────────────────────────────────────────
157
+
158
+ async function runSkillInstallStore({ args, options, logger, t }) {
159
+ const config = await readConfig();
160
+ const token = requireToken(config, t);
161
+ const projectDir = await findProjectRoot(path.resolve(process.cwd(), args[0] || '.'));
162
+ const baseUrl = resolveBaseUrl(config);
163
+
164
+ const ref = String(options.slug || options.code || args[1] || args[0] || '').trim();
165
+ if (!ref) throw new Error(t('store.error_missing_code_or_slug'));
166
+
167
+ logger.log(t('store.install_skill_fetching', { ref }));
168
+ const response = await storePost(`${baseUrl}/api/store/skills/install`, { ref }, token);
169
+
170
+ const slug = response.slug;
171
+ if (!slug || !response.files || typeof response.files !== 'object') {
172
+ throw new Error(t('store.error_invalid_response'));
173
+ }
174
+
175
+ // Install-side preview and scan
176
+ const publisher = response.publisher || 'unknown';
177
+ const version = response.version || '?';
178
+ const serverHash = response.hash || null;
179
+ const trusted = Boolean(response.trusted);
180
+ const downloads = response.downloads != null ? response.downloads : null;
181
+ const rating = response.rating != null ? `${Number(response.rating).toFixed(1)}/5` : null;
182
+
183
+ logger.log(t('store.install_preview_header', { slug, publisher, version }));
184
+ if (trusted) logger.log(t('store.install_preview_trusted'));
185
+ else logger.log(t('store.install_preview_unverified'));
186
+ if (downloads != null) logger.log(t('store.install_preview_downloads', { count: downloads }));
187
+ if (rating) logger.log(t('store.install_preview_rating', { rating }));
188
+ if (serverHash) logger.log(t('store.install_preview_hash', { hash: serverHash.slice(0, 12) }));
189
+
190
+ // Scan files received from server before writing
191
+ const stringFiles = Object.fromEntries(
192
+ Object.entries(response.files).filter(([, v]) => typeof v === 'string')
193
+ );
194
+ const scan = scanPackage(stringFiles, 'skill');
195
+ formatScanReport(scan, logger);
196
+ if (!scan.ok) throw new Error(t('store.error_install_scan_failed', { slug }));
197
+
198
+ // Verify hash integrity if server sent one
199
+ if (serverHash && scan.hash !== serverHash) {
200
+ throw new Error(t('store.error_hash_mismatch', { slug }));
201
+ }
202
+
203
+ if (options.inspect) {
204
+ logger.log(t('store.install_inspect_files', { count: Object.keys(stringFiles).length }));
205
+ for (const f of Object.keys(stringFiles).sort()) logger.log(` ${f}`);
206
+ logger.log(t('store.install_inspect_hint'));
207
+ return { ok: true, slug, inspect: true, files: Object.keys(stringFiles) };
208
+ }
209
+
210
+ if (!trusted && !options.force) {
211
+ logger.log(t('store.install_unverified_hint', { slug }));
212
+ }
213
+
214
+ const destDir = path.join(projectDir, '.aioson', 'installed-skills', slug);
215
+ await fs.mkdir(destDir, { recursive: true });
216
+
217
+ for (const [relPath, content] of Object.entries(stringFiles)) {
218
+ const filePath = path.join(destDir, relPath);
219
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
220
+ await fs.writeFile(filePath, content, 'utf8');
221
+ }
222
+
223
+ logger.log(t('store.install_skill_done', { slug, path: destDir }));
224
+ return { ok: true, slug, path: destDir };
225
+ }
226
+
227
+ // ── skill:list --remote ──────────────────────────────────────────────────────
228
+
229
+ async function runSkillListRemote({ args, options, logger, t }) {
230
+ const config = await readConfig();
231
+ const token = requireToken(config, t);
232
+ const baseUrl = resolveBaseUrl(config);
233
+ logger.log(t('store.list_remote_fetching', { type: 'skills' }));
234
+ const response = await storeGet(`${baseUrl}/api/store/skills`, token);
235
+ const skills = response.skills || [];
236
+ if (skills.length === 0) {
237
+ logger.log(t('store.list_remote_empty', { type: 'skills' }));
238
+ } else {
239
+ logger.log(t('store.list_remote_header', { count: skills.length, type: 'skills' }));
240
+ for (const s of skills) {
241
+ logger.log(t('store.list_remote_item', { slug: s.slug, name: s.title || s.slug, visibility: s.visibility || '?' }));
242
+ }
243
+ }
244
+ return { ok: true, skills, remote: true };
245
+ }
246
+
247
+ module.exports = { runSkillPublish, runSkillInstallStore, runSkillListRemote };