@jaimevalasek/aioson 1.7.2 → 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 (362) hide show
  1. package/CHANGELOG.md +35 -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 +42 -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/cypher.md +252 -0
  143. package/template/.aioson/agents/dev.md +112 -628
  144. package/template/.aioson/agents/deyvin.md +33 -236
  145. package/template/.aioson/agents/discover.md +235 -0
  146. package/template/.aioson/agents/discovery-design-doc.md +17 -252
  147. package/template/.aioson/agents/genome.md +76 -26
  148. package/template/.aioson/agents/manifests/analyst.manifest.json +26 -0
  149. package/template/.aioson/agents/manifests/architect.manifest.json +23 -0
  150. package/template/.aioson/agents/manifests/committer.manifest.json +23 -0
  151. package/template/.aioson/agents/manifests/dev.manifest.json +37 -0
  152. package/template/.aioson/agents/manifests/orchestrator.manifest.json +30 -0
  153. package/template/.aioson/agents/manifests/pentester.manifest.json +39 -0
  154. package/template/.aioson/agents/manifests/pm.manifest.json +26 -0
  155. package/template/.aioson/agents/manifests/product.manifest.json +23 -0
  156. package/template/.aioson/agents/manifests/qa.manifest.json +25 -0
  157. package/template/.aioson/agents/manifests/setup.manifest.json +20 -0
  158. package/template/.aioson/agents/manifests/ux-ui.manifest.json +24 -0
  159. package/template/.aioson/agents/neo.md +5 -7
  160. package/template/.aioson/agents/orache.md +2 -6
  161. package/template/.aioson/agents/orchestrator.md +81 -182
  162. package/template/.aioson/agents/pentester.md +235 -0
  163. package/template/.aioson/agents/pm.md +40 -104
  164. package/template/.aioson/agents/product.md +99 -344
  165. package/template/.aioson/agents/profiler-enricher.md +57 -6
  166. package/template/.aioson/agents/profiler-forge.md +17 -7
  167. package/template/.aioson/agents/profiler-researcher.md +29 -6
  168. package/template/.aioson/agents/qa.md +168 -514
  169. package/template/.aioson/agents/setup.md +52 -278
  170. package/template/.aioson/agents/sheldon.md +122 -754
  171. package/template/.aioson/agents/site-forge.md +111 -1583
  172. package/template/.aioson/agents/squad.md +139 -2010
  173. package/template/.aioson/agents/tester.md +10 -0
  174. package/template/.aioson/agents/ux-ui.md +104 -812
  175. package/template/.aioson/agents/validator.md +69 -0
  176. package/template/.aioson/brains/scripts/query.js +5 -1
  177. package/template/.aioson/config/autonomy-protocol.json +43 -0
  178. package/template/.aioson/config.md +43 -15
  179. package/template/.aioson/constitution.md +36 -33
  180. package/template/.aioson/context/design-doc.md +136 -0
  181. package/template/.aioson/context/project-map.md +57 -0
  182. package/template/.aioson/design-docs/code-reuse.md +48 -0
  183. package/template/.aioson/design-docs/componentization.md +47 -0
  184. package/template/.aioson/design-docs/file-size.md +52 -0
  185. package/template/.aioson/design-docs/folder-structure.md +51 -0
  186. package/template/.aioson/design-docs/naming.md +54 -0
  187. package/template/.aioson/docs/LAYERS.md +12 -2
  188. package/template/.aioson/docs/dev/execution-discipline.md +106 -0
  189. package/template/.aioson/docs/dev/stack-conventions.md +83 -0
  190. package/template/.aioson/docs/deyvin/continuity-recovery.md +57 -0
  191. package/template/.aioson/docs/deyvin/debugging-escalation.md +30 -0
  192. package/template/.aioson/docs/deyvin/pair-execution.md +44 -0
  193. package/template/.aioson/docs/deyvin/runtime-handoffs.md +36 -0
  194. package/template/.aioson/docs/product/conversation-playbook.md +116 -0
  195. package/template/.aioson/docs/product/prd-contract.md +107 -0
  196. package/template/.aioson/docs/product/quality-lens.md +57 -0
  197. package/template/.aioson/docs/product/research-loop.md +65 -0
  198. package/template/.aioson/docs/sheldon/enrichment-paths.md +134 -0
  199. package/template/.aioson/docs/sheldon/quality-lens.md +57 -0
  200. package/template/.aioson/docs/sheldon/research-loop.md +56 -0
  201. package/template/.aioson/docs/sheldon/web-intelligence.md +75 -0
  202. package/template/.aioson/docs/site-forge-build.md +195 -0
  203. package/template/.aioson/docs/site-forge-extraction.md +135 -0
  204. package/template/.aioson/docs/site-forge-qa.md +155 -0
  205. package/template/.aioson/docs/site-forge-recon.md +434 -0
  206. package/template/.aioson/docs/site-forge-transform.md +249 -0
  207. package/template/.aioson/docs/squad/content-output.md +91 -0
  208. package/template/.aioson/docs/squad/creation-flow.md +135 -0
  209. package/template/.aioson/docs/squad/domain-classification.md +117 -0
  210. package/template/.aioson/docs/squad/genome-bindings.md +47 -0
  211. package/template/.aioson/docs/squad/package-contract.md +234 -0
  212. package/template/.aioson/docs/squad/quality-lens.md +56 -0
  213. package/template/.aioson/docs/squad/research-loop.md +59 -0
  214. package/template/.aioson/docs/squad/session-operations.md +117 -0
  215. package/template/.aioson/docs/squad/workflow-quality.md +165 -0
  216. package/template/.aioson/docs/ux-ui/accessibility-audit.md +55 -0
  217. package/template/.aioson/docs/ux-ui/audit-mode.md +86 -0
  218. package/template/.aioson/docs/ux-ui/component-map.md +35 -0
  219. package/template/.aioson/docs/ux-ui/design-execution.md +111 -0
  220. package/template/.aioson/docs/ux-ui/design-gate.md +27 -0
  221. package/template/.aioson/docs/ux-ui/research-mode.md +39 -0
  222. package/template/.aioson/docs/ux-ui/site-delivery.md +156 -0
  223. package/template/.aioson/docs/ux-ui/token-contract.md +57 -0
  224. package/template/.aioson/genomes/copywriting.meta.json +48 -0
  225. package/template/.aioson/git-guard.json +11 -0
  226. package/template/.aioson/mcp/servers.md +0 -1
  227. package/template/.aioson/rules/agent-language-policy.md +93 -0
  228. package/template/.aioson/rules/aioson-context-boundary.md +63 -0
  229. package/template/.aioson/rules/canonical-path-contract.md +47 -0
  230. package/template/.aioson/rules/data-format-convention.md +24 -86
  231. package/template/.aioson/rules/disk-first-artifacts.md +44 -0
  232. package/template/.aioson/rules/output-brevity.md +44 -0
  233. package/template/.aioson/rules/prd-section-ownership.md +49 -0
  234. package/template/.aioson/rules/security-baseline.md +139 -0
  235. package/template/.aioson/rules/spec-level-ownership.md +61 -0
  236. package/template/.aioson/rules/squad-driver-pattern.md +81 -0
  237. package/template/.aioson/schemas/squad-blueprint.schema.json +24 -0
  238. package/template/.aioson/schemas/squad-manifest.schema.json +44 -0
  239. package/template/.aioson/skills/process/aioson-spec-driven/references/pm.md +30 -0
  240. package/template/.aioson/skills/process/secure-tdd/SKILL.md +97 -0
  241. package/template/.aioson/skills/process/secure-tdd/references/nextjs.md +81 -0
  242. package/template/.aioson/skills/process/secure-tdd/references/node-express.md +91 -0
  243. package/template/.aioson/skills/process/secure-tdd/references/planned-stacks.md +33 -0
  244. package/template/.aioson/skills/static/harness-validate/SKILL.md +46 -0
  245. package/template/.aioson/skills/static/web-research-cache.md +3 -0
  246. package/template/.aioson/tasks/squad-create.md +35 -8
  247. package/template/.aioson/tasks/squad-design.md +50 -2
  248. package/template/.aioson/tasks/squad-investigate.md +14 -1
  249. package/template/.claude/commands/aioson/agent/committer.md +5 -0
  250. package/template/.claude/commands/aioson/agent/copywriter.md +5 -0
  251. package/template/.claude/commands/aioson/agent/cypher.md +5 -0
  252. package/template/.claude/commands/aioson/agent/pair.md +5 -0
  253. package/template/.claude/commands/aioson/agent/validator.md +5 -0
  254. package/template/.gemini/commands/aios-analyst.toml +6 -3
  255. package/template/.gemini/commands/aios-architect.toml +7 -6
  256. package/template/.gemini/commands/aios-committer.toml +7 -0
  257. package/template/.gemini/commands/aios-copywriter.toml +7 -0
  258. package/template/.gemini/commands/aios-cypher.toml +7 -0
  259. package/template/.gemini/commands/aios-dev.toml +8 -7
  260. package/template/.gemini/commands/aios-deyvin.toml +6 -5
  261. package/template/.gemini/commands/aios-discovery-design-doc.toml +6 -3
  262. package/template/.gemini/commands/aios-genome.toml +7 -0
  263. package/template/.gemini/commands/aios-neo.toml +5 -3
  264. package/template/.gemini/commands/aios-orache.toml +7 -0
  265. package/template/.gemini/commands/aios-orchestrator.toml +8 -7
  266. package/template/.gemini/commands/aios-pair.toml +6 -5
  267. package/template/.gemini/commands/aios-pm.toml +8 -7
  268. package/template/.gemini/commands/aios-product.toml +5 -3
  269. package/template/.gemini/commands/aios-qa.toml +6 -5
  270. package/template/.gemini/commands/aios-setup.toml +5 -2
  271. package/template/.gemini/commands/aios-sheldon.toml +7 -0
  272. package/template/.gemini/commands/aios-site-forge.toml +7 -0
  273. package/template/.gemini/commands/aios-squad.toml +7 -0
  274. package/template/.gemini/commands/aios-tester.toml +6 -5
  275. package/template/.gemini/commands/aios-ux-ui.toml +8 -7
  276. package/template/.gemini/commands/aios-validator.toml +7 -0
  277. package/template/AGENTS.md +12 -1
  278. package/template/CLAUDE.md +5 -1
  279. package/template/.aioson/locales/en/agents/analyst.md +0 -244
  280. package/template/.aioson/locales/en/agents/architect.md +0 -245
  281. package/template/.aioson/locales/en/agents/dev.md +0 -397
  282. package/template/.aioson/locales/en/agents/deyvin.md +0 -137
  283. package/template/.aioson/locales/en/agents/discovery-design-doc.md +0 -27
  284. package/template/.aioson/locales/en/agents/genome.md +0 -212
  285. package/template/.aioson/locales/en/agents/neo.md +0 -8
  286. package/template/.aioson/locales/en/agents/orache.md +0 -6
  287. package/template/.aioson/locales/en/agents/orchestrator.md +0 -189
  288. package/template/.aioson/locales/en/agents/pair.md +0 -5
  289. package/template/.aioson/locales/en/agents/pm.md +0 -84
  290. package/template/.aioson/locales/en/agents/product.md +0 -378
  291. package/template/.aioson/locales/en/agents/profiler-enricher.md +0 -5
  292. package/template/.aioson/locales/en/agents/profiler-forge.md +0 -5
  293. package/template/.aioson/locales/en/agents/profiler-researcher.md +0 -5
  294. package/template/.aioson/locales/en/agents/qa.md +0 -270
  295. package/template/.aioson/locales/en/agents/setup.md +0 -421
  296. package/template/.aioson/locales/en/agents/sheldon.md +0 -455
  297. package/template/.aioson/locales/en/agents/squad.md +0 -449
  298. package/template/.aioson/locales/en/agents/tester.md +0 -6
  299. package/template/.aioson/locales/en/agents/ux-ui.md +0 -668
  300. package/template/.aioson/locales/es/agents/analyst.md +0 -225
  301. package/template/.aioson/locales/es/agents/architect.md +0 -245
  302. package/template/.aioson/locales/es/agents/dev.md +0 -370
  303. package/template/.aioson/locales/es/agents/deyvin.md +0 -99
  304. package/template/.aioson/locales/es/agents/discovery-design-doc.md +0 -21
  305. package/template/.aioson/locales/es/agents/genome.md +0 -104
  306. package/template/.aioson/locales/es/agents/neo.md +0 -50
  307. package/template/.aioson/locales/es/agents/orache.md +0 -105
  308. package/template/.aioson/locales/es/agents/orchestrator.md +0 -194
  309. package/template/.aioson/locales/es/agents/pair.md +0 -7
  310. package/template/.aioson/locales/es/agents/pm.md +0 -90
  311. package/template/.aioson/locales/es/agents/product.md +0 -372
  312. package/template/.aioson/locales/es/agents/profiler-enricher.md +0 -7
  313. package/template/.aioson/locales/es/agents/profiler-forge.md +0 -7
  314. package/template/.aioson/locales/es/agents/profiler-researcher.md +0 -7
  315. package/template/.aioson/locales/es/agents/qa.md +0 -198
  316. package/template/.aioson/locales/es/agents/setup.md +0 -405
  317. package/template/.aioson/locales/es/agents/sheldon.md +0 -309
  318. package/template/.aioson/locales/es/agents/squad.md +0 -532
  319. package/template/.aioson/locales/es/agents/tester.md +0 -9
  320. package/template/.aioson/locales/es/agents/ux-ui.md +0 -212
  321. package/template/.aioson/locales/fr/agents/analyst.md +0 -225
  322. package/template/.aioson/locales/fr/agents/architect.md +0 -245
  323. package/template/.aioson/locales/fr/agents/dev.md +0 -370
  324. package/template/.aioson/locales/fr/agents/deyvin.md +0 -99
  325. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +0 -21
  326. package/template/.aioson/locales/fr/agents/genome.md +0 -104
  327. package/template/.aioson/locales/fr/agents/neo.md +0 -50
  328. package/template/.aioson/locales/fr/agents/orache.md +0 -106
  329. package/template/.aioson/locales/fr/agents/orchestrator.md +0 -194
  330. package/template/.aioson/locales/fr/agents/pair.md +0 -7
  331. package/template/.aioson/locales/fr/agents/pm.md +0 -90
  332. package/template/.aioson/locales/fr/agents/product.md +0 -372
  333. package/template/.aioson/locales/fr/agents/profiler-enricher.md +0 -7
  334. package/template/.aioson/locales/fr/agents/profiler-forge.md +0 -7
  335. package/template/.aioson/locales/fr/agents/profiler-researcher.md +0 -7
  336. package/template/.aioson/locales/fr/agents/qa.md +0 -198
  337. package/template/.aioson/locales/fr/agents/setup.md +0 -405
  338. package/template/.aioson/locales/fr/agents/sheldon.md +0 -309
  339. package/template/.aioson/locales/fr/agents/squad.md +0 -532
  340. package/template/.aioson/locales/fr/agents/tester.md +0 -9
  341. package/template/.aioson/locales/fr/agents/ux-ui.md +0 -212
  342. package/template/.aioson/locales/pt-BR/agents/analyst.md +0 -319
  343. package/template/.aioson/locales/pt-BR/agents/architect.md +0 -284
  344. package/template/.aioson/locales/pt-BR/agents/dev.md +0 -483
  345. package/template/.aioson/locales/pt-BR/agents/deyvin.md +0 -184
  346. package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +0 -198
  347. package/template/.aioson/locales/pt-BR/agents/genome.md +0 -297
  348. package/template/.aioson/locales/pt-BR/agents/neo.md +0 -208
  349. package/template/.aioson/locales/pt-BR/agents/orache.md +0 -137
  350. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +0 -324
  351. package/template/.aioson/locales/pt-BR/agents/pair.md +0 -5
  352. package/template/.aioson/locales/pt-BR/agents/pm.md +0 -182
  353. package/template/.aioson/locales/pt-BR/agents/product.md +0 -466
  354. package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +0 -5
  355. package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +0 -5
  356. package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +0 -5
  357. package/template/.aioson/locales/pt-BR/agents/qa.md +0 -300
  358. package/template/.aioson/locales/pt-BR/agents/setup.md +0 -533
  359. package/template/.aioson/locales/pt-BR/agents/sheldon.md +0 -323
  360. package/template/.aioson/locales/pt-BR/agents/squad.md +0 -1330
  361. package/template/.aioson/locales/pt-BR/agents/tester.md +0 -449
  362. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +0 -669
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('node:crypto');
4
+
5
+ // ── Extension allowlists ─────────────────────────────────────────────────────
6
+
7
+ const ALLOWED_EXTENSIONS = {
8
+ genome: new Set(['.md', '.json']),
9
+ skill: new Set(['.md', '.json', '.yaml', '.yml', '.txt']),
10
+ squad: new Set(['.md', '.json', '.yaml', '.yml', '.txt'])
11
+ };
12
+
13
+ // ── Size limits ──────────────────────────────────────────────────────────────
14
+
15
+ const MAX_FILE_BYTES = 512 * 1024; // 512 KB per file
16
+ const MAX_PACKAGE_BYTES = 5 * 1024 * 1024; // 5 MB total
17
+
18
+ // ── Malicious pattern detection ──────────────────────────────────────────────
19
+
20
+ /**
21
+ * Patterns that flag a file for review.
22
+ * Each entry: { id, pattern, description }
23
+ * All patterns are applied to raw file content (string).
24
+ */
25
+ const THREAT_PATTERNS = [
26
+ // Shell execution
27
+ { id: 'shell_exec', pattern: /\$\(.*\)|`[^`]{0,200}`/, description: 'shell command substitution' },
28
+ { id: 'curl_pipe', pattern: /curl\s+.*\|\s*(ba)?sh/i, description: 'curl pipe to shell' },
29
+ { id: 'wget_pipe', pattern: /wget\s+.*-O\s*-\s*\|\s*(ba)?sh/i, description: 'wget pipe to shell' },
30
+ { id: 'exec_call', pattern: /\bexec\s*\(/, description: 'exec() call' },
31
+ { id: 'eval_call', pattern: /\beval\s*\(/, description: 'eval() call' },
32
+ { id: 'spawn_call', pattern: /child_process|\.spawn\s*\(|\.execSync\s*\(/, description: 'child_process / spawn' },
33
+
34
+ // Encoded payloads
35
+ { id: 'long_base64', pattern: /[A-Za-z0-9+/]{200,}={0,2}/, description: 'long base64 blob (potential encoded payload)' },
36
+ { id: 'hex_payload', pattern: /\\x[0-9a-fA-F]{2}(\\x[0-9a-fA-F]{2}){15,}/, description: 'hex-encoded payload sequence' },
37
+
38
+ // Network calls inside markdown/config
39
+ { id: 'js_fetch', pattern: /\bfetch\s*\(\s*['"`]https?:\/\//, description: 'fetch() to external URL' },
40
+ { id: 'require_http', pattern: /require\s*\(\s*['"`]https?:\/\//, description: 'require() from HTTP URL' },
41
+ { id: 'dynamic_import', pattern: /import\s*\(\s*['"`]https?:\/\//, description: 'dynamic import from HTTP URL' },
42
+
43
+ // Filesystem destructive ops
44
+ { id: 'rm_rf', pattern: /rm\s+-rf?\s+[/~]/, description: 'rm -rf on root or home' },
45
+ { id: 'mkfs', pattern: /\bmkfs\b|\bdd\s+if=\/dev\//, description: 'mkfs or dd on device' },
46
+
47
+ // Crypto mining markers
48
+ { id: 'miner_pool', pattern: /stratum\+tcp:\/\/|minexmr\.com|xmrig/i, description: 'crypto mining pool reference' },
49
+
50
+ // Exfiltration patterns
51
+ { id: 'env_exfil', pattern: /process\.env\b.*\b(fetch|axios|request)\b/, description: 'env vars sent over network' },
52
+ { id: 'ssh_key_path', pattern: /\.ssh\/id_rsa|\.ssh\/id_ed25519/, description: 'SSH private key path reference' },
53
+
54
+ // Obfuscation
55
+ { id: 'atob_chain', pattern: /atob\s*\(\s*atob/, description: 'double-decoded base64 (obfuscation)' },
56
+ { id: 'charcode_concat', pattern: /String\.fromCharCode\s*\(\s*\d[\d,\s]{30,}\)/, description: 'String.fromCharCode long sequence' }
57
+ ];
58
+
59
+ /**
60
+ * Scan a single file's content for threat patterns.
61
+ * Returns array of { id, description, line } for each match.
62
+ */
63
+ function scanContent(content) {
64
+ const findings = [];
65
+ const lines = content.split('\n');
66
+
67
+ for (const { id, pattern, description } of THREAT_PATTERNS) {
68
+ // Check full content first (for multi-char patterns)
69
+ if (!pattern.test(content)) continue;
70
+
71
+ // Find which line triggered it
72
+ let lineNum = null;
73
+ for (let i = 0; i < lines.length; i++) {
74
+ if (pattern.test(lines[i])) {
75
+ lineNum = i + 1;
76
+ break;
77
+ }
78
+ }
79
+
80
+ findings.push({ id, description, line: lineNum });
81
+ }
82
+
83
+ return findings;
84
+ }
85
+
86
+ // ── Public API ───────────────────────────────────────────────────────────────
87
+
88
+ /**
89
+ * Scan a files map { relPath: content } for security issues.
90
+ *
91
+ * @param {Record<string, string>} files
92
+ * @param {'genome'|'skill'|'squad'} packageType
93
+ * @returns {{ ok: boolean, errors: string[], warnings: string[], hash: string }}
94
+ */
95
+ function scanPackage(files, packageType) {
96
+ const allowedExts = ALLOWED_EXTENSIONS[packageType] ?? ALLOWED_EXTENSIONS.squad;
97
+ const errors = [];
98
+ const warnings = [];
99
+ let totalBytes = 0;
100
+
101
+ for (const [relPath, content] of Object.entries(files)) {
102
+ if (typeof content !== 'string') continue;
103
+
104
+ const ext = relPath.includes('.') ? `.${relPath.split('.').pop().toLowerCase()}` : '';
105
+ const bytes = Buffer.byteLength(content, 'utf8');
106
+ totalBytes += bytes;
107
+
108
+ // Extension check
109
+ if (!allowedExts.has(ext)) {
110
+ errors.push(`Blocked file type: "${relPath}" (extension "${ext}" not allowed for ${packageType} packages)`);
111
+ continue; // don't scan content of blocked files
112
+ }
113
+
114
+ // Per-file size check
115
+ if (bytes > MAX_FILE_BYTES) {
116
+ errors.push(`File too large: "${relPath}" (${(bytes / 1024).toFixed(0)} KB, limit is ${MAX_FILE_BYTES / 1024} KB)`);
117
+ }
118
+
119
+ // Threat patterns
120
+ const findings = scanContent(content);
121
+ for (const finding of findings) {
122
+ const loc = finding.line ? `:${finding.line}` : '';
123
+ warnings.push(`Suspicious pattern in "${relPath}"${loc} — ${finding.description} [${finding.id}]`);
124
+ }
125
+ }
126
+
127
+ // Total package size
128
+ if (totalBytes > MAX_PACKAGE_BYTES) {
129
+ errors.push(`Package too large: ${(totalBytes / 1024 / 1024).toFixed(2)} MB (limit is ${MAX_PACKAGE_BYTES / 1024 / 1024} MB)`);
130
+ }
131
+
132
+ // Deterministic hash of the full package contents
133
+ const hash = hashPackage(files);
134
+
135
+ return { ok: errors.length === 0, errors, warnings, hash, totalBytes };
136
+ }
137
+
138
+ /**
139
+ * Compute a deterministic SHA-256 of the package contents.
140
+ * Files are sorted by path before hashing.
141
+ */
142
+ function hashPackage(files) {
143
+ const h = crypto.createHash('sha256');
144
+ const sortedPaths = Object.keys(files).sort();
145
+ for (const p of sortedPaths) {
146
+ h.update(`\0${p}\0`);
147
+ h.update(files[p] ?? '');
148
+ }
149
+ return h.digest('hex');
150
+ }
151
+
152
+ /**
153
+ * Format scan results for CLI output.
154
+ * Returns lines to log.
155
+ */
156
+ function formatScanReport(scanResult, logger) {
157
+ const lines = [];
158
+
159
+ if (scanResult.errors.length > 0) {
160
+ lines.push('Security scan FAILED:');
161
+ for (const e of scanResult.errors) lines.push(` [ERROR] ${e}`);
162
+ }
163
+
164
+ if (scanResult.warnings.length > 0) {
165
+ lines.push('Security scan warnings:');
166
+ for (const w of scanResult.warnings) lines.push(` [WARN] ${w}`);
167
+ }
168
+
169
+ for (const line of lines) logger.log(line);
170
+ return lines;
171
+ }
172
+
173
+ module.exports = { scanPackage, hashPackage, formatScanReport, ALLOWED_EXTENSIONS, MAX_FILE_BYTES, MAX_PACKAGE_BYTES };
@@ -0,0 +1,130 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Lightweight terminal checkbox UI using raw mode and keypress events.
5
+ * No external dependencies.
6
+ */
7
+
8
+ const readline = require('node:readline');
9
+
10
+ function countVisualLines(text, cols) {
11
+ return text.split('\n').reduce((acc, line) => {
12
+ return acc + Math.max(1, Math.ceil((line.length || 1) / cols));
13
+ }, 0);
14
+ }
15
+
16
+ function render(items, selectedIndex, hint) {
17
+ const lines = items.map((item, index) => {
18
+ const marker = item.checked ? '[x]' : '[ ]';
19
+ const prefix = index === selectedIndex ? '> ' : ' ';
20
+ return `${prefix}${marker} ${item.label}`;
21
+ });
22
+ lines.push('');
23
+ lines.push(hint);
24
+ return lines.join('\n');
25
+ }
26
+
27
+ function promptCheckbox(items, hint = '↑/↓ navegar | Espaço selecionar | Enter confirmar | Esc cancelar | a=todos | n=limpar') {
28
+ return new Promise((resolve) => {
29
+ const state = items.map((label) => ({ label, checked: true }));
30
+ let selectedIndex = 0;
31
+ let renderedLines = 0;
32
+
33
+ const stdin = process.stdin;
34
+ const stdout = process.stdout;
35
+
36
+ const wasRaw = stdin.isRaw;
37
+ if (stdin.setRawMode) {
38
+ stdin.setRawMode(true);
39
+ }
40
+ stdin.resume();
41
+ readline.emitKeypressEvents(stdin);
42
+
43
+ function draw() {
44
+ const cols = stdout.columns || 80;
45
+ if (renderedLines > 0) {
46
+ stdout.write(`\x1B[${renderedLines}A\x1B[J`);
47
+ }
48
+ const output = render(state, selectedIndex, hint);
49
+ renderedLines = countVisualLines(output, cols);
50
+ stdout.write(output + '\n');
51
+ }
52
+
53
+ function cleanup() {
54
+ if (stdin.setRawMode) {
55
+ stdin.setRawMode(wasRaw);
56
+ }
57
+ stdin.pause();
58
+ stdin.removeListener('keypress', onKeypress);
59
+ const cols = stdout.columns || 80;
60
+ if (renderedLines > 0) {
61
+ stdout.write(`\x1B[${renderedLines}A\x1B[J`);
62
+ }
63
+ renderedLines = 0;
64
+ }
65
+
66
+ function confirm() {
67
+ cleanup();
68
+ resolve(state.filter((s) => s.checked).map((s) => s.label));
69
+ }
70
+
71
+ function cancel() {
72
+ cleanup();
73
+ resolve(null);
74
+ }
75
+
76
+ function onKeypress(str, key) {
77
+ if (!key) return;
78
+
79
+ if (key.name === 'c' && key.ctrl) {
80
+ cancel();
81
+ return;
82
+ }
83
+
84
+ if (key.name === 'escape') {
85
+ cancel();
86
+ return;
87
+ }
88
+
89
+ if (key.name === 'return' || key.name === 'enter') {
90
+ confirm();
91
+ return;
92
+ }
93
+
94
+ if (key.name === 'up') {
95
+ selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : state.length - 1;
96
+ draw();
97
+ return;
98
+ }
99
+
100
+ if (key.name === 'down') {
101
+ selectedIndex = selectedIndex < state.length - 1 ? selectedIndex + 1 : 0;
102
+ draw();
103
+ return;
104
+ }
105
+
106
+ if (key.name === 'space') {
107
+ state[selectedIndex].checked = !state[selectedIndex].checked;
108
+ draw();
109
+ return;
110
+ }
111
+
112
+ if (str === 'a' || str === 'A') {
113
+ state.forEach((s) => { s.checked = true; });
114
+ draw();
115
+ return;
116
+ }
117
+
118
+ if (str === 'n' || str === 'N') {
119
+ state.forEach((s) => { s.checked = false; });
120
+ draw();
121
+ return;
122
+ }
123
+ }
124
+
125
+ stdin.on('keypress', onKeypress);
126
+ draw();
127
+ });
128
+ }
129
+
130
+ module.exports = { promptCheckbox };
@@ -0,0 +1,163 @@
1
+ 'use strict';
2
+
3
+ const { spawn } = require('node:child_process');
4
+ const path = require('node:path');
5
+
6
+ async function isTmuxAvailable() {
7
+ return new Promise((resolve) => {
8
+ const child = spawn('which', ['tmux'], { stdio: 'pipe' });
9
+ child.on('close', (code) => resolve(code === 0));
10
+ child.on('error', () => resolve(false));
11
+ });
12
+ }
13
+
14
+ function buildSessionName(targetDir, agentName) {
15
+ const base = targetDir.split(/[\\/]/).pop() || 'aioson';
16
+ const agent = String(agentName || '').replace(/^@/, '');
17
+ const sanitized = `${base}-${agent}`.replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, 50);
18
+ return sanitized;
19
+ }
20
+
21
+ function resolveAiosonBinary() {
22
+ if (process.argv[1]) {
23
+ return path.resolve(process.argv[1]);
24
+ }
25
+ return 'aioson';
26
+ }
27
+
28
+ async function hasSession(sessionName) {
29
+ return new Promise((resolve) => {
30
+ const child = spawn('tmux', ['has-session', '-t', sessionName], { stdio: 'ignore' });
31
+ child.on('close', (code) => resolve(code === 0));
32
+ child.on('error', () => resolve(false));
33
+ });
34
+ }
35
+
36
+ async function killSession(sessionName) {
37
+ return new Promise((resolve) => {
38
+ const kill = spawn('tmux', ['kill-session', '-t', sessionName], { stdio: 'ignore' });
39
+ kill.on('close', () => resolve());
40
+ kill.on('error', () => resolve());
41
+ });
42
+ }
43
+
44
+ async function createTmuxSession(sessionName, targetDir, binaryPath, toolArgs) {
45
+ const args = [
46
+ 'new-session',
47
+ '-d',
48
+ '-s', sessionName,
49
+ '-c', targetDir,
50
+ binaryPath,
51
+ ...toolArgs
52
+ ];
53
+
54
+ return new Promise((resolve, reject) => {
55
+ const child = spawn('tmux', args, { stdio: 'ignore' });
56
+ child.on('error', (err) => reject(err));
57
+ child.on('close', (code) => {
58
+ if (code !== 0) {
59
+ reject(new Error(`tmux new-session exited with code ${code}`));
60
+ } else {
61
+ resolve();
62
+ }
63
+ });
64
+ });
65
+ }
66
+
67
+ async function configureTmuxSession(sessionName) {
68
+ const commands = [
69
+ // Mouse on so scroll works in the main pane; the bottom pane is 1 line
70
+ // and non-interactive, so accidental focus is harmless
71
+ ['set-option', '-t', sessionName, 'mouse', 'on'],
72
+ // Hide tmux status line (we use our own pane)
73
+ ['set-option', '-t', sessionName, 'status', 'off'],
74
+ // Hide pane borders for a clean look
75
+ ['set-option', '-t', sessionName, 'pane-border-status', 'off'],
76
+ // Prevent focus events from shifting to the bottom pane
77
+ ['set-option', '-t', sessionName, 'focus-events', 'off']
78
+ ];
79
+
80
+ for (const cmd of commands) {
81
+ await new Promise((resolve, reject) => {
82
+ const child = spawn('tmux', cmd, { stdio: 'ignore' });
83
+ child.on('error', (err) => reject(err));
84
+ child.on('close', () => resolve());
85
+ });
86
+ }
87
+ }
88
+
89
+ async function createStatusPane(sessionName, targetDir) {
90
+ const aiosonBin = resolveAiosonBinary();
91
+ const safeDir = String(targetDir || '.').replace(/"/g, '\\"');
92
+ const safeBin = String(aiosonBin).replace(/"/g, '\\"');
93
+
94
+ // Command runs directly in the pane (no interactive bash)
95
+ // printTmuxBar writes WITHOUT newline; we clear the line before each refresh
96
+ const cmd = `while true; do printf '\\033[2K\\r'; AIOSON_TMUX_BAR=1 "${safeBin}" live:status "${safeDir}" --format=tmux-bar; sleep 2; done`;
97
+
98
+ return new Promise((resolve, reject) => {
99
+ const split = spawn('tmux', [
100
+ 'split-window',
101
+ '-v',
102
+ '-t', `${sessionName}:0.0`,
103
+ '-c', targetDir,
104
+ '-l', '1',
105
+ cmd
106
+ ], { stdio: 'ignore' });
107
+ split.on('error', (err) => reject(err));
108
+ split.on('close', (code) => {
109
+ if (code !== 0) {
110
+ reject(new Error(`tmux split-window exited with code ${code}`));
111
+ } else {
112
+ resolve();
113
+ }
114
+ });
115
+ });
116
+ }
117
+
118
+ async function focusTopPane(sessionName) {
119
+ return new Promise((resolve, reject) => {
120
+ const focus = spawn('tmux', [
121
+ 'select-pane',
122
+ '-t', `${sessionName}:0.0`
123
+ ], { stdio: 'ignore' });
124
+ focus.on('error', (err) => reject(err));
125
+ focus.on('close', () => resolve());
126
+ });
127
+ }
128
+
129
+ async function attachSession(sessionName) {
130
+ return new Promise((resolve, reject) => {
131
+ const attach = spawn('tmux', ['attach', '-t', sessionName], { stdio: 'inherit' });
132
+ attach.on('error', (err) => reject(err));
133
+ attach.on('close', () => resolve());
134
+ });
135
+ }
136
+
137
+ async function launchTmuxSession(options) {
138
+ const { targetDir, agentName, tool, binaryPath, toolArgs = [] } = options;
139
+ const sessionName = buildSessionName(targetDir, agentName);
140
+
141
+ await killSession(sessionName);
142
+ await createTmuxSession(sessionName, targetDir, binaryPath, toolArgs);
143
+ await configureTmuxSession(sessionName);
144
+ await createStatusPane(sessionName, targetDir);
145
+ await focusTopPane(sessionName);
146
+
147
+ try {
148
+ await attachSession(sessionName);
149
+ } finally {
150
+ await killSession(sessionName);
151
+ }
152
+
153
+ return { ok: true, sessionName };
154
+ }
155
+
156
+ module.exports = {
157
+ isTmuxAvailable,
158
+ launchTmuxSession,
159
+ buildSessionName,
160
+ hasSession,
161
+ attachSession,
162
+ resolveAiosonBinary
163
+ };
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ // Capabilities map for the AI CLIs that AIOSON can spawn via `aioson live:start`.
4
+ // Each CLI persists conversation history in its own per-cwd location, so
5
+ // "continue last conversation" is achieved by passing the right resume flag
6
+ // at spawn time — AIOSON never has to track an internal session ID.
7
+ //
8
+ // Used by:
9
+ // - `aioson live:start --resume[=last|<id>]` to map to the correct argv
10
+ // - `aioson tool:capabilities` to expose this map as JSON to UI clients
11
+ // (e.g. AIOSON Play) so they don't duplicate the lookup.
12
+ //
13
+ // Keep entries minimal and source-of-truth here. Adding a new CLI = one entry.
14
+ const TOOL_CAPS = {
15
+ claude: {
16
+ install_command: 'npm install -g @anthropic-ai/claude-code',
17
+ binary: 'claude',
18
+ supports_resume: true,
19
+ resume_last: ['--continue'],
20
+ supports_session_id: true,
21
+ resume_session_id: ['--resume', '<id>'],
22
+ supports_session_picker: true,
23
+ session_picker: ['--resume'],
24
+ },
25
+ codex: {
26
+ install_command: 'npm install -g @openai/codex',
27
+ binary: 'codex',
28
+ supports_resume: true,
29
+ resume_last: ['resume', '--last'],
30
+ supports_session_id: true,
31
+ resume_session_id: ['resume', '<id>'],
32
+ supports_session_picker: true,
33
+ session_picker: ['resume'],
34
+ },
35
+ opencode: {
36
+ install_command: 'npm install -g opencode-ai',
37
+ binary: 'opencode',
38
+ supports_resume: true,
39
+ resume_last: ['--continue'],
40
+ supports_session_id: true,
41
+ resume_session_id: ['--session', '<id>'],
42
+ supports_session_picker: false,
43
+ session_picker: null,
44
+ },
45
+ gemini: {
46
+ install_command: 'npm install -g @google/gemini-cli',
47
+ binary: 'gemini',
48
+ supports_resume: false,
49
+ resume_last: null,
50
+ supports_session_id: false,
51
+ resume_session_id: null,
52
+ supports_session_picker: false,
53
+ session_picker: null,
54
+ },
55
+ };
56
+
57
+ function getToolCapabilities(tool) {
58
+ const key = String(tool || '').trim().toLowerCase();
59
+ if (!key) return null;
60
+ return TOOL_CAPS[key] || null;
61
+ }
62
+
63
+ function listSupportedTools() {
64
+ return Object.keys(TOOL_CAPS).sort();
65
+ }
66
+
67
+ // Resolve the argv prefix to add to the CLI spawn so it resumes a conversation.
68
+ // `resumeOpt` accepted shapes:
69
+ // - true → resume last
70
+ // - 'last' / 'true' → resume last
71
+ // - '' / undefined / null / false → no resume
72
+ // - any other string → treat as session id
73
+ // Returns [] when the tool doesn't support resume or resumeOpt is falsy.
74
+ function resolveResumeArgs(tool, resumeOpt) {
75
+ if (resumeOpt === undefined || resumeOpt === null || resumeOpt === '' || resumeOpt === false) {
76
+ return [];
77
+ }
78
+ const caps = getToolCapabilities(tool);
79
+ if (!caps || !caps.supports_resume) return [];
80
+
81
+ const wantsLast =
82
+ resumeOpt === true ||
83
+ resumeOpt === 'last' ||
84
+ String(resumeOpt).toLowerCase() === 'true';
85
+
86
+ if (wantsLast) {
87
+ return Array.isArray(caps.resume_last) ? [...caps.resume_last] : [];
88
+ }
89
+
90
+ if (caps.supports_session_id && Array.isArray(caps.resume_session_id)) {
91
+ return caps.resume_session_id.map((part) => (part === '<id>' ? String(resumeOpt) : part));
92
+ }
93
+
94
+ return Array.isArray(caps.resume_last) ? [...caps.resume_last] : [];
95
+ }
96
+
97
+ module.exports = {
98
+ TOOL_CAPS,
99
+ getToolCapabilities,
100
+ listSupportedTools,
101
+ resolveResumeArgs,
102
+ };
package/src/locales.js CHANGED
@@ -3,18 +3,20 @@
3
3
  const fs = require('node:fs/promises');
4
4
  const path = require('node:path');
5
5
  const { AGENT_DEFINITIONS } = require('./constants');
6
+ const { TEMPLATE_DIR } = require('./installer');
6
7
  const { exists, ensureDir } = require('./utils');
8
+ const { normalizeLanguageTag } = require('./context');
7
9
 
8
10
  const SUPPORTED_AGENT_LOCALES = ['en', 'pt-BR', 'es', 'fr'];
9
11
 
10
- function normalizeLanguageTag(value) {
11
- return String(value || '').trim();
12
- }
13
-
14
12
  function localeForPath(value) {
15
13
  return String(value || '').replace(/_/g, '-');
16
14
  }
17
15
 
16
+ function normalizeInteractionLanguage(languageTag, fallback = 'en') {
17
+ return normalizeLanguageTag(languageTag, fallback);
18
+ }
19
+
18
20
  function resolveAgentLocale(languageTag) {
19
21
  const tag = normalizeLanguageTag(languageTag);
20
22
  if (!tag) return 'en';
@@ -43,15 +45,15 @@ function getActiveAgentPath(agentId) {
43
45
  }
44
46
 
45
47
  async function applyAgentLocale(targetDir, locale, options = {}) {
46
- const resolved = resolveAgentLocale(locale);
48
+ const interactionLanguage = normalizeInteractionLanguage(locale || 'en');
47
49
  const dryRun = Boolean(options.dryRun);
48
50
  const copied = [];
49
51
  const missing = [];
50
52
 
51
53
  for (const agent of AGENT_DEFINITIONS) {
52
- const sourceRel = getLocalizedAgentPath(agent.id, resolved);
54
+ const sourceRel = getActiveAgentPath(agent.id);
55
+ const sourceAbs = path.join(TEMPLATE_DIR, sourceRel);
53
56
  const destRel = getActiveAgentPath(agent.id);
54
- const sourceAbs = path.join(targetDir, sourceRel);
55
57
  const destAbs = path.join(targetDir, destRel);
56
58
 
57
59
  if (!(await exists(sourceAbs))) {
@@ -67,7 +69,8 @@ async function applyAgentLocale(targetDir, locale, options = {}) {
67
69
  }
68
70
 
69
71
  return {
70
- locale: resolved,
72
+ locale: interactionLanguage,
73
+ promptLocale: 'en',
71
74
  copied,
72
75
  missing,
73
76
  dryRun
@@ -77,6 +80,7 @@ async function applyAgentLocale(targetDir, locale, options = {}) {
77
80
  module.exports = {
78
81
  SUPPORTED_AGENT_LOCALES,
79
82
  normalizeLanguageTag,
83
+ normalizeInteractionLanguage,
80
84
  resolveAgentLocale,
81
85
  getLocalizedAgentPath,
82
86
  getActiveAgentPath,