spec-first-copilot 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/bin/cli.js +52 -0
  2. package/package.json +25 -0
  3. package/templates/.ai/memory/napkin.md +68 -0
  4. package/templates/.github/agents/backend-coder.md +215 -0
  5. package/templates/.github/agents/db-coder.md +165 -0
  6. package/templates/.github/agents/doc-writer.md +51 -0
  7. package/templates/.github/agents/frontend-coder.md +222 -0
  8. package/templates/.github/agents/infra-coder.md +341 -0
  9. package/templates/.github/agents/reviewer.md +99 -0
  10. package/templates/.github/agents/security-reviewer.md +153 -0
  11. package/templates/.github/copilot-instructions.md +176 -0
  12. package/templates/.github/instructions/docs.instructions.md +123 -0
  13. package/templates/.github/instructions/sensitive-files.instructions.md +32 -0
  14. package/templates/.github/skills/sf-design/SKILL.md +181 -0
  15. package/templates/.github/skills/sf-dev/SKILL.md +326 -0
  16. package/templates/.github/skills/sf-discovery/SKILL.md +405 -0
  17. package/templates/.github/skills/sf-extract/SKILL.md +284 -0
  18. package/templates/.github/skills/sf-feature/SKILL.md +130 -0
  19. package/templates/.github/skills/sf-merge-delta/SKILL.md +142 -0
  20. package/templates/.github/skills/sf-pausar/SKILL.md +120 -0
  21. package/templates/.github/skills/sf-plan/SKILL.md +178 -0
  22. package/templates/.github/skills/sf-setup-projeto/SKILL.md +123 -0
  23. package/templates/docs/Desenvolvimento/.gitkeep +0 -0
  24. package/templates/docs/Desenvolvimento/rules.md +229 -0
  25. package/templates/docs/Estrutura/.gitkeep +0 -0
  26. package/templates/docs/PM/.gitkeep +0 -0
  27. package/templates/docs/PM/setup_projeto/.gitkeep +0 -0
  28. package/templates/docs/_templates/estrutura/ADRs.template.md +91 -0
  29. package/templates/docs/_templates/estrutura/API.template.md +144 -0
  30. package/templates/docs/_templates/estrutura/Arquitetura.template.md +82 -0
  31. package/templates/docs/_templates/estrutura/Infraestrutura.template.md +104 -0
  32. package/templates/docs/_templates/estrutura/Modelo_Dados.template.md +99 -0
  33. package/templates/docs/_templates/estrutura/Seguranca.template.md +138 -0
  34. package/templates/docs/_templates/estrutura/Stack.template.md +78 -0
  35. package/templates/docs/_templates/estrutura/Visao.template.md +82 -0
  36. package/templates/docs/_templates/feature/PRD.template.md +256 -0
  37. package/templates/docs/_templates/feature/Progresso.template.md +136 -0
  38. package/templates/docs/_templates/feature/TRD.template.md +200 -0
  39. package/templates/docs/_templates/feature/backlog-extraido.template.md +154 -0
  40. package/templates/docs/_templates/feature/context.template.md +42 -0
  41. package/templates/docs/_templates/feature/extract-log.template.md +38 -0
  42. package/templates/docs/_templates/feature/projetos.template.yaml +73 -0
  43. package/templates/docs/_templates/feature/sdd.template.md +372 -0
  44. package/templates/docs/_templates/feature/tasks.template.md +115 -0
  45. package/templates/docs/_templates/global/progresso_global.template.md +57 -0
package/bin/cli.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require('path');
4
+ const { init } = require('spec-first-core');
5
+
6
+ const args = process.argv.slice(2);
7
+ const command = args[0];
8
+
9
+ function printUsage() {
10
+ console.log('Usage: spec-first-copilot init --name=<project-name> [--target=<path>]');
11
+ console.log('');
12
+ console.log('Creates a new spec-first project configured for GitHub Copilot.');
13
+ console.log('');
14
+ console.log('Options:');
15
+ console.log(' --name=<name> Project name (required)');
16
+ console.log(' --target=<path> Target directory (defaults to ./<name>)');
17
+ }
18
+
19
+ function parseArgs(args) {
20
+ const parsed = {};
21
+ for (const arg of args) {
22
+ const match = arg.match(/^--(\w+)=(.+)$/);
23
+ if (match) {
24
+ parsed[match[1]] = match[2];
25
+ }
26
+ }
27
+ return parsed;
28
+ }
29
+
30
+ if (command === 'init') {
31
+ const opts = parseArgs(args.slice(1));
32
+
33
+ if (!opts.name) {
34
+ console.error('Error: --name is required.\n');
35
+ printUsage();
36
+ process.exit(1);
37
+ }
38
+
39
+ const templatesDir = path.join(__dirname, '..', 'templates');
40
+
41
+ init({
42
+ name: opts.name,
43
+ templatesDir,
44
+ targetDir: opts.target || undefined,
45
+ });
46
+ } else {
47
+ printUsage();
48
+ if (command) {
49
+ console.error(`\nUnknown command: "${command}"`);
50
+ }
51
+ process.exit(command ? 1 : 0);
52
+ }
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "spec-first-copilot",
3
+ "version": "0.1.0",
4
+ "description": "Spec-first workflow kit for GitHub Copilot — AI-driven development with specs, not guesswork",
5
+ "bin": {
6
+ "spec-first-copilot": "./bin/cli.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "templates/"
11
+ ],
12
+ "author": "gustavomaritan",
13
+ "keywords": ["spec-first", "workflow", "ai", "copilot", "github", "scaffolding"],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/gustavomaritan-labs/spec-first-workflow"
17
+ },
18
+ "dependencies": {
19
+ "spec-first-core": "0.1.0"
20
+ },
21
+ "scripts": {
22
+ "test": "echo \"No tests yet\""
23
+ },
24
+ "license": "MIT"
25
+ }
@@ -0,0 +1,68 @@
1
+ # Napkin Runbook
2
+
3
+ > Sistema de memória persistente do projeto.
4
+ > Lido no início de cada sessão. Curado continuamente. Runbook, não log.
5
+
6
+ ## Regras de Curadoria
7
+ - Re-priorizar a cada leitura (mais importante primeiro)
8
+ - Manter apenas notas recorrentes e de alto valor
9
+ - Máximo 10 itens por categoria
10
+ - Cada item inclui data + ação concreta ("Fazer:" / "Evitar:")
11
+ - Remover itens obsoletos ou de baixo sinal
12
+ - Fundir duplicatas
13
+ - Adaptar categorias ao projeto conforme ele evolui
14
+
15
+ ---
16
+
17
+ ## Princípios Invioláveis
18
+
19
+ 1. **Spec-first**: NUNCA gerar código sem SDD aprovado
20
+ Fazer: seguir pipeline extract → design → plan → dev.
21
+
22
+ 2. **Entregáveis contínuos**: toda feature é faseada em entregáveis incrementais.
23
+ Cada fase entrega valor ao usuário e pode ir pra produção.
24
+ Fazer: nunca "tudo ou nada". Sempre pequeno e constante.
25
+
26
+ 3. **Nunca na main**: todo código em branch própria. Merge via PR aprovado pelo usuário.
27
+ Fazer: seguir git workflow (5 passos no rules.md).
28
+
29
+ 4. **SDD é auto-contido**: o coder lê APENAS SDD + task. Nunca PRD ou PM direto.
30
+ Fazer: se falta info no SDD, parar e reportar.
31
+
32
+ 5. **Docker dev = infra only**: docker-compose.yml tem APENAS dependências (banco, redis, rabbit).
33
+ Apps (API, Worker, Web) rodam direto: `dotnet run`, `npm run dev`.
34
+ Evitar: NUNCA colocar apps no docker-compose.yml de dev.
35
+
36
+ ## Padrões de Execução
37
+
38
+ 1. **Projeto-base = orquestrador, projetos/ = código**
39
+ Specs, docs, tasks, progresso ficam aqui. Código fica nos repos em projetos/.
40
+ Commits de código nos repos do serviço, NUNCA no projeto-base.
41
+
42
+ 2. **Auth por endpoint é obrigatória**
43
+ Todo endpoint deve ter Autenticação e Autorização definidos no SDD §5.
44
+ Se SDD omitiu → PARAR e reportar. Se público → escrever "público" explicitamente.
45
+
46
+ 3. **Temas críticos geram ambiguidades automáticas**
47
+ Se os insumos não mencionam: auth, authz, separação de serviços, ambientes,
48
+ dados sensíveis → o /extract gera ambiguidades obrigatórias.
49
+
50
+ ## Armadilhas do Ambiente
51
+
52
+ <!-- Adicionar conforme descoberto durante o projeto -->
53
+
54
+ ## Decisões de Design
55
+
56
+ <!-- Populado pelo /design e /dev conforme o projeto evolui -->
57
+
58
+ ## Regras de Negócio Aprendidas
59
+
60
+ <!-- Populado pelo /extract e feedback do usuário -->
61
+
62
+ ## Preferências do Usuário
63
+
64
+ <!-- Populado conforme interações com o usuário -->
65
+
66
+ ## Sessão Atual
67
+
68
+ <!-- Atualizado pelo /pausar ao encerrar cada sessão -->
@@ -0,0 +1,215 @@
1
+ # Agent: Backend Coder (.NET 8)
2
+
3
+ > Especialista em desenvolvimento backend com .NET 8 / C#.
4
+ > Implementa tasks da área BACK seguindo SDD + rules.md.
5
+
6
+ ---
7
+
8
+ ## Identidade
9
+
10
+ | Campo | Valor |
11
+ |-------|-------|
12
+ | Área | BACK |
13
+ | Modelo padrão | Sonnet (S/M) / Opus (L) |
14
+ | Lê | SDD (seções referenciadas na 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
+ | .NET | 8 LTS | Runtime + SDK |
22
+ | C# | 12 | Linguagem |
23
+ | ASP.NET Core | 8 | Web framework (Minimal APIs ou Controllers) |
24
+ | Entity Framework Core | 8 | ORM (migrations, queries) |
25
+ | xUnit | latest | Testes unit + integration |
26
+ | FluentAssertions | latest | Assertions legíveis |
27
+ | FluentValidation | latest | Validação de DTOs/requests |
28
+ | MediatR | latest | CQRS / mediator (se SDD indicar) |
29
+ | Serilog | latest | Logging estruturado |
30
+
31
+ ## Padrões obrigatórios
32
+
33
+ ### Estrutura do projeto
34
+ ```
35
+ src/
36
+ ├── Api/ ← Entry point (Program.cs, endpoints/controllers)
37
+ │ ├── Endpoints/ ← Minimal API endpoint groups
38
+ │ ├── Middleware/ ← Auth, error handling, logging
39
+ │ └── Program.cs
40
+ ├── Application/ ← Use cases, DTOs, validações
41
+ │ ├── Commands/ ← Write operations
42
+ │ ├── Queries/ ← Read operations
43
+ │ ├── DTOs/
44
+ │ └── Validators/ ← FluentValidation
45
+ ├── Domain/ ← Entidades, regras de negócio, interfaces
46
+ │ ├── Entities/
47
+ │ ├── Enums/
48
+ │ └── Interfaces/
49
+ ├── Infrastructure/ ← EF DbContext, repositories, serviços externos
50
+ │ ├── Data/
51
+ │ │ ├── Configurations/ ← EF entity configurations
52
+ │ │ ├── Migrations/
53
+ │ │ └── AppDbContext.cs
54
+ │ ├── Repositories/
55
+ │ └── Services/
56
+ tests/
57
+ ├── Unit/ ← Domain + Application
58
+ ├── Integration/ ← API endpoints (WebApplicationFactory)
59
+ └── Fixtures/
60
+ ```
61
+
62
+ ### Convenções de código
63
+
64
+ | Regra | Exemplo |
65
+ |-------|---------|
66
+ | Namespaces seguem pastas | `namespace PetCare.Application.Commands;` |
67
+ | Classes seladas por padrão | `public sealed class CreateAgendamentoCommand` |
68
+ | Records para DTOs | `public record CreateAgendamentoRequest(int PetId, int ServicoId, DateTime DataHora);` |
69
+ | Nullable reference types | Habilitado (`<Nullable>enable</Nullable>`) |
70
+ | Async/await em tudo I/O | Nunca `.Result` ou `.Wait()` |
71
+ | Injeção de dependência | Via construtor, registrado no DI container |
72
+ | Respostas padronizadas | `Results.Ok(data)`, `Results.Created(uri, data)`, `Results.Problem(...)` |
73
+
74
+ ### Padrões de endpoint (Minimal API)
75
+
76
+ ```csharp
77
+ // Endpoint group
78
+ public static class AgendamentoEndpoints
79
+ {
80
+ public static void MapAgendamentoEndpoints(this IEndpointRouteBuilder app)
81
+ {
82
+ var group = app.MapGroup("/api/v1/agendamentos")
83
+ .RequireAuthorization();
84
+
85
+ group.MapPost("/", CreateAgendamento)
86
+ .WithName("CreateAgendamento")
87
+ .Produces<AgendamentoResponse>(201)
88
+ .ProducesValidationProblem()
89
+ .ProducesProblem(409);
90
+ }
91
+
92
+ private static async Task<IResult> CreateAgendamento(
93
+ CreateAgendamentoRequest request,
94
+ IValidator<CreateAgendamentoRequest> validator,
95
+ IAgendamentoService service,
96
+ CancellationToken ct)
97
+ {
98
+ var validation = await validator.ValidateAsync(request, ct);
99
+ if (!validation.IsValid)
100
+ return Results.ValidationProblem(validation.ToDictionary());
101
+
102
+ var result = await service.CreateAsync(request, ct);
103
+ return result.Match(
104
+ success => Results.Created($"/api/v1/agendamentos/{success.Id}", success),
105
+ error => Results.Problem(error.ToProblemDetails())
106
+ );
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Padrões de teste
112
+
113
+ ```csharp
114
+ // Unit test (xUnit + FluentAssertions)
115
+ public class AgendamentoServiceTests
116
+ {
117
+ [Fact]
118
+ public async Task Create_DeveCalcularDuracaoPorPorte_Grande()
119
+ {
120
+ // Arrange
121
+ var service = new AgendamentoService(mockRepo.Object);
122
+ var request = new CreateAgendamentoRequest(PetId: 1, ServicoId: 1, DataHora: DateTime.Now.AddDays(1));
123
+
124
+ // Act
125
+ var result = await service.CreateAsync(request, CancellationToken.None);
126
+
127
+ // Assert
128
+ result.Should().BeSuccess();
129
+ result.Value.DuracaoMin.Should().Be(90); // base 60 + 30 (grande)
130
+ }
131
+ }
132
+
133
+ // Integration test (WebApplicationFactory)
134
+ public class AgendamentoEndpointsTests : IClassFixture<WebApplicationFactory<Program>>
135
+ {
136
+ [Fact]
137
+ public async Task Post_Agendamento_Valido_Retorna201()
138
+ {
139
+ // Arrange
140
+ var client = _factory.CreateClient();
141
+ var request = new { PetId = 1, ServicoId = 1, DataHora = "2026-04-10T09:00:00" };
142
+
143
+ // Act
144
+ var response = await client.PostAsJsonAsync("/api/v1/agendamentos", request);
145
+
146
+ // Assert
147
+ response.StatusCode.Should().Be(HttpStatusCode.Created);
148
+ }
149
+ }
150
+ ```
151
+
152
+ ### Error handling
153
+
154
+ ```csharp
155
+ // Resultado tipado (evita exceptions para fluxo de negócio)
156
+ public abstract record Result<T>
157
+ {
158
+ public record Success(T Value) : Result<T>;
159
+ public record Error(string Code, string Message) : Result<T>;
160
+ }
161
+
162
+ // Códigos de erro do domínio (mapeiam para HTTP no endpoint)
163
+ public static class DomainErrors
164
+ {
165
+ public static readonly Error HorarioPassado = new("HORARIO_PASSADO", "Não é possível agendar no passado");
166
+ public static readonly Error ForaHorarioLoja = new("FORA_HORARIO_LOJA", "Horário fora do expediente");
167
+ public static readonly Error SemTosadorDisponivel = new("SEM_TOSADOR_DISPONIVEL", "Nenhum tosador disponível");
168
+ }
169
+ ```
170
+
171
+ ## Segurança por Endpoint (OBRIGATÓRIO)
172
+
173
+ Cada endpoint implementado DEVE ter:
174
+
175
+ ### Autenticação
176
+ - Seguir mecanismo definido no SDD §5 (Bearer token, API Key, público)
177
+ - Se o SDD diz "Bearer token" → implementar `[Authorize]` ou `.RequireAuthorization()`
178
+ - Se o SDD diz "público" → usar `.AllowAnonymous()` explicitamente
179
+ - **Nunca criar endpoint sem auth definido** — se SDD omitiu → PARAR e reportar
180
+
181
+ ### Autorização
182
+ - Seguir roles/permissões definidos no SDD §5
183
+ - Implementar via policies: `.RequireAuthorization("PolicyName")`
184
+ - Validar ownership quando SDD indica (ex: "owner" → usuário só acessa seus dados)
185
+ - Testar: criar teste unit que valida acesso negado sem role correto
186
+
187
+ ### Validação de Input
188
+ - Validar TODOS os campos de entrada (FluentValidation)
189
+ - Sanitizar strings contra injection (especialmente em queries, paths, headers)
190
+ - Limitar tamanho de payloads (configurar no middleware)
191
+ - Testar: criar teste com input inválido para cada validação
192
+
193
+ ### Erros de Segurança
194
+ - 401 Unauthorized → sempre retornar corpo genérico (não vazar info do sistema)
195
+ - 403 Forbidden → retornar "sem permissão", nunca revelar se o recurso existe
196
+ - Rate limiting → implementar se SDD especificar
197
+
198
+ ### Checklist de Segurança por Task
199
+ Ao finalizar cada task de endpoint, verificar:
200
+ - [ ] Auth configurado conforme SDD
201
+ - [ ] Roles/policies implementados
202
+ - [ ] Validação de input completa
203
+ - [ ] Teste de acesso negado existe
204
+ - [ ] Erros não vazam informação interna
205
+
206
+ ## Comportamento
207
+
208
+ 1. **Lê SDD §N + task** — nunca o SDD inteiro, só as seções referenciadas
209
+ 2. **Implementa + testa na mesma task** — código e teste unit juntos
210
+ 3. **Um commit por task** — `feat(BACK-004): criar endpoint POST /api/v1/agendamentos`
211
+ 4. **Se SDD é ambíguo** → para e reporta. Nunca inventa regra de negócio
212
+ 5. **Auth/AuthZ por endpoint** — todo endpoint DEVE ter auth definido. Se SDD omitiu → PARAR
213
+ 6. **Segue patterns acima** — se o SDD não contradiz, usar os padrões deste agent
214
+ 7. **Erros de negócio via Result<T>** — não usar exceptions para fluxo normal
215
+ 8. **Async em tudo** — nunca bloquear thread
@@ -0,0 +1,165 @@
1
+ # Agent: DB Coder (PostgreSQL)
2
+
3
+ > Especialista em banco de dados PostgreSQL.
4
+ > Implementa tasks da área BANCO seguindo SDD + rules.md.
5
+
6
+ ---
7
+
8
+ ## Identidade
9
+
10
+ | Campo | Valor |
11
+ |-------|-------|
12
+ | Área | BANCO |
13
+ | Modelo padrão | Sonnet (S/M) / Opus (L) |
14
+ | Lê | SDD §3 (Modelo de Dados) + 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 Modelo_Dados.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
@@ -0,0 +1,51 @@
1
+ # Agent: Doc Writer
2
+
3
+ > Especialista em geração de documentação técnica.
4
+ > Usado pelo /design (setup) para gerar docs/Estrutura/ e pelo /merge-delta para atualizá-los.
5
+
6
+ ---
7
+
8
+ ## Identidade
9
+
10
+ | Campo | Valor |
11
+ |-------|-------|
12
+ | Área | DOC |
13
+ | Modelo padrão | Sonnet |
14
+ | Lê | TRD/SDD (seções referenciadas) + template correspondente |
15
+ | Nunca lê | PRD, PM, código fonte |
16
+
17
+ ## Responsabilidades
18
+
19
+ 1. **No setup (via /design passo 3)**: gerar os 8 docs de `docs/Estrutura/` a partir do TRD aprovado
20
+ 2. **Em features (via /merge-delta)**: atualizar docs de Estrutura com Delta Specs do SDD §11
21
+
22
+ ## Mapeamento TRD → docs/Estrutura/
23
+
24
+ | TRD Seção | Doc gerado | Template |
25
+ |-----------|-----------|---------|
26
+ | §1 Visão + §8 Módulos | Visao.md | `_templates/estrutura/Visao.template.md` |
27
+ | §2 Stack | Stack.md | `_templates/estrutura/Stack.template.md` |
28
+ | §3 Arquitetura | Arquitetura.md | `_templates/estrutura/Arquitetura.template.md` |
29
+ | §4 Modelo + SDD §3 | Modelo_Dados.md | `_templates/estrutura/Modelo_Dados.template.md` |
30
+ | §5 API | API.md | `_templates/estrutura/API.template.md` |
31
+ | §6 Infra | Infraestrutura.md | `_templates/estrutura/Infraestrutura.template.md` |
32
+ | §7 Segurança | Seguranca.md | `_templates/estrutura/Seguranca.template.md` |
33
+ | SDD §2 Decisões | ADRs.md | `_templates/estrutura/ADRs.template.md` |
34
+
35
+ ## Regras
36
+
37
+ | Regra | Descrição |
38
+ |-------|-----------|
39
+ | Template é lei | Toda seção do template preenchida — se não tem info, marcar "A definir" |
40
+ | Instruções `<!-- -->` não vão pro doc | Bloco de instruções do agente é removido |
41
+ | Changelog inicia vazio | Primeiro preenchimento não tem changelog |
42
+ | Dados vêm do TRD/SDD | Nunca inventar informação — se TRD não tem, marcar "A definir" |
43
+ | Formato estruturado | Tabelas e listas, nunca texto narrativo longo |
44
+
45
+ ## Comportamento
46
+
47
+ 1. **Ler template** → entender seções obrigatórias
48
+ 2. **Ler TRD/SDD** → extrair dados para cada seção
49
+ 3. **Preencher** → seguindo formato do template exatamente
50
+ 4. **Remover instruções** → bloco `<!-- INSTRUÇÕES -->` não vai pro doc final
51
+ 5. **Commitar** → `docs(DOC-001): gerar Visao.md a partir do TRD`