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
@@ -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
  }
@@ -0,0 +1,90 @@
1
+ import { buildReport } from "../lib/core/token-report.js";
2
+ import { resolveEnvPath, loadEnv } from "../lib/env-loader.js";
3
+ import { getFrameworkRoot } from "../lib/utils/paths.js";
4
+ import { showBanner, RED, GREEN, BLUE, YELLOW, CYAN, DIM, NC } from "../lib/utils/ui.js";
5
+ import { logger } from "../lib/utils/logger.js";
6
+
7
+ const AXES = ["HUB", "POSITION", "AREA", "SQUAD"];
8
+
9
+ /** Perfil: as flags (`--hub` etc.) mandam; o que faltar vem do ENV.md. */
10
+ function resolveProfile(flags) {
11
+ const profile = {};
12
+ for (const axis of AXES) {
13
+ const value = flags[axis.toLowerCase()];
14
+ if (typeof value === "string") profile[axis] = value;
15
+ }
16
+
17
+ let rtkEnabled = flags.rtk === true || flags.rtk === "true";
18
+ // O ENV.md só entra quando falta algum eixo; com os 4 eixos nas flags, o RTK vem só da flag.
19
+ if (AXES.some((axis) => !profile[axis])) {
20
+ try {
21
+ const { path } = resolveEnvPath(process.cwd(), flags);
22
+ const env = loadEnv(process.cwd(), path);
23
+ for (const axis of AXES) {
24
+ if (!profile[axis] && env[axis]) profile[axis] = env[axis];
25
+ }
26
+ if (flags.rtk === undefined) rtkEnabled = env.RTK_ENABLED === "true";
27
+ } catch {
28
+ // sem ENV.md: valem só as flags
29
+ }
30
+ }
31
+
32
+ const missing = AXES.filter((axis) => !profile[axis]);
33
+ return { profile, rtkEnabled, missing };
34
+ }
35
+
36
+ const kb = (bytes) => (bytes / 1000).toFixed(1);
37
+
38
+ export async function tokens(flags) {
39
+ const { profile, rtkEnabled, missing } = resolveProfile(flags);
40
+
41
+ if (missing.length > 0) {
42
+ logger.error(`${RED}❌ Perfil incompleto: faltam ${missing.join(", ")}${NC}`);
43
+ logger.info(
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`
48
+ );
49
+ process.exit(1);
50
+ }
51
+
52
+ const report = buildReport(getFrameworkRoot(), profile, { rtkEnabled });
53
+
54
+ if (flags.json) {
55
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
56
+ return;
57
+ }
58
+
59
+ showBanner();
60
+ logger.info(`${CYAN}📏 Custo estimado no início da sessão${NC}`);
61
+ logger.info(
62
+ `${DIM}Perfil: HUB=${profile.HUB} | POSITION=${profile.POSITION} | AREA=${profile.AREA} | SQUAD=${profile.SQUAD}` +
63
+ ` | RTK=${rtkEnabled ? "ligado" : "desligado"}${NC}`
64
+ );
65
+ logger.info(`${DIM}${report.estimate}${NC}`);
66
+ logger.info("");
67
+ logger.info(
68
+ `${DIM}${"Tipo".padEnd(26)}${"Arquivos".padStart(9)}${"KB".padStart(10)}${"Tokens (≈)".padStart(13)}${NC}`
69
+ );
70
+ logger.info(`${DIM}${"─".repeat(58)}${NC}`);
71
+
72
+ for (const c of report.categories) {
73
+ logger.info(
74
+ `${GREEN}${c.label.padEnd(26)}${NC}${String(c.files.length).padStart(9)}` +
75
+ `${kb(c.bytes).padStart(10)}${String(c.tokens).padStart(13)}`
76
+ );
77
+ if (c.files[0]) {
78
+ logger.info(
79
+ ` ${DIM}maior: ${c.files[0].path} (${kb(c.files[0].bytes)} KB) — ${c.note}${NC}`
80
+ );
81
+ }
82
+ }
83
+
84
+ logger.info(`${DIM}${"─".repeat(58)}${NC}`);
85
+ logger.info(
86
+ `${BLUE}${"Total".padEnd(26)}${NC}${"".padStart(9)}` +
87
+ `${kb(report.total.bytes).padStart(10)}${String(report.total.tokens).padStart(13)}`
88
+ );
89
+ logger.info("");
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
  }
package/bin/jarvis.js CHANGED
@@ -1,159 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { argv, exit } from "node:process";
4
- import { readFileSync } from "node:fs";
5
- import { dirname, join } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
- import { init } from "./commands/init.js";
8
- import { list } from "./commands/list.js";
9
- import { info } from "./commands/info.js";
10
- import { whoami } from "./commands/whoami.js";
11
- import { docsSync } from "./commands/docs-sync.js";
12
- import { docsPublish } from "./commands/docs-publish.js"
13
- import { qaSignoff } from "./commands/qa-signoff.js";
14
- import { installRtk } from "./commands/install-rtk.js";
15
- import { formatIDEsList } from "./lib/config/ide-config.js";
16
- import { showBanner, BLUE, GREEN, YELLOW, DIM, NC } from "./lib/utils/ui.js";
17
- import { logger } from "./lib/utils/logger.js";
3
+ import { buildProgram } from "./lib/cli/program.js";
18
4
 
19
- const __filename = fileURLToPath(import.meta.url);
20
- const __dirname = dirname(__filename);
21
- const args = argv.slice(2);
22
- const command = args[0];
5
+ const program = buildProgram();
23
6
 
24
- // Lazy loading do package.json (só quando necessário)
25
- let _version = null;
26
- function getVersion() {
27
- if (_version === null) {
28
- const packageJson = JSON.parse(
29
- readFileSync(join(__dirname, "../package.json"), "utf-8"),
30
- );
31
- _version = packageJson.version;
32
- }
33
- return _version;
7
+ // Sem comando: mostra a ajuda e sai com sucesso (não é um erro de uso).
8
+ // O default do commander para esse caso é process.exit(1); aqui replicamos
9
+ // o comportamento do dispatcher antigo, que apenas chamava help() e seguia.
10
+ if (process.argv.length <= 2) {
11
+ program.outputHelp();
12
+ process.exit(0);
34
13
  }
35
14
 
36
- function help() {
37
- showBanner();
38
-
39
- logger.info(`${BLUE}📚 Ajuda${NC}\n`);
40
-
41
- logger.info(`${YELLOW}Uso:${NC}`);
42
- logger.info(
43
- ` ${GREEN}jarvis init${NC} [--ide <ide>] Bootstrap framework no workspace`,
44
- );
45
- logger.info(
46
- ` ${GREEN}jarvis list${NC} Listar agents, skills & workflows`,
47
- );
48
- logger.info(
49
- ` ${GREEN}jarvis info${NC} <type/name> Detalhes de um prompt`,
50
- );
51
- logger.info(
52
- ` ${GREEN}jarvis whoami${NC} Exibir identidade (ENV.md / git / SO)`,
53
- );
54
- logger.info(
55
- ` ${GREEN}jarvis logout${NC} Remover auth.json legado`,
56
- );
57
- logger.info(
58
- ` ${GREEN}jarvis docs sync${NC} [--silent] [--verbose] Sincronizar docs do central-docs`,
59
- );
60
- logger.info(
61
- ` ${GREEN}jarvis docs publish${NC} --file <path> --tipo <tipo> --feature <slug> [--squad <squad>] [--workspace <workspace>]`,
62
- );
63
- logger.info(
64
- ` ${GREEN}jarvis install-rtk${NC} Instalar RTK (token killer — economia 60-90%)`,
65
- );
66
- logger.info(
67
- ` ${GREEN}jarvis qa-signoff${NC} [--branch <branch>] [--max-age <horas>] Verificar sign-off QA (usado pelo CI)`,
68
- );
69
- logger.info(
70
- ` ${GREEN}jarvis --version${NC} Versão instalada`,
71
- );
72
- logger.info("");
73
-
74
- logger.info(`${YELLOW}IDEs Suportadas:${NC}`);
75
- logger.info(` ${formatIDEsList()}`);
76
- logger.info("");
77
-
78
- logger.info(`${YELLOW}🚀 Começar:${NC}`);
79
- logger.info(
80
- ` ${DIM}1.${NC} npm install -g ${GREEN}/caminho/para/jarvis${NC}`,
81
- );
82
- logger.info(` ${DIM}2.${NC} ${GREEN}jarvis init${NC} --ide cursor`);
83
- logger.info(` ${DIM}3.${NC} No chat da IDE: ${GREEN}/jarvis-init${NC}`);
84
- logger.info("");
85
-
86
- logger.info(`${BLUE}📖 Exemplos:${NC}`);
87
- logger.info(
88
- ` ${GREEN}jarvis list${NC} Listar todos os prompts`,
89
- );
90
- logger.info(
91
- ` ${GREEN}jarvis info agent/eng${NC} Detalhes do agent eng`,
92
- );
93
- logger.info(
94
- ` ${GREEN}jarvis docs sync${NC} Sincronizar docs do central-docs`,
95
- );
96
- logger.info(
97
- ` ${GREEN}jarvis docs publish --file ./docs/ard.md --tipo ard --feature auth-jwt${NC}`,
98
- );
99
- logger.info("");
100
- }
101
-
102
- function parseFlags(args) {
103
- const flags = {};
104
- for (let i = 0; i < args.length; i++) {
105
- if (args[i].startsWith("--")) {
106
- const key = args[i].slice(2);
107
- flags[key] =
108
- args[i + 1] && !args[i + 1].startsWith("--") ? args[++i] : true;
109
- } else {
110
- flags._ = flags._ || [];
111
- flags._.push(args[i]);
112
- }
113
- }
114
- return flags;
115
- }
116
-
117
- const flags = parseFlags(args.slice(1));
118
-
119
- const commands = {
120
- init: () => init(flags),
121
- list: () => list(flags),
122
- ls: () => list(flags),
123
- info: () => info(flags._?.[0], flags),
124
- logout: () => whoami({ ...flags, logout: true }),
125
- whoami: () => whoami(flags),
126
- docs: () => {
127
- const subcommand = flags._?.[0];
128
- if (subcommand === "sync") {
129
- return docsSync(flags);
130
- } else if (subcommand === "publish") {
131
- return docsPublish(flags);
132
- } else {
133
- logger.error("\n Subcomando inválido para docs\n");
134
- logger.info("Uso:");
135
- logger.info(` ${GREEN}jarvis docs sync${NC} [--silent] [--verbose]`);
136
- logger.info(
137
- ` ${GREEN}jarvis docs publish${NC} --file <path> --tipo <prd|frd|ard|rfc> --feature <slug> [--squad <squad>] [--workspace <workspace>]`,
138
- );
139
- logger.info("");
140
- exit(1);
141
- }
142
- },
143
- "install-rtk": () => installRtk(flags),
144
- "qa-signoff": () => qaSignoff(flags),
145
- "--version": () => logger.info(getVersion()),
146
- "-v": () => logger.info(getVersion()),
147
- "--help": () => help(),
148
- "-h": () => help(),
149
- };
150
-
151
- if (command in commands) {
152
- await commands[command]();
153
- } else if (!command) {
154
- help();
155
- } else {
156
- logger.error(`\n Unknown command: ${command}\n`);
157
- help();
158
- exit(1);
159
- }
15
+ await program.parseAsync(process.argv);
@@ -1,22 +1,22 @@
1
- import { existsSync, readFileSync, unlinkSync } from 'node:fs'
2
- import { execSync } from 'node:child_process'
3
- import { join } from 'node:path'
4
- import { homedir, userInfo } from 'node:os'
1
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
2
+ import { execSync } from "node:child_process";
3
+ import { join } from "node:path";
4
+ import { homedir, userInfo } from "node:os";
5
5
 
6
- const SESSION_FILE = join(homedir(), '.jarvis', 'auth.json')
6
+ const SESSION_FILE = join(homedir(), ".jarvis", "auth.json");
7
7
 
8
8
  export function readSession() {
9
- if (!existsSync(SESSION_FILE)) return null
9
+ if (!existsSync(SESSION_FILE)) return null;
10
10
  try {
11
- return JSON.parse(readFileSync(SESSION_FILE, 'utf-8'))
11
+ return JSON.parse(readFileSync(SESSION_FILE, "utf-8"));
12
12
  } catch {
13
- return null
13
+ return null;
14
14
  }
15
15
  }
16
16
 
17
17
  export function clearSession() {
18
18
  if (existsSync(SESSION_FILE)) {
19
- unlinkSync(SESSION_FILE)
19
+ unlinkSync(SESSION_FILE);
20
20
  }
21
21
  }
22
22
 
@@ -25,32 +25,32 @@ export function clearSession() {
25
25
  * Order: ENV.md USER → git user.email → OS username → "local"
26
26
  */
27
27
  export function resolveUser(env = {}) {
28
- const envUser = typeof env.USER === 'string' ? env.USER.trim() : ''
29
- if (envUser) return { id: envUser, source: 'ENV.md' }
28
+ const envUser = typeof env.USER === "string" ? env.USER.trim() : "";
29
+ if (envUser) return { id: envUser, source: "ENV.md" };
30
30
 
31
31
  try {
32
- const email = execSync('git config --get user.email', {
33
- encoding: 'utf8',
34
- stdio: ['ignore', 'pipe', 'ignore'],
35
- }).trim()
36
- if (email) return { id: email, source: 'git' }
32
+ const email = execSync("git config --get user.email", {
33
+ encoding: "utf8",
34
+ stdio: ["ignore", "pipe", "ignore"],
35
+ }).trim();
36
+ if (email) return { id: email, source: "git" };
37
37
  } catch {
38
38
  // ignore
39
39
  }
40
40
 
41
41
  try {
42
- const username = userInfo().username
43
- if (username) return { id: username, source: 'os' }
42
+ const username = userInfo().username;
43
+ if (username) return { id: username, source: "os" };
44
44
  } catch {
45
45
  // ignore
46
46
  }
47
47
 
48
- return { id: 'local', source: 'fallback' }
48
+ return { id: "local", source: "fallback" };
49
49
  }
50
50
 
51
51
  /**
52
52
  * Identity used as dev_id. Never requires jarvis login.
53
53
  */
54
54
  export function getAuthUser(env = {}) {
55
- return resolveUser(env).id
55
+ return resolveUser(env).id;
56
56
  }