jarvis-ai-framework 2.1.1 → 3.2.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 (266) hide show
  1. package/AGENTS.md +14 -115
  2. package/agents/AGENTS.md +11 -23
  3. package/agents/README.md +27 -129
  4. package/agents/engineering/data/eng.data-engineer.agent.md +11 -34
  5. package/agents/engineering/eng.advisor.agent.md +56 -0
  6. package/agents/engineering/eng.agent.md +14 -24
  7. package/agents/engineering/eng.bug-hunter.md +7 -15
  8. package/agents/engineering/eng.dev-code-reviewer.md +1 -1
  9. package/agents/engineering/eng.frontend.agent.md +3 -7
  10. package/agents/engineering/eng.rpa.agent.md +2 -8
  11. package/agents/engineering/qa/eng.qa.quality-strategist.md +6 -11
  12. package/agents/engineering/qa/eng.qa.test-architect.md +8 -18
  13. package/agents/engineering/qa/eng.qa.test-planner.md +10 -14
  14. package/agents/engineering/qa/eng.qa.testing-engineer.md +91 -24
  15. package/agents/product/prod.discovery-interviewer.md +3 -3
  16. package/bin/README.md +142 -0
  17. package/bin/commands/docs-publish.js +105 -141
  18. package/bin/commands/docs-sync.js +66 -104
  19. package/bin/commands/info.js +7 -27
  20. package/bin/commands/init.js +23 -51
  21. package/bin/commands/install-rtk.js +9 -3
  22. package/bin/commands/list.js +5 -18
  23. package/bin/commands/map.js +20 -5
  24. package/bin/commands/qa-signoff.js +58 -55
  25. package/bin/commands/tokens.js +14 -17
  26. package/bin/commands/whoami.js +30 -26
  27. package/bin/jarvis.js +9 -163
  28. package/bin/lib/auth/session.js +20 -20
  29. package/bin/lib/cli/program.js +219 -0
  30. package/bin/lib/cli/shared-options.js +29 -0
  31. package/bin/lib/config/constants.js +59 -2
  32. package/bin/lib/config/ide-config.js +4 -8
  33. package/bin/lib/core/profile-filter.js +4 -1
  34. package/bin/lib/core/scanner.js +3 -29
  35. package/bin/lib/core/sync-engine.js +21 -14
  36. package/bin/lib/core/token-report.js +12 -2
  37. package/bin/lib/docs/fetch-file.js +39 -0
  38. package/bin/lib/docs/publish-file.js +194 -0
  39. package/bin/lib/docs/redis-cache.js +49 -0
  40. package/bin/lib/docs/validate-frontmatter.js +9 -39
  41. package/bin/lib/env-loader.js +11 -34
  42. package/bin/lib/flow-map/parse.js +11 -5
  43. package/bin/lib/flow-map/render.js +5 -2
  44. package/bin/lib/flow-map/tree.js +59 -10
  45. package/bin/lib/tasks/comment.js +40 -35
  46. package/bin/lib/utils/frontmatter.js +57 -0
  47. package/bin/lib/utils/git-parser.js +4 -6
  48. package/bin/lib/utils/npmrc-parser.js +6 -13
  49. package/bin/lib/utils/paths.js +2 -4
  50. package/bin/lib/utils/ui.js +3 -9
  51. package/bin/lib/vcs/api.js +25 -41
  52. package/bin/lib/vcs/create-issue.js +49 -33
  53. package/bin/lib/vcs/create-merge.js +47 -31
  54. package/bin/lib/vcs/fetch-raw.js +35 -23
  55. package/package.json +14 -5
  56. package/rules/engineering/eng-rules.md +1 -1
  57. package/rules/engineering/eng-security-rules.md +18 -16
  58. package/rules/engineering/eng.bump-rules.md +3 -2
  59. package/rules/engineering/eng.docs-scraping-rules.md +4 -4
  60. package/rules/engineering/eng.integrations-rules.md +6 -4
  61. package/rules/engineering/eng.skills-rules.md +1 -1
  62. package/rules/engineering/eng.specializations-rules.md +18 -4
  63. package/rules/engineering/frontend/eng.frontend-rules.md +1 -4
  64. package/rules/engineering/qa/eng.qa.cypress-standards-rules.md +1 -1
  65. package/rules/engineering/rpa/eng.rpa-rules.md +4 -9
  66. package/rules-on-demand/engineering/eng.pre-pr-rules.md +1 -1
  67. package/rules-on-demand/engineering/eng.start-rules.md +2 -0
  68. package/skills/AGENTS.md +52 -87
  69. package/skills/SKILLS-ROADMAP.md +47 -128
  70. package/skills/eng-ai/SKILL.md +270 -0
  71. package/skills/eng-ai/references/1-fundamentos-ml.md +24 -0
  72. package/skills/eng-ai/references/10-arquitetura-solucoes-ia.md +24 -0
  73. package/skills/eng-ai/references/11-governanca-ia.md +24 -0
  74. package/skills/eng-ai/references/12-seguranca-ia-responsavel.md +25 -0
  75. package/skills/eng-ai/references/2-matematica-estatistica.md +24 -0
  76. package/skills/eng-ai/references/3-dados-para-ia.md +24 -0
  77. package/skills/eng-ai/references/4-deep-learning-fundacionais.md +24 -0
  78. package/skills/eng-ai/references/5-llms-chatbots-agentes-rag.md +25 -0
  79. package/skills/eng-ai/references/6-avaliacao-experimentacao.md +24 -0
  80. package/skills/eng-ai/references/7-engenharia-sistemas-ia.md +24 -0
  81. package/skills/eng-ai/references/8-mlops-plataforma.md +24 -0
  82. package/skills/eng-ai/references/9-produto-ia.md +24 -0
  83. package/skills/eng-ai/references/especializacoes.md +17 -0
  84. package/skills/eng-automation/SKILL.md +290 -0
  85. package/skills/eng-automation/references/1-fundamentos-automacao.md +25 -0
  86. package/skills/eng-automation/references/10-ingestao-dados.md +25 -0
  87. package/skills/eng-automation/references/11-captcha-antibot.md +25 -0
  88. package/skills/eng-automation/references/12-limites-taxa-sessoes.md +25 -0
  89. package/skills/eng-automation/references/13-agendamento-orquestracao.md +24 -0
  90. package/skills/eng-automation/references/14-retentativa-erros.md +25 -0
  91. package/skills/eng-automation/references/15-autenticacao-credenciais.md +24 -0
  92. package/skills/eng-automation/references/16-observabilidade-confiabilidade.md +24 -0
  93. package/skills/eng-automation/references/2-aquisicao-dados.md +25 -0
  94. package/skills/eng-automation/references/3-automacao-navegador.md +24 -0
  95. package/skills/eng-automation/references/4-scraping-crawling.md +25 -0
  96. package/skills/eng-automation/references/5-apis-rest-graphql-soap.md +26 -0
  97. package/skills/eng-automation/references/6-webhooks-integracao.md +25 -0
  98. package/skills/eng-automation/references/7-rpa.md +25 -0
  99. package/skills/eng-automation/references/8-extracao-estruturada.md +25 -0
  100. package/skills/eng-automation/references/9-extracao-documentos.md +25 -0
  101. package/skills/eng-automation/references/especializacoes.md +18 -0
  102. package/skills/eng-backend-nestjs/SKILL.md +1 -1
  103. package/skills/eng-data/SKILL.md +271 -0
  104. package/skills/eng-data/references/1-fundamentos-dados.md +24 -0
  105. package/skills/eng-data/references/10-ciencia-dados.md +24 -0
  106. package/skills/eng-data/references/11-dataops-plataforma.md +24 -0
  107. package/skills/eng-data/references/12-seguranca-privacidade.md +24 -0
  108. package/skills/eng-data/references/2-modelagem-dados.md +24 -0
  109. package/skills/eng-data/references/3-bancos-dados.md +24 -0
  110. package/skills/eng-data/references/4-arquitetura-dados.md +24 -0
  111. package/skills/eng-data/references/5-pipelines-integracao.md +24 -0
  112. package/skills/eng-data/references/6-qualidade-dados.md +24 -0
  113. package/skills/eng-data/references/7-governanca-metadados.md +24 -0
  114. package/skills/eng-data/references/8-estatistica-analise.md +24 -0
  115. package/skills/eng-data/references/9-analytics-bi.md +24 -0
  116. package/skills/eng-data/references/especializacoes.md +20 -0
  117. package/skills/eng-frontend/SKILL.md +12 -5
  118. package/skills/eng-frontend/references/13-design-system.md +48 -0
  119. package/skills/eng-frontend/references/14-microfrontend.md +46 -0
  120. package/skills/eng-global-task-comment/SKILL.md +3 -3
  121. package/skills/eng-platform/SKILL.md +331 -0
  122. package/skills/eng-platform/references/1-fundamentos-sistemas.md +23 -0
  123. package/skills/eng-platform/references/10-resiliencia-arquitetura.md +24 -0
  124. package/skills/eng-platform/references/11-plataforma-devex.md +24 -0
  125. package/skills/eng-platform/references/12-finops-custos.md +24 -0
  126. package/skills/eng-platform/references/13-seguranca-fundamentos.md +26 -0
  127. package/skills/eng-platform/references/14-profiling-performance.md +23 -0
  128. package/skills/eng-platform/references/15-testes-carga-chaos.md +23 -0
  129. package/skills/eng-platform/references/16-cache-multicamada.md +22 -0
  130. package/skills/eng-platform/references/2-redes.md +23 -0
  131. package/skills/eng-platform/references/3-cloud.md +24 -0
  132. package/skills/eng-platform/references/4-iac-automacao.md +24 -0
  133. package/skills/eng-platform/references/5-containers-orquestracao.md +25 -0
  134. package/skills/eng-platform/references/6-cicd-entrega.md +24 -0
  135. package/skills/eng-platform/references/7-observabilidade.md +24 -0
  136. package/skills/eng-platform/references/8-confiabilidade-sre.md +24 -0
  137. package/skills/eng-platform/references/9-seguranca-infra.md +26 -0
  138. package/skills/eng-platform/references/especializacoes.md +34 -0
  139. package/skills/eng-qa/SKILL.md +283 -0
  140. package/skills/eng-qa/references/1-fundamentos-qualidade.md +25 -0
  141. package/skills/eng-qa/references/10-confiabilidade.md +25 -0
  142. package/skills/eng-qa/references/11-seguranca.md +24 -0
  143. package/skills/eng-qa/references/12-acessibilidade.md +24 -0
  144. package/skills/eng-qa/references/13-dados-testes.md +24 -0
  145. package/skills/eng-qa/references/14-gestao-testes-defeitos.md +25 -0
  146. package/skills/eng-qa/references/15-arquitetura-qa.md +25 -0
  147. package/skills/eng-qa/references/2-estrategia-planejamento.md +25 -0
  148. package/skills/eng-qa/references/3-design-testes.md +25 -0
  149. package/skills/eng-qa/references/4-manual-exploratorio.md +24 -0
  150. package/skills/eng-qa/references/5-automacao-testes.md +25 -0
  151. package/skills/eng-qa/references/6-api-integracao.md +25 -0
  152. package/skills/eng-qa/references/7-contrato.md +24 -0
  153. package/skills/eng-qa/references/8-interface-compat-mobile.md +24 -0
  154. package/skills/eng-qa/references/9-performance.md +24 -0
  155. package/skills/eng-qa/references/especializacoes.md +29 -0
  156. package/skills/eng-qa-planner/SKILL.md +264 -0
  157. package/skills/jarvis-context-detect/SKILL.md +1 -1
  158. package/skills/jarvis-context-detect/assets/context-profile-template.md +1 -1
  159. package/skills/jarvis-create-specialization/SKILL.md +8 -0
  160. package/skills/jarvis-docs-central/README.md +31 -28
  161. package/skills/jarvis-docs-central/SKILL.md +5 -5
  162. package/skills/jarvis-init/SKILL.md +9 -8
  163. package/skills/jarvis-init/assets/passo-adicionar-stacks.md +47 -18
  164. package/skills/jarvis-list-specializations/SKILL.md +30 -17
  165. package/skills/jarvis-report-issue/SKILL.md +1 -1
  166. package/taxonomy.md +4 -16
  167. package/templates/AGENTS.md +2 -0
  168. package/templates/ENV-template.md +20 -2
  169. package/templates/engineering/advisor-template.md +65 -0
  170. package/templates/engineering/architecture-template.md +52 -4
  171. package/templates/engineering/qa/qa.sprint-plan-template.md +1 -1
  172. package/workflows/AGENTS.md +3 -1
  173. package/workflows/README.md +0 -10
  174. package/workflows/engineering/data/data.new-pipeline.md +6 -5
  175. package/workflows/engineering/eng.bug-audit.md +4 -14
  176. package/workflows/engineering/eng.debug.md +4 -20
  177. package/workflows/engineering/eng.plan.md +4 -26
  178. package/workflows/engineering/eng.pr.md +13 -63
  179. package/workflows/engineering/eng.pre-pr.md +14 -51
  180. package/workflows/engineering/eng.review.md +7 -13
  181. package/workflows/engineering/eng.rpa.robot.md +3 -9
  182. package/workflows/engineering/eng.start.md +37 -32
  183. package/workflows/engineering/eng.work.md +17 -40
  184. package/workflows/engineering/qa/eng.qa-sprint-planning.md +1 -1
  185. package/workflows/product/prod.spec.discovery.md +2 -2
  186. package/workflows/warm-up.md +35 -63
  187. package/agents/engineering/eng.cybersecurity.agent.md +0 -486
  188. package/agents/engineering/qa/eng.qa.cypress-specialist.md +0 -112
  189. package/bin/lib/docs/fetch-file.sh +0 -41
  190. package/bin/lib/docs/publish-file.sh +0 -284
  191. package/rules/engineering/qa/eng.qa.exploratory-session-rules.md +0 -137
  192. package/rules/engineering/qa/eng.qa.quality-gate-scoring-rules.md +0 -181
  193. package/rules/engineering/qa/eng.qa.tech-spec-validation-criteria-rules.md +0 -120
  194. package/skills/eng-ai-engineer/SKILL.md +0 -303
  195. package/skills/eng-data-bi/SKILL.md +0 -206
  196. package/skills/eng-data-debug/SKILL.md +0 -314
  197. package/skills/eng-data-engineer/SKILL.md +0 -266
  198. package/skills/eng-data-onboard/SKILL.md +0 -317
  199. package/skills/eng-data-orchestrator/SKILL.md +0 -433
  200. package/skills/eng-devops-performance-engineer/SKILL.md +0 -319
  201. package/skills/eng-frontend-design-system/SKILL.md +0 -155
  202. package/skills/eng-frontend-design-system/references/1-estrutura-pacote.md +0 -57
  203. package/skills/eng-frontend-design-system/references/2-tokens.md +0 -116
  204. package/skills/eng-frontend-design-system/references/3-componentes.md +0 -165
  205. package/skills/eng-frontend-design-system/references/4-storybook.md +0 -85
  206. package/skills/eng-frontend-design-system/references/5-auditoria-versionamento.md +0 -76
  207. package/skills/eng-frontend-microfrontend/SKILL.md +0 -164
  208. package/skills/eng-frontend-microfrontend/references/1-criando-remote.md +0 -109
  209. package/skills/eng-frontend-microfrontend/references/2-configurando-shell.md +0 -70
  210. package/skills/eng-frontend-microfrontend/references/3-contratos-interface.md +0 -73
  211. package/skills/eng-frontend-microfrontend/references/4-shared-dependencies.md +0 -48
  212. package/skills/eng-frontend-microfrontend/references/5-event-bus.md +0 -59
  213. package/skills/eng-frontend-microfrontend/references/6-monorepo-deploy.md +0 -77
  214. package/skills/eng-frontend-microfrontend/references/7-troubleshooting.md +0 -45
  215. package/skills/eng-global-browser-extension-builder/SKILL.md +0 -392
  216. package/skills/eng-global-jira-comment/SKILL.md +0 -27
  217. package/skills/eng-qa-a11y-audit/SKILL.md +0 -276
  218. package/skills/eng-qa-bug-report/SKILL.md +0 -877
  219. package/skills/eng-qa-bug-report/TASK_MANAGERS.md +0 -138
  220. package/skills/eng-qa-bug-report/references/1-integracao-task-managers.md +0 -148
  221. package/skills/eng-qa-bug-report/references/2-exemplos-de-uso.md +0 -46
  222. package/skills/eng-qa-bug-report/references/3-bug-to-test.md +0 -45
  223. package/skills/eng-qa-cypress-e2e/SKILL.md +0 -184
  224. package/skills/eng-qa-dev-guide/SKILL.md +0 -173
  225. package/skills/eng-qa-e2e/SKILL.md +0 -407
  226. package/skills/eng-qa-e2e-spec-writer/SKILL.md +0 -329
  227. package/skills/eng-qa-exploratory/SKILL.md +0 -196
  228. package/skills/eng-qa-gate/SKILL.md +0 -377
  229. package/skills/eng-qa-gate/assets/checklist-validacao.md +0 -291
  230. package/skills/eng-qa-graphql-contract/SKILL.md +0 -263
  231. package/skills/eng-qa-quality-report/SKILL.md +0 -419
  232. package/skills/eng-qa-test-plan/SKILL.md +0 -473
  233. package/skills/eng-qa-testsprite/SKILL.md +0 -332
  234. package/skills/eng-qa-testsprite/references/testsprite-mcp.md +0 -224
  235. package/skills/eng-qa-unit-test/SKILL.md +0 -478
  236. package/skills/eng-scraper/SKILL.md +0 -260
  237. package/skills/eng-scraper/references/1-puppeteer.md +0 -140
  238. package/skills/eng-scraper/references/2-playwright-cheerio-pdf.md +0 -82
  239. package/skills/eng-scraper/references/3-anti-bot.md +0 -94
  240. package/skills/eng-scraper/references/4-resiliencia-etl-monitoramento.md +0 -137
  241. package/skills/eng-scraper-robot-builder/SKILL.md +0 -377
  242. package/skills/eng-security-cybersecurity/SKILL.md +0 -250
  243. package/skills/eng-security-cybersecurity/references/1-owasp-top-10.md +0 -331
  244. package/skills/eng-security-cybersecurity/references/2-secrets-management.md +0 -31
  245. package/skills/eng-security-cybersecurity/references/3-input-validation.md +0 -43
  246. package/skills/eng-security-cybersecurity/references/4-compliance.md +0 -20
  247. package/skills/eng-security-patch/SKILL.md +0 -388
  248. package/skills/eng-security-threat-model/SKILL.md +0 -171
  249. package/skills/eng-security-triage/SKILL.md +0 -276
  250. package/templates/engineering/qa/eng.qa.quality-gate-examples-template.md +0 -311
  251. package/templates/engineering/qa/eng.qa.quality-gate-report-template.md +0 -249
  252. package/templates/engineering/qa/qa.cypress-test-template.md +0 -172
  253. package/templates/engineering/qa/qa.exploratory-session-template.md +0 -148
  254. package/templates/engineering/qa/qa.quality-report-template.md +0 -130
  255. package/workflows/engineering/eng.security-audit.md +0 -319
  256. package/workflows/engineering/eng.security-incident.md +0 -281
  257. package/workflows/engineering/eng.security-pipeline.md +0 -219
  258. package/workflows/engineering/eng.security-review.md +0 -241
  259. package/workflows/engineering/qa/eng.qa-dev-quality-guide.md +0 -57
  260. package/workflows/engineering/qa/eng.qa-e2e-test-generation.md +0 -57
  261. package/workflows/engineering/qa/eng.qa-exploratory-session.md +0 -68
  262. package/workflows/engineering/qa/eng.qa-quality-gate-validation.md +0 -209
  263. package/workflows/engineering/qa/eng.qa-quality-report.md +0 -85
  264. /package/skills/{eng-qa-test-plan → eng-qa-planner}/assets/test-coverage-template.md +0 -0
  265. /package/skills/{eng-qa-test-plan → eng-qa-planner}/assets/test-patterns.md +0 -0
  266. /package/templates/{CDD aplicado a Prompts.md → cdd-aplicado-a-prompts.md} +0 -0
@@ -10,17 +10,7 @@ import {
10
10
  getWorkflowsFolder,
11
11
  isIDESupported,
12
12
  } from "../lib/config/ide-config.js";
13
- import {
14
- showBanner,
15
- RED,
16
- GREEN,
17
- BLUE,
18
- YELLOW,
19
- CYAN,
20
- DIM,
21
- BOLD,
22
- NC,
23
- } from "../lib/utils/ui.js";
13
+ import { showBanner, RED, GREEN, BLUE, YELLOW, CYAN, DIM, BOLD, NC } from "../lib/utils/ui.js";
24
14
  import { getPackageInfo } from "../lib/utils/paths.js";
25
15
  import { logger, configureFromFlags } from "../lib/utils/logger.js";
26
16
 
@@ -40,7 +30,9 @@ export async function init(flags) {
40
30
  if (!isIDESupported(flags.ide)) {
41
31
  logger.error(`${RED}❌ IDE inválida: ${flags.ide}${NC}`);
42
32
  logger.info(
43
- `${YELLOW}IDEs disponíveis: ${IDES.filter((i) => i.supported).map((i) => i.value).join(", ")}${NC}\n`,
33
+ `${YELLOW}IDEs disponíveis: ${IDES.filter((i) => i.supported)
34
+ .map((i) => i.value)
35
+ .join(", ")}${NC}\n`
44
36
  );
45
37
  return;
46
38
  }
@@ -55,9 +47,7 @@ export async function init(flags) {
55
47
  if (ideObj.supported) {
56
48
  logger.info(` ${GREEN}${index + 1}${NC}) ${ideObj.name}`);
57
49
  } else {
58
- logger.info(
59
- ` ${DIM}${index + 1}) ${ideObj.name} (não suportado)${NC}`,
60
- );
50
+ logger.info(` ${DIM}${index + 1}) ${ideObj.name} (não suportado)${NC}`);
61
51
  }
62
52
  });
63
53
  logger.info("");
@@ -69,10 +59,7 @@ export async function init(flags) {
69
59
 
70
60
  let choice;
71
61
  while (true) {
72
- choice = await ask(
73
- rl,
74
- `${BLUE}Digite o número da sua escolha (1-${IDES.length}): ${NC}`,
75
- );
62
+ choice = await ask(rl, `${BLUE}Digite o número da sua escolha (1-${IDES.length}): ${NC}`);
76
63
  const choiceNum = parseInt(choice, 10);
77
64
 
78
65
  if (choiceNum >= 1 && choiceNum <= IDES.length) {
@@ -80,9 +67,7 @@ export async function init(flags) {
80
67
  if (selectedIde.supported) {
81
68
  ide = selectedIde.value;
82
69
  logger.info("");
83
- logger.info(
84
- `${GREEN}Interface selecionada: ${selectedIde.name}${NC}`,
85
- );
70
+ logger.info(`${GREEN}Interface selecionada: ${selectedIde.name}${NC}`);
86
71
  logger.info(`${DIM}Pasta destino: .${getIDEFolder(ide)}${NC}`);
87
72
  logger.info("");
88
73
  break;
@@ -91,7 +76,7 @@ export async function init(flags) {
91
76
  }
92
77
  } else {
93
78
  logger.info(
94
- `${RED}Opção inválida. Por favor, escolha um número entre 1 e ${IDES.length}.${NC}\n`,
79
+ `${RED}Opção inválida. Por favor, escolha um número entre 1 e ${IDES.length}.${NC}\n`
95
80
  );
96
81
  }
97
82
  }
@@ -114,7 +99,7 @@ export async function init(flags) {
114
99
  });
115
100
  const confirm = await ask(
116
101
  rl,
117
- `Deseja reinstalar? Isso irá sobrescrever a instalação existente. (s/N): `,
102
+ `Deseja reinstalar? Isso irá sobrescrever a instalação existente. (s/N): `
118
103
  );
119
104
  rl.close();
120
105
 
@@ -127,9 +112,7 @@ export async function init(flags) {
127
112
  }
128
113
 
129
114
  const ideConfig = getIDEConfig(ide);
130
- logger.info(
131
- `${BLUE}Configurando ambiente para ${ideConfig?.name}...${NC}`,
132
- );
115
+ logger.info(`${BLUE}Configurando ambiente para ${ideConfig?.name}...${NC}`);
133
116
  logger.info("");
134
117
  const result = syncAssets(cwd, ide, {
135
118
  force: forceSync,
@@ -146,16 +129,16 @@ export async function init(flags) {
146
129
  logger.error(`${RED} ✗ ${item}${NC}`);
147
130
  }
148
131
 
149
- const jarvisRoot = join(cwd, '.jarvis');
150
- for (const area of ['eng', 'prod', 'qa']) {
151
- mkdirSync(join(jarvisRoot, 'sessions', area), { recursive: true });
132
+ const jarvisRoot = join(cwd, ".jarvis");
133
+ for (const area of ["eng", "prod", "qa"]) {
134
+ mkdirSync(join(jarvisRoot, "sessions", area), { recursive: true });
152
135
  }
153
- const gitignore = join(cwd, '.gitignore');
154
- const ignoreLine = '.jarvis/';
136
+ const gitignore = join(cwd, ".gitignore");
137
+ const ignoreLine = ".jarvis/";
155
138
  if (existsSync(gitignore)) {
156
- const text = readFileSync(gitignore, 'utf8');
157
- if (!text.split('\n').some((l) => l.trim() === ignoreLine || l.trim() === '.jarvis')) {
158
- appendFileSync(gitignore, `${text.endsWith('\n') ? '' : '\n'}${ignoreLine}\n`);
139
+ const text = readFileSync(gitignore, "utf8");
140
+ if (!text.split("\n").some((l) => l.trim() === ignoreLine || l.trim() === ".jarvis")) {
141
+ appendFileSync(gitignore, `${text.endsWith("\n") ? "" : "\n"}${ignoreLine}\n`);
159
142
  }
160
143
  } else {
161
144
  writeFileSync(gitignore, `${ignoreLine}\n`);
@@ -165,22 +148,16 @@ export async function init(flags) {
165
148
 
166
149
  logger.info("");
167
150
  logger.info(`${GREEN}✓ Configuração concluída!${NC}`);
168
- logger.info(
169
- `${BOLD}${CYAN} versão: ${pkg.name} v${pkg.version}${NC}`,
170
- );
151
+ logger.info(`${BOLD}${CYAN} versão: ${pkg.name} v${pkg.version}${NC}`);
171
152
  logger.info(`${DIM} origem: ${pkg.root}${NC}`);
172
153
  logger.info(`${DIM} pasta criada: ${ideDir}${NC}`);
173
154
  logger.info("");
174
155
 
175
156
  const all = discoverAll();
176
157
 
177
- logger.info(
178
- `${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`,
179
- );
158
+ logger.info(`${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
180
159
  logger.info(`${CYAN} 🏁 PRÓXIMO PASSO${NC}`);
181
- logger.info(
182
- `${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`,
183
- );
160
+ logger.info(`${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
184
161
  logger.info("");
185
162
 
186
163
  if (ide === "codex") {
@@ -213,14 +190,10 @@ export async function init(flags) {
213
190
  }
214
191
 
215
192
  logger.info("");
216
- logger.info(
217
- `${DIM} Isso irá criar o arquivo ENV.md com as configurações${NC}`,
218
- );
193
+ logger.info(`${DIM} Isso irá criar o arquivo ENV.md com as configurações${NC}`);
219
194
  logger.info(`${DIM} necessárias para o funcionamento do JARVIS.${NC}`);
220
195
  logger.info("");
221
- logger.info(
222
- `${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`,
223
- );
196
+ logger.info(`${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}`);
224
197
  logger.info("");
225
198
  logger.info(`${GREEN}✓ Instalação completa! 🎉${NC}`);
226
199
  logger.info("");
@@ -233,5 +206,4 @@ export async function init(flags) {
233
206
  logger.info(`${BLUE}📖 Para ver todos os prompts disponíveis:${NC}`);
234
207
  logger.info(` ${YELLOW}jarvis list${NC}`);
235
208
  logger.info("");
236
-
237
209
  }
@@ -40,7 +40,9 @@ export async function installRtk(flags) {
40
40
  return;
41
41
  } catch {}
42
42
  } else {
43
- logger.info(`${YELLOW}⚠ RTK encontrado mas não é o Token Killer (Rust Type Kit detectado)${NC}`);
43
+ logger.info(
44
+ `${YELLOW}⚠ RTK encontrado mas não é o Token Killer (Rust Type Kit detectado)${NC}`
45
+ );
44
46
  logger.info(`${DIM} Sobrescrevendo com Token Killer...${NC}`);
45
47
  logger.info("");
46
48
  }
@@ -95,12 +97,16 @@ export async function installRtk(flags) {
95
97
  logger.info(`${GREEN}✓ RTK instalado com sucesso: ${version}${NC}`);
96
98
  logger.info("");
97
99
  logger.info(`${YELLOW}Próximo passo:${NC}`);
98
- logger.info(` Execute ${GREEN}jarvis init${NC} (ou atualize o ENV.md) para ativar ${GREEN}RTK_ENABLED=true${NC}`);
100
+ logger.info(
101
+ ` Execute ${GREEN}jarvis init${NC} (ou atualize o ENV.md) para ativar ${GREEN}RTK_ENABLED=true${NC}`
102
+ );
99
103
  logger.info(` A rule de economia de tokens será ativada automaticamente.`);
100
104
  logger.info("");
101
105
  } else {
102
106
  logger.error(`${RED}✗ RTK instalado mas não é o Token Killer${NC}`);
103
- logger.info(`${DIM} Possível conflito: crate 'rtk' no crates.io é Rust Type Kit, não Token Killer${NC}`);
107
+ logger.info(
108
+ `${DIM} Possível conflito: crate 'rtk' no crates.io é Rust Type Kit, não Token Killer${NC}`
109
+ );
104
110
  logger.info(`${DIM} Use: cargo install brokk-rtk${NC}`);
105
111
  logger.info("");
106
112
  process.exit(1);
@@ -1,13 +1,5 @@
1
1
  import { discoverAll } from "../lib/core/scanner.js";
2
- import {
3
- showBanner,
4
- GREEN,
5
- BLUE,
6
- YELLOW,
7
- CYAN,
8
- DIM,
9
- NC,
10
- } from "../lib/utils/ui.js";
2
+ import { showBanner, GREEN, BLUE, YELLOW, CYAN, DIM, NC } from "../lib/utils/ui.js";
11
3
  import { logger } from "../lib/utils/logger.js";
12
4
 
13
5
  export async function list(flags) {
@@ -25,20 +17,15 @@ export async function list(flags) {
25
17
  logger.info(`${DIM}${"─".repeat(80)}${NC}`);
26
18
  for (const item of items) {
27
19
  const desc =
28
- item.description.length > 45
29
- ? item.description.slice(0, 45) + "..."
30
- : item.description;
20
+ item.description.length > 45 ? item.description.slice(0, 45) + "..." : item.description;
31
21
  logger.info(` ${GREEN}${item.id.padEnd(30)}${NC} ${DIM}${desc}${NC}`);
32
22
  }
33
23
  logger.info("");
34
24
  }
35
25
 
36
- if (!filter || filter === "agent")
37
- printSection("AGENTS", all.agents, "🤖");
38
- if (!filter || filter === "skill")
39
- printSection("SKILLS", all.skills, "⚡");
40
- if (!filter || filter === "workflow")
41
- printSection("WORKFLOWS", all.workflows, "🔄");
26
+ if (!filter || filter === "agent") printSection("AGENTS", all.agents, "🤖");
27
+ if (!filter || filter === "skill") printSection("SKILLS", all.skills, "⚡");
28
+ if (!filter || filter === "workflow") printSection("WORKFLOWS", all.workflows, "🔄");
42
29
 
43
30
  const total = all.agents.length + all.skills.length + all.workflows.length;
44
31
  logger.info(`${BLUE}📦 Total: ${GREEN}${total}${BLUE} prompts disponíveis${NC}`);
@@ -1,9 +1,16 @@
1
- import { buildGraph, forwardTree, reverseEdges, suggest, DEFAULT_DEPTH } from "../lib/flow-map/tree.js";
1
+ import {
2
+ buildGraph,
3
+ forwardTree,
4
+ reverseEdges,
5
+ suggest,
6
+ DEFAULT_DEPTH,
7
+ } from "../lib/flow-map/tree.js";
2
8
  import { renderTree, renderReverse } from "../lib/flow-map/render.js";
3
9
  import { getFrameworkRoot } from "../lib/utils/paths.js";
4
10
  import { logger } from "../lib/utils/logger.js";
5
11
 
6
- const USAGE = "Uso: jarvis map <nome> [--depth N] [--reverse] (nome de um workflow, skill ou agente)";
12
+ const USAGE =
13
+ "Uso: jarvis map <nome> [--depth N] [--reverse] (nome de um workflow, skill ou agente)";
7
14
 
8
15
  /**
9
16
  * Monta a saída do mapa. Separado de `map` para ser testável.
@@ -13,12 +20,17 @@ const USAGE = "Uso: jarvis map <nome> [--depth N] [--reverse] (nome de um work
13
20
  * @returns {{ code: number, lines: string[] }}
14
21
  */
15
22
  export function runMap(name, flags = {}, root = getFrameworkRoot()) {
16
- if (!name) return { code: 1, lines: ["❌ Informe o nome de um workflow, skill ou agente.", USAGE] };
23
+ if (!name)
24
+ return { code: 1, lines: ["❌ Informe o nome de um workflow, skill ou agente.", USAGE] };
17
25
 
18
26
  let depth = DEFAULT_DEPTH;
19
27
  if (flags.depth !== undefined) {
20
28
  depth = Number.parseInt(String(flags.depth), 10);
21
- if (!Number.isInteger(depth) || depth < 1) return { code: 1, lines: ["❌ --depth precisa ser um número inteiro maior que zero.", USAGE] };
29
+ if (!Number.isInteger(depth) || depth < 1)
30
+ return {
31
+ code: 1,
32
+ lines: ["❌ --depth precisa ser um número inteiro maior que zero.", USAGE],
33
+ };
22
34
  }
23
35
 
24
36
  const graph = buildGraph(root);
@@ -31,7 +43,10 @@ export function runMap(name, flags = {}, root = getFrameworkRoot()) {
31
43
  }
32
44
 
33
45
  if (flags.reverse) {
34
- return { code: 0, lines: renderReverse(name, graph.items.get(name).type, reverseEdges(graph, name)) };
46
+ return {
47
+ code: 0,
48
+ lines: renderReverse(name, graph.items.get(name).type, reverseEdges(graph, name)),
49
+ };
35
50
  }
36
51
  return { code: 0, lines: renderTree(forwardTree(graph, name, { depth })) };
37
52
  }
@@ -1,8 +1,9 @@
1
- import { existsSync, readdirSync, readFileSync } from 'node:fs'
2
- import { join } from 'node:path'
3
- import { loadEnv, resolveEnvPath } from '../lib/env-loader.js'
4
- import { GREEN, RED, YELLOW, DIM, NC } from '../lib/utils/ui.js'
5
- import { logger } from '../lib/utils/logger.js'
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { loadEnv, resolveEnvPath } from "../lib/env-loader.js";
4
+ import { extractFrontmatterBlock } from "../lib/utils/frontmatter.js";
5
+ import { GREEN, RED, YELLOW, DIM, NC } from "../lib/utils/ui.js";
6
+ import { logger } from "../lib/utils/logger.js";
6
7
 
7
8
  /**
8
9
  * Verifica se existe um sign-off QA válido para a branch atual (ou informada).
@@ -13,100 +14,102 @@ import { logger } from '../lib/utils/logger.js'
13
14
  * @param {string} flags['max-age'] - Validade máxima em horas (padrão: 24)
14
15
  */
15
16
  export async function qaSignoff(flags = {}) {
16
- const cwd = process.cwd()
17
- const maxAgeHours = parseInt(flags['max-age'] ?? '24', 10)
17
+ const cwd = process.cwd();
18
+ const maxAgeHours = parseInt(flags["max-age"] ?? "24", 10);
18
19
 
19
20
  // Resolver branch
20
- let branch = flags.branch
21
+ let branch = flags.branch;
21
22
  if (!branch) {
22
23
  try {
23
- const { execSync } = await import('node:child_process')
24
- branch = execSync('git branch --show-current', { cwd, encoding: 'utf-8' }).trim()
24
+ const { execSync } = await import("node:child_process");
25
+ branch = execSync("git branch --show-current", { cwd, encoding: "utf-8" }).trim();
25
26
  } catch {
26
- logger.error(`${RED}❌ Não foi possível detectar a branch atual.${NC}`)
27
- logger.info(`${YELLOW}Passe a branch via --branch <nome>${NC}`)
28
- process.exit(1)
27
+ logger.error(`${RED}❌ Não foi possível detectar a branch atual.${NC}`);
28
+ logger.info(`${YELLOW}Passe a branch via --branch <nome>${NC}`);
29
+ process.exit(1);
29
30
  }
30
31
  }
31
32
 
32
33
  if (!branch) {
33
- logger.error(`${RED}❌ Branch não identificada.${NC}`)
34
- process.exit(1)
34
+ logger.error(`${RED}❌ Branch não identificada.${NC}`);
35
+ process.exit(1);
35
36
  }
36
37
 
37
38
  // Carregar ENV.md para descobrir DOCS_FOLDER
38
- let docsFolder = 'docs'
39
+ let docsFolder = "docs";
39
40
  try {
40
- const resolved = resolveEnvPath(cwd, flags)
41
- const env = loadEnv(cwd, resolved.path)
42
- if (env.DOCS_FOLDER) docsFolder = env.DOCS_FOLDER
41
+ const resolved = resolveEnvPath(cwd, flags);
42
+ const env = loadEnv(cwd, resolved.path);
43
+ if (env.DOCS_FOLDER) docsFolder = env.DOCS_FOLDER;
43
44
  } catch {
44
45
  // Se não encontrar ENV.md, usa default
45
46
  }
46
47
 
47
- const signoffsDir = join(cwd, docsFolder, 'engineering', 'qa', 'signoffs')
48
+ const signoffsDir = join(cwd, docsFolder, "engineering", "qa", "signoffs");
48
49
 
49
50
  if (!existsSync(signoffsDir)) {
50
- logger.error(`${RED}❌ Nenhum sign-off QA encontrado para a branch: ${branch}${NC}`)
51
- logger.info(`${YELLOW}Execute o workflow qa.release-signoff antes do deploy.${NC}`)
52
- process.exit(1)
51
+ logger.error(`${RED}❌ Nenhum sign-off QA encontrado para a branch: ${branch}${NC}`);
52
+ logger.info(`${YELLOW}Execute o workflow qa.release-signoff antes do deploy.${NC}`);
53
+ process.exit(1);
53
54
  }
54
55
 
55
56
  // Normalizar slug da branch para busca nos nomes de arquivo
56
- const branchSlug = branch.replace(/\//g, '-').replace(/[^a-zA-Z0-9-_]/g, '-')
57
+ const branchSlug = branch.replace(/\//g, "-").replace(/[^a-zA-Z0-9-_]/g, "-");
57
58
 
58
59
  // Buscar arquivos de sign-off que correspondam à branch
59
60
  const files = readdirSync(signoffsDir)
60
- .filter(f => f.endsWith('.md') && f.includes(branchSlug))
61
+ .filter((f) => f.endsWith(".md") && f.includes(branchSlug))
61
62
  .sort()
62
- .reverse() // mais recente primeiro
63
+ .reverse(); // mais recente primeiro
63
64
 
64
65
  if (files.length === 0) {
65
- logger.error(`${RED}❌ Nenhum sign-off QA encontrado para a branch: ${branch}${NC}`)
66
- logger.info(`${YELLOW}Execute o workflow qa.release-signoff antes do deploy.${NC}`)
67
- process.exit(1)
66
+ logger.error(`${RED}❌ Nenhum sign-off QA encontrado para a branch: ${branch}${NC}`);
67
+ logger.info(`${YELLOW}Execute o workflow qa.release-signoff antes do deploy.${NC}`);
68
+ process.exit(1);
68
69
  }
69
70
 
70
71
  // Ler o sign-off mais recente
71
- const latestFile = files[0]
72
- const filePath = join(signoffsDir, latestFile)
73
- const content = readFileSync(filePath, 'utf-8')
72
+ const latestFile = files[0];
73
+ const filePath = join(signoffsDir, latestFile);
74
+ const content = readFileSync(filePath, "utf-8");
74
75
 
75
76
  // Extrair frontmatter
76
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/)
77
- if (!frontmatterMatch) {
78
- logger.error(`${RED}❌ Sign-off inválido: frontmatter ausente em ${latestFile}${NC}`)
79
- process.exit(1)
77
+ const frontmatter = extractFrontmatterBlock(content);
78
+ if (frontmatter === null) {
79
+ logger.error(`${RED}❌ Sign-off inválido: frontmatter ausente em ${latestFile}${NC}`);
80
+ process.exit(1);
80
81
  }
82
+ const statusMatch = frontmatter.match(/^status:\s*(.+)$/m);
83
+ const dateMatch = frontmatter.match(/^date:\s*(.+)$/m);
81
84
 
82
- const frontmatter = frontmatterMatch[1]
83
- const statusMatch = frontmatter.match(/^status:\s*(.+)$/m)
84
- const dateMatch = frontmatter.match(/^date:\s*(.+)$/m)
85
-
86
- const status = statusMatch?.[1]?.trim().replace(/['"]/g, '') ?? ''
87
- const dateStr = dateMatch?.[1]?.trim().replace(/['"]/g, '') ?? ''
85
+ const status = statusMatch?.[1]?.trim().replace(/['"]/g, "") ?? "";
86
+ const dateStr = dateMatch?.[1]?.trim().replace(/['"]/g, "") ?? "";
88
87
 
89
88
  // Verificar status
90
- if (status.toUpperCase() !== 'GO') {
91
- logger.error(`${RED}❌ Sign-off com status ${status} — deploy bloqueado.${NC}`)
92
- logger.info(`${DIM}Arquivo: ${latestFile}${NC}`)
93
- process.exit(1)
89
+ if (status.toUpperCase() !== "GO") {
90
+ logger.error(`${RED}❌ Sign-off com status ${status} — deploy bloqueado.${NC}`);
91
+ logger.info(`${DIM}Arquivo: ${latestFile}${NC}`);
92
+ process.exit(1);
94
93
  }
95
94
 
96
95
  // Verificar validade (max-age)
97
96
  if (dateStr) {
98
- const signoffDate = new Date(dateStr)
99
- const now = new Date()
100
- const ageHours = (now - signoffDate) / (1000 * 60 * 60)
97
+ const signoffDate = new Date(dateStr);
98
+ const now = new Date();
99
+ const ageHours = (now - signoffDate) / (1000 * 60 * 60);
101
100
 
102
101
  if (ageHours > maxAgeHours) {
103
- logger.error(`${RED}❌ Sign-off expirado: criado há ${Math.round(ageHours)}h (máximo: ${maxAgeHours}h).${NC}`)
104
- logger.info(`${YELLOW}Execute qa.release-signoff novamente antes do deploy.${NC}`)
105
- process.exit(1)
102
+ logger.error(
103
+ `${RED}❌ Sign-off expirado: criado há ${Math.round(ageHours)}h (máximo: ${maxAgeHours}h).${NC}`
104
+ );
105
+ logger.info(`${YELLOW}Execute qa.release-signoff novamente antes do deploy.${NC}`);
106
+ process.exit(1);
106
107
  }
107
108
  }
108
109
 
109
- logger.info(`${GREEN}✅ Sign-off QA válido para branch: ${branch}${NC}`)
110
- logger.info(`${DIM}Arquivo: ${latestFile} | Status: GO | Válido por mais ${Math.round(maxAgeHours - ((new Date() - new Date(dateStr)) / (1000 * 60 * 60)))}h${NC}`)
111
- process.exit(0)
110
+ logger.info(`${GREEN}✅ Sign-off QA válido para branch: ${branch}${NC}`);
111
+ logger.info(
112
+ `${DIM}Arquivo: ${latestFile} | Status: GO | Válido por mais ${Math.round(maxAgeHours - (new Date() - new Date(dateStr)) / (1000 * 60 * 60))}h${NC}`
113
+ );
114
+ process.exit(0);
112
115
  }
@@ -1,16 +1,7 @@
1
1
  import { buildReport } from "../lib/core/token-report.js";
2
2
  import { resolveEnvPath, loadEnv } from "../lib/env-loader.js";
3
3
  import { getFrameworkRoot } from "../lib/utils/paths.js";
4
- import {
5
- showBanner,
6
- RED,
7
- GREEN,
8
- BLUE,
9
- YELLOW,
10
- CYAN,
11
- DIM,
12
- NC,
13
- } from "../lib/utils/ui.js";
4
+ import { showBanner, RED, GREEN, BLUE, YELLOW, CYAN, DIM, NC } from "../lib/utils/ui.js";
14
5
  import { logger } from "../lib/utils/logger.js";
15
6
 
16
7
  const AXES = ["HUB", "POSITION", "AREA", "SQUAD"];
@@ -50,9 +41,11 @@ export async function tokens(flags) {
50
41
  if (missing.length > 0) {
51
42
  logger.error(`${RED}❌ Perfil incompleto: faltam ${missing.join(", ")}${NC}`);
52
43
  logger.info(
53
- `${YELLOW}Uso: jarvis tokens [--hub X --position Y --area Z --squad W] [--rtk] [--json]${NC}`,
44
+ `${YELLOW}Uso: jarvis tokens [--hub X --position Y --area Z --squad W] [--rtk] [--json]${NC}`
45
+ );
46
+ logger.info(
47
+ `${DIM}Sem flags, o perfil vem do ENV.md do workspace (use --ide <ide> se houver mais de um).${NC}\n`
54
48
  );
55
- logger.info(`${DIM}Sem flags, o perfil vem do ENV.md do workspace (use --ide <ide> se houver mais de um).${NC}\n`);
56
49
  process.exit(1);
57
50
  }
58
51
 
@@ -67,27 +60,31 @@ export async function tokens(flags) {
67
60
  logger.info(`${CYAN}📏 Custo estimado no início da sessão${NC}`);
68
61
  logger.info(
69
62
  `${DIM}Perfil: HUB=${profile.HUB} | POSITION=${profile.POSITION} | AREA=${profile.AREA} | SQUAD=${profile.SQUAD}` +
70
- ` | RTK=${rtkEnabled ? "ligado" : "desligado"}${NC}`,
63
+ ` | RTK=${rtkEnabled ? "ligado" : "desligado"}${NC}`
71
64
  );
72
65
  logger.info(`${DIM}${report.estimate}${NC}`);
73
66
  logger.info("");
74
- logger.info(`${DIM}${"Tipo".padEnd(26)}${"Arquivos".padStart(9)}${"KB".padStart(10)}${"Tokens (≈)".padStart(13)}${NC}`);
67
+ logger.info(
68
+ `${DIM}${"Tipo".padEnd(26)}${"Arquivos".padStart(9)}${"KB".padStart(10)}${"Tokens (≈)".padStart(13)}${NC}`
69
+ );
75
70
  logger.info(`${DIM}${"─".repeat(58)}${NC}`);
76
71
 
77
72
  for (const c of report.categories) {
78
73
  logger.info(
79
74
  `${GREEN}${c.label.padEnd(26)}${NC}${String(c.files.length).padStart(9)}` +
80
- `${kb(c.bytes).padStart(10)}${String(c.tokens).padStart(13)}`,
75
+ `${kb(c.bytes).padStart(10)}${String(c.tokens).padStart(13)}`
81
76
  );
82
77
  if (c.files[0]) {
83
- logger.info(` ${DIM}maior: ${c.files[0].path} (${kb(c.files[0].bytes)} KB) — ${c.note}${NC}`);
78
+ logger.info(
79
+ ` ${DIM}maior: ${c.files[0].path} (${kb(c.files[0].bytes)} KB) — ${c.note}${NC}`
80
+ );
84
81
  }
85
82
  }
86
83
 
87
84
  logger.info(`${DIM}${"─".repeat(58)}${NC}`);
88
85
  logger.info(
89
86
  `${BLUE}${"Total".padEnd(26)}${NC}${"".padStart(9)}` +
90
- `${kb(report.total.bytes).padStart(10)}${String(report.total.tokens).padStart(13)}`,
87
+ `${kb(report.total.bytes).padStart(10)}${String(report.total.tokens).padStart(13)}`
91
88
  );
92
89
  logger.info("");
93
90
  }
@@ -1,43 +1,47 @@
1
- import { resolveUser, readSession, clearSession } from '../lib/auth/session.js'
2
- import { loadEnv, resolveEnvPath } from '../lib/env-loader.js'
3
- import { logger, configureFromFlags } from '../lib/utils/logger.js'
4
- import { GREEN, YELLOW, BLUE, DIM, NC } from '../lib/utils/ui.js'
1
+ import { resolveUser, readSession, clearSession } from "../lib/auth/session.js";
2
+ import { loadEnv, resolveEnvPath } from "../lib/env-loader.js";
3
+ import { logger, configureFromFlags } from "../lib/utils/logger.js";
4
+ import { GREEN, YELLOW, BLUE, DIM, NC } from "../lib/utils/ui.js";
5
5
 
6
6
  export async function whoami(flags) {
7
- configureFromFlags(flags)
7
+ configureFromFlags(flags);
8
8
 
9
9
  if (flags.logout) {
10
- clearSession()
11
- logger.info(`${GREEN}✓ ~/.jarvis/auth.json removido${NC}`)
12
- logger.info(`${DIM}Login não é mais necessário — identidade vem de USER= no ENV.md, git ou SO.${NC}`)
13
- return
10
+ clearSession();
11
+ logger.info(`${GREEN}✓ ~/.jarvis/auth.json removido${NC}`);
12
+ logger.info(
13
+ `${DIM}Login não é mais necessário — identidade vem de USER= no ENV.md, git ou SO.${NC}`
14
+ );
15
+ return;
14
16
  }
15
17
 
16
- let env = {}
18
+ let env = {};
17
19
  try {
18
- const cwd = process.cwd()
19
- const resolved = resolveEnvPath(cwd, flags)
20
- env = loadEnv(cwd, resolved.path)
20
+ const cwd = process.cwd();
21
+ const resolved = resolveEnvPath(cwd, flags);
22
+ env = loadEnv(cwd, resolved.path);
21
23
  } catch {
22
24
  // sem ENV.md ainda — resolve via git/os
23
25
  }
24
26
 
25
- const { id, source } = resolveUser(env)
27
+ const { id, source } = resolveUser(env);
26
28
 
27
- logger.info('')
28
- logger.info(`${BLUE}👤 Identidade${NC}`)
29
- logger.info('')
30
- logger.info(` ${BLUE}USER:${NC} ${id}`)
31
- logger.info(` ${BLUE}Fonte:${NC} ${source}`)
32
- logger.info('')
33
- logger.info(`${DIM}Sem login. Ordem: ENV.md (USER=) → git config user.email → usuário do SO.${NC}`)
29
+ logger.info("");
30
+ logger.info(`${BLUE}👤 Identidade${NC}`);
31
+ logger.info("");
32
+ logger.info(` ${BLUE}USER:${NC} ${id}`);
33
+ logger.info(` ${BLUE}Fonte:${NC} ${source}`);
34
+ logger.info("");
35
+ logger.info(
36
+ `${DIM}Sem login. Ordem: ENV.md (USER=) → git config user.email → usuário do SO.${NC}`
37
+ );
34
38
 
35
- const leftover = readSession()
39
+ const leftover = readSession();
36
40
  if (leftover?.email) {
37
- logger.info('')
38
- logger.info(` ${YELLOW}⚠ ~/.jarvis/auth.json legado (${leftover.email}) — não é usado.${NC}`)
39
- logger.info(` ${DIM}Remova com: jarvis logout${NC}`)
41
+ logger.info("");
42
+ logger.info(` ${YELLOW}⚠ ~/.jarvis/auth.json legado (${leftover.email}) — não é usado.${NC}`);
43
+ logger.info(` ${DIM}Remova com: jarvis logout${NC}`);
40
44
  }
41
45
 
42
- logger.info('')
46
+ logger.info("");
43
47
  }