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.
- package/AGENTS.md +22 -122
- package/agents/AGENTS.md +20 -24
- package/agents/README.md +25 -129
- package/agents/engineering/data/eng.data-engineer.agent.md +12 -35
- package/agents/engineering/eng.agent.md +18 -30
- package/agents/engineering/eng.bug-hunter.md +9 -12
- package/agents/engineering/eng.dev-code-reviewer.md +5 -1
- package/agents/engineering/eng.docs-writer.md +3 -3
- package/agents/engineering/eng.frontend.agent.md +13 -8
- package/agents/engineering/eng.rpa.agent.md +5 -13
- package/agents/engineering/eng.ux-designer.agent.md +4 -0
- package/agents/engineering/qa/eng.qa.quality-champion-task-agent.md +4 -0
- package/agents/engineering/qa/eng.qa.quality-strategist.md +13 -8
- package/agents/engineering/qa/eng.qa.test-architect.md +16 -15
- package/agents/engineering/qa/eng.qa.test-planner.md +22 -17
- package/agents/engineering/qa/eng.qa.testing-engineer.md +99 -15
- package/agents/product/prod.discovery-interviewer.md +22 -3
- package/agents/product/prod.pm-checker.md +4 -0
- package/bin/README.md +142 -0
- package/bin/commands/docs-publish.js +105 -141
- package/bin/commands/docs-sync.js +66 -104
- package/bin/commands/info.js +7 -27
- package/bin/commands/init.js +23 -51
- package/bin/commands/install-rtk.js +9 -3
- package/bin/commands/list.js +5 -18
- package/bin/commands/map.js +58 -0
- package/bin/commands/qa-signoff.js +58 -55
- package/bin/commands/tokens.js +90 -0
- package/bin/commands/whoami.js +30 -26
- package/bin/jarvis.js +9 -153
- package/bin/lib/auth/session.js +20 -20
- package/bin/lib/cli/program.js +219 -0
- package/bin/lib/cli/shared-options.js +29 -0
- package/bin/lib/config/constants.js +70 -2
- package/bin/lib/config/ide-config.js +4 -8
- package/bin/lib/core/profile-filter.js +116 -0
- package/bin/lib/core/scanner.js +5 -31
- package/bin/lib/core/sync-engine.js +21 -14
- package/bin/lib/core/token-report.js +100 -0
- package/bin/lib/docs/fetch-file.js +39 -0
- package/bin/lib/docs/publish-file.js +194 -0
- package/bin/lib/docs/redis-cache.js +49 -0
- package/bin/lib/docs/validate-frontmatter.js +9 -39
- package/bin/lib/env-loader.js +11 -34
- package/bin/lib/flow-map/index.js +65 -0
- package/bin/lib/flow-map/parse.js +223 -0
- package/bin/lib/flow-map/render.js +89 -0
- package/bin/lib/flow-map/tree.js +248 -0
- package/bin/lib/tasks/comment.js +40 -35
- package/bin/lib/utils/frontmatter.js +57 -0
- package/bin/lib/utils/git-parser.js +4 -6
- package/bin/lib/utils/npmrc-parser.js +6 -13
- package/bin/lib/utils/paths.js +2 -4
- package/bin/lib/utils/ui.js +3 -9
- package/bin/lib/vcs/api.js +25 -41
- package/bin/lib/vcs/create-issue.js +49 -33
- package/bin/lib/vcs/create-merge.js +47 -31
- package/bin/lib/vcs/fetch-raw.js +35 -23
- package/members.md +1 -1
- package/package.json +15 -4
- package/rules/AGENTS.md +18 -7
- package/rules/engineering/eng-rules.md +3 -13
- package/rules/engineering/eng-security-rules.md +19 -18
- package/rules/engineering/eng.bump-rules.md +3 -2
- package/rules/engineering/eng.docs-scraping-rules.md +4 -4
- package/rules/engineering/eng.integrations-rules.md +3 -7
- package/rules/engineering/eng.skills-rules.md +1 -5
- package/rules/engineering/eng.specializations-rules.md +18 -8
- package/rules/engineering/frontend/eng.frontend-rules.md +1 -4
- package/rules/engineering/qa/eng.qa.cypress-standards-rules.md +1 -1
- package/rules/engineering/rpa/eng.rpa-rules.md +4 -9
- package/rules/product/README.md +1 -0
- package/rules/product/prod-rules.md +1 -4
- package/rules/product/prod.spec-rules.md +0 -4
- package/rules/rtk-rules.md +0 -1
- package/{rules → rules-on-demand}/engineering/eng.breakdown-subtasks-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.plan-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.pr-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.pre-pr-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.start-rules.md +0 -4
- package/{rules → rules-on-demand}/engineering/eng.tech-spec-rules.md +1 -2
- package/{rules → rules-on-demand}/engineering/eng.work-rules.md +0 -4
- package/skills/AGENTS.md +69 -106
- package/skills/SKILLS-ROADMAP.md +47 -132
- package/skills/eng-ai/SKILL.md +270 -0
- package/skills/eng-ai/references/1-fundamentos-ml.md +24 -0
- package/skills/eng-ai/references/10-arquitetura-solucoes-ia.md +24 -0
- package/skills/eng-ai/references/11-governanca-ia.md +24 -0
- package/skills/eng-ai/references/12-seguranca-ia-responsavel.md +25 -0
- package/skills/eng-ai/references/2-matematica-estatistica.md +24 -0
- package/skills/eng-ai/references/3-dados-para-ia.md +24 -0
- package/skills/eng-ai/references/4-deep-learning-fundacionais.md +24 -0
- package/skills/eng-ai/references/5-llms-chatbots-agentes-rag.md +25 -0
- package/skills/eng-ai/references/6-avaliacao-experimentacao.md +24 -0
- package/skills/eng-ai/references/7-engenharia-sistemas-ia.md +24 -0
- package/skills/eng-ai/references/8-mlops-plataforma.md +24 -0
- package/skills/eng-ai/references/9-produto-ia.md +24 -0
- package/skills/eng-ai/references/especializacoes.md +17 -0
- package/skills/eng-automation/SKILL.md +290 -0
- package/skills/eng-automation/references/1-fundamentos-automacao.md +25 -0
- package/skills/eng-automation/references/10-ingestao-dados.md +25 -0
- package/skills/eng-automation/references/11-captcha-antibot.md +25 -0
- package/skills/eng-automation/references/12-limites-taxa-sessoes.md +25 -0
- package/skills/eng-automation/references/13-agendamento-orquestracao.md +24 -0
- package/skills/eng-automation/references/14-retentativa-erros.md +25 -0
- package/skills/eng-automation/references/15-autenticacao-credenciais.md +24 -0
- package/skills/eng-automation/references/16-observabilidade-confiabilidade.md +24 -0
- package/skills/eng-automation/references/2-aquisicao-dados.md +25 -0
- package/skills/eng-automation/references/3-automacao-navegador.md +24 -0
- package/skills/eng-automation/references/4-scraping-crawling.md +25 -0
- package/skills/eng-automation/references/5-apis-rest-graphql-soap.md +26 -0
- package/skills/eng-automation/references/6-webhooks-integracao.md +25 -0
- package/skills/eng-automation/references/7-rpa.md +25 -0
- package/skills/eng-automation/references/8-extracao-estruturada.md +25 -0
- package/skills/eng-automation/references/9-extracao-documentos.md +25 -0
- package/skills/eng-automation/references/especializacoes.md +18 -0
- package/skills/eng-backend/SKILL.md +6 -0
- package/skills/eng-backend-arch-c4/SKILL.md +10 -4
- package/skills/eng-backend-microservices-trace/SKILL.md +6 -0
- package/skills/eng-backend-nestjs/SKILL.md +17 -462
- package/skills/eng-backend-nestjs/references/1-arquitetura-modulos.md +54 -0
- package/skills/eng-backend-nestjs/references/2-guards-autenticacao.md +118 -0
- package/skills/eng-backend-nestjs/references/3-interceptors-pipes-filters.md +113 -0
- package/skills/eng-backend-nestjs/references/4-config-logging.md +61 -0
- package/skills/eng-backend-nestjs/references/5-testes.md +83 -0
- package/skills/eng-backend-nestjs/references/6-problemas-comuns.md +53 -0
- package/skills/eng-backend-rabbitmq/SKILL.md +15 -298
- package/skills/eng-backend-rabbitmq/references/1-referencia-endpoints.md +28 -0
- package/skills/eng-backend-rabbitmq/references/2-codigo-consumer-producer.md +90 -0
- package/skills/eng-backend-rabbitmq/references/3-arquiteturas-comuns.md +101 -0
- package/skills/eng-backend-rabbitmq/references/4-troubleshooting.md +93 -0
- package/skills/eng-data/SKILL.md +271 -0
- package/skills/eng-data/references/1-fundamentos-dados.md +24 -0
- package/skills/eng-data/references/10-ciencia-dados.md +24 -0
- package/skills/eng-data/references/11-dataops-plataforma.md +24 -0
- package/skills/eng-data/references/12-seguranca-privacidade.md +24 -0
- package/skills/eng-data/references/2-modelagem-dados.md +24 -0
- package/skills/eng-data/references/3-bancos-dados.md +24 -0
- package/skills/eng-data/references/4-arquitetura-dados.md +24 -0
- package/skills/eng-data/references/5-pipelines-integracao.md +24 -0
- package/skills/eng-data/references/6-qualidade-dados.md +24 -0
- package/skills/eng-data/references/7-governanca-metadados.md +24 -0
- package/skills/eng-data/references/8-estatistica-analise.md +24 -0
- package/skills/eng-data/references/9-analytics-bi.md +24 -0
- package/skills/eng-data/references/especializacoes.md +20 -0
- package/skills/eng-frontend/SKILL.md +18 -5
- package/skills/eng-frontend/references/13-design-system.md +48 -0
- package/skills/eng-frontend/references/14-microfrontend.md +46 -0
- package/skills/eng-global-docs-write/SKILL.md +10 -5
- package/skills/eng-global-pr/SKILL.md +7 -1
- package/skills/eng-global-task-comment/SKILL.md +8 -2
- package/skills/eng-platform/SKILL.md +331 -0
- package/skills/eng-platform/references/1-fundamentos-sistemas.md +23 -0
- package/skills/eng-platform/references/10-resiliencia-arquitetura.md +24 -0
- package/skills/eng-platform/references/11-plataforma-devex.md +24 -0
- package/skills/eng-platform/references/12-finops-custos.md +24 -0
- package/skills/eng-platform/references/13-seguranca-fundamentos.md +26 -0
- package/skills/eng-platform/references/14-profiling-performance.md +23 -0
- package/skills/eng-platform/references/15-testes-carga-chaos.md +23 -0
- package/skills/eng-platform/references/16-cache-multicamada.md +22 -0
- package/skills/eng-platform/references/2-redes.md +23 -0
- package/skills/eng-platform/references/3-cloud.md +24 -0
- package/skills/eng-platform/references/4-iac-automacao.md +24 -0
- package/skills/eng-platform/references/5-containers-orquestracao.md +25 -0
- package/skills/eng-platform/references/6-cicd-entrega.md +24 -0
- package/skills/eng-platform/references/7-observabilidade.md +24 -0
- package/skills/eng-platform/references/8-confiabilidade-sre.md +24 -0
- package/skills/eng-platform/references/9-seguranca-infra.md +26 -0
- package/skills/eng-platform/references/especializacoes.md +34 -0
- package/skills/eng-qa/SKILL.md +283 -0
- package/skills/eng-qa/references/1-fundamentos-qualidade.md +25 -0
- package/skills/eng-qa/references/10-confiabilidade.md +25 -0
- package/skills/eng-qa/references/11-seguranca.md +24 -0
- package/skills/eng-qa/references/12-acessibilidade.md +24 -0
- package/skills/eng-qa/references/13-dados-testes.md +24 -0
- package/skills/eng-qa/references/14-gestao-testes-defeitos.md +25 -0
- package/skills/eng-qa/references/15-arquitetura-qa.md +25 -0
- package/skills/eng-qa/references/2-estrategia-planejamento.md +25 -0
- package/skills/eng-qa/references/3-design-testes.md +25 -0
- package/skills/eng-qa/references/4-manual-exploratorio.md +24 -0
- package/skills/eng-qa/references/5-automacao-testes.md +25 -0
- package/skills/eng-qa/references/6-api-integracao.md +25 -0
- package/skills/eng-qa/references/7-contrato.md +24 -0
- package/skills/eng-qa/references/8-interface-compat-mobile.md +24 -0
- package/skills/eng-qa/references/9-performance.md +24 -0
- package/skills/eng-qa/references/especializacoes.md +29 -0
- package/skills/eng-qa-planner/SKILL.md +264 -0
- package/skills/jarvis-context-detect/SKILL.md +7 -1
- package/skills/jarvis-context-detect/assets/context-profile-template.md +1 -1
- package/skills/jarvis-create-specialization/SKILL.md +14 -0
- package/skills/jarvis-docs-central/README.md +31 -28
- package/skills/jarvis-docs-central/SKILL.md +11 -5
- package/skills/jarvis-docs-index/SKILL.md +10 -2
- package/skills/jarvis-evolution-architect/SKILL.md +6 -0
- package/skills/jarvis-init/SKILL.md +22 -15
- package/skills/jarvis-init/assets/passo-adicionar-stacks.md +47 -18
- package/skills/jarvis-list-specializations/SKILL.md +36 -17
- package/skills/jarvis-report-issue/SKILL.md +7 -1
- package/skills/product-roadmap-report/SKILL.md +8 -0
- package/skills/product-specs/SKILL.md +9 -0
- package/skills/product-specs-update/SKILL.md +6 -0
- package/taxonomy.md +16 -28
- package/templates/AGENTS.md +2 -0
- package/templates/ENV-template.md +10 -2
- package/templates/engineering/qa/qa.sprint-plan-template.md +1 -1
- package/templates/engineering/tech-spec-delivery-template.md +179 -0
- package/workflows/AGENTS.md +14 -2
- package/workflows/README.md +8 -16
- package/workflows/all-tools.md +7 -1
- package/workflows/engineering/data/data.contract.md +8 -0
- package/workflows/engineering/data/data.new-pipeline.md +15 -4
- package/workflows/engineering/eng.breakdown-subtasks.md +9 -0
- package/workflows/engineering/eng.bug-audit.md +10 -13
- package/workflows/engineering/eng.build-tech-spec.md +17 -146
- package/workflows/engineering/eng.create-ard-from-code.md +8 -0
- package/workflows/engineering/eng.create-ard.md +8 -0
- package/workflows/engineering/eng.create-rfc.md +7 -0
- package/workflows/engineering/eng.debug.md +5 -21
- package/workflows/engineering/eng.docs.md +9 -0
- package/workflows/engineering/eng.light-arch.md +7 -0
- package/workflows/engineering/eng.plan.md +15 -2
- package/workflows/engineering/eng.pr.md +24 -30
- package/workflows/engineering/eng.pre-pr.md +33 -15
- package/workflows/engineering/eng.review.md +18 -11
- package/workflows/engineering/eng.rpa.robot.md +17 -7
- package/workflows/engineering/eng.start.md +33 -12
- package/workflows/engineering/eng.work.md +25 -17
- package/workflows/engineering/frontend/eng.frontend-component.md +7 -0
- package/workflows/engineering/frontend/eng.frontend-perf-audit.md +8 -0
- package/workflows/engineering/frontend/eng.frontend-review.md +8 -0
- package/workflows/engineering/qa/eng.qa-refinement-entry.md +7 -0
- package/workflows/engineering/qa/eng.qa-release-signoff.md +6 -0
- package/workflows/engineering/qa/eng.qa-sprint-planning.md +7 -1
- package/workflows/product/prod.roadmap.preview.md +9 -0
- package/workflows/product/prod.spec.ard.md +97 -0
- package/workflows/product/prod.spec.breakdown.md +10 -0
- package/workflows/product/prod.spec.clarify.md +8 -2
- package/workflows/product/prod.spec.discovery.md +11 -1
- package/workflows/product/prod.spec.epic.md +8 -0
- package/workflows/product/prod.spec.frd.md +7 -0
- package/workflows/product/prod.spec.issue.md +6 -0
- package/workflows/product/prod.spec.md +15 -1
- package/workflows/product/prod.spec.prd.md +7 -0
- package/workflows/taxonomy.md +58 -6
- package/workflows/warm-up.md +47 -60
- package/agents/engineering/eng.cybersecurity.agent.md +0 -488
- package/agents/engineering/qa/eng.qa.cypress-specialist.md +0 -109
- package/bin/lib/docs/fetch-file.sh +0 -41
- package/bin/lib/docs/publish-file.sh +0 -284
- package/rules/engineering/eng.downstream-flow-rules.md +0 -297
- package/rules/engineering/qa/eng.qa.exploratory-session-rules.md +0 -137
- package/rules/engineering/qa/eng.qa.quality-gate-scoring-rules.md +0 -181
- package/rules/engineering/qa/eng.qa.tech-spec-validation-criteria-rules.md +0 -120
- package/skills/eng-ai-engineer/SKILL.md +0 -297
- package/skills/eng-data-bi/SKILL.md +0 -200
- package/skills/eng-data-debug/SKILL.md +0 -308
- package/skills/eng-data-engineer/SKILL.md +0 -257
- package/skills/eng-data-onboard/SKILL.md +0 -311
- package/skills/eng-data-orchestrator/SKILL.md +0 -427
- package/skills/eng-devops-performance-engineer/SKILL.md +0 -313
- package/skills/eng-frontend-design-system/SKILL.md +0 -621
- package/skills/eng-frontend-microfrontend/SKILL.md +0 -604
- package/skills/eng-global-browser-extension-builder/SKILL.md +0 -386
- package/skills/eng-global-jira-comment/SKILL.md +0 -21
- package/skills/eng-qa-a11y-audit/SKILL.md +0 -270
- package/skills/eng-qa-bug-report/SKILL.md +0 -1089
- package/skills/eng-qa-bug-report/TASK_MANAGERS.md +0 -138
- package/skills/eng-qa-cypress-e2e/SKILL.md +0 -178
- package/skills/eng-qa-dev-guide/SKILL.md +0 -165
- package/skills/eng-qa-e2e/SKILL.md +0 -401
- package/skills/eng-qa-e2e-spec-writer/SKILL.md +0 -323
- package/skills/eng-qa-exploratory/SKILL.md +0 -189
- package/skills/eng-qa-gate/SKILL.md +0 -371
- package/skills/eng-qa-gate/assets/checklist-validacao.md +0 -291
- package/skills/eng-qa-graphql-contract/SKILL.md +0 -257
- package/skills/eng-qa-quality-report/SKILL.md +0 -413
- package/skills/eng-qa-test-plan/SKILL.md +0 -467
- package/skills/eng-qa-testsprite/SKILL.md +0 -326
- package/skills/eng-qa-testsprite/references/testsprite-mcp.md +0 -224
- package/skills/eng-qa-unit-test/SKILL.md +0 -472
- package/skills/eng-scraper/SKILL.md +0 -684
- package/skills/eng-scraper-robot-builder/SKILL.md +0 -371
- package/skills/eng-security-cybersecurity/SKILL.md +0 -646
- package/skills/eng-security-patch/SKILL.md +0 -382
- package/skills/eng-security-threat-model/SKILL.md +0 -165
- package/skills/eng-security-triage/SKILL.md +0 -270
- package/templates/engineering/qa/eng.qa.quality-gate-examples-template.md +0 -311
- package/templates/engineering/qa/eng.qa.quality-gate-report-template.md +0 -249
- package/templates/engineering/qa/qa.cypress-test-template.md +0 -172
- package/templates/engineering/qa/qa.exploratory-session-template.md +0 -148
- package/templates/engineering/qa/qa.quality-report-template.md +0 -130
- package/workflows/engineering/eng.security-audit.md +0 -312
- package/workflows/engineering/eng.security-incident.md +0 -275
- package/workflows/engineering/eng.security-pipeline.md +0 -210
- package/workflows/engineering/eng.security-review.md +0 -235
- package/workflows/engineering/qa/eng.qa-dev-quality-guide.md +0 -51
- package/workflows/engineering/qa/eng.qa-e2e-test-generation.md +0 -51
- package/workflows/engineering/qa/eng.qa-exploratory-session.md +0 -60
- package/workflows/engineering/qa/eng.qa-quality-gate-validation.md +0 -202
- package/workflows/engineering/qa/eng.qa-quality-report.md +0 -78
- /package/skills/{eng-qa-test-plan → eng-qa-planner}/assets/test-coverage-template.md +0 -0
- /package/skills/{eng-qa-test-plan → eng-qa-planner}/assets/test-patterns.md +0 -0
- /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
|
-
|
|
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
|
+
}
|
package/bin/lib/core/scanner.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
34
|
-
if (
|
|
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
|
|
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 =
|
|
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"))
|
|
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 {
|
|
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 {
|
|
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
|
|
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 || "")
|
|
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
|
|