jarvis-ai-framework 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/AGENTS.md +22 -122
  2. package/agents/AGENTS.md +20 -24
  3. package/agents/README.md +25 -129
  4. package/agents/engineering/data/eng.data-engineer.agent.md +12 -35
  5. package/agents/engineering/eng.agent.md +18 -30
  6. package/agents/engineering/eng.bug-hunter.md +9 -12
  7. package/agents/engineering/eng.dev-code-reviewer.md +5 -1
  8. package/agents/engineering/eng.docs-writer.md +3 -3
  9. package/agents/engineering/eng.frontend.agent.md +13 -8
  10. package/agents/engineering/eng.rpa.agent.md +5 -13
  11. package/agents/engineering/eng.ux-designer.agent.md +4 -0
  12. package/agents/engineering/qa/eng.qa.quality-champion-task-agent.md +4 -0
  13. package/agents/engineering/qa/eng.qa.quality-strategist.md +13 -8
  14. package/agents/engineering/qa/eng.qa.test-architect.md +16 -15
  15. package/agents/engineering/qa/eng.qa.test-planner.md +22 -17
  16. package/agents/engineering/qa/eng.qa.testing-engineer.md +99 -15
  17. package/agents/product/prod.discovery-interviewer.md +22 -3
  18. package/agents/product/prod.pm-checker.md +4 -0
  19. package/bin/README.md +142 -0
  20. package/bin/commands/docs-publish.js +105 -141
  21. package/bin/commands/docs-sync.js +66 -104
  22. package/bin/commands/info.js +7 -27
  23. package/bin/commands/init.js +23 -51
  24. package/bin/commands/install-rtk.js +9 -3
  25. package/bin/commands/list.js +5 -18
  26. package/bin/commands/map.js +58 -0
  27. package/bin/commands/qa-signoff.js +58 -55
  28. package/bin/commands/tokens.js +90 -0
  29. package/bin/commands/whoami.js +30 -26
  30. package/bin/jarvis.js +9 -153
  31. package/bin/lib/auth/session.js +20 -20
  32. package/bin/lib/cli/program.js +219 -0
  33. package/bin/lib/cli/shared-options.js +29 -0
  34. package/bin/lib/config/constants.js +70 -2
  35. package/bin/lib/config/ide-config.js +4 -8
  36. package/bin/lib/core/profile-filter.js +116 -0
  37. package/bin/lib/core/scanner.js +5 -31
  38. package/bin/lib/core/sync-engine.js +21 -14
  39. package/bin/lib/core/token-report.js +100 -0
  40. package/bin/lib/docs/fetch-file.js +39 -0
  41. package/bin/lib/docs/publish-file.js +194 -0
  42. package/bin/lib/docs/redis-cache.js +49 -0
  43. package/bin/lib/docs/validate-frontmatter.js +9 -39
  44. package/bin/lib/env-loader.js +11 -34
  45. package/bin/lib/flow-map/index.js +65 -0
  46. package/bin/lib/flow-map/parse.js +223 -0
  47. package/bin/lib/flow-map/render.js +89 -0
  48. package/bin/lib/flow-map/tree.js +248 -0
  49. package/bin/lib/tasks/comment.js +40 -35
  50. package/bin/lib/utils/frontmatter.js +57 -0
  51. package/bin/lib/utils/git-parser.js +4 -6
  52. package/bin/lib/utils/npmrc-parser.js +6 -13
  53. package/bin/lib/utils/paths.js +2 -4
  54. package/bin/lib/utils/ui.js +3 -9
  55. package/bin/lib/vcs/api.js +25 -41
  56. package/bin/lib/vcs/create-issue.js +49 -33
  57. package/bin/lib/vcs/create-merge.js +47 -31
  58. package/bin/lib/vcs/fetch-raw.js +35 -23
  59. package/members.md +1 -1
  60. package/package.json +15 -4
  61. package/rules/AGENTS.md +18 -7
  62. package/rules/engineering/eng-rules.md +3 -13
  63. package/rules/engineering/eng-security-rules.md +19 -18
  64. package/rules/engineering/eng.bump-rules.md +3 -2
  65. package/rules/engineering/eng.docs-scraping-rules.md +4 -4
  66. package/rules/engineering/eng.integrations-rules.md +3 -7
  67. package/rules/engineering/eng.skills-rules.md +1 -5
  68. package/rules/engineering/eng.specializations-rules.md +18 -8
  69. package/rules/engineering/frontend/eng.frontend-rules.md +1 -4
  70. package/rules/engineering/qa/eng.qa.cypress-standards-rules.md +1 -1
  71. package/rules/engineering/rpa/eng.rpa-rules.md +4 -9
  72. package/rules/product/README.md +1 -0
  73. package/rules/product/prod-rules.md +1 -4
  74. package/rules/product/prod.spec-rules.md +0 -4
  75. package/rules/rtk-rules.md +0 -1
  76. package/{rules → rules-on-demand}/engineering/eng.breakdown-subtasks-rules.md +0 -4
  77. package/{rules → rules-on-demand}/engineering/eng.plan-rules.md +0 -4
  78. package/{rules → rules-on-demand}/engineering/eng.pr-rules.md +0 -4
  79. package/{rules → rules-on-demand}/engineering/eng.pre-pr-rules.md +0 -4
  80. package/{rules → rules-on-demand}/engineering/eng.start-rules.md +0 -4
  81. package/{rules → rules-on-demand}/engineering/eng.tech-spec-rules.md +1 -2
  82. package/{rules → rules-on-demand}/engineering/eng.work-rules.md +0 -4
  83. package/skills/AGENTS.md +69 -106
  84. package/skills/SKILLS-ROADMAP.md +47 -132
  85. package/skills/eng-ai/SKILL.md +270 -0
  86. package/skills/eng-ai/references/1-fundamentos-ml.md +24 -0
  87. package/skills/eng-ai/references/10-arquitetura-solucoes-ia.md +24 -0
  88. package/skills/eng-ai/references/11-governanca-ia.md +24 -0
  89. package/skills/eng-ai/references/12-seguranca-ia-responsavel.md +25 -0
  90. package/skills/eng-ai/references/2-matematica-estatistica.md +24 -0
  91. package/skills/eng-ai/references/3-dados-para-ia.md +24 -0
  92. package/skills/eng-ai/references/4-deep-learning-fundacionais.md +24 -0
  93. package/skills/eng-ai/references/5-llms-chatbots-agentes-rag.md +25 -0
  94. package/skills/eng-ai/references/6-avaliacao-experimentacao.md +24 -0
  95. package/skills/eng-ai/references/7-engenharia-sistemas-ia.md +24 -0
  96. package/skills/eng-ai/references/8-mlops-plataforma.md +24 -0
  97. package/skills/eng-ai/references/9-produto-ia.md +24 -0
  98. package/skills/eng-ai/references/especializacoes.md +17 -0
  99. package/skills/eng-automation/SKILL.md +290 -0
  100. package/skills/eng-automation/references/1-fundamentos-automacao.md +25 -0
  101. package/skills/eng-automation/references/10-ingestao-dados.md +25 -0
  102. package/skills/eng-automation/references/11-captcha-antibot.md +25 -0
  103. package/skills/eng-automation/references/12-limites-taxa-sessoes.md +25 -0
  104. package/skills/eng-automation/references/13-agendamento-orquestracao.md +24 -0
  105. package/skills/eng-automation/references/14-retentativa-erros.md +25 -0
  106. package/skills/eng-automation/references/15-autenticacao-credenciais.md +24 -0
  107. package/skills/eng-automation/references/16-observabilidade-confiabilidade.md +24 -0
  108. package/skills/eng-automation/references/2-aquisicao-dados.md +25 -0
  109. package/skills/eng-automation/references/3-automacao-navegador.md +24 -0
  110. package/skills/eng-automation/references/4-scraping-crawling.md +25 -0
  111. package/skills/eng-automation/references/5-apis-rest-graphql-soap.md +26 -0
  112. package/skills/eng-automation/references/6-webhooks-integracao.md +25 -0
  113. package/skills/eng-automation/references/7-rpa.md +25 -0
  114. package/skills/eng-automation/references/8-extracao-estruturada.md +25 -0
  115. package/skills/eng-automation/references/9-extracao-documentos.md +25 -0
  116. package/skills/eng-automation/references/especializacoes.md +18 -0
  117. package/skills/eng-backend/SKILL.md +6 -0
  118. package/skills/eng-backend-arch-c4/SKILL.md +10 -4
  119. package/skills/eng-backend-microservices-trace/SKILL.md +6 -0
  120. package/skills/eng-backend-nestjs/SKILL.md +17 -462
  121. package/skills/eng-backend-nestjs/references/1-arquitetura-modulos.md +54 -0
  122. package/skills/eng-backend-nestjs/references/2-guards-autenticacao.md +118 -0
  123. package/skills/eng-backend-nestjs/references/3-interceptors-pipes-filters.md +113 -0
  124. package/skills/eng-backend-nestjs/references/4-config-logging.md +61 -0
  125. package/skills/eng-backend-nestjs/references/5-testes.md +83 -0
  126. package/skills/eng-backend-nestjs/references/6-problemas-comuns.md +53 -0
  127. package/skills/eng-backend-rabbitmq/SKILL.md +15 -298
  128. package/skills/eng-backend-rabbitmq/references/1-referencia-endpoints.md +28 -0
  129. package/skills/eng-backend-rabbitmq/references/2-codigo-consumer-producer.md +90 -0
  130. package/skills/eng-backend-rabbitmq/references/3-arquiteturas-comuns.md +101 -0
  131. package/skills/eng-backend-rabbitmq/references/4-troubleshooting.md +93 -0
  132. package/skills/eng-data/SKILL.md +271 -0
  133. package/skills/eng-data/references/1-fundamentos-dados.md +24 -0
  134. package/skills/eng-data/references/10-ciencia-dados.md +24 -0
  135. package/skills/eng-data/references/11-dataops-plataforma.md +24 -0
  136. package/skills/eng-data/references/12-seguranca-privacidade.md +24 -0
  137. package/skills/eng-data/references/2-modelagem-dados.md +24 -0
  138. package/skills/eng-data/references/3-bancos-dados.md +24 -0
  139. package/skills/eng-data/references/4-arquitetura-dados.md +24 -0
  140. package/skills/eng-data/references/5-pipelines-integracao.md +24 -0
  141. package/skills/eng-data/references/6-qualidade-dados.md +24 -0
  142. package/skills/eng-data/references/7-governanca-metadados.md +24 -0
  143. package/skills/eng-data/references/8-estatistica-analise.md +24 -0
  144. package/skills/eng-data/references/9-analytics-bi.md +24 -0
  145. package/skills/eng-data/references/especializacoes.md +20 -0
  146. package/skills/eng-frontend/SKILL.md +18 -5
  147. package/skills/eng-frontend/references/13-design-system.md +48 -0
  148. package/skills/eng-frontend/references/14-microfrontend.md +46 -0
  149. package/skills/eng-global-docs-write/SKILL.md +10 -5
  150. package/skills/eng-global-pr/SKILL.md +7 -1
  151. package/skills/eng-global-task-comment/SKILL.md +8 -2
  152. package/skills/eng-platform/SKILL.md +331 -0
  153. package/skills/eng-platform/references/1-fundamentos-sistemas.md +23 -0
  154. package/skills/eng-platform/references/10-resiliencia-arquitetura.md +24 -0
  155. package/skills/eng-platform/references/11-plataforma-devex.md +24 -0
  156. package/skills/eng-platform/references/12-finops-custos.md +24 -0
  157. package/skills/eng-platform/references/13-seguranca-fundamentos.md +26 -0
  158. package/skills/eng-platform/references/14-profiling-performance.md +23 -0
  159. package/skills/eng-platform/references/15-testes-carga-chaos.md +23 -0
  160. package/skills/eng-platform/references/16-cache-multicamada.md +22 -0
  161. package/skills/eng-platform/references/2-redes.md +23 -0
  162. package/skills/eng-platform/references/3-cloud.md +24 -0
  163. package/skills/eng-platform/references/4-iac-automacao.md +24 -0
  164. package/skills/eng-platform/references/5-containers-orquestracao.md +25 -0
  165. package/skills/eng-platform/references/6-cicd-entrega.md +24 -0
  166. package/skills/eng-platform/references/7-observabilidade.md +24 -0
  167. package/skills/eng-platform/references/8-confiabilidade-sre.md +24 -0
  168. package/skills/eng-platform/references/9-seguranca-infra.md +26 -0
  169. package/skills/eng-platform/references/especializacoes.md +34 -0
  170. package/skills/eng-qa/SKILL.md +283 -0
  171. package/skills/eng-qa/references/1-fundamentos-qualidade.md +25 -0
  172. package/skills/eng-qa/references/10-confiabilidade.md +25 -0
  173. package/skills/eng-qa/references/11-seguranca.md +24 -0
  174. package/skills/eng-qa/references/12-acessibilidade.md +24 -0
  175. package/skills/eng-qa/references/13-dados-testes.md +24 -0
  176. package/skills/eng-qa/references/14-gestao-testes-defeitos.md +25 -0
  177. package/skills/eng-qa/references/15-arquitetura-qa.md +25 -0
  178. package/skills/eng-qa/references/2-estrategia-planejamento.md +25 -0
  179. package/skills/eng-qa/references/3-design-testes.md +25 -0
  180. package/skills/eng-qa/references/4-manual-exploratorio.md +24 -0
  181. package/skills/eng-qa/references/5-automacao-testes.md +25 -0
  182. package/skills/eng-qa/references/6-api-integracao.md +25 -0
  183. package/skills/eng-qa/references/7-contrato.md +24 -0
  184. package/skills/eng-qa/references/8-interface-compat-mobile.md +24 -0
  185. package/skills/eng-qa/references/9-performance.md +24 -0
  186. package/skills/eng-qa/references/especializacoes.md +29 -0
  187. package/skills/eng-qa-planner/SKILL.md +264 -0
  188. package/skills/jarvis-context-detect/SKILL.md +7 -1
  189. package/skills/jarvis-context-detect/assets/context-profile-template.md +1 -1
  190. package/skills/jarvis-create-specialization/SKILL.md +14 -0
  191. package/skills/jarvis-docs-central/README.md +31 -28
  192. package/skills/jarvis-docs-central/SKILL.md +11 -5
  193. package/skills/jarvis-docs-index/SKILL.md +10 -2
  194. package/skills/jarvis-evolution-architect/SKILL.md +6 -0
  195. package/skills/jarvis-init/SKILL.md +22 -15
  196. package/skills/jarvis-init/assets/passo-adicionar-stacks.md +47 -18
  197. package/skills/jarvis-list-specializations/SKILL.md +36 -17
  198. package/skills/jarvis-report-issue/SKILL.md +7 -1
  199. package/skills/product-roadmap-report/SKILL.md +8 -0
  200. package/skills/product-specs/SKILL.md +9 -0
  201. package/skills/product-specs-update/SKILL.md +6 -0
  202. package/taxonomy.md +16 -28
  203. package/templates/AGENTS.md +2 -0
  204. package/templates/ENV-template.md +10 -2
  205. package/templates/engineering/qa/qa.sprint-plan-template.md +1 -1
  206. package/templates/engineering/tech-spec-delivery-template.md +179 -0
  207. package/workflows/AGENTS.md +14 -2
  208. package/workflows/README.md +8 -16
  209. package/workflows/all-tools.md +7 -1
  210. package/workflows/engineering/data/data.contract.md +8 -0
  211. package/workflows/engineering/data/data.new-pipeline.md +15 -4
  212. package/workflows/engineering/eng.breakdown-subtasks.md +9 -0
  213. package/workflows/engineering/eng.bug-audit.md +10 -13
  214. package/workflows/engineering/eng.build-tech-spec.md +17 -146
  215. package/workflows/engineering/eng.create-ard-from-code.md +8 -0
  216. package/workflows/engineering/eng.create-ard.md +8 -0
  217. package/workflows/engineering/eng.create-rfc.md +7 -0
  218. package/workflows/engineering/eng.debug.md +5 -21
  219. package/workflows/engineering/eng.docs.md +9 -0
  220. package/workflows/engineering/eng.light-arch.md +7 -0
  221. package/workflows/engineering/eng.plan.md +15 -2
  222. package/workflows/engineering/eng.pr.md +24 -30
  223. package/workflows/engineering/eng.pre-pr.md +33 -15
  224. package/workflows/engineering/eng.review.md +18 -11
  225. package/workflows/engineering/eng.rpa.robot.md +17 -7
  226. package/workflows/engineering/eng.start.md +33 -12
  227. package/workflows/engineering/eng.work.md +25 -17
  228. package/workflows/engineering/frontend/eng.frontend-component.md +7 -0
  229. package/workflows/engineering/frontend/eng.frontend-perf-audit.md +8 -0
  230. package/workflows/engineering/frontend/eng.frontend-review.md +8 -0
  231. package/workflows/engineering/qa/eng.qa-refinement-entry.md +7 -0
  232. package/workflows/engineering/qa/eng.qa-release-signoff.md +6 -0
  233. package/workflows/engineering/qa/eng.qa-sprint-planning.md +7 -1
  234. package/workflows/product/prod.roadmap.preview.md +9 -0
  235. package/workflows/product/prod.spec.ard.md +97 -0
  236. package/workflows/product/prod.spec.breakdown.md +10 -0
  237. package/workflows/product/prod.spec.clarify.md +8 -2
  238. package/workflows/product/prod.spec.discovery.md +11 -1
  239. package/workflows/product/prod.spec.epic.md +8 -0
  240. package/workflows/product/prod.spec.frd.md +7 -0
  241. package/workflows/product/prod.spec.issue.md +6 -0
  242. package/workflows/product/prod.spec.md +15 -1
  243. package/workflows/product/prod.spec.prd.md +7 -0
  244. package/workflows/taxonomy.md +58 -6
  245. package/workflows/warm-up.md +47 -60
  246. package/agents/engineering/eng.cybersecurity.agent.md +0 -488
  247. package/agents/engineering/qa/eng.qa.cypress-specialist.md +0 -109
  248. package/bin/lib/docs/fetch-file.sh +0 -41
  249. package/bin/lib/docs/publish-file.sh +0 -284
  250. package/rules/engineering/eng.downstream-flow-rules.md +0 -297
  251. package/rules/engineering/qa/eng.qa.exploratory-session-rules.md +0 -137
  252. package/rules/engineering/qa/eng.qa.quality-gate-scoring-rules.md +0 -181
  253. package/rules/engineering/qa/eng.qa.tech-spec-validation-criteria-rules.md +0 -120
  254. package/skills/eng-ai-engineer/SKILL.md +0 -297
  255. package/skills/eng-data-bi/SKILL.md +0 -200
  256. package/skills/eng-data-debug/SKILL.md +0 -308
  257. package/skills/eng-data-engineer/SKILL.md +0 -257
  258. package/skills/eng-data-onboard/SKILL.md +0 -311
  259. package/skills/eng-data-orchestrator/SKILL.md +0 -427
  260. package/skills/eng-devops-performance-engineer/SKILL.md +0 -313
  261. package/skills/eng-frontend-design-system/SKILL.md +0 -621
  262. package/skills/eng-frontend-microfrontend/SKILL.md +0 -604
  263. package/skills/eng-global-browser-extension-builder/SKILL.md +0 -386
  264. package/skills/eng-global-jira-comment/SKILL.md +0 -21
  265. package/skills/eng-qa-a11y-audit/SKILL.md +0 -270
  266. package/skills/eng-qa-bug-report/SKILL.md +0 -1089
  267. package/skills/eng-qa-bug-report/TASK_MANAGERS.md +0 -138
  268. package/skills/eng-qa-cypress-e2e/SKILL.md +0 -178
  269. package/skills/eng-qa-dev-guide/SKILL.md +0 -165
  270. package/skills/eng-qa-e2e/SKILL.md +0 -401
  271. package/skills/eng-qa-e2e-spec-writer/SKILL.md +0 -323
  272. package/skills/eng-qa-exploratory/SKILL.md +0 -189
  273. package/skills/eng-qa-gate/SKILL.md +0 -371
  274. package/skills/eng-qa-gate/assets/checklist-validacao.md +0 -291
  275. package/skills/eng-qa-graphql-contract/SKILL.md +0 -257
  276. package/skills/eng-qa-quality-report/SKILL.md +0 -413
  277. package/skills/eng-qa-test-plan/SKILL.md +0 -467
  278. package/skills/eng-qa-testsprite/SKILL.md +0 -326
  279. package/skills/eng-qa-testsprite/references/testsprite-mcp.md +0 -224
  280. package/skills/eng-qa-unit-test/SKILL.md +0 -472
  281. package/skills/eng-scraper/SKILL.md +0 -684
  282. package/skills/eng-scraper-robot-builder/SKILL.md +0 -371
  283. package/skills/eng-security-cybersecurity/SKILL.md +0 -646
  284. package/skills/eng-security-patch/SKILL.md +0 -382
  285. package/skills/eng-security-threat-model/SKILL.md +0 -165
  286. package/skills/eng-security-triage/SKILL.md +0 -270
  287. package/templates/engineering/qa/eng.qa.quality-gate-examples-template.md +0 -311
  288. package/templates/engineering/qa/eng.qa.quality-gate-report-template.md +0 -249
  289. package/templates/engineering/qa/qa.cypress-test-template.md +0 -172
  290. package/templates/engineering/qa/qa.exploratory-session-template.md +0 -148
  291. package/templates/engineering/qa/qa.quality-report-template.md +0 -130
  292. package/workflows/engineering/eng.security-audit.md +0 -312
  293. package/workflows/engineering/eng.security-incident.md +0 -275
  294. package/workflows/engineering/eng.security-pipeline.md +0 -210
  295. package/workflows/engineering/eng.security-review.md +0 -235
  296. package/workflows/engineering/qa/eng.qa-dev-quality-guide.md +0 -51
  297. package/workflows/engineering/qa/eng.qa-e2e-test-generation.md +0 -51
  298. package/workflows/engineering/qa/eng.qa-exploratory-session.md +0 -60
  299. package/workflows/engineering/qa/eng.qa-quality-gate-validation.md +0 -202
  300. package/workflows/engineering/qa/eng.qa-quality-report.md +0 -78
  301. /package/skills/{eng-qa-test-plan → eng-qa-planner}/assets/test-coverage-template.md +0 -0
  302. /package/skills/{eng-qa-test-plan → eng-qa-planner}/assets/test-patterns.md +0 -0
  303. /package/templates/{CDD aplicado a Prompts.md → cdd-aplicado-a-prompts.md} +0 -0
@@ -0,0 +1,219 @@
1
+ /**
2
+ * @fileoverview Monta o `program` do commander — único lugar que precisa mudar
3
+ * para adicionar, remover ou alterar um comando do CLI `jarvis`.
4
+ *
5
+ * Os arquivos de `bin/commands/*.js` continuam puros: cada um exporta uma
6
+ * função `async (flags) => {...}` sem saber nada sobre commander. Este módulo
7
+ * só traduz as opções do commander (camelCase: `--env-file` -> `envFile`)
8
+ * para o formato antigo que essas funções já esperam (`flags["env-file"]`,
9
+ * `flags._` para positionals) — ver `architecture.md` da sessão `eng/72`,
10
+ * Decisão 3.3.
11
+ * @module cli/program
12
+ */
13
+
14
+ import { readFileSync } from "node:fs";
15
+ import { dirname, join } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+ import { Command } from "commander";
18
+
19
+ import { init } from "../../commands/init.js";
20
+ import { list } from "../../commands/list.js";
21
+ import { info } from "../../commands/info.js";
22
+ import { whoami } from "../../commands/whoami.js";
23
+ import { docsSync } from "../../commands/docs-sync.js";
24
+ import { docsPublish } from "../../commands/docs-publish.js";
25
+ import { qaSignoff } from "../../commands/qa-signoff.js";
26
+ import { installRtk } from "../../commands/install-rtk.js";
27
+ import { tokens } from "../../commands/tokens.js";
28
+ import { map } from "../../commands/map.js";
29
+ import { runCreateMerge } from "../vcs/create-merge.js";
30
+ import { runCreateIssue } from "../vcs/create-issue.js";
31
+ import { runFetchRaw } from "../vcs/fetch-raw.js";
32
+ import { runComment } from "../tasks/comment.js";
33
+ import { fetchFile } from "../docs/fetch-file.js";
34
+ import { formatIDEsList } from "../config/ide-config.js";
35
+ import { showBanner } from "../utils/ui.js";
36
+ import { withEnvOptions, withLogOptions } from "./shared-options.js";
37
+
38
+ const __dirname = dirname(fileURLToPath(import.meta.url));
39
+
40
+ function getVersion() {
41
+ const packageJson = JSON.parse(readFileSync(join(__dirname, "../../../package.json"), "utf-8"));
42
+ return packageJson.version;
43
+ }
44
+
45
+ /**
46
+ * Remonta as opções do commander (camelCase) no formato antigo de `flags`
47
+ * que `bin/commands/*.js` espera. `extra` (positionals, `logout: true`, etc.)
48
+ * é aplicado por último e sempre vence.
49
+ * @param {Record<string, unknown>} options
50
+ * @param {Record<string, unknown>} [extra]
51
+ */
52
+ function toLegacyFlags(options, extra = {}) {
53
+ const { envFile, maxAge, ...rest } = options;
54
+ const flags = { ...rest };
55
+ if (envFile !== undefined) flags["env-file"] = envFile;
56
+ if (maxAge !== undefined) flags["max-age"] = maxAge;
57
+ return { ...flags, ...extra };
58
+ }
59
+
60
+ /**
61
+ * `parent.command(name)` + `allowUnknownOption()` + `allowExcessArguments()`.
62
+ * O commander não propaga essas duas configurações do pai para os
63
+ * subcomandos — precisa repetir em cada um para manter a mesma
64
+ * permissividade do parser manual antigo, que nunca validava flag nem
65
+ * contava argumentos (ver `architecture.md` da sessão `eng/72`, Decisão 3.4).
66
+ * @param {Command} parent
67
+ * @param {string} name
68
+ */
69
+ function cmd(parent, name) {
70
+ return parent.command(name).allowUnknownOption().allowExcessArguments();
71
+ }
72
+
73
+ /** @returns {Command} */
74
+ export function buildProgram() {
75
+ const program = new Command("jarvis")
76
+ .description("Framework Jarvis para desenvolvimento assistido por IA")
77
+ .version(getVersion(), "-v, --version", "Versão instalada")
78
+ .allowUnknownOption() // o parser antigo nunca validava flags — mantém a mesma permissividade
79
+ .allowExcessArguments()
80
+ .showHelpAfterError(true);
81
+
82
+ program.addHelpText("beforeAll", () => {
83
+ showBanner();
84
+ return "";
85
+ });
86
+ program.addHelpText("after", () => `\nIDEs Suportadas:\n ${formatIDEsList()}\n`);
87
+
88
+ const initCmd = cmd(program, "init")
89
+ .description("Bootstrap do framework no workspace")
90
+ .option("--ide <ide>", "IDE a configurar (pula o menu interativo)")
91
+ .option("--force", "Sobrescreve a instalação existente sem perguntar");
92
+ withLogOptions(initCmd).action((options) => init(toLegacyFlags(options)));
93
+
94
+ cmd(program, "list")
95
+ .alias("ls")
96
+ .description("Listar agents, skills & workflows")
97
+ .argument("[type]", "Filtra por tipo: agent, skill ou workflow")
98
+ .option("--type <type>", "Mesmo filtro que o positional acima")
99
+ .action((type, options) => list(toLegacyFlags(options, { _: [type].filter(Boolean) })));
100
+
101
+ cmd(program, "info")
102
+ .description("Detalhes de um prompt")
103
+ .argument("[target]", "Ex: agent/eng.agent, skill/eng-backend")
104
+ .action((target) => info(target));
105
+
106
+ const whoamiCmd = cmd(program, "whoami").description("Exibir identidade (ENV.md / git / SO)");
107
+ withEnvOptions(withLogOptions(whoamiCmd)).action((options) => whoami(toLegacyFlags(options)));
108
+
109
+ const logoutCmd = cmd(program, "logout").description("Remover auth.json legado");
110
+ withLogOptions(logoutCmd).action((options) => whoami(toLegacyFlags(options, { logout: true })));
111
+
112
+ const docs = cmd(program, "docs").description("Sincronizar ou publicar documentação");
113
+
114
+ const docsSyncCmd = cmd(docs, "sync").description(
115
+ "Sincronizar docs do central-docs (usado por /warm-up)"
116
+ );
117
+ withEnvOptions(withLogOptions(docsSyncCmd)).action((options) => docsSync(toLegacyFlags(options)));
118
+
119
+ cmd(docs, "fetch")
120
+ .description(
121
+ "Buscar um arquivo do central-docs, com cache Redis best-effort (lê CENTRAL_DOCS_REPO do ambiente)"
122
+ )
123
+ .argument("<file-path>", "Path do arquivo dentro do repo central-docs")
124
+ .argument("[ref]", "Branch/ref", "main")
125
+ .action(async (filePath, ref) => {
126
+ try {
127
+ const content = await fetchFile(filePath, ref);
128
+ process.stdout.write(content);
129
+ } catch (error) {
130
+ console.error(error.message);
131
+ process.exit(error.code === 404 ? 2 : 1);
132
+ }
133
+ });
134
+
135
+ const docsPublishCmd = cmd(docs, "publish")
136
+ .description("Publicar documento no central-docs (branch + MR/PR)")
137
+ .option("--file <path>", "Caminho do arquivo local")
138
+ .option("--tipo <tipo>", "prd|frd|ard|rfc|swagger|qa-report")
139
+ .option("--feature <slug>", "Slug da feature (kebab-case)")
140
+ .option("--squad <squad>", "Override do SQUAD do ENV.md")
141
+ .option("--workspace <workspace>", "Override do WORKSPACE do ENV.md");
142
+ withEnvOptions(withLogOptions(docsPublishCmd)).action((options) =>
143
+ docsPublish(toLegacyFlags(options))
144
+ );
145
+
146
+ const installRtkCmd = cmd(program, "install-rtk").description(
147
+ "Instalar RTK (token killer — economia 60-90% em tokens de shell)"
148
+ );
149
+ withLogOptions(installRtkCmd).action((options) => installRtk(toLegacyFlags(options)));
150
+
151
+ const qaSignoffCmd = cmd(program, "qa-signoff")
152
+ .description("Verificar sign-off QA válido para a branch atual (usado pelo CI)")
153
+ .option("--branch <branch>", "Branch a verificar (padrão: lido do git)")
154
+ .option("--max-age <horas>", "Validade máxima em horas (padrão: 24)");
155
+ withEnvOptions(qaSignoffCmd).action((options) => qaSignoff(toLegacyFlags(options)));
156
+
157
+ cmd(program, "tokens")
158
+ .description("Estimar o que carrega no início da sessão")
159
+ .option("--hub <hub>")
160
+ .option("--position <position>")
161
+ .option("--area <area>")
162
+ .option("--squad <squad>")
163
+ .option("--rtk", "Força RTK ligado (padrão: lido do ENV.md)")
164
+ .option("--json", "Saída em JSON")
165
+ .option("--ide <ide>")
166
+ .option("--env-file <path>")
167
+ .action((options) => tokens(toLegacyFlags(options)));
168
+
169
+ cmd(program, "map")
170
+ .description("Mapa de chamadas de um workflow, skill ou agente")
171
+ .argument("[name]", "Nome do workflow, skill ou agente")
172
+ .option("--depth <n>", "Profundidade máxima")
173
+ .option("--reverse", "Mostra quem chama, em vez do que é chamado")
174
+ .action((name, options) => map(toLegacyFlags(options, { _: [name].filter(Boolean) })));
175
+
176
+ const vcs = cmd(program, "vcs").description("Adapters de Git host (GitLab/GitHub/Bitbucket)");
177
+
178
+ cmd(vcs, "create-merge")
179
+ .description("Abrir um MR/PR")
180
+ .option("--source <branch>")
181
+ .option("--target <branch>")
182
+ .option("--title <titulo>")
183
+ .option("--body-file <path>")
184
+ .option("--repo <url>", "Padrão: git remote get-url origin")
185
+ .action((options) =>
186
+ runCreateMerge({
187
+ source: options.source,
188
+ target: options.target,
189
+ title: options.title,
190
+ bodyFile: options.bodyFile,
191
+ repo: options.repo,
192
+ })
193
+ );
194
+
195
+ cmd(vcs, "create-issue")
196
+ .description("Abrir uma issue")
197
+ .option("--repo <url-ou-path>")
198
+ .option("--title <titulo>")
199
+ .option("--body-file <path>")
200
+ .action((options) =>
201
+ runCreateIssue({ repo: options.repo, title: options.title, bodyFile: options.bodyFile })
202
+ );
203
+
204
+ cmd(vcs, "fetch-raw")
205
+ .description("Buscar o conteúdo bruto de um arquivo no central-docs (lê CENTRAL_DOCS_REPO)")
206
+ .argument("[file-path]")
207
+ .argument("[ref]", "Branch/ref", "main")
208
+ .action((filePath, ref) => runFetchRaw(filePath, ref));
209
+
210
+ const tasks = cmd(program, "tasks").description("Adapters de task manager");
211
+
212
+ cmd(tasks, "comment")
213
+ .description("Comentar num card (Jira/Linear/GitHub/Asana — lê TASK_MANAGER do ENV.md)")
214
+ .argument("[card-key]")
215
+ .argument("[message...]", "Texto do comentário (pode ter espaços)")
216
+ .action((cardKey, messageParts) => runComment(cardKey, messageParts.join(" ")));
217
+
218
+ return program;
219
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @fileoverview Opções do commander repetidas entre vários comandos — evita
3
+ * reescrever `.option(...)` em cada registro de `program.js`.
4
+ * @module cli/shared-options
5
+ */
6
+
7
+ /**
8
+ * `--ide`/`--env-file`, usados por todo comando que resolve o ENV.md
9
+ * (via `env-loader.js#resolveEnvPath`).
10
+ * @param {import("commander").Command} cmd
11
+ * @returns {import("commander").Command}
12
+ */
13
+ export function withEnvOptions(cmd) {
14
+ return cmd
15
+ .option("--ide <ide>", "IDE alvo (ex: claude, windsurf, cursor)")
16
+ .option("--env-file <path>", "Path explícito do ENV.md");
17
+ }
18
+
19
+ /**
20
+ * `-q/--quiet`, `-v/--verbose`, `--silent` — lidos por `logger.js#configureFromFlags`.
21
+ * @param {import("commander").Command} cmd
22
+ * @returns {import("commander").Command}
23
+ */
24
+ export function withLogOptions(cmd) {
25
+ return cmd
26
+ .option("-q, --quiet", "Só mostra erros")
27
+ .option("-v, --verbose", "Mostra detalhes extras (nível debug)")
28
+ .option("--silent", "Não mostra nada, nem erros");
29
+ }
@@ -19,6 +19,7 @@ export const SYNC_DIRS = Object.freeze([
19
19
  "workflows",
20
20
  "templates",
21
21
  "rules",
22
+ "rules-on-demand",
22
23
  "scripts",
23
24
  ]);
24
25
 
@@ -67,6 +68,74 @@ export const OBSOLETE_PATHS = Object.freeze([
67
68
  "skills/report-issue",
68
69
  "skills/docs-central",
69
70
  "skills/docs-index",
71
+ // eng.downstream-flow-rules (removida): processo de board de um time, acoplado a Jira
72
+ "rules/engineering/eng.downstream-flow-rules.md",
73
+ // rules de uma etapa só: saíram de rules/ (carregada no início) para rules-on-demand/ (lida pelo workflow)
74
+ "rules/engineering/eng.start-rules.md",
75
+ "rules/engineering/eng.plan-rules.md",
76
+ "rules/engineering/eng.work-rules.md",
77
+ "rules/engineering/eng.pr-rules.md",
78
+ "rules/engineering/eng.pre-pr-rules.md",
79
+ "rules/engineering/eng.tech-spec-rules.md",
80
+ "rules/engineering/eng.breakdown-subtasks-rules.md",
81
+ // Consolidação de QA (removidos): área QA ficou só com eng-qa (base) e eng-qa-planner
82
+ "skills/eng-qa-test-plan",
83
+ "skills/eng-qa-gate",
84
+ "skills/eng-qa-cypress-e2e",
85
+ "skills/eng-qa-dev-guide",
86
+ "skills/eng-qa-exploratory",
87
+ "skills/eng-qa-bug-report",
88
+ "skills/eng-qa-quality-report",
89
+ "skills/eng-qa-testsprite",
90
+ "skills/eng-qa-a11y-audit",
91
+ "skills/eng-qa-graphql-contract",
92
+ "skills/eng-qa-e2e-spec-writer",
93
+ "skills/eng-qa-e2e",
94
+ "skills/eng-qa-unit-test",
95
+ "workflows/engineering/qa/eng.qa-dev-quality-guide.md",
96
+ "workflows/engineering/qa/eng.qa-e2e-test-generation.md",
97
+ "workflows/engineering/qa/eng.qa-exploratory-session.md",
98
+ "workflows/engineering/qa/eng.qa-quality-gate-validation.md",
99
+ "workflows/engineering/qa/eng.qa-quality-report.md",
100
+ "rules/engineering/qa/eng.qa.exploratory-session-rules.md",
101
+ "rules/engineering/qa/eng.qa.quality-gate-scoring-rules.md",
102
+ "rules/engineering/qa/eng.qa.tech-spec-validation-criteria-rules.md",
103
+ "templates/engineering/qa/eng.qa.quality-gate-examples-template.md",
104
+ "templates/engineering/qa/eng.qa.quality-gate-report-template.md",
105
+ "templates/engineering/qa/qa.cypress-test-template.md",
106
+ "templates/engineering/qa/qa.exploratory-session-template.md",
107
+ "templates/engineering/qa/qa.quality-report-template.md",
108
+ // Descontinuação da área security (removidos): segurança de app fica em eng-backend/eng-frontend,
109
+ // segurança de infra e fundamentos entram em eng-platform ou em PLATFORM_SPECIALIZATIONS
110
+ "skills/eng-security-cybersecurity",
111
+ "skills/eng-security-threat-model",
112
+ "skills/eng-security-triage",
113
+ "skills/eng-security-patch",
114
+ "agents/engineering/eng.cybersecurity.agent.md",
115
+ "workflows/engineering/eng.security-review.md",
116
+ "workflows/engineering/eng.security-incident.md",
117
+ "workflows/engineering/eng.security-audit.md",
118
+ "workflows/engineering/eng.security-pipeline.md",
119
+ // eng-automation-robot-builder (removido): conversão de fluxo manual em robô Playwright
120
+ // via Stagehand — sem skill de substituição hoje
121
+ "skills/eng-automation-robot-builder",
122
+ // eng-ai-engineer (removido): virou a base neutra eng-ai (padrão eng-backend, com references/)
123
+ "skills/eng-ai-engineer",
124
+ // Consolidação de data (removidos): área data ficou só com a base eng-data (padrão eng-backend)
125
+ "skills/eng-data-engineer",
126
+ "skills/eng-data-bi",
127
+ "skills/eng-data-debug",
128
+ "skills/eng-data-onboard",
129
+ "skills/eng-data-orchestrator",
130
+ // eng-global-browser-extension-builder (removido): sem uso real no framework
131
+ "skills/eng-global-browser-extension-builder",
132
+ // eng-devops-performance-engineer (removido): profiling, load testing/chaos e cache
133
+ // multi-camada entraram no eng-platform (temas 14, 15, 16)
134
+ "skills/eng-devops-performance-engineer",
135
+ // eng-frontend-design-system e eng-frontend-microfrontend (removidos): princípios agnósticos
136
+ // entraram na base eng-frontend (temas 13, 14)
137
+ "skills/eng-frontend-design-system",
138
+ "skills/eng-frontend-microfrontend",
70
139
  ]);
71
140
 
72
141
  /**
@@ -95,7 +164,7 @@ export const OPENCODE_MODEL_MAP = Object.freeze({
95
164
  "gpt-4.1": "openai/gpt-4.1",
96
165
  "gpt-4.1-mini": "openai/gpt-4.1-mini",
97
166
  "gpt-4.1-nano": "openai/gpt-4.1-nano",
98
- "o3": "openai/o3",
167
+ o3: "openai/o3",
99
168
  "o3-mini": "openai/o3-mini",
100
169
  "o4-mini": "openai/o4-mini",
101
170
  // Google
@@ -167,4 +236,3 @@ export const KIRO_HUB_FILE_PATTERNS = Object.freeze({
167
236
  DATA: "**/*.py,**/*.sql,**/*.ipynb",
168
237
  AI: "**/*.ts,**/*.py",
169
238
  });
170
-
@@ -111,25 +111,21 @@ function _validateIDEConfig(config) {
111
111
  throw new Error(`IDE config inválida: 'name' é obrigatório (string)`);
112
112
  }
113
113
  if (!config.value || typeof config.value !== "string") {
114
- throw new Error(
115
- `IDE config inválida: 'value' é obrigatório (string) para ${config.name}`,
116
- );
114
+ throw new Error(`IDE config inválida: 'value' é obrigatório (string) para ${config.name}`);
117
115
  }
118
116
  if (typeof config.supported !== "boolean") {
119
- throw new Error(
120
- `IDE config inválida: 'supported' é obrigatório (boolean) para ${config.name}`,
121
- );
117
+ throw new Error(`IDE config inválida: 'supported' é obrigatório (boolean) para ${config.name}`);
122
118
  }
123
119
  if (!config.workflowsFolder || typeof config.workflowsFolder !== "string") {
124
120
  throw new Error(
125
- `IDE config inválida: 'workflowsFolder' é obrigatório (string) para ${config.name}`,
121
+ `IDE config inválida: 'workflowsFolder' é obrigatório (string) para ${config.name}`
126
122
  );
127
123
  }
128
124
  // Validar valores conhecidos
129
125
  const knownFolders = [DEFAULT_WORKFLOWS_FOLDER, COMMANDS_FOLDER, STEERING_FOLDER];
130
126
  if (!knownFolders.includes(config.workflowsFolder)) {
131
127
  logger.warn(
132
- `⚠️ Atenção: IDE '${config.name}' usa workflowsFolder customizado: '${config.workflowsFolder}'`,
128
+ `⚠️ Atenção: IDE '${config.name}' usa workflowsFolder customizado: '${config.workflowsFolder}'`
133
129
  );
134
130
  }
135
131
  }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @fileoverview Filtro de rules por perfil (bloco "Applies to").
3
+ *
4
+ * Espelha em JS a lógica do Passo 8 ("Profile-Aware Rules Sync") do skill
5
+ * `skills/jarvis-init/SKILL.md`, que é executada pela IA. As duas fontes da
6
+ * regra são esse passo e a seção "Profile-Aware Rules Loading" de
7
+ * `rules/AGENTS.md`: ao mudar uma, mude as três.
8
+ *
9
+ * Regras:
10
+ * - Os quatro eixos (HUB, POSITION, AREA, SQUAD) são combinados com AND.
11
+ * - `all` casa qualquer valor; listas são separadas por vírgula.
12
+ * - FULLCYCLE (HUB) satisfaz qualquer HUB.
13
+ * - GENERALIST (POSITION) satisfaz qualquer POSITION e qualquer AREA.
14
+ * - Arquivo sem bloco "Applies to" é universal.
15
+ * - `rules/AGENTS.md` nunca é filtrado.
16
+ * - `rtk-rules.md` só entra com RTK habilitado (opt-in).
17
+ * @module core/profile-filter
18
+ */
19
+
20
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
21
+ import { join, relative, sep } from "node:path";
22
+
23
+ const APPLIES_TO_RE =
24
+ /> \*\*Applies to:\*\* HUB: ([^|]+)\| POSITION: ([^|]+)\| AREA: ([^|]+)\| SQUAD: (.+)/;
25
+
26
+ /**
27
+ * @typedef {Object} AppliesTo
28
+ * @property {string} HUB
29
+ * @property {string} POSITION
30
+ * @property {string} AREA
31
+ * @property {string} SQUAD
32
+ */
33
+
34
+ /**
35
+ * @typedef {Object} Profile
36
+ * @property {string} HUB
37
+ * @property {string} POSITION
38
+ * @property {string} AREA
39
+ * @property {string} SQUAD
40
+ */
41
+
42
+ /**
43
+ * Lê o primeiro bloco "Applies to" do conteúdo.
44
+ * @param {string} content
45
+ * @returns {AppliesTo | null} `null` quando não há bloco (arquivo universal)
46
+ */
47
+ export function parseAppliesTo(content) {
48
+ const match = content.match(APPLIES_TO_RE);
49
+ if (!match) return null;
50
+ return {
51
+ HUB: match[1].trim(),
52
+ POSITION: match[2].trim(),
53
+ AREA: match[3].trim(),
54
+ SQUAD: match[4].trim(),
55
+ };
56
+ }
57
+
58
+ function axisMatches(list, value) {
59
+ if (list.toLowerCase() === "all") return true;
60
+ return list
61
+ .split(",")
62
+ .map((s) => s.trim())
63
+ .includes(value);
64
+ }
65
+
66
+ /**
67
+ * Decide se um bloco "Applies to" casa com o perfil.
68
+ * @param {AppliesTo | null} appliesTo
69
+ * @param {Profile} profile
70
+ * @returns {boolean}
71
+ */
72
+ export function matchesProfile(appliesTo, profile) {
73
+ if (!appliesTo) return true;
74
+ const hub = profile.HUB === "FULLCYCLE" || axisMatches(appliesTo.HUB, profile.HUB);
75
+ const generalist = profile.POSITION === "GENERALIST";
76
+ const position = generalist || axisMatches(appliesTo.POSITION, profile.POSITION);
77
+ const area = generalist || axisMatches(appliesTo.AREA, profile.AREA);
78
+ const squad = axisMatches(appliesTo.SQUAD, profile.SQUAD);
79
+ return hub && position && area && squad;
80
+ }
81
+
82
+ function walkMarkdown(dir) {
83
+ return readdirSync(dir).flatMap((name) => {
84
+ const p = join(dir, name);
85
+ if (statSync(p).isDirectory()) return walkMarkdown(p);
86
+ return p.endsWith(".md") ? [p] : [];
87
+ });
88
+ }
89
+
90
+ /**
91
+ * Lista as rules que o perfil recebe, com o tamanho em bytes.
92
+ * @param {string} rulesDir - Pasta `rules/` do framework
93
+ * @param {Profile} profile
94
+ * @param {{ rtkEnabled?: boolean }} [opts]
95
+ * @returns {Array<{ path: string, bytes: number }>} Ordenado do maior para o menor;
96
+ * `path` é relativo a `rulesDir`, com `/` como separador
97
+ */
98
+ export function listRulesForProfile(rulesDir, profile, opts = {}) {
99
+ if (!existsSync(rulesDir)) return [];
100
+ const result = [];
101
+ for (const file of walkMarkdown(rulesDir)) {
102
+ const rel = relative(rulesDir, file).split(sep).join("/");
103
+ const content = readFileSync(file, "utf-8");
104
+ const bytes = Buffer.byteLength(content, "utf-8");
105
+
106
+ if (rel === "AGENTS.md") {
107
+ result.push({ path: rel, bytes });
108
+ continue;
109
+ }
110
+ if (rel.endsWith("rtk-rules.md") && !opts.rtkEnabled) continue;
111
+ if (matchesProfile(parseAppliesTo(content), profile)) {
112
+ result.push({ path: rel, bytes });
113
+ }
114
+ }
115
+ return result.sort((a, b) => b.bytes - a.bytes || a.path.localeCompare(b.path));
116
+ }
@@ -1,41 +1,19 @@
1
1
  import { existsSync, readdirSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { getFrameworkRoot } from "../utils/paths.js";
4
-
5
- function parseFrontmatter(content) {
6
- const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
7
- if (!match) return {};
8
-
9
- const fm = {};
10
- for (const line of match[1].split("\n")) {
11
- const kv = line.match(/^(\w[\w-]*):\s*(.+)$/);
12
- if (kv) {
13
- let val = kv[2].trim();
14
- if (
15
- (val.startsWith('"') && val.endsWith('"')) ||
16
- (val.startsWith("'") && val.endsWith("'"))
17
- ) {
18
- val = val.slice(1, -1);
19
- }
20
- fm[kv[1]] = val;
21
- }
22
- }
23
- return fm;
24
- }
4
+ import { parseFrontmatter } from "../utils/frontmatter.js";
25
5
 
26
6
  function extractDeps(content) {
27
7
  const deps = { rules: [], templates: [], skills: [], agents: [] };
28
8
 
29
- const ruleFile = content.match(/rules_file:\s*"?\$IDE\/rules\/(.+?)\.md"?/);
9
+ const ruleFile = content.match(/rules_file:\s*"?\$IDE\/rules(?:-on-demand)?\/(.+?)\.md"?/);
30
10
  if (ruleFile) deps.rules.push(ruleFile[1]);
31
11
 
32
- for (const m of content.matchAll(/rules\/([\w./-]+)\.md/g)) {
12
+ for (const m of content.matchAll(/rules(?:-on-demand)?\/([\w./-]+)\.md/g)) {
33
13
  if (!deps.rules.includes(m[1])) deps.rules.push(m[1]);
34
14
  }
35
15
 
36
- const tplFile = content.match(
37
- /template_file:\s*"?\$IDE\/templates\/(.+?)\.md"?/,
38
- );
16
+ const tplFile = content.match(/template_file:\s*"?\$IDE\/templates\/(.+?)\.md"?/);
39
17
  if (tplFile) deps.templates.push(tplFile[1]);
40
18
 
41
19
  const agentFile = content.match(/agent:\s*"?\$IDE\/agents\/(.+?)\.md"?/);
@@ -75,11 +53,7 @@ function scanDir(dir, type) {
75
53
  continue;
76
54
  }
77
55
 
78
- if (
79
- !entry.name.endsWith(".md") ||
80
- entry.name === "README.md" ||
81
- entry.name === "AGENTS.md"
82
- ) {
56
+ if (!entry.name.endsWith(".md") || entry.name === "README.md" || entry.name === "AGENTS.md") {
83
57
  continue;
84
58
  }
85
59
 
@@ -12,6 +12,7 @@ import { execSync } from "node:child_process";
12
12
  import { join, relative, basename } from "node:path";
13
13
  import { getFrameworkRoot } from "../utils/paths.js";
14
14
  import { getIDEFolder } from "../config/ide-config.js";
15
+ import { extractFrontmatterBlock } from "../utils/frontmatter.js";
15
16
  import {
16
17
  SYNC_DIRS,
17
18
  SYNC_ROOT_FILES,
@@ -30,12 +31,11 @@ import {
30
31
  * @returns {{ name: string, description: string } | null}
31
32
  */
32
33
  function parseSkillFrontmatter(content) {
33
- const match = content.match(/^---\n([\s\S]*?)\n---/);
34
- if (!match) return null;
35
- const fm = match[1];
34
+ const fm = extractFrontmatterBlock(content);
35
+ if (fm === null) return null;
36
36
  const name = (fm.match(/^name:\s*(.+)$/m) || [])[1]?.trim();
37
37
  // description pode ser multiline com `>`
38
- const descMatch = fm.match(/^description:\s*[>|]?\n?([\s\S]*?)(?=\n\S|\n---|\Z)/m);
38
+ const descMatch = fm.match(/^description:\s*[>|]?\n?([\s\S]*?)(?=\n\S|\n---|Z)/m);
39
39
  const description = descMatch
40
40
  ? descMatch[1].replace(/^\s+/gm, "").replace(/\n+/g, " ").trim()
41
41
  : "";
@@ -59,8 +59,7 @@ function generateCodexOpenAIYaml(skillsDir) {
59
59
  const parsed = parseSkillFrontmatter(content);
60
60
  if (!parsed) continue;
61
61
  const yaml =
62
- `name: ${parsed.name}\n` +
63
- `description: "${parsed.description.replace(/"/g, '\\"')}"\n`;
62
+ `name: ${parsed.name}\n` + `description: "${parsed.description.replace(/"/g, '\\"')}"\n`;
64
63
  writeFileSync(yamlPath, yaml, "utf-8");
65
64
  }
66
65
  }
@@ -77,9 +76,7 @@ export function syncAssets(targetDir, ide, opts = {}) {
77
76
  for (const dir of SYNC_DIRS) {
78
77
  const src = join(frameworkRoot, dir);
79
78
  // Se for "workflows" e a IDE usa outro nome, usa o nome configurado
80
- const destDirName = (dir === "workflows" && opts.workflowsFolder)
81
- ? opts.workflowsFolder
82
- : dir;
79
+ const destDirName = dir === "workflows" && opts.workflowsFolder ? opts.workflowsFolder : dir;
83
80
  const dest = join(ideDir, destDirName);
84
81
 
85
82
  if (!existsSync(src)) {
@@ -246,7 +243,8 @@ function resolveOpenCodeModel(model) {
246
243
  if (OPENCODE_MODEL_MAP[trimmed]) return OPENCODE_MODEL_MAP[trimmed];
247
244
  // Inferir provider pelo prefixo do modelo
248
245
  if (trimmed.startsWith("claude")) return `anthropic/${trimmed}`;
249
- if (trimmed.startsWith("gpt") || trimmed.startsWith("o3") || trimmed.startsWith("o4")) return `openai/${trimmed}`;
246
+ if (trimmed.startsWith("gpt") || trimmed.startsWith("o3") || trimmed.startsWith("o4"))
247
+ return `openai/${trimmed}`;
250
248
  if (trimmed.startsWith("gemini")) return `google/${trimmed}`;
251
249
  // Fallback: retornar sem provider — OpenCode resolverá pelo provider padrão
252
250
  return trimmed;
@@ -370,11 +368,16 @@ function flattenDir(dir, rootDir) {
370
368
  const fullPath = join(dir, entry.name);
371
369
  if (entry.isDirectory()) {
372
370
  moved += flattenDir(fullPath, root);
373
- try { rmSync(fullPath, { recursive: true, force: true }); } catch {}
371
+ try {
372
+ rmSync(fullPath, { recursive: true, force: true });
373
+ } catch {}
374
374
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
375
375
  const dest = join(root, basename(entry.name));
376
376
  if (fullPath !== dest) {
377
- try { renameSync(fullPath, dest); moved++; } catch {}
377
+ try {
378
+ renameSync(fullPath, dest);
379
+ moved++;
380
+ } catch {}
378
381
  }
379
382
  }
380
383
  }
@@ -402,9 +405,13 @@ function toKiroSteeringFile(content, inclusion, fileMatchPattern) {
402
405
 
403
406
  if (fmMatch) {
404
407
  const fm = fmMatch[1];
405
- const description = (fm.match(/^description:\s*[>|]?\s*\n?([\s\S]*?)(?=\n\S|\n---|\Z)/m) || [])[1];
408
+ const description = (fm.match(/^description:\s*[>|]?\s*\n?([\s\S]*?)(?=\n\S|\n---|Z)/m) ||
409
+ [])[1];
406
410
  const descInline = (fm.match(/^description:\s*(.+)$/m) || [])[1];
407
- const finalDesc = (description || descInline || "").replace(/^\s+/gm, "").replace(/\n+/g, " ").trim();
411
+ const finalDesc = (description || descInline || "")
412
+ .replace(/^\s+/gm, "")
413
+ .replace(/\n+/g, " ")
414
+ .trim();
408
415
  if (finalDesc) lines.push(`description: "${finalDesc.replace(/"/g, '\\"')}"`);
409
416
  }
410
417