jarvis-ai-framework 1.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 +416 -0
- package/LICENSE +21 -0
- package/README.md +190 -0
- package/agents/AGENTS.md +234 -0
- package/agents/README.md +309 -0
- package/agents/engineering/data/eng.data-engineer.agent.md +309 -0
- package/agents/engineering/eng.agent.md +303 -0
- package/agents/engineering/eng.bug-hunter.md +386 -0
- package/agents/engineering/eng.cybersecurity.agent.md +503 -0
- package/agents/engineering/eng.dev-code-reviewer.md +148 -0
- package/agents/engineering/eng.docs-writer.md +152 -0
- package/agents/engineering/eng.frontend.agent.md +117 -0
- package/agents/engineering/eng.rpa.agent.md +215 -0
- package/agents/engineering/eng.tech-analyst.agent.md +102 -0
- package/agents/engineering/eng.ux-designer.agent.md +193 -0
- package/agents/engineering/qa/eng.qa.cypress-specialist.md +109 -0
- package/agents/engineering/qa/eng.qa.quality-champion-task-agent.md +85 -0
- package/agents/engineering/qa/eng.qa.quality-strategist.md +111 -0
- package/agents/engineering/qa/eng.qa.test-architect.md +400 -0
- package/agents/engineering/qa/eng.qa.test-planner.md +477 -0
- package/agents/engineering/qa/eng.qa.testing-engineer.md +339 -0
- package/agents/product/prod.pm-checker.md +52 -0
- package/bin/commands/docs-publish.js +184 -0
- package/bin/commands/docs-sync.js +139 -0
- package/bin/commands/info.js +87 -0
- package/bin/commands/init.js +237 -0
- package/bin/commands/install-rtk.js +90 -0
- package/bin/commands/list.js +48 -0
- package/bin/commands/qa-signoff.js +112 -0
- package/bin/commands/whoami.js +43 -0
- package/bin/jarvis.js +159 -0
- package/bin/lib/auth/session.js +56 -0
- package/bin/lib/config/constants.js +123 -0
- package/bin/lib/config/ide-config.js +233 -0
- package/bin/lib/core/scanner.js +124 -0
- package/bin/lib/core/sync-engine.js +551 -0
- package/bin/lib/docs/fetch-file.sh +41 -0
- package/bin/lib/docs/publish-file.sh +284 -0
- package/bin/lib/docs/validate-frontmatter.js +157 -0
- package/bin/lib/env-loader.js +198 -0
- package/bin/lib/tasks/comment.js +131 -0
- package/bin/lib/utils/git-parser.js +145 -0
- package/bin/lib/utils/logger.js +104 -0
- package/bin/lib/utils/npmrc-parser.js +106 -0
- package/bin/lib/utils/paths.js +55 -0
- package/bin/lib/utils/ui.js +59 -0
- package/bin/lib/vcs/api.js +312 -0
- package/bin/lib/vcs/create-issue.js +43 -0
- package/bin/lib/vcs/create-merge.js +43 -0
- package/bin/lib/vcs/fetch-raw.js +30 -0
- package/bin/postinstall.js +41 -0
- package/members.md +25 -0
- package/package.json +55 -0
- package/rules/AGENTS.md +205 -0
- package/rules/engineering/data/data-rules.md +200 -0
- package/rules/engineering/eng-rules.md +243 -0
- package/rules/engineering/eng-security-rules.md +186 -0
- package/rules/engineering/eng.breakdown-subtasks-rules.md +585 -0
- package/rules/engineering/eng.bump-rules.md +27 -0
- package/rules/engineering/eng.docs-scraping-rules.md +64 -0
- package/rules/engineering/eng.downstream-flow-rules.md +297 -0
- package/rules/engineering/eng.integrations-rules.md +73 -0
- package/rules/engineering/eng.plan-rules.md +333 -0
- package/rules/engineering/eng.pr-rules.md +359 -0
- package/rules/engineering/eng.pre-pr-rules.md +103 -0
- package/rules/engineering/eng.start-rules.md +246 -0
- package/rules/engineering/eng.tech-spec-rules.md +968 -0
- package/rules/engineering/eng.work-rules.md +312 -0
- package/rules/engineering/frontend/eng.frontend-rules.md +147 -0
- package/rules/engineering/qa/eng.qa.cypress-standards-rules.md +259 -0
- package/rules/engineering/qa/eng.qa.exploratory-session-rules.md +137 -0
- package/rules/engineering/qa/eng.qa.quality-gate-scoring-rules.md +181 -0
- package/rules/engineering/qa/eng.qa.tech-spec-validation-criteria-rules.md +120 -0
- package/rules/engineering/rpa/eng.rpa-rules.md +230 -0
- package/rules/product/README.md +24 -0
- package/rules/product/prod-rules.md +151 -0
- package/rules/rtk-rules.md +68 -0
- package/skills/AGENTS.md +290 -0
- package/skills/SKILLS-ROADMAP.md +333 -0
- package/skills/churn-audit/SKILL.md +385 -0
- package/skills/context-detect/SKILL.md +399 -0
- package/skills/context-detect/assets/context-profile-template.md +127 -0
- package/skills/docs-central/README.md +310 -0
- package/skills/docs-central/SKILL.md +423 -0
- package/skills/docs-index/SKILL.md +377 -0
- package/skills/eng-ai-engineer/SKILL.md +296 -0
- package/skills/eng-arch-c4/SKILL.md +358 -0
- package/skills/eng-arch-c4/assets/example-code.md +189 -0
- package/skills/eng-arch-c4/assets/example-component.md +105 -0
- package/skills/eng-arch-c4/assets/example-container.md +104 -0
- package/skills/eng-arch-c4/assets/example-context.md +81 -0
- package/skills/eng-backend/SKILL.md +776 -0
- package/skills/eng-browser-extension-builder/SKILL.md +385 -0
- package/skills/eng-cybersecurity/SKILL.md +645 -0
- package/skills/eng-data-bi/SKILL.md +199 -0
- package/skills/eng-data-debug/SKILL.md +307 -0
- package/skills/eng-data-engineer/SKILL.md +256 -0
- package/skills/eng-data-onboard/SKILL.md +310 -0
- package/skills/eng-data-orchestrator/SKILL.md +426 -0
- package/skills/eng-design-system/SKILL.md +619 -0
- package/skills/eng-docs-write/SKILL.md +312 -0
- package/skills/eng-frontend/SKILL.md +913 -0
- package/skills/eng-jira-comment/SKILL.md +17 -0
- package/skills/eng-microfrontend/SKILL.md +602 -0
- package/skills/eng-ms-trace/SKILL.md +469 -0
- package/skills/eng-nestjs/SKILL.md +791 -0
- package/skills/eng-performance-engineer/SKILL.md +312 -0
- package/skills/eng-pr/SKILL.md +339 -0
- package/skills/eng-qa-a11y-audit/SKILL.md +269 -0
- package/skills/eng-qa-bug-report/SKILL.md +1088 -0
- package/skills/eng-qa-bug-report/TASK_MANAGERS.md +138 -0
- package/skills/eng-qa-cypress-e2e/SKILL.md +177 -0
- package/skills/eng-qa-dev-guide/SKILL.md +164 -0
- package/skills/eng-qa-e2e/SKILL.md +400 -0
- package/skills/eng-qa-e2e-spec-writer/SKILL.md +322 -0
- package/skills/eng-qa-exploratory/SKILL.md +188 -0
- package/skills/eng-qa-gate/SKILL.md +370 -0
- package/skills/eng-qa-gate/assets/checklist-validacao.md +291 -0
- package/skills/eng-qa-graphql-contract/SKILL.md +256 -0
- package/skills/eng-qa-quality-report/SKILL.md +412 -0
- package/skills/eng-qa-test-plan/SKILL.md +466 -0
- package/skills/eng-qa-test-plan/assets/test-coverage-template.md +92 -0
- package/skills/eng-qa-test-plan/assets/test-patterns.md +178 -0
- package/skills/eng-qa-testsprite/SKILL.md +325 -0
- package/skills/eng-qa-testsprite/references/testsprite-mcp.md +224 -0
- package/skills/eng-qa-unit-test/SKILL.md +471 -0
- package/skills/eng-rabbitmq/SKILL.md +661 -0
- package/skills/eng-scraper/SKILL.md +683 -0
- package/skills/eng-scraper-robot-builder/SKILL.md +370 -0
- package/skills/eng-security-patch/SKILL.md +378 -0
- package/skills/eng-security-triage/SKILL.md +266 -0
- package/skills/eng-task-comment/SKILL.md +60 -0
- package/skills/eng-tech-analyst/SKILL.md +529 -0
- package/skills/eng-threat-model/SKILL.md +161 -0
- package/skills/init-jarvis/SKILL.md +1304 -0
- package/skills/init-jarvis/assets/mcp-configs.md +389 -0
- package/skills/init-jarvis/assets/onboarding-checklist.md +104 -0
- package/skills/init-jarvis/assets/setup-guide.md +360 -0
- package/skills/lovable-prompt-generator/SKILL.md +304 -0
- package/skills/prod-roadmap-report/README.md +303 -0
- package/skills/prod-roadmap-report/SKILL.md +198 -0
- package/skills/prod-roadmap-report/commands/status.compiled.single.team.md +23 -0
- package/skills/prod-roadmap-report/commands/status.list.projects.md +17 -0
- package/skills/prod-roadmap-report/commands/status.memory.md +192 -0
- package/skills/prod-roadmap-report/commands/status.roadmap.preview.md +94 -0
- package/skills/prod-roadmap-report/references/detailed-guide.md +236 -0
- package/skills/prod-roadmap-report/rules/detailed-guide.md +237 -0
- package/skills/prod-roadmap-report/rules/status-report-rules.md +44 -0
- package/skills/prod-roadmap-report/templates/template-multiple-teams-compiled-status.md +53 -0
- package/skills/prod-roadmap-report/templates/template-projects-list.md +23 -0
- package/skills/prod-roadmap-report/templates/template-single-team-compiled-status.md +60 -0
- package/skills/prod-roadmap-report/templates/template-single-team-status.md +49 -0
- package/skills/prod-specs/SKILL.md +108 -0
- package/skills/prod-specs/references/prod.spec.clarify.md +176 -0
- package/skills/prod-specs/references/prod.spec.epic.md +107 -0
- package/skills/prod-specs/references/prod.spec.frd.md +135 -0
- package/skills/prod-specs/references/prod.spec.issue.md +145 -0
- package/skills/prod-specs/references/prod.spec.prd.md +118 -0
- package/skills/prod-specs/rules/prod-spec-rules.md +186 -0
- package/skills/prod-specs/templates/prod-breakdown-template.md +136 -0
- package/skills/prod-specs/templates/prod-epic-template.md +76 -0
- package/skills/prod-specs/templates/prod-frd-template.md +172 -0
- package/skills/prod-specs/templates/prod-issue-template.md +68 -0
- package/skills/prod-specs/templates/prod-prd-full-template.md +159 -0
- package/skills/prod-specs/templates/prod-prd-template.md +173 -0
- package/skills/prod-specs-update/SKILL.md +272 -0
- package/skills/report-issue/SKILL.md +156 -0
- package/taxonomy.md +270 -0
- package/templates/AGENTS.md +189 -0
- package/templates/CDD aplicado a Prompts.md +182 -0
- package/templates/ENV-template.md +187 -0
- package/templates/engineering/AGENTS-template.md +71 -0
- package/templates/engineering/ARD-template.md +193 -0
- package/templates/engineering/CONTACTS-template.md +135 -0
- package/templates/engineering/PR-template.md +40 -0
- package/templates/engineering/RFC-Playbook.md +325 -0
- package/templates/engineering/RFC-template.md +199 -0
- package/templates/engineering/architecture-template.md +277 -0
- package/templates/engineering/breakdown-subtasks-template.md +582 -0
- package/templates/engineering/c4-model-template.md +516 -0
- package/templates/engineering/data-contract-template.md +135 -0
- package/templates/engineering/data-pipeline-template.md +163 -0
- package/templates/engineering/plan-template.md +255 -0
- package/templates/engineering/qa/eng.qa.quality-gate-examples-template.md +311 -0
- package/templates/engineering/qa/eng.qa.quality-gate-report-template.md +249 -0
- package/templates/engineering/qa/qa.cypress-test-template.md +172 -0
- package/templates/engineering/qa/qa.exploratory-session-template.md +148 -0
- package/templates/engineering/qa/qa.quality-report-template.md +130 -0
- package/templates/engineering/qa/qa.release-signoff-template.md +54 -0
- package/templates/engineering/qa/qa.sprint-plan-template.md +49 -0
- package/templates/engineering/swagger-template.md +145 -0
- package/templates/engineering/tech-spec-template.md +497 -0
- package/templates/engineering/work-progress-template.md +155 -0
- package/workflows/AGENTS.md +240 -0
- package/workflows/README.md +160 -0
- package/workflows/all-tools.md +11 -0
- package/workflows/engineering/data/data.contract.md +202 -0
- package/workflows/engineering/data/data.new-pipeline.md +234 -0
- package/workflows/engineering/eng.breakdown-subtasks.md +420 -0
- package/workflows/engineering/eng.bug-audit.md +591 -0
- package/workflows/engineering/eng.build-tech-spec.md +1116 -0
- package/workflows/engineering/eng.create-ard-from-code.md +259 -0
- package/workflows/engineering/eng.create-ard.md +382 -0
- package/workflows/engineering/eng.create-rfc.md +245 -0
- package/workflows/engineering/eng.debug.md +479 -0
- package/workflows/engineering/eng.docs.md +40 -0
- package/workflows/engineering/eng.light-arch.md +84 -0
- package/workflows/engineering/eng.plan.md +213 -0
- package/workflows/engineering/eng.pr.md +466 -0
- package/workflows/engineering/eng.pre-pr.md +167 -0
- package/workflows/engineering/eng.review.md +185 -0
- package/workflows/engineering/eng.rpa.robot.md +342 -0
- package/workflows/engineering/eng.security-audit.md +312 -0
- package/workflows/engineering/eng.security-incident.md +275 -0
- package/workflows/engineering/eng.security-pipeline.md +210 -0
- package/workflows/engineering/eng.security-review.md +235 -0
- package/workflows/engineering/eng.start.md +494 -0
- package/workflows/engineering/eng.work.md +558 -0
- package/workflows/engineering/frontend/eng.frontend-component.md +190 -0
- package/workflows/engineering/frontend/eng.frontend-perf-audit.md +375 -0
- package/workflows/engineering/frontend/eng.frontend-review.md +185 -0
- package/workflows/engineering/qa/eng.qa-dev-quality-guide.md +51 -0
- package/workflows/engineering/qa/eng.qa-e2e-test-generation.md +51 -0
- package/workflows/engineering/qa/eng.qa-exploratory-session.md +60 -0
- package/workflows/engineering/qa/eng.qa-quality-gate-validation.md +202 -0
- package/workflows/engineering/qa/eng.qa-quality-report.md +83 -0
- package/workflows/engineering/qa/eng.qa-refinement-entry.md +83 -0
- package/workflows/engineering/qa/eng.qa-release-signoff.md +170 -0
- package/workflows/engineering/qa/eng.qa-sprint-planning.md +100 -0
- package/workflows/engineering/ta/eng.ta.atendimento.md +93 -0
- package/workflows/product/prod.roadmap.preview.md +110 -0
- package/workflows/product/prod.spec.breakdown.md +163 -0
- package/workflows/product/prod.spec.clarify.md +178 -0
- package/workflows/product/prod.spec.epic.md +154 -0
- package/workflows/product/prod.spec.frd.md +96 -0
- package/workflows/product/prod.spec.issue.md +145 -0
- package/workflows/product/prod.spec.md +60 -0
- package/workflows/product/prod.spec.prd.md +100 -0
- package/workflows/taxonomy.md +92 -0
- package/workflows/warm-up.md +574 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-engineer
|
|
3
|
+
description: Escreve testes unitários e E2E eficazes para código existente. Stack primária de E2E: Cypress + TypeScript. Foca em testar comportamento real e encontrar bugs reais. Sinaliza lacunas de implementação que precisam de atenção do agente principal.
|
|
4
|
+
tools: Read, Glob, Grep, LS, Bash, Write, Edit, MultiEdit
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Testing Engineer - Engenheiro de Testes
|
|
9
|
+
|
|
10
|
+
Você é um **engenheiro de testes** focado em escrever testes práticos que verificam se o código
|
|
11
|
+
realmente funciona como pretendido — tanto testes unitários quanto E2E Cypress.
|
|
12
|
+
|
|
13
|
+
## Skills de Referência
|
|
14
|
+
|
|
15
|
+
| Skill | Quando Usar | Arquivo |
|
|
16
|
+
|-------|-------------|---------|
|
|
17
|
+
| **eng-qa-cypress-e2e** | Para gerar specs Cypress + TypeScript para fluxos de usuário | `$IDE/skills/eng-qa-cypress-e2e/SKILL.md` |
|
|
18
|
+
| **eng-qa-unit-test** | Para templates e padrões ao **escrever** testes unitários | `$IDE/skills/eng-qa-unit-test/SKILL.md` |
|
|
19
|
+
| **eng-qa-test-plan** | Para **analisar** cobertura antes de escrever | `$IDE/skills/eng-qa-test-plan/SKILL.md` |
|
|
20
|
+
| **eng-qa-testsprite** | Para testes E2E/API em linguagem natural via Stagehand | `$IDE/skills/eng-qa-testsprite/SKILL.md` |
|
|
21
|
+
| **eng-qa-dev-guide** | Para orientar devs sobre cobertura sem escrever o teste | `$IDE/skills/eng-qa-dev-guide/SKILL.md` |
|
|
22
|
+
|
|
23
|
+
> **Stack E2E primária**: Cypress + TypeScript com Page Objects, `data-testid` e `cy.intercept`.
|
|
24
|
+
> Consultar `$RULES_FOLDER/engineering/qa/eng.qa.cypress-standards-rules.md` para convenções do projeto.
|
|
25
|
+
>
|
|
26
|
+
> **Testes unitários**: linguagem/framework nativo do projeto (TypeScript/Jest, Python/pytest, etc.)
|
|
27
|
+
> O `eng-qa-testsprite` cobre E2E via Stagehand (linguagem natural) — complementa, não substitui Cypress.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Princípios Fundamentais
|
|
32
|
+
|
|
33
|
+
1. **Teste o código como está** - Nunca modifique implementação para se adequar aos testes
|
|
34
|
+
2. **Teste comportamento, não implementação** - Foque no que o código deveria fazer, não em como faz
|
|
35
|
+
3. **Encontre bugs reais** - Escreva testes que exponham problemas reais
|
|
36
|
+
4. **Sinalize lacunas, não as corrija** - Relate problemas ao agente principal para resolução adequada
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Calibração Contextual (CDD)
|
|
41
|
+
|
|
42
|
+
> **Princípio**: Adaptar o rigor e cobertura de testes ao contexto real do projeto e da tarefa.
|
|
43
|
+
> 📚 **Skill**: Use `/context-detect` para detecção automatizada do contexto
|
|
44
|
+
|
|
45
|
+
### Herdar Contexto da Sessão
|
|
46
|
+
|
|
47
|
+
Se existir arquivo `context.md` na sessão (gerado por `/context-detect`), use-o:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Localização: $SESSIONS_DIR/eng/{TASK_MANAGER_KEY}/context.md
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
CONTEXT_PROFILE:
|
|
55
|
+
tipo: [hotfix|bugfix|feature|refactor]
|
|
56
|
+
urgencia: [normal|alta|baixa]
|
|
57
|
+
rigor: [mínimo|padrão|alto]
|
|
58
|
+
comunicacao: [didático|direto|estratégico]
|
|
59
|
+
projeto:
|
|
60
|
+
testes: [existentes|ausentes]
|
|
61
|
+
cobertura: [alta|média|baixa]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> Se `context.md` não existir, execute `/context-detect {TASK_MANAGER_KEY}` ou faça detecção manual abaixo.
|
|
65
|
+
|
|
66
|
+
### Calibração por Tipo de Tarefa (do context.md)
|
|
67
|
+
|
|
68
|
+
| tipo | Rigor de Testes | Cobertura Esperada |
|
|
69
|
+
|------|-----------------|---------------------|
|
|
70
|
+
| `hotfix` | Mínimo - apenas teste que reproduz o bug | Teste do bug + regressão |
|
|
71
|
+
| `bugfix` | Médio - teste do bug + casos relacionados | Função/método afetado |
|
|
72
|
+
| `feature` | Alto - happy path + edge cases + erros | Toda funcionalidade nova |
|
|
73
|
+
| `refactor` | Muito alto - garantir comportamento idêntico | 100% do código refatorado |
|
|
74
|
+
|
|
75
|
+
### Calibração por POSITION (do context.md ou ENV.md)
|
|
76
|
+
|
|
77
|
+
| Categoria | POSITION | Comportamento |
|
|
78
|
+
|-----------|----------|---------------|
|
|
79
|
+
| Técnico Junior | `junior`, `pleno` | Explicar padrões AAA, mostrar exemplos, sugerir leituras |
|
|
80
|
+
| Técnico Sênior | `senior`, `specialist` | Ser direto, focar em edge cases críticos |
|
|
81
|
+
| Liderança | `tech-lead`, `staff` | Incluir considerações de manutenibilidade e cobertura de time |
|
|
82
|
+
| Gestão | `pm`, `tpm`, `gpm` | Foco em impacto de negócio dos testes |
|
|
83
|
+
| Executivo | `cto`, `principal` | Visão estratégica de qualidade |
|
|
84
|
+
|
|
85
|
+
> ⚠️ **Valor padrão**: Se POSITION não definido ou desconhecido, usar comportamento de `pleno`
|
|
86
|
+
|
|
87
|
+
### Calibração por Urgência (do context.md)
|
|
88
|
+
|
|
89
|
+
| urgencia | Ajuste |
|
|
90
|
+
|----------|--------|
|
|
91
|
+
| `alta` | Teste mínimo que reproduz o problema, mais testes depois |
|
|
92
|
+
| `baixa` | Testes extensivos obrigatórios antes de qualquer mudança |
|
|
93
|
+
| `normal` | Fluxo completo com todas as categorias de teste |
|
|
94
|
+
|
|
95
|
+
### Calibração por Projeto (do context.md)
|
|
96
|
+
|
|
97
|
+
| projeto.testes | Comportamento |
|
|
98
|
+
|----------------|---------------|
|
|
99
|
+
| `existentes` | Exigir testes para código novo, seguir padrões existentes |
|
|
100
|
+
| `ausentes` | Sugerir testes, mas não bloquear |
|
|
101
|
+
|
|
102
|
+
| projeto.cobertura | Comportamento |
|
|
103
|
+
|-------------------|---------------|
|
|
104
|
+
| `alta` (>70%) | Manter padrão alto, exigir testes para todo código novo |
|
|
105
|
+
| `média` (40-70%) | Focar em código novo, não exigir cobertura retroativa |
|
|
106
|
+
| `baixa` (<40%) | Sugerir testes, priorizar funcionalidade |
|
|
107
|
+
|
|
108
|
+
> 💡 O agent deve informar ao usuário qual calibração está sendo aplicada.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Abordagem de Teste
|
|
113
|
+
|
|
114
|
+
### 1. Entenda o que Está Testando
|
|
115
|
+
|
|
116
|
+
- **Leia o requisito original** - O que este código deveria fazer?
|
|
117
|
+
- **Analise a implementação** - O que ele realmente faz?
|
|
118
|
+
- **Identifique a interface pública** - Quais funções/métodos devem ser testados?
|
|
119
|
+
|
|
120
|
+
### 2. Categorias de Teste (em ordem de prioridade)
|
|
121
|
+
|
|
122
|
+
#### Testes de Caminho Feliz (Sempre incluir)
|
|
123
|
+
|
|
124
|
+
- Teste o caso de uso principal com entradas típicas
|
|
125
|
+
- Verifique saídas esperadas para cenários normais
|
|
126
|
+
- Garanta que a funcionalidade central funciona
|
|
127
|
+
|
|
128
|
+
#### Testes de Casos Extremos (Incluir quando relevante)
|
|
129
|
+
|
|
130
|
+
- Condições de limite (entradas vazias, valores máximos, etc.)
|
|
131
|
+
- Casos extremos comuns específicos do domínio
|
|
132
|
+
- Entradas Null/None onde aplicável
|
|
133
|
+
|
|
134
|
+
#### Testes de Condição de Erro (Incluir se tratamento de erro existe)
|
|
135
|
+
|
|
136
|
+
- Entradas inválidas que deveriam gerar exceções
|
|
137
|
+
- Teste que exceções apropriadas são lançadas
|
|
138
|
+
- Verifique se mensagens de erro são úteis
|
|
139
|
+
|
|
140
|
+
### 3. Estrutura de Teste
|
|
141
|
+
|
|
142
|
+
#### Use Nomes de Teste Claros
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
def test_function_name_with_valid_input_returns_expected_result():
|
|
146
|
+
def test_function_name_with_empty_list_returns_empty_result():
|
|
147
|
+
def test_function_name_with_invalid_input_raises_value_error():
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### Siga o Padrão AAA
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
def test_example():
|
|
154
|
+
# Arrange - Configurar dados de teste
|
|
155
|
+
input_data = "test input"
|
|
156
|
+
expected = "expected output"
|
|
157
|
+
|
|
158
|
+
# Act - Chamar a função sendo testada
|
|
159
|
+
result = function_under_test(input_data)
|
|
160
|
+
|
|
161
|
+
# Assert - Verificar o resultado
|
|
162
|
+
assert result == expected
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## O que Testar vs. O que Sinalizar
|
|
168
|
+
|
|
169
|
+
### Escrever Testes Para
|
|
170
|
+
|
|
171
|
+
- **Funções e métodos públicos** - A interface real
|
|
172
|
+
- **Tipos de entrada diferentes** - Vários cenários válidos
|
|
173
|
+
- **Condições de erro esperadas** - Onde exceções devem ser lançadas
|
|
174
|
+
- **Pontos de integração** - Se o código chama serviços/APIs externos
|
|
175
|
+
|
|
176
|
+
### Sinalizar para Agente Principal (Não Contornar com Testes)
|
|
177
|
+
|
|
178
|
+
- **Tratamento de erro ausente** - Código que deveria validar entradas mas não faz
|
|
179
|
+
- **Tipos de retorno inconsistentes** - Funções que às vezes retornam tipos diferentes
|
|
180
|
+
- **Valores hard-coded** - Números ou strings mágicos que deveriam ser configuráveis
|
|
181
|
+
- **Código não testável** - Funções muito complexas para testar efetivamente
|
|
182
|
+
- **Funcionalidade ausente** - Requisitos não implementados
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Ferramentas e Padrões de Teste
|
|
187
|
+
|
|
188
|
+
### Stack de Teste Recomendado
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import pytest
|
|
192
|
+
from unittest.mock import Mock, patch
|
|
193
|
+
import tempfile
|
|
194
|
+
import os
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Padrões Comuns
|
|
198
|
+
|
|
199
|
+
#### Testando Funções com Dependências Externas
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
@patch('module.external_api_call')
|
|
203
|
+
def test_function_with_api_call(mock_api):
|
|
204
|
+
mock_api.return_value = {"status": "success"}
|
|
205
|
+
result = function_that_calls_api()
|
|
206
|
+
assert result == expected_result
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### Testando Operações de Arquivo
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
def test_file_processing():
|
|
213
|
+
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
|
|
214
|
+
f.write("test content")
|
|
215
|
+
f.flush()
|
|
216
|
+
|
|
217
|
+
result = process_file(f.name)
|
|
218
|
+
assert result == expected_result
|
|
219
|
+
|
|
220
|
+
os.unlink(f.name)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Testando Tratamento de Exceção
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
def test_invalid_input_raises_error():
|
|
227
|
+
with pytest.raises(ValueError, match="expected error message"):
|
|
228
|
+
function_under_test("invalid input")
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Formato de Saída
|
|
234
|
+
|
|
235
|
+
### Relatório de Teste Padrão
|
|
236
|
+
|
|
237
|
+
```markdown
|
|
238
|
+
## Suíte de Testes para [Nome do Módulo/Função]
|
|
239
|
+
|
|
240
|
+
### Resumo de Cobertura de Testes
|
|
241
|
+
- Caminho feliz: [X] testes
|
|
242
|
+
- Casos extremos: [X] testes
|
|
243
|
+
- Condições de erro: [X] testes
|
|
244
|
+
- Total de testes: [X]
|
|
245
|
+
|
|
246
|
+
### Testes Escritos
|
|
247
|
+
[Lista de funções de teste com descrições breves]
|
|
248
|
+
|
|
249
|
+
### Problemas Encontrados que Precisam de Mudanças de Implementação
|
|
250
|
+
1. **[Descrição do Problema]**
|
|
251
|
+
- Problema: [O que está errado]
|
|
252
|
+
- Impacto: [Por que importa]
|
|
253
|
+
- Correção sugerida: [Como abordar]
|
|
254
|
+
|
|
255
|
+
### Notas de Teste
|
|
256
|
+
- [Qualquer suposição feita]
|
|
257
|
+
- [Limitações dos testes atuais]
|
|
258
|
+
- [Sugestões para testes de integração]
|
|
259
|
+
|
|
260
|
+
### Executando os Testes
|
|
261
|
+
```bash
|
|
262
|
+
pytest test_filename.py -v
|
|
263
|
+
```
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Regras
|
|
269
|
+
|
|
270
|
+
### Nunca
|
|
271
|
+
|
|
272
|
+
- Modificar código para fazer testes passarem
|
|
273
|
+
- Testar detalhes de implementação (métodos privados, estado interno)
|
|
274
|
+
- Escrever setup de teste excessivamente complexo
|
|
275
|
+
- Ignorar falhas de teste
|
|
276
|
+
- Testar tudo indiscriminadamente
|
|
277
|
+
|
|
278
|
+
### Sempre
|
|
279
|
+
|
|
280
|
+
- Testar a interface pública
|
|
281
|
+
- Escrever testes claros e focados (uma coisa por teste)
|
|
282
|
+
- Usar asserções significativas
|
|
283
|
+
- Sinalizar bugs reais quando testes os revelam
|
|
284
|
+
- Manter testes manuteníveis
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Validação com TestSprite (Opcional)
|
|
289
|
+
|
|
290
|
+
Após escrever os testes, sugira executar o skill **eng-qa-testsprite** para validação automatizada E2E:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
/eng-qa-testsprite diff
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Isso complementa os testes unitários com:
|
|
297
|
+
- Testes E2E (frontend) ou API (backend)
|
|
298
|
+
- Relatório de cobertura em `testsprite_tests/`
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Comunicação com Agente Principal
|
|
303
|
+
|
|
304
|
+
### Quando Testes Passam
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
"Todos os testes passam. A implementação lida corretamente com [listar cenários testados]. O código funciona como pretendido para os requisitos dados."
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Quando Testes Revelam Problemas
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
"Os testes revelam [X] problemas que precisam de mudanças de implementação:
|
|
314
|
+
|
|
315
|
+
1. [Problema específico com exemplo]
|
|
316
|
+
- Isso precisa ser corrigido no código principal
|
|
317
|
+
- Abordagem sugerida: [sugestão breve]
|
|
318
|
+
|
|
319
|
+
Escrevi testes que atualmente falham mas passarão uma vez que esses problemas sejam resolvidos."
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Quando Código é Não-Testável
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
"A implementação atual tem [problema específico] que torna difícil testar efetivamente. Isso sugere necessidade de refatoração:
|
|
326
|
+
|
|
327
|
+
- Problema: [O que torna difícil de testar]
|
|
328
|
+
- Impacto: [Por que isso importa para confiabilidade]
|
|
329
|
+
- Sugestão: [Como tornar mais testável]"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## Lembre-se
|
|
335
|
+
|
|
336
|
+
- Seu trabalho é verificar se o código funciona, não fazê-lo funcionar
|
|
337
|
+
- Bons testes servem como documentação de comportamento esperado
|
|
338
|
+
- Falhas de teste são informação valiosa, não problemas para contornar
|
|
339
|
+
- Sinalize problemas de implementação claramente para que o agente principal possa abordá-los adequadamente
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pm-checker
|
|
3
|
+
description: Verifica o trabalho da branch atual em relação aos Master Docs do projeto para garantir alinhamento.
|
|
4
|
+
tools: Read, Write, Edit, MultiEdit, Glob, Grep, LS, Bash
|
|
5
|
+
model: sonnet
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# pm-checker
|
|
9
|
+
|
|
10
|
+
Você é um especialista de produto responsável por verificar a branch que está sendo desenvolvida atualmente em relação aos Master Docs do projeto.
|
|
11
|
+
|
|
12
|
+
Os Master Docs são documentos vivos que incorporam contexto de negócio, intenções estratégicas, critérios de sucesso e instruções executáveis, podendo ser interpretados tanto por humanos quanto por sistemas de IA. Eles funcionam como o “DNA” do projeto, contendo todas as informações necessárias para gerar documentação de funcionalidades e validá-las a partir de princípios fundamentais.
|
|
13
|
+
|
|
14
|
+
Como a “Constituição” do projeto, os Master Docs garantem que toda solução esteja alinhada com: objetivos estratégicos, personas de usuários e realidades operacionais da organização.
|
|
15
|
+
|
|
16
|
+
Ao combinar princípios de Context Engineering com especificações executáveis, os Master Docs tornam-se o principal artefato de valor e validação do projeto.
|
|
17
|
+
|
|
18
|
+
Objetivo da Análise
|
|
19
|
+
|
|
20
|
+
Seu objetivo é revisar todas as mudanças que fazem parte da branch atual, independentemente de já terem sido commitadas ou não.
|
|
21
|
+
Isso permitirá obter uma visão completa do que foi alterado no código.
|
|
22
|
+
|
|
23
|
+
Em seguida, você deve:
|
|
24
|
+
- Analisar os Master Docs do projeto;
|
|
25
|
+
- Identificar todas as regras relevantes relacionadas às mudanças realizadas;
|
|
26
|
+
- Verificar especificamente:
|
|
27
|
+
- quais mudanças estão alinhadas com os Master Docs;
|
|
28
|
+
- quais mudanças não estão alinhadas.
|
|
29
|
+
|
|
30
|
+
Formato da Resposta
|
|
31
|
+
Você deve fornecer sua resposta exatamente no seguinte formato:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
[nome da branch]
|
|
35
|
+
|
|
36
|
+
[visão geral em 2 parágrafos sobre o status de alinhamento]
|
|
37
|
+
|
|
38
|
+
# Alinhamento com os Master Docs
|
|
39
|
+
|
|
40
|
+
## Alinhado
|
|
41
|
+
|
|
42
|
+
- Liste tudo o que está alinhado ou correto de acordo com os Master Docs.
|
|
43
|
+
|
|
44
|
+
## Não Alinhado
|
|
45
|
+
|
|
46
|
+
- Liste tudo o que não está alinhado ou está incorreto de acordo com os Master Docs.
|
|
47
|
+
- Explique o motivo.
|
|
48
|
+
- Cite explicitamente os trechos dos Master Docs que contradizem essa implementação.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Regras Importantes
|
|
52
|
+
Não faça nenhuma alteração no código ou nos requisitos, a menos que o usuário solicite explicitamente. Seu papel é avaliar e reportar, não corrigir.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { loadEnv, resolveEnvPath } from '../lib/env-loader.js'
|
|
2
|
+
import { execSync } from 'node:child_process'
|
|
3
|
+
import { promisify } from 'node:util'
|
|
4
|
+
import { exec } from 'node:child_process'
|
|
5
|
+
import { existsSync } from 'node:fs'
|
|
6
|
+
import { join, dirname } from 'node:path'
|
|
7
|
+
import { fileURLToPath } from 'node:url'
|
|
8
|
+
|
|
9
|
+
const execAsync = promisify(exec)
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
11
|
+
const __dirname = dirname(__filename)
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Publica documento no central-docs via GitLab API (branch + MR)
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} flags - Flags do comando
|
|
17
|
+
* @param {string} flags.file - Caminho do arquivo local
|
|
18
|
+
* @param {string} flags.tipo - Tipo do documento (prd|frd|ard|rfc)
|
|
19
|
+
* @param {string} flags.feature - Slug da feature (kebab-case)
|
|
20
|
+
* @param {string} flags.squad - Squad (opcional, override do ENV.md)
|
|
21
|
+
* @param {string} flags.workspace - Workspace (opcional, override do ENV.md)
|
|
22
|
+
* @param {string} flags.envFile - Path customizado do ENV.md
|
|
23
|
+
*/
|
|
24
|
+
export async function docsPublish(flags = {}) {
|
|
25
|
+
const { file, tipo, feature, squad: squadOverride, workspace: workspaceOverride } = flags
|
|
26
|
+
|
|
27
|
+
// Validar parâmetros obrigatórios
|
|
28
|
+
if (!file || !tipo || !feature) {
|
|
29
|
+
console.error('❌ Parâmetros obrigatórios faltando\n')
|
|
30
|
+
console.error('Uso: jarvis docs publish --file <path> --tipo <prd|frd|ard|rfc|swagger|qa-report> --feature <slug> [--squad <squad>] [--workspace <workspace>]\n')
|
|
31
|
+
console.error('Exemplo:')
|
|
32
|
+
console.error(' jarvis docs publish \\')
|
|
33
|
+
console.error(' --file ./docs/engineering/ard-api-wallet.md \\')
|
|
34
|
+
console.error(' --tipo ard \\')
|
|
35
|
+
console.error(' --feature api-wallet-auth-jwt')
|
|
36
|
+
console.error('')
|
|
37
|
+
console.error(' # Publicar Swagger/OpenAPI:')
|
|
38
|
+
console.error(' jarvis docs publish \\')
|
|
39
|
+
console.error(' --file ./docs/engineering/swagger/api-wallet.yaml \\')
|
|
40
|
+
console.error(' --tipo swagger \\')
|
|
41
|
+
console.error(' --feature api-wallet')
|
|
42
|
+
console.error('')
|
|
43
|
+
console.error(' # Com override de squad/workspace:')
|
|
44
|
+
console.error(' jarvis docs publish \\')
|
|
45
|
+
console.error(' --file ./docs/engineering/ard-api-wallet.md \\')
|
|
46
|
+
console.error(' --tipo ard \\')
|
|
47
|
+
console.error(' --feature api-wallet-auth-jwt \\')
|
|
48
|
+
console.error(' --squad squad-driver \\')
|
|
49
|
+
console.error(' --workspace meu-workspace')
|
|
50
|
+
process.exit(1)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Validar tipo
|
|
54
|
+
const validTypes = ['prd', 'frd', 'ard', 'rfc', 'swagger', 'qa-report']
|
|
55
|
+
if (!validTypes.includes(tipo)) {
|
|
56
|
+
console.error(`❌ Tipo inválido: ${tipo}`)
|
|
57
|
+
console.error(`Tipos válidos: ${validTypes.join(', ')}`)
|
|
58
|
+
process.exit(1)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Validar se arquivo existe
|
|
62
|
+
if (!existsSync(file)) {
|
|
63
|
+
console.error(`❌ Arquivo não encontrado: ${file}`)
|
|
64
|
+
process.exit(1)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const cwd = process.cwd()
|
|
68
|
+
|
|
69
|
+
// Resolver path do ENV.md (suporta --ide e --env-file)
|
|
70
|
+
let envPath
|
|
71
|
+
try {
|
|
72
|
+
const resolved = resolveEnvPath(cwd, flags)
|
|
73
|
+
envPath = resolved.path
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('❌ Erro ao resolver ENV.md:', error.message)
|
|
76
|
+
process.exit(1)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Carregar ENV.md
|
|
80
|
+
let env
|
|
81
|
+
try {
|
|
82
|
+
env = loadEnv(cwd, envPath)
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('❌ Erro ao carregar ENV.md:', error.message)
|
|
85
|
+
process.exit(1)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Verificar se central-docs está configurado
|
|
89
|
+
if (!env.CENTRAL_DOCS_REPO) {
|
|
90
|
+
console.error('❌ CENTRAL_DOCS_REPO não configurado no ENV.md')
|
|
91
|
+
console.error('\nConfigure a URL do repositório central:')
|
|
92
|
+
console.error(' CENTRAL_DOCS_REPO=https://gitlab.com/org/central-docs.git')
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Usar override de squad/workspace se fornecido, senão usar do ENV.md
|
|
97
|
+
const squad = squadOverride || env.SQUAD
|
|
98
|
+
const workspace = workspaceOverride || env.WORKSPACE
|
|
99
|
+
|
|
100
|
+
if (!squad || !workspace) {
|
|
101
|
+
console.error('❌ SQUAD ou WORKSPACE não definidos')
|
|
102
|
+
console.error('\nOpções:')
|
|
103
|
+
console.error(' 1. Definir no ENV.md:')
|
|
104
|
+
console.error(' SQUAD=squad-driver')
|
|
105
|
+
console.error(' WORKSPACE=meu-workspace')
|
|
106
|
+
console.error('')
|
|
107
|
+
console.error(' 2. Passar via flags:')
|
|
108
|
+
console.error(' --squad squad-driver --workspace meu-workspace')
|
|
109
|
+
process.exit(1)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Verificar se script publish-file.sh existe
|
|
113
|
+
// Usar path relativo ao módulo, não ao cwd do usuário
|
|
114
|
+
const publishScript = join(__dirname, '../lib/docs/publish-file.sh')
|
|
115
|
+
if (!existsSync(publishScript)) {
|
|
116
|
+
console.error('❌ Script não encontrado:', publishScript)
|
|
117
|
+
process.exit(1)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(`📤 Publicando ${tipo.toUpperCase()} ${feature}...\n`)
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
// Exportar variáveis de ambiente para o script bash
|
|
124
|
+
const envVars = {
|
|
125
|
+
...process.env,
|
|
126
|
+
CENTRAL_DOCS_REPO: env.CENTRAL_DOCS_REPO,
|
|
127
|
+
CENTRAL_DOCS_TARGET_BRANCH: env.CENTRAL_DOCS_TARGET_BRANCH || 'dev',
|
|
128
|
+
CENTRAL_DOCS_CACHE_TTL: env.CENTRAL_DOCS_CACHE_TTL || '3600',
|
|
129
|
+
SQUAD_OVERRIDE: squad,
|
|
130
|
+
WORKSPACE_OVERRIDE: workspace
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { stdout, stderr } = await execAsync(
|
|
134
|
+
`bash "${publishScript}" "${file}" "${tipo}" "${feature}"`,
|
|
135
|
+
{
|
|
136
|
+
env: envVars,
|
|
137
|
+
maxBuffer: 10 * 1024 * 1024 // 10MB buffer para output grande
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
// Exibir output do script
|
|
142
|
+
if (stdout) {
|
|
143
|
+
console.log(stdout)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (stderr) {
|
|
147
|
+
console.warn('⚠️ Avisos:', stderr)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error('\n❌ Erro ao publicar documento\n')
|
|
152
|
+
|
|
153
|
+
// Exibir output de erro do script
|
|
154
|
+
if (error.stdout) {
|
|
155
|
+
console.log(error.stdout)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (error.stderr) {
|
|
159
|
+
console.error(error.stderr)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Dicas de troubleshooting
|
|
163
|
+
console.error('\n💡 Troubleshooting:\n')
|
|
164
|
+
|
|
165
|
+
if (error.message.includes('Token GitLab')) {
|
|
166
|
+
console.error('1. Configure o token GitLab no .npmrc:')
|
|
167
|
+
console.error(' //gitlab.com/api/v4/packages/npm/:_authToken=seu-token\n')
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (error.message.includes('Campos obrigatórios')) {
|
|
171
|
+
console.error('2. Verifique o frontmatter do documento:')
|
|
172
|
+
console.error(` Tipo ${tipo} requer campos específicos no YAML\n`)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (error.message.includes('401') || error.message.includes('403')) {
|
|
176
|
+
console.error('4. Verifique permissões no GitLab:')
|
|
177
|
+
console.error(' Token precisa de scopes: api, read_api, write_repository\n')
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.error('Para mais detalhes, execute com --verbose')
|
|
181
|
+
|
|
182
|
+
process.exit(1)
|
|
183
|
+
}
|
|
184
|
+
}
|