kakaroto-config 1.0.4 → 1.0.6
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/config/ARCHITECTURE.md +5 -7
- package/config/CLAUDE.md +11 -0
- package/config/agents/code-reviewer.md +66 -230
- package/config/agents/code-simplifier.md +70 -116
- package/config/agents/{visual-validator.md → functional-validator.md} +118 -92
- package/config/agents/memory-sync.md +193 -134
- package/config/commands/debug/02-investigate.md +3 -3
- package/config/commands/debug/03-fix.md +28 -6
- package/config/commands/debug/05-commit.md +1 -1
- package/config/commands/debug/validators/fix-permanence.md +1 -1
- package/config/commands/feature/01-understand.md +217 -0
- package/config/commands/feature/02-analyze.md +168 -0
- package/config/commands/feature/03-strategy.md +300 -0
- package/config/commands/feature/04-red.md +160 -0
- package/config/commands/feature/05-green.md +179 -0
- package/config/commands/feature/06-quality.md +109 -0
- package/config/commands/feature/07-validation.md +168 -0
- package/config/commands/feature/08-delivery.md +86 -0
- package/config/commands/feature/09-evaluate.md +140 -0
- package/config/commands/feature/playbooks/_e2e-base.md +39 -0
- package/config/commands/feature/playbooks/api/analyze.md +20 -0
- package/config/commands/feature/playbooks/api/e2e.md +29 -0
- package/config/commands/feature/playbooks/api/red.md +66 -0
- package/config/commands/feature/playbooks/job/analyze.md +29 -0
- package/config/commands/feature/playbooks/job/e2e.md +30 -0
- package/config/commands/feature/playbooks/job/red.md +77 -0
- package/config/commands/feature/playbooks/service/analyze.md +28 -0
- package/config/commands/feature/playbooks/service/e2e.md +25 -0
- package/config/commands/feature/playbooks/service/red.md +75 -0
- package/config/commands/feature/playbooks/ui/analyze.md +26 -0
- package/config/commands/feature/playbooks/ui/e2e.md +61 -0
- package/config/commands/feature/playbooks/ui/red.md +71 -0
- package/config/commands/feature.md +37 -4
- package/config/commands/gate.md +11 -23
- package/config/templates/spec-template.md +82 -68
- package/package.json +3 -3
- package/config/agents/dry-enforcer.md +0 -227
- package/config/commands/debug/techniques/flow-tracing.md +0 -75
- package/config/commands/debug/techniques/hypothesis-generation.md +0 -30
- package/config/commands/debug/techniques/sequential-thinking-config.md +0 -79
- package/config/commands/feature/01-interview.md +0 -143
- package/config/commands/feature/02-spec.md +0 -98
- package/config/commands/feature/03-planner.md +0 -200
- package/config/commands/feature/04-implement.md +0 -81
- package/config/commands/feature/05-quality.md +0 -140
- package/config/commands/feature/06-commit.md +0 -91
- package/config/commands/feature/07-evaluate.md +0 -129
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Fase 9: Evaluate
|
|
2
|
+
|
|
3
|
+
## Responsabilidade
|
|
4
|
+
Auto-avaliacao do workflow e propor melhorias.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Passo 1: Coletar Metricas
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git diff --stat HEAD~1
|
|
12
|
+
git log -1 --format="%s"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Passo 2: Sequential Thinking #1 - DIAGNOSTICO
|
|
18
|
+
|
|
19
|
+
Usar `mcp__sequential-thinking__sequentialthinking`:
|
|
20
|
+
|
|
21
|
+
| Criterio | Peso | Como Medir |
|
|
22
|
+
|----------|------|------------|
|
|
23
|
+
| Completude | 40% | Todos itens implementados? |
|
|
24
|
+
| Qualidade | 20% | Review passou limpo? |
|
|
25
|
+
| Testes | 15% | Cobertura adequada? |
|
|
26
|
+
| Build | 10% | Passou na primeira? |
|
|
27
|
+
| Autonomia | 10% | Quantas perguntas? (ideal <=1) |
|
|
28
|
+
| Docs | 5% | Spec reflete implementacao? |
|
|
29
|
+
|
|
30
|
+
Para criterios < 80%: Aplicar 5 Whys
|
|
31
|
+
|
|
32
|
+
`totalThoughts`: 5-7
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Passo 3: Sequential Thinking #2 - SINTESE
|
|
37
|
+
|
|
38
|
+
Para cada problema identificado:
|
|
39
|
+
|
|
40
|
+
1. Tipo de mudanca? (Config/Skill/Pattern)
|
|
41
|
+
2. Qual arquivo editar?
|
|
42
|
+
3. Diff exato?
|
|
43
|
+
4. Efeitos colaterais?
|
|
44
|
+
5. Prioridade?
|
|
45
|
+
|
|
46
|
+
`totalThoughts`: 3-5
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Passo 4: Propor Melhorias (AUQ)
|
|
51
|
+
|
|
52
|
+
Para melhorias identificadas (max 3):
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
AskUserQuestion({
|
|
56
|
+
questions: [{
|
|
57
|
+
question: "Detectei: {problema}. Causa: {causa}. Sugiro: {diff}. Aplicar?",
|
|
58
|
+
header: "Melhoria",
|
|
59
|
+
options: [
|
|
60
|
+
{ label: "Aplicar", description: "Editar arquivo" },
|
|
61
|
+
{ label: "Ignorar", description: "Pular desta vez" },
|
|
62
|
+
{ label: "Nunca sugerir", description: "Adicionar excecao" }
|
|
63
|
+
],
|
|
64
|
+
multiSelect: false
|
|
65
|
+
}]
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Acoes:**
|
|
70
|
+
- **Aplicar:** Edit tool
|
|
71
|
+
- **Ignorar:** Prosseguir
|
|
72
|
+
- **Nunca sugerir:** Adicionar em evaluation-exceptions.json
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Passo 5: Relatorio Final
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
## Workflow Completo
|
|
80
|
+
|
|
81
|
+
**Score Final:** X%
|
|
82
|
+
- Completude: X%
|
|
83
|
+
- Qualidade: X%
|
|
84
|
+
- Testes: X%
|
|
85
|
+
- Build: X%
|
|
86
|
+
- Autonomia: X%
|
|
87
|
+
|
|
88
|
+
**Commit:** {hash} {message}
|
|
89
|
+
|
|
90
|
+
**Melhorias Aplicadas:** N
|
|
91
|
+
- [lista]
|
|
92
|
+
|
|
93
|
+
**Workflow /feature concluido.**
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Gate (BLOQUEANTE)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Verificar que commit existe
|
|
102
|
+
git log -1 --format="%s" | grep -qE "^(feat|fix|refactor|test|docs):" || { echo "❌ Commit não encontrado"; exit 1; }
|
|
103
|
+
|
|
104
|
+
# Verificar E2E foi executado (no contract)
|
|
105
|
+
SLUG=$(jq -r '.feature' .claude/workflow-state.json 2>/dev/null)
|
|
106
|
+
grep -qE "Status:.*(PASSED|FAILED)" ".claude/contracts/${SLUG}.md" 2>/dev/null || { echo "❌ E2E não executado"; exit 1; }
|
|
107
|
+
|
|
108
|
+
echo "✅ Gate 09-evaluate passou"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Passo 6: Finalizar Estado do Workflow
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
if command -v jq &> /dev/null; then
|
|
117
|
+
jq '
|
|
118
|
+
.currentPhase = "COMPLETED" |
|
|
119
|
+
.completedPhases += ["09-evaluate"] |
|
|
120
|
+
.completedAt = "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'" |
|
|
121
|
+
.resumeHint = "Workflow COMPLETO. Nenhuma acao necessaria." |
|
|
122
|
+
.lastStep = "Passo 6: Finalizar Estado"
|
|
123
|
+
' .claude/workflow-state.json > .claude/workflow-state.tmp && mv .claude/workflow-state.tmp .claude/workflow-state.json
|
|
124
|
+
else
|
|
125
|
+
echo "Atualizar .claude/workflow-state.json: currentPhase=COMPLETED, all phases complete"
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
echo "✅ Workflow /feature COMPLETO"
|
|
129
|
+
cat .claude/workflow-state.json
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Arquivar State File (Opcional)
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Mover para histórico após conclusão bem-sucedida
|
|
136
|
+
FEATURE_SLUG=$(jq -r '.feature' .claude/workflow-state.json)
|
|
137
|
+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
138
|
+
mkdir -p .claude/workflow-history
|
|
139
|
+
mv .claude/workflow-state.json ".claude/workflow-history/${FEATURE_SLUG}-${TIMESTAMP}.json"
|
|
140
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# E2E Validation - Base
|
|
2
|
+
|
|
3
|
+
## Tipos
|
|
4
|
+
|
|
5
|
+
| Tipo | Quando | Fluxo |
|
|
6
|
+
|------|--------|-------|
|
|
7
|
+
| auto | UI, scripts prontos | Comando direto |
|
|
8
|
+
| semi-auto | APIs, webhooks | Claude trigger + poll + verify |
|
|
9
|
+
| hybrid | Integracao externa | User acao + Claude verifica |
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Verificacoes que Claude Pode Fazer
|
|
14
|
+
|
|
15
|
+
| Tipo | Como |
|
|
16
|
+
|------|------|
|
|
17
|
+
| Database | Query conforme sintaxe do projeto |
|
|
18
|
+
| API | `GET /api/resource` expect 200 |
|
|
19
|
+
| Logs | `grep "pattern" /logs/file` |
|
|
20
|
+
| File | `ls /path/to/file` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Criterios de Falha
|
|
25
|
+
|
|
26
|
+
E2E FALHOU se:
|
|
27
|
+
1. Timeout (auto/semi-auto: 60s, hybrid: 5min)
|
|
28
|
+
2. Criterio de sucesso nao atingido
|
|
29
|
+
3. Erro inesperado
|
|
30
|
+
4. User: "Nao consigo" (hybrid)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Recovery
|
|
35
|
+
|
|
36
|
+
SE E2E falhou:
|
|
37
|
+
1. Perguntar ao user se quer debugar
|
|
38
|
+
2. SE sim: `/debug` workflow
|
|
39
|
+
3. SE nao: continuar (marcar FAILED)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# API - Analyze
|
|
2
|
+
|
|
3
|
+
## Localizacao
|
|
4
|
+
- `api/handlers/` - Handler functions
|
|
5
|
+
- `api/routes/` - Route definitions
|
|
6
|
+
- `services/` - Business logic
|
|
7
|
+
|
|
8
|
+
## Pattern de Handler (Producao)
|
|
9
|
+
```typescript
|
|
10
|
+
export async function handleFeature(req, res) {
|
|
11
|
+
const data = featureSchema.parse(req.body);
|
|
12
|
+
const result = await featureService.execute(data);
|
|
13
|
+
res.json(result);
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Criterios de Testabilidade
|
|
18
|
+
- Endpoint novo: Integration obrigatorio
|
|
19
|
+
- Validacao de input: Unit recomendado
|
|
20
|
+
- Multiplos servicos: Integration com mocks
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# API - E2E
|
|
2
|
+
|
|
3
|
+
## Tipo Recomendado: semi-auto
|
|
4
|
+
|
|
5
|
+
API pode ser testada via request + verificacao automatizada.
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
## E2E Validation
|
|
11
|
+
|
|
12
|
+
**Tipo:** semi-auto
|
|
13
|
+
|
|
14
|
+
**Trigger:** `POST /api/{endpoint}` com payload:
|
|
15
|
+
```json
|
|
16
|
+
{ "field": "value" }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Verificacoes do Claude:**
|
|
20
|
+
- [ ] Response status 200/201
|
|
21
|
+
- [ ] Response body contem campos esperados
|
|
22
|
+
- [ ] Query DB: verificar registro criado/atualizado
|
|
23
|
+
|
|
24
|
+
**Criterio de Sucesso:**
|
|
25
|
+
- [ ] Record existe no DB com campos corretos
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Alternativa: hybrid
|
|
29
|
+
SE depender de integracao externa (OAuth, webhook externo).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# API - RED (Testes)
|
|
2
|
+
|
|
3
|
+
## Testes Requeridos
|
|
4
|
+
|
|
5
|
+
| Tipo | Obrigatorio | Motivo |
|
|
6
|
+
|------|-------------|--------|
|
|
7
|
+
| Unit | SE complexo | Logica isolada com transformacoes |
|
|
8
|
+
| Integration | **SIM** | Fluxo completo request->response |
|
|
9
|
+
| E2E | NAO | API testada via integration |
|
|
10
|
+
|
|
11
|
+
## Mocks Tipicos
|
|
12
|
+
- Database: `vi.mock('./databaseService')`
|
|
13
|
+
- APIs externas (identificar do projeto)
|
|
14
|
+
- Auth/Session
|
|
15
|
+
|
|
16
|
+
## Test Pattern (Vitest)
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
20
|
+
|
|
21
|
+
// Mock antes do import
|
|
22
|
+
vi.mock('./databaseService', () => ({
|
|
23
|
+
getAllItems: vi.fn(),
|
|
24
|
+
createItem: vi.fn(),
|
|
25
|
+
updateItem: vi.fn(),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
import { handleFeature } from './featureHandler';
|
|
29
|
+
import { getAllItems, createItem } from './databaseService';
|
|
30
|
+
|
|
31
|
+
describe('handleFeature', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.clearAllMocks();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return data when valid input', async () => {
|
|
37
|
+
vi.mocked(getAllItems).mockResolvedValue([{ id: '1', name: 'Test' }]);
|
|
38
|
+
|
|
39
|
+
const result = await handleFeature({ campaign: 'X' });
|
|
40
|
+
|
|
41
|
+
expect(result.success).toBe(true);
|
|
42
|
+
expect(getAllItems).toHaveBeenCalledTimes(1);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should handle empty results', async () => {
|
|
46
|
+
vi.mocked(getAllItems).mockResolvedValue([]);
|
|
47
|
+
|
|
48
|
+
const result = await handleFeature({ campaign: 'Y' });
|
|
49
|
+
|
|
50
|
+
expect(result.success).toBe(true);
|
|
51
|
+
expect(result.data).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should propagate errors', async () => {
|
|
55
|
+
vi.mocked(getAllItems).mockRejectedValue(new Error('DB error'));
|
|
56
|
+
|
|
57
|
+
await expect(handleFeature({ campaign: 'Z' }))
|
|
58
|
+
.rejects.toThrow('DB error');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Convenções
|
|
64
|
+
- 1 criterio do contract -> 1+ testes
|
|
65
|
+
- Usar `vi.mocked()` para type-safe mocks
|
|
66
|
+
- `beforeEach` com `vi.clearAllMocks()`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Job - Analyze
|
|
2
|
+
|
|
3
|
+
## Localizacao
|
|
4
|
+
- `cron/` - Cron job definitions
|
|
5
|
+
- `jobs/` - Job handlers
|
|
6
|
+
- `executors/` - Job executors
|
|
7
|
+
|
|
8
|
+
## Pattern de Job (Producao)
|
|
9
|
+
```typescript
|
|
10
|
+
export async function executeFeatureJob(context: JobContext) {
|
|
11
|
+
const items = await fetchPendingItems();
|
|
12
|
+
for (const item of items) {
|
|
13
|
+
await processItem(item);
|
|
14
|
+
}
|
|
15
|
+
return { processed: items.length };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Executor pattern
|
|
19
|
+
export const featureExecutor = {
|
|
20
|
+
name: 'feature-job',
|
|
21
|
+
schedule: '0 */6 * * *',
|
|
22
|
+
handler: executeFeatureJob
|
|
23
|
+
};
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Criterios de Testabilidade
|
|
27
|
+
- Job novo: Integration obrigatorio
|
|
28
|
+
- Logica de retry: Unit recomendado
|
|
29
|
+
- Job simples: Integration basico
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Job - E2E
|
|
2
|
+
|
|
3
|
+
## Tipo Recomendado: hybrid
|
|
4
|
+
|
|
5
|
+
Jobs requerem trigger manual ou aguardar schedule.
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
## E2E Validation
|
|
11
|
+
|
|
12
|
+
**Tipo:** hybrid
|
|
13
|
+
|
|
14
|
+
**Acao do User:**
|
|
15
|
+
- [ ] Disparar job via admin/script
|
|
16
|
+
OU
|
|
17
|
+
- [ ] Aguardar execucao automatica
|
|
18
|
+
|
|
19
|
+
**Verificacoes do Claude:**
|
|
20
|
+
- [ ] Query DB: verificar status do job
|
|
21
|
+
- [ ] Verificar logs: `grep "job.completed"`
|
|
22
|
+
- [ ] Confirmar side effects: registros processados > 0
|
|
23
|
+
|
|
24
|
+
**Criterio de Sucesso:**
|
|
25
|
+
- [ ] Job status = 'completed'
|
|
26
|
+
- [ ] Nenhum erro nos logs
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Alternativa: semi-auto
|
|
30
|
+
SE job puder ser disparado via API interna.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Job - RED (Testes)
|
|
2
|
+
|
|
3
|
+
## Testes Requeridos
|
|
4
|
+
|
|
5
|
+
| Tipo | Obrigatorio | Motivo |
|
|
6
|
+
|------|-------------|--------|
|
|
7
|
+
| Unit | SE complexo | Logica de transformacao |
|
|
8
|
+
| Integration | **SIM** | Fluxo completo do job |
|
|
9
|
+
| E2E | NAO | Jobs testados via integration |
|
|
10
|
+
|
|
11
|
+
## Mocks Tipicos
|
|
12
|
+
- Database: `vi.mock('./databaseService')`
|
|
13
|
+
- Schedulers (Cloud Scheduler, cron)
|
|
14
|
+
- APIs externas (notificacoes, etc)
|
|
15
|
+
- Message queue (se aplicavel)
|
|
16
|
+
|
|
17
|
+
## Test Pattern (Vitest)
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
21
|
+
|
|
22
|
+
vi.mock('./databaseService', () => ({
|
|
23
|
+
getPendingItems: vi.fn(),
|
|
24
|
+
updateItemStatus: vi.fn(),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
import { executeFeatureJob } from './featureJob';
|
|
28
|
+
import { getPendingItems, updateItemStatus } from './databaseService';
|
|
29
|
+
|
|
30
|
+
describe('executeFeatureJob', () => {
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
vi.clearAllMocks();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should process all pending items', async () => {
|
|
36
|
+
vi.mocked(getPendingItems).mockResolvedValue([
|
|
37
|
+
{ id: '1', status: 'pending' },
|
|
38
|
+
{ id: '2', status: 'pending' },
|
|
39
|
+
]);
|
|
40
|
+
vi.mocked(updateItemStatus).mockResolvedValue(undefined);
|
|
41
|
+
|
|
42
|
+
const result = await executeFeatureJob({ runId: 'test' });
|
|
43
|
+
|
|
44
|
+
expect(result.processed).toBe(2);
|
|
45
|
+
expect(updateItemStatus).toHaveBeenCalledTimes(2);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should handle empty queue', async () => {
|
|
49
|
+
vi.mocked(getPendingItems).mockResolvedValue([]);
|
|
50
|
+
|
|
51
|
+
const result = await executeFeatureJob({ runId: 'test' });
|
|
52
|
+
|
|
53
|
+
expect(result.processed).toBe(0);
|
|
54
|
+
expect(updateItemStatus).not.toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should continue on item failure', async () => {
|
|
58
|
+
vi.mocked(getPendingItems).mockResolvedValue([
|
|
59
|
+
{ id: '1', status: 'pending' },
|
|
60
|
+
{ id: '2', status: 'pending' },
|
|
61
|
+
]);
|
|
62
|
+
vi.mocked(updateItemStatus)
|
|
63
|
+
.mockRejectedValueOnce(new Error('Item 1 failed'))
|
|
64
|
+
.mockResolvedValueOnce(undefined);
|
|
65
|
+
|
|
66
|
+
const result = await executeFeatureJob({ runId: 'test' });
|
|
67
|
+
|
|
68
|
+
expect(result.processed).toBe(1);
|
|
69
|
+
expect(result.errors.length).toBe(1);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Convenções
|
|
75
|
+
- Testar processamento em batch
|
|
76
|
+
- Testar comportamento com erros parciais
|
|
77
|
+
- Testar fila vazia
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Service - Analyze
|
|
2
|
+
|
|
3
|
+
## Localizacao
|
|
4
|
+
- `services/` - Business logic services
|
|
5
|
+
- `utils/` - Utility functions
|
|
6
|
+
- `lib/` - Shared libraries
|
|
7
|
+
|
|
8
|
+
## Pattern de Service (Producao)
|
|
9
|
+
```typescript
|
|
10
|
+
export const featureService = {
|
|
11
|
+
async execute(input: FeatureInput): Promise<FeatureOutput> {
|
|
12
|
+
const validated = featureSchema.parse(input);
|
|
13
|
+
// business logic
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Utility pattern
|
|
19
|
+
export function transformData(input: Input): Output {
|
|
20
|
+
// pure transformation
|
|
21
|
+
return output;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Criterios de Testabilidade
|
|
26
|
+
- Funcao pura: Unit obrigatorio
|
|
27
|
+
- Servico com DB: Unit + Integration
|
|
28
|
+
- Utility simples: Unit basico
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Service - E2E
|
|
2
|
+
|
|
3
|
+
## Tipo Recomendado: auto (integration test)
|
|
4
|
+
|
|
5
|
+
Services sao testados via integration tests existentes.
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
## E2E Validation
|
|
11
|
+
|
|
12
|
+
**Tipo:** auto
|
|
13
|
+
|
|
14
|
+
**Script/Ferramenta:** integration test existente
|
|
15
|
+
|
|
16
|
+
**Cenario:**
|
|
17
|
+
- Given: {pre-condicao}
|
|
18
|
+
- When: service.execute({input})
|
|
19
|
+
- Then: {resultado esperado}
|
|
20
|
+
|
|
21
|
+
**Comando:** `npm test -- --grep "{nome-do-teste}"`
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Alternativa: hybrid
|
|
25
|
+
SE depender de sistema externo nao mockavel.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Service - RED (Testes)
|
|
2
|
+
|
|
3
|
+
## Testes Requeridos
|
|
4
|
+
|
|
5
|
+
| Tipo | Obrigatorio | Motivo |
|
|
6
|
+
|------|-------------|--------|
|
|
7
|
+
| Unit | **SIM** | Logica pura e isolada |
|
|
8
|
+
| Integration | SE multi-service | Interacao entre servicos |
|
|
9
|
+
| E2E | NAO | Servicos testados via unit/integration |
|
|
10
|
+
|
|
11
|
+
## Mocks Tipicos
|
|
12
|
+
- Database: `vi.mock('./databaseService')`
|
|
13
|
+
- APIs externas
|
|
14
|
+
- File system (se aplicavel)
|
|
15
|
+
|
|
16
|
+
## Test Pattern (Vitest) - Service
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
20
|
+
|
|
21
|
+
vi.mock('./databaseService', () => ({
|
|
22
|
+
getAll: vi.fn(),
|
|
23
|
+
getItems: vi.fn(),
|
|
24
|
+
create: vi.fn(),
|
|
25
|
+
update: vi.fn(),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
import { processItems } from './itemService';
|
|
29
|
+
import { getAll, create } from './databaseService';
|
|
30
|
+
|
|
31
|
+
describe('processItems', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.clearAllMocks();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should create new items from unique tags', async () => {
|
|
37
|
+
vi.mocked(getAll).mockResolvedValue([
|
|
38
|
+
{ id: 'item-1', tags: ['Tag A'] },
|
|
39
|
+
{ id: 'item-2', tags: ['Tag A', 'Tag B'] },
|
|
40
|
+
]);
|
|
41
|
+
vi.mocked(create).mockResolvedValue('new-id');
|
|
42
|
+
|
|
43
|
+
const result = await processItems();
|
|
44
|
+
|
|
45
|
+
expect(result.success).toBe(true);
|
|
46
|
+
expect(result.created).toBe(2);
|
|
47
|
+
expect(create).toHaveBeenCalledTimes(2);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Test Pattern (Vitest) - Utility
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { describe, it, expect } from 'vitest';
|
|
56
|
+
import { transformData } from './dataTransformer';
|
|
57
|
+
|
|
58
|
+
describe('transformData', () => {
|
|
59
|
+
it('should transform input correctly', () => {
|
|
60
|
+
const input = { raw: 'value' };
|
|
61
|
+
const result = transformData(input);
|
|
62
|
+
expect(result.processed).toBe('VALUE');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should handle edge cases', () => {
|
|
66
|
+
expect(transformData({ raw: '' })).toEqual({ processed: '' });
|
|
67
|
+
expect(transformData({ raw: null })).toEqual({ processed: null });
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Convenções
|
|
73
|
+
- Services: mock dependencias externas
|
|
74
|
+
- Utilities: testar como funcoes puras (sem mocks)
|
|
75
|
+
- `vi.clearAllMocks()` no beforeEach
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# UI - Analyze
|
|
2
|
+
|
|
3
|
+
## Localizacao
|
|
4
|
+
- `components/` - React components
|
|
5
|
+
- `app/` - Next.js pages/routes
|
|
6
|
+
- `hooks/` - Custom hooks
|
|
7
|
+
|
|
8
|
+
## Pattern de Component (Producao)
|
|
9
|
+
```typescript
|
|
10
|
+
export function FeatureComponent({ data }: FeatureProps) {
|
|
11
|
+
const { state, actions } = useFeature(data);
|
|
12
|
+
return <div>...</div>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Hook pattern
|
|
16
|
+
export function useFeature(initial) {
|
|
17
|
+
const [state, setState] = useState(initial);
|
|
18
|
+
// ...
|
|
19
|
+
return { state, actions };
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Criterios de Testabilidade
|
|
24
|
+
- Formulario novo: E2E obrigatorio
|
|
25
|
+
- Hook com logica: Unit obrigatorio
|
|
26
|
+
- Componente display-only: Nenhum
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# UI - E2E
|
|
2
|
+
|
|
3
|
+
## Tipo Recomendado: auto (Playwright)
|
|
4
|
+
|
|
5
|
+
Fluxos visuais testados via browser automation.
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
## E2E Validation
|
|
11
|
+
|
|
12
|
+
**Tipo:** auto
|
|
13
|
+
|
|
14
|
+
**Script/Ferramenta:** Playwright + functional-validator
|
|
15
|
+
|
|
16
|
+
**Cenario:**
|
|
17
|
+
- Given: Usuario na pagina {page}
|
|
18
|
+
- When: Usuario preenche form e submete
|
|
19
|
+
- Then: {resultado visual/funcional}
|
|
20
|
+
|
|
21
|
+
**Comando:** `npm run test:e2e -- {arquivo.spec.ts}`
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Playwright Pattern
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { test, expect } from '@playwright/test';
|
|
28
|
+
|
|
29
|
+
test('should submit form successfully', async ({ page }) => {
|
|
30
|
+
await page.goto('/feature');
|
|
31
|
+
|
|
32
|
+
await page.fill('[name="title"]', 'Test Title');
|
|
33
|
+
await page.fill('[name="description"]', 'Test Description');
|
|
34
|
+
await page.click('button[type="submit"]');
|
|
35
|
+
|
|
36
|
+
await expect(page.locator('.success-message')).toBeVisible();
|
|
37
|
+
await expect(page).toHaveURL(/\/feature\/[a-z0-9]+/);
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Alternativa: hybrid (fallback)
|
|
42
|
+
SE Playwright falhar ou for overkill:
|
|
43
|
+
|
|
44
|
+
```markdown
|
|
45
|
+
## E2E Validation
|
|
46
|
+
|
|
47
|
+
**Tipo:** hybrid
|
|
48
|
+
|
|
49
|
+
**Acao do User:**
|
|
50
|
+
- [ ] Navegue para {url}
|
|
51
|
+
- [ ] Execute {acao}
|
|
52
|
+
- [ ] Confirme visualmente o resultado
|
|
53
|
+
|
|
54
|
+
**Verificacoes do Claude:**
|
|
55
|
+
- [ ] API call: `GET /api/{resource}` retorna dados esperados
|
|
56
|
+
- [ ] Query DB: verificar dados persistidos
|
|
57
|
+
|
|
58
|
+
**Criterio de Sucesso:**
|
|
59
|
+
- [ ] User confirma que UI funcionou
|
|
60
|
+
- [ ] Dados persistidos corretamente
|
|
61
|
+
```
|