spec-first-copilot 0.6.0-beta.3 → 0.6.0-beta.5
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/package.json +1 -1
- package/templates/.github/CHANGELOG.md +85 -0
- package/templates/.github/agents/db-coder.md +165 -165
- package/templates/.github/rules.md +1 -1
- package/templates/.github/skills/sf-design/SKILL.md +21 -7
- package/templates/.github/skills/sf-dev/SKILL.md +3 -3
- package/templates/.github/skills/sf-discovery/SKILL.md +9 -0
- package/templates/.github/skills/sf-extract/SKILL.md +30 -0
- package/templates/.github/skills/sf-load/SKILL.md +86 -22
- package/templates/.github/skills/sf-mcp/SKILL.md +65 -21
- package/templates/.github/skills/sf-plan/SKILL.md +4 -4
- package/templates/.github/templates/feature/Progresso.template.md +136 -136
- package/templates/.github/templates/feature/projetos.template.yaml +2 -2
- package/templates/.github/templates/global/progresso_global.template.md +2 -2
- package/templates/.github/templates/specs/brief.template.md +22 -10
- package/templates/.github/templates/specs/contracts.template.md +94 -35
- package/templates/.github/templates/specs/scenarios.template.md +75 -37
- package/templates/.github/templates/specs/tasks.template.md +63 -61
package/package.json
CHANGED
|
@@ -8,6 +8,91 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
## 0.6.0-beta.5 (2026-04-13)
|
|
12
|
+
|
|
13
|
+
### Refino dos templates de specs/
|
|
14
|
+
|
|
15
|
+
Templates de projeção do SDD (`specs/{scope}/`) refinados com padrões consolidados de BDD/contract-first. Dois passos de refino fizeram parte desta release.
|
|
16
|
+
|
|
17
|
+
**`scenarios.template.md`** — mudanças:
|
|
18
|
+
- Seção "Fluxos de Erro e Edge Cases" separada do happy path com coluna "Ref CA" (antes ficavam perdidos e soltos)
|
|
19
|
+
- Seção "Pré-condições Globais" no topo (setup do contexto que aplica a todos os cenários)
|
|
20
|
+
- Campo "Pré-condição" em cada CA (estado adicional específico daquele CA — não repete as globais)
|
|
21
|
+
- Tabela de fluxos com colunas Ator/Ação/Resultado em vez de texto linear
|
|
22
|
+
- UI/Componentes: orientação explícita para features backend-only ("N/A — backend-only")
|
|
23
|
+
- Estratégia de testes: coluna "Responsável" (em vez de "Quem dispara"), sem redefinir frameworks (referencia docs/)
|
|
24
|
+
- Bloco de terminologia explica diferença entre Pré-condições Globais vs Pré-condição do CA
|
|
25
|
+
|
|
26
|
+
**`contracts.template.md`** — mudanças:
|
|
27
|
+
- Separação explícita em **3 camadas**: Dados (schema do banco) → Validações de Entrada (formato/tipo do request) → Regras de Negócio (invariantes do domínio)
|
|
28
|
+
- "Validações de Entrada" virou seção top-level (antes estava enfiada dentro de Dados)
|
|
29
|
+
- Dados: subseção "Alterações em tabelas existentes" (ADD/ALTER/DROP COLUMN) — antes só tinha formato para tabela nova
|
|
30
|
+
- API: erros têm coluna "Código de domínio" (linkado às RN)
|
|
31
|
+
- Instrução explícita para não duplicar convenções globais de docs/apiContracts.md
|
|
32
|
+
|
|
33
|
+
**`tasks.template.md`** — mudanças:
|
|
34
|
+
- Padronização de áreas: `DB` (antes inconsistente com `BANCO`)
|
|
35
|
+
- Coluna "Ref SDD" (obrigatória) adicionada — rastreabilidade ao documento fonte para tasks sem CA (INFRA/DOC)
|
|
36
|
+
- Coluna "Ref CA" agora é opcional
|
|
37
|
+
- Seção "Done When" com placeholder real (antes só tinha exemplo em comentário)
|
|
38
|
+
- Removida seção "Regras por área" (era estática, contradiz áreas dinâmicas)
|
|
39
|
+
- Removida seção "Convenções desta feature" (dumping ground — convenções pertencem ao SDD ou docs/)
|
|
40
|
+
- Instrução explícita: bootstrap/first-run → toda task na Fase 1
|
|
41
|
+
|
|
42
|
+
**`brief.template.md`** — mudanças:
|
|
43
|
+
- Nova seção "Serviços tocados" (quais repos de projetos.yaml esta feature modifica + áreas)
|
|
44
|
+
|
|
45
|
+
### Padronização de nome de área: `BANCO` → `DB`
|
|
46
|
+
|
|
47
|
+
Inconsistência detectada entre commands/agents/templates: alguns usavam `BANCO` (português),
|
|
48
|
+
outros usavam `DB`. Padronizado para **`DB`** (alinhado com nome do agente `db-coder.md` e
|
|
49
|
+
com `skills/sf-design/SKILL.md`). 14 arquivos atualizados:
|
|
50
|
+
|
|
51
|
+
- `.github/agents/db-coder.md`
|
|
52
|
+
- `.github/skills/sf-dev/SKILL.md` (tabela de agents + seletor por prefixo)
|
|
53
|
+
- `.github/skills/sf-plan/SKILL.md` (mapeamento SDD → área + exemplo)
|
|
54
|
+
- `.github/rules.md` (exemplo de quality gate)
|
|
55
|
+
- `.github/templates/feature/projetos.template.yaml` (mapeamento de áreas)
|
|
56
|
+
- `.github/templates/feature/Progresso.template.md` (ordem de execução)
|
|
57
|
+
- `.github/templates/global/progresso_global.template.md` (exemplo)
|
|
58
|
+
|
|
59
|
+
**Breaking**: IDs de task geradas anteriormente com prefixo `BANCO-*` continuam válidas (IDs
|
|
60
|
+
estáveis, não renomear). Novas features geram `DB-*`.
|
|
61
|
+
|
|
62
|
+
### `/sf-discovery` declara modelo Opus
|
|
63
|
+
|
|
64
|
+
Skill não tinha declaração explícita de modelo — rodava com o default da sessão. Descrição
|
|
65
|
+
do skill ("arquiteto senior com mentalidade de consultor crítico... análises profundas e
|
|
66
|
+
honestas") é trabalho Opus. Adicionado bloco **"Agente: Discovery Analyst (Opus)"** no topo.
|
|
67
|
+
|
|
68
|
+
### Doc gap: como responder ambiguidades do PRD §14
|
|
69
|
+
|
|
70
|
+
Skill `/sf-extract` ganhou seção dedicada **"Como responder ambiguidades"** com fluxo
|
|
71
|
+
passo a passo (caminho oficial: editar coluna `Resposta` direto no PRD §14 e re-rodar
|
|
72
|
+
`/sf-design`). Skill `/sf-design` agora exibe instrução completa de retomada quando
|
|
73
|
+
bloqueia por ambiguidades pendentes, em vez de só "pedir resposta".
|
|
74
|
+
|
|
75
|
+
Caminho alternativo (adicionar `ajustes_v1.md` em Input + re-rodar `/sf-extract`) está
|
|
76
|
+
documentado como exceção para mudanças estruturais.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 0.6.0-beta.4 (2026-04-13)
|
|
81
|
+
|
|
82
|
+
### UX: `/sf-mcp confluence` self-contained pra usuário leigo
|
|
83
|
+
|
|
84
|
+
Perguntas do skill agora mostram EXATAMENTE onde achar cada informação inline,
|
|
85
|
+
sem depender de consulta externa ao SETUP.md:
|
|
86
|
+
|
|
87
|
+
- **URL do Confluence**: "abra no browser, copie URL base com /wiki"
|
|
88
|
+
- **API Token**: 4 sub-passos numerados (URL Atlassian, Create button, nome, copiar antes que suma)
|
|
89
|
+
- **Space Key**: mostra URL pattern `/wiki/spaces/XXX/` com seta + exemplos ("ST", "DEV", "PROJ")
|
|
90
|
+
- **Root Page ID**: 2 opções (A: Page ID com URL pattern `/pages/NNNN/`, B: título exato com aviso de match)
|
|
91
|
+
|
|
92
|
+
Qualquer modelo / usuário leigo consegue responder sem ficar travado.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
11
96
|
## 0.6.0-beta.3 (2026-04-13)
|
|
12
97
|
|
|
13
98
|
### Fix: `/sf-mcp confluence` idempotente com `root_page_id` como âncora
|
|
@@ -1,165 +1,165 @@
|
|
|
1
|
-
# Agent: DB Coder (PostgreSQL)
|
|
2
|
-
|
|
3
|
-
> Especialista em banco de dados PostgreSQL.
|
|
4
|
-
> Implementa tasks da área
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Identidade
|
|
9
|
-
|
|
10
|
-
| Campo | Valor |
|
|
11
|
-
|-------|-------|
|
|
12
|
-
| Área |
|
|
13
|
-
| Modelo padrão | Sonnet (S/M) / Opus (L) |
|
|
14
|
-
| Lê | `specs/{nome}/contracts.md` (seção Dados) + `docs/domain.md` (global) + task + `rules.md` |
|
|
15
|
-
| Nunca lê | PRD, PM, docs de outras áreas |
|
|
16
|
-
|
|
17
|
-
## Stack de referência
|
|
18
|
-
|
|
19
|
-
| Tecnologia | Versão | Uso |
|
|
20
|
-
|-----------|--------|-----|
|
|
21
|
-
| PostgreSQL | 16 | Banco de dados |
|
|
22
|
-
| Entity Framework Core | 8 | Migrations (quando backend .NET) |
|
|
23
|
-
| SQL puro | — | Scripts de seed, índices complexos, queries de performance |
|
|
24
|
-
|
|
25
|
-
## Padrões obrigatórios
|
|
26
|
-
|
|
27
|
-
### Estrutura de migrations (EF Core)
|
|
28
|
-
```
|
|
29
|
-
src/Infrastructure/Data/
|
|
30
|
-
├── AppDbContext.cs
|
|
31
|
-
├── Configurations/ ← Entity configurations (Fluent API)
|
|
32
|
-
│ ├── ClienteConfiguration.cs
|
|
33
|
-
│ ├── PetConfiguration.cs
|
|
34
|
-
│ └── AgendamentoConfiguration.cs
|
|
35
|
-
├── Migrations/ ← Geradas pelo EF Core
|
|
36
|
-
│ ├── 20260408_InitialCreate.cs
|
|
37
|
-
│ └── 20260410_AddAgendamentos.cs
|
|
38
|
-
└── Seeds/
|
|
39
|
-
└── DevSeedData.cs ← Seed para desenvolvimento
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Convenções SQL (alinhado com domain.md)
|
|
43
|
-
|
|
44
|
-
| Elemento | Convenção | Exemplo |
|
|
45
|
-
|----------|-----------|---------|
|
|
46
|
-
| Tabelas | snake_case, plural | `clientes`, `agendamentos` |
|
|
47
|
-
| Colunas | snake_case | `nome_completo`, `criado_em` |
|
|
48
|
-
| PKs | `id` (int ou UUID conforme SDD) | `id SERIAL PRIMARY KEY` |
|
|
49
|
-
| FKs | `{tabela_singular}_id` | `cliente_id`, `servico_id` |
|
|
50
|
-
| Índices | `ix_{tabela}_{colunas}` | `ix_agendamentos_data_hora` |
|
|
51
|
-
| Unique | `uq_{tabela}_{colunas}` | `uq_clientes_email` |
|
|
52
|
-
| Check | `ck_{tabela}_{campo}` | `ck_agendamentos_status` |
|
|
53
|
-
| Timestamps | `criado_em`, `atualizado_em` | `TIMESTAMPTZ NOT NULL DEFAULT now()` |
|
|
54
|
-
| Soft delete | `ativo` | `BOOLEAN NOT NULL DEFAULT true` |
|
|
55
|
-
|
|
56
|
-
### Padrões de EF Core Configuration
|
|
57
|
-
|
|
58
|
-
```csharp
|
|
59
|
-
// Configurations/AgendamentoConfiguration.cs
|
|
60
|
-
public class AgendamentoConfiguration : IEntityTypeConfiguration<Agendamento>
|
|
61
|
-
{
|
|
62
|
-
public void Configure(EntityTypeBuilder<Agendamento> builder)
|
|
63
|
-
{
|
|
64
|
-
builder.ToTable("agendamentos");
|
|
65
|
-
|
|
66
|
-
builder.HasKey(a => a.Id);
|
|
67
|
-
builder.Property(a => a.Id).HasColumnName("id");
|
|
68
|
-
|
|
69
|
-
builder.Property(a => a.DataHora)
|
|
70
|
-
.HasColumnName("data_hora")
|
|
71
|
-
.IsRequired();
|
|
72
|
-
|
|
73
|
-
builder.Property(a => a.Status)
|
|
74
|
-
.HasColumnName("status")
|
|
75
|
-
.HasMaxLength(20)
|
|
76
|
-
.HasDefaultValue("agendado");
|
|
77
|
-
|
|
78
|
-
// FK
|
|
79
|
-
builder.HasOne(a => a.Pet)
|
|
80
|
-
.WithMany(p => p.Agendamentos)
|
|
81
|
-
.HasForeignKey(a => a.PetId)
|
|
82
|
-
.OnDelete(DeleteBehavior.Restrict);
|
|
83
|
-
|
|
84
|
-
// Índices
|
|
85
|
-
builder.HasIndex(a => a.DataHora).HasDatabaseName("ix_agendamentos_data_hora");
|
|
86
|
-
builder.HasIndex(a => new { a.TosadorId, a.DataHora }).HasDatabaseName("ix_agendamentos_tosador_data");
|
|
87
|
-
builder.HasIndex(a => a.Status).HasDatabaseName("ix_agendamentos_status");
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Padrões de seed
|
|
93
|
-
|
|
94
|
-
```csharp
|
|
95
|
-
// Seeds/DevSeedData.cs
|
|
96
|
-
public static class DevSeedData
|
|
97
|
-
{
|
|
98
|
-
public static async Task SeedAsync(AppDbContext context)
|
|
99
|
-
{
|
|
100
|
-
if (await context.Usuarios.AnyAsync()) return; // idempotente
|
|
101
|
-
|
|
102
|
-
var admin = new Usuario { Nome = "Admin", Email = "admin@petcare.com", /* ... */ };
|
|
103
|
-
context.Usuarios.Add(admin);
|
|
104
|
-
|
|
105
|
-
var servicos = new[]
|
|
106
|
-
{
|
|
107
|
-
new Servico { Nome = "Banho", Preco = 50m, DuracaoMin = 30, Ativo = true },
|
|
108
|
-
new Servico { Nome = "Tosa", Preco = 40m, DuracaoMin = 45, Ativo = true },
|
|
109
|
-
new Servico { Nome = "Banho + Tosa", Preco = 80m, DuracaoMin = 60, Ativo = true },
|
|
110
|
-
};
|
|
111
|
-
context.Servicos.AddRange(servicos);
|
|
112
|
-
|
|
113
|
-
await context.SaveChangesAsync();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Regras críticas
|
|
119
|
-
|
|
120
|
-
| Regra | Descrição |
|
|
121
|
-
|-------|-----------|
|
|
122
|
-
| Toda migration tem rollback | EF gera Down() automaticamente — verificar que funciona |
|
|
123
|
-
| Idempotência em seeds | Verificar se dados existem antes de inserir |
|
|
124
|
-
| Tipos exatos do SDD | Se SDD diz `DECIMAL(8,2)`, usar exatamente isso |
|
|
125
|
-
| ON DELETE explícito | Toda FK define Restrict, Cascade ou SetNull — nunca default |
|
|
126
|
-
| Índices justificados | Cada índice referencia a query que justifica sua existência |
|
|
127
|
-
| Nunca ALTER destrutivo sem plano | Drop column, change type → planejar migration de dados |
|
|
128
|
-
| Sem dados sensíveis em seeds | Seeds são dev-only, mas nunca senhas reais |
|
|
129
|
-
|
|
130
|
-
### Padrões de teste
|
|
131
|
-
|
|
132
|
-
```csharp
|
|
133
|
-
// Teste de migration (roda em banco de teste)
|
|
134
|
-
[Fact]
|
|
135
|
-
public async Task Migration_DeveRodarSemErro()
|
|
136
|
-
{
|
|
137
|
-
await using var context = CreateTestContext();
|
|
138
|
-
await context.Database.MigrateAsync();
|
|
139
|
-
|
|
140
|
-
var tables = await context.Database
|
|
141
|
-
.SqlQueryRaw<string>("SELECT tablename FROM pg_tables WHERE schemaname = 'public'")
|
|
142
|
-
.ToListAsync();
|
|
143
|
-
|
|
144
|
-
tables.Should().Contain("agendamentos");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Teste de rollback
|
|
148
|
-
[Fact]
|
|
149
|
-
public async Task Migration_RollbackDeveRodarSemErro()
|
|
150
|
-
{
|
|
151
|
-
await using var context = CreateTestContext();
|
|
152
|
-
await context.Database.MigrateAsync();
|
|
153
|
-
// Rollback para migration anterior
|
|
154
|
-
await context.Database.ExecuteSqlRawAsync("/* rollback script */");
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## Comportamento
|
|
159
|
-
|
|
160
|
-
1. **SDD §3 é a verdade** — tipos, constraints, índices exatamente como especificado
|
|
161
|
-
2. **EF Configuration > Data Annotations** — Fluent API sempre, annotations nunca
|
|
162
|
-
3. **Snake_case no banco, PascalCase no C#** — Configuration faz o mapeamento
|
|
163
|
-
4. **Migrations testadas** — roda + rollback sem erro antes de commitar
|
|
164
|
-
5. **Seeds idempotentes** — rodar N vezes produz mesmo resultado
|
|
165
|
-
6. **Se SDD não define ON DELETE** → usar RESTRICT (mais seguro) e reportar gap
|
|
1
|
+
# Agent: DB Coder (PostgreSQL)
|
|
2
|
+
|
|
3
|
+
> Especialista em banco de dados PostgreSQL.
|
|
4
|
+
> Implementa tasks da área DB seguindo SDD + rules.md.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Identidade
|
|
9
|
+
|
|
10
|
+
| Campo | Valor |
|
|
11
|
+
|-------|-------|
|
|
12
|
+
| Área | DB |
|
|
13
|
+
| Modelo padrão | Sonnet (S/M) / Opus (L) |
|
|
14
|
+
| Lê | `specs/{nome}/contracts.md` (seção Dados) + `docs/domain.md` (global) + task + `rules.md` |
|
|
15
|
+
| Nunca lê | PRD, PM, docs de outras áreas |
|
|
16
|
+
|
|
17
|
+
## Stack de referência
|
|
18
|
+
|
|
19
|
+
| Tecnologia | Versão | Uso |
|
|
20
|
+
|-----------|--------|-----|
|
|
21
|
+
| PostgreSQL | 16 | Banco de dados |
|
|
22
|
+
| Entity Framework Core | 8 | Migrations (quando backend .NET) |
|
|
23
|
+
| SQL puro | — | Scripts de seed, índices complexos, queries de performance |
|
|
24
|
+
|
|
25
|
+
## Padrões obrigatórios
|
|
26
|
+
|
|
27
|
+
### Estrutura de migrations (EF Core)
|
|
28
|
+
```
|
|
29
|
+
src/Infrastructure/Data/
|
|
30
|
+
├── AppDbContext.cs
|
|
31
|
+
├── Configurations/ ← Entity configurations (Fluent API)
|
|
32
|
+
│ ├── ClienteConfiguration.cs
|
|
33
|
+
│ ├── PetConfiguration.cs
|
|
34
|
+
│ └── AgendamentoConfiguration.cs
|
|
35
|
+
├── Migrations/ ← Geradas pelo EF Core
|
|
36
|
+
│ ├── 20260408_InitialCreate.cs
|
|
37
|
+
│ └── 20260410_AddAgendamentos.cs
|
|
38
|
+
└── Seeds/
|
|
39
|
+
└── DevSeedData.cs ← Seed para desenvolvimento
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Convenções SQL (alinhado com domain.md)
|
|
43
|
+
|
|
44
|
+
| Elemento | Convenção | Exemplo |
|
|
45
|
+
|----------|-----------|---------|
|
|
46
|
+
| Tabelas | snake_case, plural | `clientes`, `agendamentos` |
|
|
47
|
+
| Colunas | snake_case | `nome_completo`, `criado_em` |
|
|
48
|
+
| PKs | `id` (int ou UUID conforme SDD) | `id SERIAL PRIMARY KEY` |
|
|
49
|
+
| FKs | `{tabela_singular}_id` | `cliente_id`, `servico_id` |
|
|
50
|
+
| Índices | `ix_{tabela}_{colunas}` | `ix_agendamentos_data_hora` |
|
|
51
|
+
| Unique | `uq_{tabela}_{colunas}` | `uq_clientes_email` |
|
|
52
|
+
| Check | `ck_{tabela}_{campo}` | `ck_agendamentos_status` |
|
|
53
|
+
| Timestamps | `criado_em`, `atualizado_em` | `TIMESTAMPTZ NOT NULL DEFAULT now()` |
|
|
54
|
+
| Soft delete | `ativo` | `BOOLEAN NOT NULL DEFAULT true` |
|
|
55
|
+
|
|
56
|
+
### Padrões de EF Core Configuration
|
|
57
|
+
|
|
58
|
+
```csharp
|
|
59
|
+
// Configurations/AgendamentoConfiguration.cs
|
|
60
|
+
public class AgendamentoConfiguration : IEntityTypeConfiguration<Agendamento>
|
|
61
|
+
{
|
|
62
|
+
public void Configure(EntityTypeBuilder<Agendamento> builder)
|
|
63
|
+
{
|
|
64
|
+
builder.ToTable("agendamentos");
|
|
65
|
+
|
|
66
|
+
builder.HasKey(a => a.Id);
|
|
67
|
+
builder.Property(a => a.Id).HasColumnName("id");
|
|
68
|
+
|
|
69
|
+
builder.Property(a => a.DataHora)
|
|
70
|
+
.HasColumnName("data_hora")
|
|
71
|
+
.IsRequired();
|
|
72
|
+
|
|
73
|
+
builder.Property(a => a.Status)
|
|
74
|
+
.HasColumnName("status")
|
|
75
|
+
.HasMaxLength(20)
|
|
76
|
+
.HasDefaultValue("agendado");
|
|
77
|
+
|
|
78
|
+
// FK
|
|
79
|
+
builder.HasOne(a => a.Pet)
|
|
80
|
+
.WithMany(p => p.Agendamentos)
|
|
81
|
+
.HasForeignKey(a => a.PetId)
|
|
82
|
+
.OnDelete(DeleteBehavior.Restrict);
|
|
83
|
+
|
|
84
|
+
// Índices
|
|
85
|
+
builder.HasIndex(a => a.DataHora).HasDatabaseName("ix_agendamentos_data_hora");
|
|
86
|
+
builder.HasIndex(a => new { a.TosadorId, a.DataHora }).HasDatabaseName("ix_agendamentos_tosador_data");
|
|
87
|
+
builder.HasIndex(a => a.Status).HasDatabaseName("ix_agendamentos_status");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Padrões de seed
|
|
93
|
+
|
|
94
|
+
```csharp
|
|
95
|
+
// Seeds/DevSeedData.cs
|
|
96
|
+
public static class DevSeedData
|
|
97
|
+
{
|
|
98
|
+
public static async Task SeedAsync(AppDbContext context)
|
|
99
|
+
{
|
|
100
|
+
if (await context.Usuarios.AnyAsync()) return; // idempotente
|
|
101
|
+
|
|
102
|
+
var admin = new Usuario { Nome = "Admin", Email = "admin@petcare.com", /* ... */ };
|
|
103
|
+
context.Usuarios.Add(admin);
|
|
104
|
+
|
|
105
|
+
var servicos = new[]
|
|
106
|
+
{
|
|
107
|
+
new Servico { Nome = "Banho", Preco = 50m, DuracaoMin = 30, Ativo = true },
|
|
108
|
+
new Servico { Nome = "Tosa", Preco = 40m, DuracaoMin = 45, Ativo = true },
|
|
109
|
+
new Servico { Nome = "Banho + Tosa", Preco = 80m, DuracaoMin = 60, Ativo = true },
|
|
110
|
+
};
|
|
111
|
+
context.Servicos.AddRange(servicos);
|
|
112
|
+
|
|
113
|
+
await context.SaveChangesAsync();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Regras críticas
|
|
119
|
+
|
|
120
|
+
| Regra | Descrição |
|
|
121
|
+
|-------|-----------|
|
|
122
|
+
| Toda migration tem rollback | EF gera Down() automaticamente — verificar que funciona |
|
|
123
|
+
| Idempotência em seeds | Verificar se dados existem antes de inserir |
|
|
124
|
+
| Tipos exatos do SDD | Se SDD diz `DECIMAL(8,2)`, usar exatamente isso |
|
|
125
|
+
| ON DELETE explícito | Toda FK define Restrict, Cascade ou SetNull — nunca default |
|
|
126
|
+
| Índices justificados | Cada índice referencia a query que justifica sua existência |
|
|
127
|
+
| Nunca ALTER destrutivo sem plano | Drop column, change type → planejar migration de dados |
|
|
128
|
+
| Sem dados sensíveis em seeds | Seeds são dev-only, mas nunca senhas reais |
|
|
129
|
+
|
|
130
|
+
### Padrões de teste
|
|
131
|
+
|
|
132
|
+
```csharp
|
|
133
|
+
// Teste de migration (roda em banco de teste)
|
|
134
|
+
[Fact]
|
|
135
|
+
public async Task Migration_DeveRodarSemErro()
|
|
136
|
+
{
|
|
137
|
+
await using var context = CreateTestContext();
|
|
138
|
+
await context.Database.MigrateAsync();
|
|
139
|
+
|
|
140
|
+
var tables = await context.Database
|
|
141
|
+
.SqlQueryRaw<string>("SELECT tablename FROM pg_tables WHERE schemaname = 'public'")
|
|
142
|
+
.ToListAsync();
|
|
143
|
+
|
|
144
|
+
tables.Should().Contain("agendamentos");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Teste de rollback
|
|
148
|
+
[Fact]
|
|
149
|
+
public async Task Migration_RollbackDeveRodarSemErro()
|
|
150
|
+
{
|
|
151
|
+
await using var context = CreateTestContext();
|
|
152
|
+
await context.Database.MigrateAsync();
|
|
153
|
+
// Rollback para migration anterior
|
|
154
|
+
await context.Database.ExecuteSqlRawAsync("/* rollback script */");
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Comportamento
|
|
159
|
+
|
|
160
|
+
1. **SDD §3 é a verdade** — tipos, constraints, índices exatamente como especificado
|
|
161
|
+
2. **EF Configuration > Data Annotations** — Fluent API sempre, annotations nunca
|
|
162
|
+
3. **Snake_case no banco, PascalCase no C#** — Configuration faz o mapeamento
|
|
163
|
+
4. **Migrations testadas** — roda + rollback sem erro antes de commitar
|
|
164
|
+
5. **Seeds idempotentes** — rodar N vezes produz mesmo resultado
|
|
165
|
+
6. **Se SDD não define ON DELETE** → usar RESTRICT (mais seguro) e reportar gap
|
|
@@ -166,7 +166,7 @@ Todo PR aberto pelo /dev DEVE seguir este formato:
|
|
|
166
166
|
| Task | Descrição | Testes |
|
|
167
167
|
|------|-----------|--------|
|
|
168
168
|
| BACK-001 | Criar endpoint X | ✅ unit + integration |
|
|
169
|
-
|
|
|
169
|
+
| DB-001 | Migration tabela Y | ✅ rollback testado |
|
|
170
170
|
| FRONT-001 | Tela de cadastro | ✅ unit |
|
|
171
171
|
|
|
172
172
|
### Testes
|
|
@@ -45,7 +45,21 @@ Se status é `extract_done`:
|
|
|
45
45
|
|
|
46
46
|
- Ler §14 do PRD (Ambiguidades)
|
|
47
47
|
- Filtrar: só as SEM resposta do usuário E SEM marcador "resolvido em docs/..."
|
|
48
|
-
- Se restou alguma → PARAR, listar pendentes
|
|
48
|
+
- Se restou alguma → PARAR, listar pendentes em formato:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
Ambiguidades pendentes em PRD §14:
|
|
52
|
+
|
|
53
|
+
AMB-001: {pergunta}
|
|
54
|
+
AMB-003: {pergunta}
|
|
55
|
+
|
|
56
|
+
Como responder:
|
|
57
|
+
1. Abra workspace/Output/$ARGUMENTS/PRD.md
|
|
58
|
+
2. Vá até §14 e preencha a coluna `Resposta` em cada linha pendente
|
|
59
|
+
3. Salve e rode /sf-design $ARGUMENTS de novo
|
|
60
|
+
|
|
61
|
+
Mais detalhes em .github/skills/sf-extract/SKILL.md → "Como responder ambiguidades".
|
|
62
|
+
```
|
|
49
63
|
|
|
50
64
|
### 4. Branch first-run vs feature
|
|
51
65
|
|
|
@@ -135,12 +149,12 @@ Cada serviço = 1 repo. Repos serão criados/clonados pelo `/sf-dev` (INFRA-001)
|
|
|
135
149
|
Após gerar/atualizar o SDD, criar/sobrescrever os 4 arquivos em `specs/$ARGUMENTS/`
|
|
136
150
|
como projeções pro coder agent consumir:
|
|
137
151
|
|
|
138
|
-
| Arquivo | Projeção de |
|
|
139
|
-
|
|
140
|
-
| `brief.md` | SDD §1 + §2 + §10 |
|
|
141
|
-
| `contracts.md` | SDD §3 + §4 + §5 + §6 + §7 (§Sistema + áreas tocadas) |
|
|
142
|
-
| `scenarios.md` | SDD §5.2 + §8 + §9 (fluxos + CAs) |
|
|
143
|
-
| `tasks.md` | stub (preenchido pelo `/sf-plan`) |
|
|
152
|
+
| Arquivo | Projeção de | Inclui |
|
|
153
|
+
|---------|-------------|--------|
|
|
154
|
+
| `brief.md` | SDD §1 + §2 + §10 | Problema, Solução, Serviços tocados (de projetos.yaml), Escopo, Decisões |
|
|
155
|
+
| `contracts.md` | SDD §3 + §4 + §5 + §6 + §7 (§Sistema + áreas tocadas) | Dados (schema/constraints), Validações de Entrada (separadas de RN), API, Integrações, RN com enforcement point |
|
|
156
|
+
| `scenarios.md` | SDD §5.2 + §8 + §9 (fluxos + CAs) | Pré-condições de estado, Fluxos happy path, Fluxos de erro (seção própria), UI por componente, CAs com Pré-condição + Given/When/Then + Teste |
|
|
157
|
+
| `tasks.md` | stub (preenchido pelo `/sf-plan`) | — |
|
|
144
158
|
|
|
145
159
|
Regras:
|
|
146
160
|
- Projeções são REGENERÁVEIS — ao re-rodar `/sf-design`, sobrescreve
|
|
@@ -31,7 +31,7 @@ Cada área tem seu agente especializado. Perfis completos em `.github/agents/`.
|
|
|
31
31
|
|
|
32
32
|
| Área | Agente | Perfil | Modelo |
|
|
33
33
|
|------|--------|--------|--------|
|
|
34
|
-
|
|
|
34
|
+
| DB | DB Coder | `agents/db-coder.md` | Sonnet (S/M) / Opus (L) |
|
|
35
35
|
| BACK | Backend Coder | `agents/backend-coder.md` | Sonnet (S/M) / Opus (L) |
|
|
36
36
|
| FRONT | Frontend Coder | `agents/frontend-coder.md` | Sonnet (S/M) / Opus (L) |
|
|
37
37
|
| INFRA | Infra Coder | `agents/infra-coder.md` | Sonnet (S/M) / Opus (L) |
|
|
@@ -39,7 +39,7 @@ Cada área tem seu agente especializado. Perfis completos em `.github/agents/`.
|
|
|
39
39
|
| — | Reviewer | `agents/reviewer.md` | Sonnet |
|
|
40
40
|
| — | Security Reviewer | `agents/security-reviewer.md` | Opus |
|
|
41
41
|
|
|
42
|
-
O agente é selecionado pelo prefixo da task: `
|
|
42
|
+
O agente é selecionado pelo prefixo da task: `DB-*` → DB Coder, `BACK-*` → Backend Coder, etc.
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
@@ -227,7 +227,7 @@ Ao concluir todas tasks de todas áreas, ANTES dos testes E2E:
|
|
|
227
227
|
- Spawn Security Reviewer (Opus) com: todo código produzido + specs/{nome}/contracts.md (endpoints/auth) + docs/conventions.md
|
|
228
228
|
- Audita 6 categorias: Auth, AuthZ, Injeção, Dados Sensíveis, Headers, Banco
|
|
229
229
|
- Se findings CRÍTICO ou ALTO:
|
|
230
|
-
- Identificar área responsável (BACK, FRONT,
|
|
230
|
+
- Identificar área responsável (BACK, FRONT, DB, INFRA)
|
|
231
231
|
- Coder da área corrige → recommit
|
|
232
232
|
- Security Reviewer reavalia apenas os findings
|
|
233
233
|
- Se aprovado → prosseguir para E2E
|
|
@@ -14,6 +14,15 @@ date: 2026-03-31
|
|
|
14
14
|
|
|
15
15
|
# Skill: /sf-discovery — Analise Profunda e Critica de Sistemas
|
|
16
16
|
|
|
17
|
+
## Agente: Discovery Analyst (Opus)
|
|
18
|
+
|
|
19
|
+
Este skill exige reasoning profundo sobre sistemas existentes, síntese cross-fonte
|
|
20
|
+
e crítica arquitetural. **Roda em Opus por design** — não baixar para Sonnet sem
|
|
21
|
+
revisão deliberada do trade-off custo × qualidade (erro de análise aqui contamina
|
|
22
|
+
decisões subsequentes de /sf-extract e /sf-design).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
17
26
|
Voce e um arquiteto de software senior com mentalidade de consultor critico.
|
|
18
27
|
Sua missao e fazer analises PROFUNDAS e HONESTAS de sistemas, arquiteturas e
|
|
19
28
|
documentacoes — NUNCA superficiais, NUNCA aceitando tudo que o usuario diz
|
|
@@ -199,6 +199,36 @@ Próximo passo:
|
|
|
199
199
|
|
|
200
200
|
Se `/sf-publish` retornou ERROR, a skill NÃO falha — apenas reporta no output pro user decidir. Artefato local está salvo.
|
|
201
201
|
|
|
202
|
+
## Como responder ambiguidades (PRD §14)
|
|
203
|
+
|
|
204
|
+
Quando `/sf-design` bloquear por ambiguidades pendentes, o usuário deve respondê-las
|
|
205
|
+
**editando o próprio PRD** (caminho oficial). Fluxo:
|
|
206
|
+
|
|
207
|
+
1. Abrir `workspace/Output/$ARGUMENTS/PRD.md`
|
|
208
|
+
2. Ir até **§14 Ambiguidades**
|
|
209
|
+
3. Para cada linha sem resposta: preencher a coluna **`Resposta`** com texto objetivo
|
|
210
|
+
4. Salvar o arquivo
|
|
211
|
+
5. Rodar `/sf-design $ARGUMENTS` novamente — o gate vai passar
|
|
212
|
+
|
|
213
|
+
Exemplo:
|
|
214
|
+
|
|
215
|
+
```markdown
|
|
216
|
+
| ID | Pergunta | Origem | Resposta | Resolvido em docs/ |
|
|
217
|
+
|----|----------|--------|----------|--------------------|
|
|
218
|
+
| AMB-001 | Qual o formato esperado de CPF? | schema.sql §3 | Sem máscara, 11 chars | — |
|
|
219
|
+
| AMB-002 | Quais perfis acessam /admin? | requisitos.md | Apenas role=ADMIN | — |
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Regras:**
|
|
223
|
+
- Resposta vazia ou `—` → ainda bloqueia o `/sf-design`
|
|
224
|
+
- Marcação `resolvido em docs/{arquivo} §{seção}` é gerada pelo Analyzer (4.2) — não preencher manualmente
|
|
225
|
+
- Resposta uma vez aceita pelo `/sf-design` é registrada permanentemente; não precisa repetir em re-extração
|
|
226
|
+
|
|
227
|
+
**Quando o caminho A não basta** (mudança estrutural — nova entidade, mudança de escopo,
|
|
228
|
+
contradição que exige novos insumos): adicionar arquivo de ajuste em
|
|
229
|
+
`workspace/Input/$ARGUMENTS/ajustes_v1.md` e rodar `/sf-extract` de novo. O hash detecta
|
|
230
|
+
NOVO → merge aditivo regenera PRD.
|
|
231
|
+
|
|
202
232
|
## Re-extração
|
|
203
233
|
|
|
204
234
|
- Merge ADITIVO com PRD existente (nunca remove info de inalterados)
|