@ds9-solutions/mcp 0.1.0 → 0.3.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/LICENSE +43 -0
- package/README.md +53 -0
- package/content/agents/code-reviewer.agent.md +52 -22
- package/content/agents/db-analyser.agent.md +121 -0
- package/content/agents/security-reviewer.agent.md +119 -37
- package/content/agents/test-writer.agent.md +84 -35
- package/content/skills/dart/SKILL.md +139 -0
- package/content/skills/dart/examples/entity.dart +37 -0
- package/content/skills/dart/examples/error_handling.dart +36 -0
- package/content/skills/dart/examples/order_test.dart +34 -0
- package/content/skills/dart/examples/repository.dart +57 -0
- package/content/skills/dart/references/checklist.md +12 -0
- package/content/skills/dart/references/documentation.md +26 -0
- package/content/skills/dart/references/naming.md +27 -0
- package/content/skills/dart-frog/SKILL.md +208 -0
- package/content/skills/dart-frog/examples/auth_middleware.dart +50 -0
- package/content/skills/dart-frog/examples/controller.dart +75 -0
- package/content/skills/dart-frog/examples/dto.dart +41 -0
- package/content/skills/dart-frog/examples/error_response.dart +35 -0
- package/content/skills/dart-frog/examples/exceptions.dart +60 -0
- package/content/skills/dart-frog/examples/middleware_composition.dart +34 -0
- package/content/skills/dart-frog/examples/model.dart +20 -0
- package/content/skills/dart-frog/examples/port.dart +17 -0
- package/content/skills/dart-frog/examples/repository.dart +56 -0
- package/content/skills/dart-frog/examples/route_collection.dart +25 -0
- package/content/skills/dart-frog/examples/route_item.dart +24 -0
- package/content/skills/dart-frog/examples/route_test.dart +33 -0
- package/content/skills/dart-frog/examples/service.dart +51 -0
- package/content/skills/dart-frog/examples/service_test.dart +55 -0
- package/content/skills/dart-frog/references/checklist.md +31 -0
- package/content/skills/dart-frog/references/error-handling.md +48 -0
- package/content/skills/dart-frog/references/fpdart-taskeither.md +53 -0
- package/content/skills/dart-frog/references/layers.md +43 -0
- package/content/skills/dart-frog/references/middlewares-di.md +45 -0
- package/content/skills/dart-frog/references/project-structure.md +67 -0
- package/content/skills/dart-frog/references/routing.md +53 -0
- package/content/skills/dart-frog/references/testing.md +24 -0
- package/content/skills/docker/SKILL.md +3 -3
- package/content/skills/driftorm/SKILL.md +249 -0
- package/content/skills/flutter/SKILL.md +419 -0
- package/content/skills/hex-pattern-dart/SKILL.md +83 -0
- package/content/skills/hex-pattern-dart/examples/adapter-in.md +24 -0
- package/content/skills/hex-pattern-dart/examples/adapter-out.md +20 -0
- package/content/skills/hex-pattern-dart/examples/errors.md +25 -0
- package/content/skills/hex-pattern-dart/examples/port.md +11 -0
- package/content/skills/hex-pattern-dart/examples/service.md +20 -0
- package/content/skills/hex-pattern-dart/examples/structure-tree.md +28 -0
- package/content/skills/hex-pattern-dart/references/anti-patterns.md +16 -0
- package/content/skills/hex-pattern-dart/references/checklist.md +34 -0
- package/content/skills/hex-pattern-dart/references/dependency-injection.md +32 -0
- package/content/skills/hex-pattern-dart/references/error-layers.md +27 -0
- package/content/skills/hex-pattern-dart/references/layers-and-dependency-rule.md +29 -0
- package/content/skills/hex-pattern-dart/references/persistence.md +23 -0
- package/content/skills/hex-pattern-dart/references/ports-and-adapters.md +33 -0
- package/content/skills/hex-pattern-dart/references/testing.md +30 -0
- package/content/skills/mysql/SKILL.md +3 -3
- package/content/skills/typescript/SKILL.md +4 -4
- package/dist/src/content.js +10 -2
- package/dist/src/init.js +1 -0
- package/dist/src/search.js +20 -12
- package/dist/src/server.js +60 -4
- package/dist/src/skill-files.js +125 -0
- package/package.json +2 -2
- package/content/agents/db-specialist.agent.md +0 -78
- package/content/agents/nestjs-api-designer.agent.md +0 -61
- package/content/skills/hexagonal/SKILL.md +0 -156
- package/content/skills/jest-testing/SKILL.md +0 -88
- package/content/skills/nestjs/SKILL.md +0 -100
- package/content/skills/typeorm/SKILL.md +0 -119
- package/dist/test/mcp.test.js +0 -112
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Test Writer
|
|
3
|
-
description: "Cria e
|
|
4
|
-
tools: ["read", "search", "edit"]
|
|
3
|
+
description: "Cria, atualiza e/ou executa testes de qualquer linguagem/framework, conforme o modo pedido (somente criar, somente executar, ou criar e executar), e informa a cobertura de linhas quando executa. Segue as convenções de testes do projeto e as skills do MCP aplicáveis. Use quando pedirem para criar/atualizar testes, executar testes, medir cobertura, cobrir um arquivo novo, ou quando um arquivo de código for criado/editado sem teste associado."
|
|
4
|
+
tools: ["read", "search", "edit", "execute", "web"] # permissionamento do agente no caso de usar como plugin. Não válido via MCP. `execute` só para rodar testes/cobertura e instalar dependências já autorizadas pelo usuário; `web` só como fallback quando não há skill aplicável
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
user-invocable: true
|
|
7
7
|
is_background: true
|
|
@@ -9,57 +9,106 @@ is_background: true
|
|
|
9
9
|
|
|
10
10
|
# Test Writer — DS9
|
|
11
11
|
|
|
12
|
-
Cria
|
|
12
|
+
Cria, atualiza e/ou executa testes para qualquer linguagem ou framework, seguindo as convenções do projeto e as skills do MCP aplicáveis. Regra inegociável: **a organização dos testes deve seguir a convenção já existente no projeto; se os testes ficarem em pasta separada, ela espelha 1:1 a estrutura do código-fonte.**
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## 0. Entradas obrigatórias
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
- O usuário pede explicitamente para "criar teste", "cobrir esse arquivo", "gerar testes para X".
|
|
16
|
+
Antes de qualquer ação, confirme duas informações. Se o agente principal ou o usuário não as informou, **pergunte** — não presuma.
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
1. **Pasta principal do projeto** (raiz onde ficam manifestos, código-fonte e testes). Não assuma `src/`, a raiz do repositório nem qualquer outro caminho; todos os caminhos relativos partem dela.
|
|
19
|
+
2. **Modo de operação** (ver abaixo).
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
### Modos de operação
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
| Modo | O que faz | Edita arquivos | Executa testes |
|
|
24
|
+
|---|---|---|---|
|
|
25
|
+
| **Criar** | Cria/atualiza os testes e para. Não roda nada. | sim | não |
|
|
26
|
+
| **Executar** | Roda os testes existentes e informa resultado e cobertura. | não | sim |
|
|
27
|
+
| **Criar e executar** | Cria/atualiza os testes, depois roda e informa resultado e cobertura. | sim | sim |
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
- Identifique o modo pelo pedido ("só crie", "rode os testes", "crie e rode", "qual a cobertura?"). Se for ambíguo, pergunte.
|
|
30
|
+
- No modo **Criar**, nunca execute testes, nem para "conferir".
|
|
31
|
+
- No modo **Executar**, nunca crie nem altere arquivos.
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|---|---|
|
|
31
|
-
| `src/orders/application/use-cases/create-order.use-case.ts` | `test/orders/application/use-cases/create-order.use-case.spec.ts` |
|
|
32
|
-
| `src/orders/infrastructure/adapters/in/order.controller.ts` | `test/orders/infrastructure/adapters/in/order.controller.e2e-spec.ts` |
|
|
33
|
+
## 0.1 Progresso durante a execução
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
Mantenha o usuário informado enquanto trabalha, com mensagens curtas, de uma linha, **antes** de cada passo relevante (não apenas no resumo final):
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
- **Skills:** ao carregar cada skill do MCP, informe qual (`Skill carregada: <id>`). Se usar fallback web, informe a fonte (`Referência externa: <nome/link>`).
|
|
38
|
+
- **Bibliotecas:** informe a biblioteca de testes e de cobertura detectadas e as demais em uso (`Biblioteca de testes: <nome> <versão>`). Ao instalar uma dependência autorizada, informe cada uma.
|
|
39
|
+
- **Criação/atualização:** antes de escrever, informe o arquivo (`Criando: <caminho>` ou `Atualizando: <caminho>`), indicando o arquivo-fonte que ele cobre.
|
|
40
|
+
- **Execução:** informe o comando e o alvo (`Executando: <comando> — <arquivo ou suíte>`) e, ao concluir cada execução, o resultado resumido (passaram/falharam).
|
|
41
|
+
- **Ignorados:** ao pular um arquivo, informe o motivo na hora.
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
Não repita no progresso o conteúdo dos testes; o detalhe fica no resumo final.
|
|
44
|
+
|
|
45
|
+
## 1. Descobrir a stack e a convenção de testes
|
|
46
|
+
|
|
47
|
+
Não presuma — inspecione o projeto real, a partir da pasta principal informada:
|
|
48
|
+
|
|
49
|
+
1. **Linguagem e framework:** identifique pela extensão dos arquivos, imports/dependências declaradas, manifestos/configuração do ecossistema em uso e estrutura de pastas.
|
|
50
|
+
2. **Biblioteca de testes e de cobertura:** descubra qual está instalada/configurada (dependências declaradas, arquivos de configuração do runner, scripts/tarefas de teste do projeto). Use somente a que o projeto já usa; não instale nem troque de biblioteca sem pedir ao usuário.
|
|
51
|
+
3. **Skills do MCP:** descubra as disponíveis (plugin, ou via MCP: `list_skills`, `recommend_for_task`, `search_guidelines`) e carregue (`get_skill`) apenas as relevantes à stack e a testes. Elas são a fonte de verdade das convenções. Se indicarem arquivos complementares, leia só os necessários (`list_skill_files` / `get_skill_file`).
|
|
52
|
+
4. **Fallback externo:** se não houver skill aplicável à stack ou à biblioteca de testes, consulte referências confiáveis na web (documentação oficial da biblioteca/framework). Use a web somente nesse caso, nunca para contradizer uma skill existente.
|
|
53
|
+
5. **Onde ficam os testes:** observe os testes já existentes e a configuração do runner (padrões/diretórios de busca de testes) para saber se ficam ao lado do código-fonte ou em pasta separada, e qual o padrão de nome de arquivo.
|
|
54
|
+
|
|
55
|
+
### Dependências necessárias e autorização
|
|
56
|
+
|
|
57
|
+
Concluída a análise, determine quais bibliotecas faltam para realizar **todas** as tarefas do modo escolhido (por exemplo: runner de testes, biblioteca de mocks, ferramenta de cobertura, utilitários de teste de integração) e que não estão instaladas nem declaradas no projeto.
|
|
58
|
+
|
|
59
|
+
- Se não faltar nada, siga em frente.
|
|
60
|
+
- Se faltar algo, **pare e peça autorização** antes de instalar, apresentando em uma lista: cada biblioteca, para que serve, versão sugerida (compatível com a stack e a biblioteca de testes já em uso), se é dependência de desenvolvimento e o comando exato que será executado com o gerenciador de pacotes do projeto.
|
|
61
|
+
- Só instale após resposta afirmativa explícita, e apenas o que foi autorizado. Se o usuário negar, siga com o que já existe e informe as limitações (por exemplo, execução sem cobertura ou testes sem determinado tipo de mock).
|
|
62
|
+
- Após instalar, informe no resumo o que foi adicionado e quais arquivos de manifesto/lock foram alterados.
|
|
63
|
+
|
|
64
|
+
### Espelhamento
|
|
65
|
+
|
|
66
|
+
- Se o projeto usa **pasta de testes separada**, o caminho dentro dela reproduz exatamente o caminho relativo do arquivo-fonte, trocando apenas o nome/sufixo do arquivo final conforme o padrão do projeto.
|
|
67
|
+
- Se o projeto coloca testes **ao lado do código-fonte**, siga esse padrão; o espelhamento já é implícito.
|
|
68
|
+
- Se não houver testes existentes para inferir a convenção, use a recomendada pela skill/referência aplicável e informe a escolha no resumo.
|
|
69
|
+
|
|
70
|
+
## 2. Selecionar o que testar (modos Criar e Criar e executar)
|
|
71
|
+
|
|
72
|
+
- Identifique o código criado/alterado sem teste correspondente (ou com teste desatualizado). Se o usuário indicou arquivos, restrinja-se a eles.
|
|
73
|
+
- Priorize lógica de negócio, regras de domínio, serviços/casos de uso, acesso a dados e camadas de entrada (controllers/handlers).
|
|
74
|
+
- Não gere teste para arquivos sem lógica (configuração pura, barris de exportação, estruturas de dados sem comportamento), a menos que o usuário peça.
|
|
75
|
+
- Não sobrescreva um teste existente que já tem asserções reais; **complemente** com os casos faltantes.
|
|
41
76
|
|
|
42
77
|
## 3. Escrever o teste
|
|
43
78
|
|
|
44
|
-
Siga
|
|
79
|
+
Siga as skills/referências aplicáveis à stack. Princípios gerais:
|
|
80
|
+
|
|
81
|
+
- Nomes que descrevem comportamento, não implementação.
|
|
82
|
+
- Isole dependências externas com mocks/fakes/stubs no estilo da biblioteca em uso.
|
|
83
|
+
- Teste pelo comportamento público; cubra o caminho feliz, bordas e pelo menos um caso de erro.
|
|
84
|
+
- Determinismo: sem dependência de tempo real, rede, ordem de execução ou estado compartilhado.
|
|
85
|
+
- Não deixe apenas esqueleto vazio (`todo`/`skip`) se for possível escrever uma asserção real; use-os só quando faltar contexto de verdade e explique no resumo.
|
|
86
|
+
|
|
87
|
+
## 4. Executar e medir cobertura (modos Executar e Criar e executar)
|
|
45
88
|
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
89
|
+
1. Use o comando de teste e de cobertura que o projeto já define; se não houver, derive-o da documentação da biblioteca descoberta. Execute a partir da pasta principal.
|
|
90
|
+
2. Rode com cobertura habilitada. Se a ferramenta de cobertura não estiver instalada/configurada, inclua-a na solicitação de autorização de dependências (seção 1). Sem autorização, execute os testes sem cobertura e informe que ela não está disponível, sugerindo como habilitar.
|
|
91
|
+
3. Execute somente comandos de teste/cobertura e, quando autorizado, a instalação das dependências aprovadas. Não rode comandos que alterem o repositório ou o ambiente (`git commit/push/checkout/reset`, migrations, deploy etc.).
|
|
92
|
+
4. Se houver falhas, **não corrija o código de produção**. Reporte cada teste que falhou, com a mensagem e a causa provável.
|
|
93
|
+
5. Extraia do relatório a **cobertura de linhas** (percentual total e, quando disponível, por arquivo revisado/alterado). Se o relatório também trouxer ramos/funções, pode citar, mas o número principal é o de linhas.
|
|
50
94
|
|
|
51
|
-
##
|
|
95
|
+
## 5. Resumo final
|
|
52
96
|
|
|
53
|
-
|
|
97
|
+
Apresente, conforme o modo:
|
|
54
98
|
|
|
55
|
-
1. **
|
|
56
|
-
2. **Atualizados:**
|
|
57
|
-
3. **
|
|
58
|
-
4. **
|
|
99
|
+
1. **Stack detectada:** linguagem/framework, biblioteca de testes e de cobertura, skills consultadas ou referências externas usadas (nome e link).
|
|
100
|
+
2. **Criados / Atualizados / Ignorados:** caminhos completos e o motivo dos ignorados (modos com criação).
|
|
101
|
+
3. **Execução:** comando usado, total de testes, passaram, falharam, ignorados (modos com execução).
|
|
102
|
+
4. **Cobertura de linhas:** percentual total e dos arquivos relevantes; ou o motivo de não estar disponível (modos com execução).
|
|
103
|
+
5. **Pendências:** testes marcados como `todo`/`skip`, falhas a tratar e o que falta para resolvê-los.
|
|
59
104
|
|
|
60
105
|
## Não fazer
|
|
61
106
|
|
|
62
|
-
- Não
|
|
63
|
-
- Não
|
|
107
|
+
- Não presumir a pasta principal do projeto nem o modo de operação; perguntar.
|
|
108
|
+
- Não alterar código de produção — apenas arquivos de teste.
|
|
109
|
+
- Não executar testes no modo Criar, nem criar/alterar arquivos no modo Executar.
|
|
110
|
+
- Não instalar dependências sem autorização explícita do usuário, nem trocar a biblioteca de testes do projeto.
|
|
111
|
+
- Não corrigir código de produção para fazer teste passar; apenas reportar a falha.
|
|
64
112
|
- Não sobrescrever testes existentes com asserções reais sem necessidade.
|
|
65
|
-
- Não
|
|
113
|
+
- Não usar a web quando houver skill aplicável, nem para contradizer uma skill.
|
|
114
|
+
- Não aplicar tratamento diferente por linguagem/framework além do que a skill ou referência aplicável determinar.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dart
|
|
3
|
+
description: Convenções da linguagem Dart da DS9 — orientação a objetos como abordagem padrão, nomenclatura oficial do Dart (Effective Dart), documentação com `///`, null safety, tratamento de erros, análise estática, formatação e testes. Use ao escrever ou revisar qualquer código Dart (CLI, servidor, pacote ou app Flutter), definir classes/tipos, nomear arquivos e identificadores, documentar código, ou quando o usuário pedir "boas práticas Dart", "padrão Dart", "nomenclatura Dart" ou "documentar com ///".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dart — Diretrizes DS9
|
|
7
|
+
|
|
8
|
+
Convenções da **linguagem Dart**, válidas para qualquer projeto (CLI, servidor, pacote ou aplicativo). Regras específicas de Flutter (widgets, estado, UI) não fazem parte desta skill. Base: guia oficial *Effective Dart*, documentação do Dart e as skills Dart do projeto `lazy_forge` (`.agents/skills`). Em caso de dúvida sobre versão da linguagem, confirme a versão do SDK no `pubspec.yaml` antes de usar recursos novos.
|
|
9
|
+
|
|
10
|
+
## 1. Orientação a objetos como padrão
|
|
11
|
+
|
|
12
|
+
O código Dart da DS9 é **orientado a objetos**. Modele o domínio com classes e deixe o comportamento junto dos dados.
|
|
13
|
+
|
|
14
|
+
- **Comportamento em métodos, não em funções soltas:** lógica de negócio vive em classes (entidades, serviços, casos de uso). Funções de nível superior ficam restritas a `main()` e a pequenos utilitários verdadeiramente genéricos e sem estado; mesmo estes, prefira como métodos estáticos de uma classe coesa ou como `extension`.
|
|
15
|
+
- **Encapsulamento:** campos privados (`_campo`) com acesso por getters/métodos; exponha o mínimo necessário. Estado interno nunca é alterado de fora da classe.
|
|
16
|
+
- **Imutabilidade por padrão:** campos `final`, construtores `const` quando possível, e novas instâncias (`copyWith`/métodos que retornam um novo objeto) em vez de mutação onde o domínio pedir.
|
|
17
|
+
- **Composição sobre herança:** injete dependências pelo construtor (como `abstract interface class` ou `abstract class`) e componha objetos; use herança só para relação "é um" genuína.
|
|
18
|
+
- **Polimorfismo no lugar de `if`/`switch` por tipo:** variação de comportamento vai em subclasses/implementações, não em cadeias de `is`/`switch` espalhadas. Use `sealed class` para famílias fechadas de tipos; `switch` exaustivo sobre elas é aceitável quando o comportamento não pertence ao tipo (ex.: decodificar dados externos).
|
|
19
|
+
- **Contratos explícitos:** dependências externas (banco, rede, relógio) atrás de uma interface (`abstract interface class`), para troca e teste.
|
|
20
|
+
|
|
21
|
+
### Evite o estilo funcional como abordagem principal
|
|
22
|
+
|
|
23
|
+
Dart é multiparadigma, mas aqui o padrão é objetos. Isso **não** proíbe os recursos idiomáticos da linguagem; proíbe construir a arquitetura em torno de funções.
|
|
24
|
+
|
|
25
|
+
- Evite pipelines longos e encadeados (`map().where().fold().expand()...`) que escondem regra de negócio; se passar de 2 ou 3 etapas, extraia para um método nomeado ou use um laço `for` claro.
|
|
26
|
+
- Evite passar funções/closures como mecanismo principal de extensão (callbacks em cascata, funções de ordem superior como "estratégia"); prefira um objeto com método bem nomeado.
|
|
27
|
+
- Evite funções que retornam funções, currying e composição de funções; evite tipos como `Function` solto (use `typedef` ou interface quando um callback for inevitável).
|
|
28
|
+
- Evite `Either`/`Result` genéricos e estilos monádicos criados à mão quando exceção tipada ou um tipo de resultado `sealed` do domínio resolve de forma mais legível. **Exceção:** em projetos que seguem as skills `hex-pattern-dart`, `dart-frog` ou `flutter`, o `TaskEither` do `fpdart` (com `TaskEither.tryCatch`, `map`, `flatMap`, `mapLeft`) é o padrão obrigatório nos contratos entre camadas; ele não se estende ao domínio e aos models, que continuam orientados a objetos.
|
|
29
|
+
- Aceitável e idiomático: `for` com `collection-if`/`collection-for` em literais, `map`/`where`/`toList` simples (1 a 2 etapas), `async`/`await`, callbacks exigidos por APIs de terceiros e a composição de `TaskEither` conforme essas skills.
|
|
30
|
+
|
|
31
|
+
## 2. Nomenclatura (Effective Dart)
|
|
32
|
+
|
|
33
|
+
| Elemento | Convenção | Exemplo |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| Classes, enums, mixins, extensions, typedefs, parâmetros de tipo | `UpperCamelCase` | `OrderService`, `PaymentStatus`, `T` |
|
|
36
|
+
| Variáveis, parâmetros, campos, métodos, funções, getters | `lowerCamelCase` | `totalPrice`, `findById()` |
|
|
37
|
+
| **Constantes** (incl. `const`/`static const`/valores de enum) | `lowerCamelCase` (**não** `SCREAMING_CAPS`) | `defaultTimeout`, `maxRetries` |
|
|
38
|
+
| Pacotes, diretórios, arquivos, prefixos de import | `lowercase_with_underscores` | `order_service.dart`, `import '...' as http_client;` |
|
|
39
|
+
| Membros e tipos privados da biblioteca | prefixo `_` | `_cache`, `_OrderMapper` |
|
|
40
|
+
|
|
41
|
+
Regras adicionais:
|
|
42
|
+
|
|
43
|
+
- **Arquivo = classe principal:** `UserRepository` fica em `user_repository.dart`. Uma classe pública principal por arquivo; testes em `<nome>_test.dart`.
|
|
44
|
+
- **Siglas:** com mais de duas letras, capitalize como palavra (`HttpClient`, `JsonParser`, `UserId`); com duas letras, mantenha maiúsculas (`IOSink`).
|
|
45
|
+
- **Sem prefixos/sufixos de tipo:** não use `I` para interfaces (`IUserRepository`), notação húngara, nem `k` em constantes (`kTimeout`).
|
|
46
|
+
- **Booleanos** com nome afirmativo: `isEmpty`, `hasPermission`, `canRetry`; evite negações (`isNotValid`).
|
|
47
|
+
- **Métodos** começam com verbo (`calculateTotal`, `save`); **getters e propriedades** são substantivos, sem prefixo `get` (`total`, não `getTotal`).
|
|
48
|
+
- **Nomes descritivos:** sem abreviações obscuras nem nomes de uma letra fora de laços/lambdas curtos; o nome expressa intenção, não implementação.
|
|
49
|
+
- **Variáveis não usadas:** use `_` (wildcard) em vez de nomes sem uso.
|
|
50
|
+
- **Ordem em arquivos:** `dart:` → `package:` → relativos, cada grupo em ordem alfabética; prefira imports relativos dentro de `lib/` do próprio pacote, exceto quando a skill do framework definir outro padrão (a `flutter` usa `package:`).
|
|
51
|
+
|
|
52
|
+
## 3. Documentação e comentários (`///`)
|
|
53
|
+
|
|
54
|
+
**Regra de inclusão:** toda declaração **pública** (biblioteca, classe, enum, mixin, extension, construtor nomeado relevante, método, função, getter/setter, campo e constante) **deve** ter comentário de documentação com `///`. Declarações privadas só precisam quando a lógica não for óbvia. Código novo sem `///` nas declarações públicas é pendência de review.
|
|
55
|
+
|
|
56
|
+
- Use **sempre `///`**, em linhas consecutivas; **nunca** `/** ... */`. Use `//` apenas para comentários de implementação internos, explicando o **porquê**, nunca o óbvio.
|
|
57
|
+
- **Primeira linha:** uma frase única e resumida, terminada em ponto, seguida de uma linha `///` vazia antes do restante. Uma linha totalmente em branco (sem `///`) encerra o comentário.
|
|
58
|
+
- **Abertura por tipo de membro:** propriedades/getters com sintagma nominal (`/// O raio da esfera.`); booleanos com "Se"/"Whether" no idioma do projeto (`/// Se a conexão está ativa.`); métodos com verbo na 3ª pessoa (`/// Inicializa o banco.`).
|
|
59
|
+
- **Sem redundância:** não repita a assinatura nem o nome ("Esta classe é...", "O método foo faz...").
|
|
60
|
+
- **Sem tags estilo Javadoc** (`@param`, `@return`, `@throws`): descreva parâmetros, retorno e exceções em prosa, referenciando parâmetros com `[nome]`.
|
|
61
|
+
- **Links:** use colchetes para símbolos no escopo (`[Order]`, `[Order.total]`, sem parênteses); construtor sem nome como `[Order.new]`; crases para palavras-chave e literais (`` `null` ``, `` `true` ``). Blocos de código com a linguagem (` ```dart `).
|
|
62
|
+
- **Posição:** o comentário `///` vem **antes** das anotações (`@override` etc.).
|
|
63
|
+
- **Herança e pares getter/setter:** não duplique documentação em `@override` sem mudança de comportamento; em par getter/setter, documente só o getter.
|
|
64
|
+
- **Idioma:** siga o idioma já usado no projeto, de forma consistente.
|
|
65
|
+
- Valide com `dart analyze` (referências entre colchetes resolvidas) e, opcionalmente, `dart doc`.
|
|
66
|
+
|
|
67
|
+
```dart
|
|
68
|
+
// Evitar
|
|
69
|
+
/**
|
|
70
|
+
* Busca o pedido.
|
|
71
|
+
* @param id identificador
|
|
72
|
+
* @return o pedido
|
|
73
|
+
*/
|
|
74
|
+
Order find(String id) { ... }
|
|
75
|
+
|
|
76
|
+
// Preferir
|
|
77
|
+
/// Busca o pedido pelo [id].
|
|
78
|
+
///
|
|
79
|
+
/// Lança [OrderNotFoundException] se não existir pedido com esse identificador.
|
|
80
|
+
Order findById(String id) { ... }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## 4. Construtores e classes
|
|
84
|
+
|
|
85
|
+
- Prefira **parâmetros iniciais** (`this.campo`) e `super.parametro` a atribuições manuais; use `required` em parâmetros nomeados obrigatórios.
|
|
86
|
+
- Construtores `const` em classes imutáveis; `factory` para validação/cache e para criar a partir de dados externos (`fromJson`).
|
|
87
|
+
- **Invariantes no construtor/factory:** estado inválido não pode existir; valide e lance exceção de domínio.
|
|
88
|
+
- **Primary constructors** (declarar campos no cabeçalho da classe): disponíveis só a partir do Dart 3.13 (experimental no 3.12, via flag). Use **somente se o SDK do projeto suportar**; caso contrário, use construtores tradicionais. Não migre código existente apenas por isso.
|
|
89
|
+
- Use `sealed`, `final`, `base` e `interface` para controlar quem pode estender ou implementar uma classe, quando a API for pública.
|
|
90
|
+
|
|
91
|
+
## 5. Null safety e tipos
|
|
92
|
+
|
|
93
|
+
- Nada de `dynamic` em código novo; tipos explícitos em APIs públicas, em genéricos (`List<Order>`) e em retornos.
|
|
94
|
+
- Evite `!` (asserção de nulo); prefira promoção de tipo, `?.`, `??` ou tratar o nulo. `late` só quando a inicialização estiver garantida antes do uso.
|
|
95
|
+
- Prefira `final` a `var` quando o valor não muda; evite `as` sem garantia do tipo em tempo de execução.
|
|
96
|
+
- **Pattern matching e records** (Dart 3): use para decodificar dados externos (JSON) e `switch` exaustivo em `sealed`; não use para o que um `is` simples, um acesso a propriedade ou uma comparação booleana resolvem. Dados malformados devem falhar com erro explícito (`FormatException`), nunca ser descartados em silêncio.
|
|
97
|
+
|
|
98
|
+
## 6. Tratamento de erros
|
|
99
|
+
|
|
100
|
+
- Falhas recuperáveis: **`Exception` tipada do domínio** (`class OrderNotFoundException implements Exception`), nunca `throw 'texto'` nem lançar `Exception` genérica. Em projetos `hex-pattern-dart`/`dart-frog`, as falhas trafegam como `Left` de `TaskEither` com as exceções por camada definidas em `hex-pattern-dart` (em Flutter, siga a skill `flutter`) (`BusinessException`, `ClientException`, `MiddlewareException`).
|
|
101
|
+
- **Nunca capture `Error`** (nem `TypeError`, `ArgumentError`, etc.): indicam bugs de programação. Capture tipos específicos; não use `catch (e)` amplo sem relançar.
|
|
102
|
+
- Use `rethrow` para propagar preservando o stack trace; não engula exceções em silêncio nem registre dados sensíveis.
|
|
103
|
+
- Mensagens de erro expostas a usuários não vazam detalhes internos.
|
|
104
|
+
|
|
105
|
+
## 7. Assincronismo
|
|
106
|
+
|
|
107
|
+
- `async`/`await` em vez de encadear `.then()`; sempre aguarde (`await`) ou trate explicitamente os `Future`s (sem "fire-and-forget" acidental).
|
|
108
|
+
- Libere recursos (`close`/`cancel`/`dispose`) em `try/finally`; cancele subscriptions e controllers de `Stream`.
|
|
109
|
+
- Não bloqueie o isolate principal com trabalho pesado síncrono; use isolates quando necessário.
|
|
110
|
+
|
|
111
|
+
## 8. Qualidade, formatação e testes
|
|
112
|
+
|
|
113
|
+
- **Análise estática:** `analysis_options.yaml` na raiz do pacote com um conjunto base (`package:lints/recommended.yaml` ou `package:flutter_lints/flutter.yaml`) e `strict-casts`, `strict-inference` e `strict-raw-types` ativos. Exclua só código gerado (`**/*.g.dart`).
|
|
114
|
+
- Rode `dart analyze` e corrija os avisos; use `dart fix --apply` para correções mecânicas (revise com `--dry-run`) e `dart format .` antes de commitar. Suprima diagnósticos (`// ignore:`) só com justificativa e no menor escopo.
|
|
115
|
+
- **Testes:** `package:test` (ou `flutter_test` em Flutter), arquivos em `test/` espelhando `lib/` com sufixo `_test.dart`; `group()` por funcionalidade, `setUp()`/`tearDown()` para preparo, `expect()` com matchers; dependências externas isoladas por interface/mocks. Para criar e executar testes, use o agente `test-writer`.
|
|
116
|
+
|
|
117
|
+
## 9. Checklist de review
|
|
118
|
+
|
|
119
|
+
- [ ] Regra de negócio está em classes, sem funções soltas nem cadeias funcionais longas?
|
|
120
|
+
- [ ] Toda declaração pública tem `///` no formato da seção 3?
|
|
121
|
+
- [ ] Nomes seguem a tabela da seção 2 (inclusive constantes em `lowerCamelCase` e arquivos em `snake_case`)?
|
|
122
|
+
- [ ] Sem `dynamic`, `!` desnecessário ou `catch` de `Error`?
|
|
123
|
+
- [ ] Campos `final`, encapsulamento e construtores `const` onde cabem?
|
|
124
|
+
- [ ] `dart analyze` limpo, `dart format` aplicado e testes cobrindo o comportamento novo?
|
|
125
|
+
|
|
126
|
+
## 10. Arquivos complementares
|
|
127
|
+
|
|
128
|
+
Em caso de dúvida, consulte (via `list_skill_files` / `get_skill_file` com `skill="dart"`; ou direto na pasta `dart/`, se o host não tiver as tools):
|
|
129
|
+
|
|
130
|
+
- `examples/` — código de referência: `entity.dart`, `repository.dart`, `error_handling.dart`, `order_test.dart`. Use quando precisar de um exemplo de entidade, contrato/caso de uso, erros ou teste.
|
|
131
|
+
- `references/` — `naming.md` (nomenclatura), `documentation.md` (`///`), `checklist.md` (review detalhado).
|
|
132
|
+
|
|
133
|
+
## Não fazer
|
|
134
|
+
|
|
135
|
+
- Não usar `/** ... */` nem tags `@param`/`@return`/`@throws`.
|
|
136
|
+
- Não usar `SCREAMING_CAPS`, prefixo `I`, `k` ou notação húngara.
|
|
137
|
+
- Não criar funções de nível superior com regra de negócio nem pipelines funcionais extensos (exceto a composição de `TaskEither` exigida pelas skills `hex-pattern-dart`, `dart-frog` e `flutter`).
|
|
138
|
+
- Não declarar `dynamic`, `Function` solto ou `throw` de strings.
|
|
139
|
+
- Não duplicar regras de outras skills; para testes, ver o agente `test-writer`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/// Exemplo: entidade imutável, encapsulada e documentada com `///`.
|
|
2
|
+
library;
|
|
3
|
+
|
|
4
|
+
/// Status possíveis de um [Order].
|
|
5
|
+
enum OrderStatus {
|
|
6
|
+
/// Pedido criado e ainda não pago.
|
|
7
|
+
pending,
|
|
8
|
+
|
|
9
|
+
/// Pedido pago.
|
|
10
|
+
paid,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/// Pedido do domínio, com invariantes validadas na criação.
|
|
14
|
+
class Order {
|
|
15
|
+
/// Cria um pedido.
|
|
16
|
+
///
|
|
17
|
+
/// Lança [ArgumentError] se [id] estiver vazio ou [total] for negativo.
|
|
18
|
+
Order({required this.id, required this.total, this.status = OrderStatus.pending}) {
|
|
19
|
+
if (id.isEmpty) throw ArgumentError.value(id, 'id', 'não pode ser vazio');
|
|
20
|
+
if (total < 0) throw ArgumentError.value(total, 'total', 'não pode ser negativo');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Identificador único do pedido.
|
|
24
|
+
final String id;
|
|
25
|
+
|
|
26
|
+
/// Valor total do pedido.
|
|
27
|
+
final double total;
|
|
28
|
+
|
|
29
|
+
/// Situação atual do pedido.
|
|
30
|
+
final OrderStatus status;
|
|
31
|
+
|
|
32
|
+
/// Se o pedido já foi pago.
|
|
33
|
+
bool get isPaid => status == OrderStatus.paid;
|
|
34
|
+
|
|
35
|
+
/// Retorna uma cópia deste pedido já marcada como paga.
|
|
36
|
+
Order markAsPaid() => Order(id: id, total: total, status: OrderStatus.paid);
|
|
37
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/// Exemplo: exceções tipadas e tratamento sem engolir erros.
|
|
2
|
+
library;
|
|
3
|
+
|
|
4
|
+
/// Falha ao decodificar dados externos.
|
|
5
|
+
class InvalidPayloadException implements Exception {
|
|
6
|
+
/// Cria a exceção com a [message] explicando o problema.
|
|
7
|
+
const InvalidPayloadException(this.message);
|
|
8
|
+
|
|
9
|
+
/// Descrição do problema, segura para exibir.
|
|
10
|
+
final String message;
|
|
11
|
+
|
|
12
|
+
@override
|
|
13
|
+
String toString() => 'InvalidPayloadException: $message';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Lê um valor numérico de um payload externo.
|
|
17
|
+
class PayloadReader {
|
|
18
|
+
/// Lê o campo `amount` de [json].
|
|
19
|
+
///
|
|
20
|
+
/// Lança [InvalidPayloadException] se ele não existir ou não for numérico.
|
|
21
|
+
double readAmount(Map<String, Object?> json) {
|
|
22
|
+
return switch (json['amount']) {
|
|
23
|
+
final num amount => amount.toDouble(),
|
|
24
|
+
_ => throw const InvalidPayloadException('campo "amount" ausente ou inválido'),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Lê o valor e propaga falhas de domínio preservando o stack trace.
|
|
29
|
+
double readOrRethrow(Map<String, Object?> json) {
|
|
30
|
+
try {
|
|
31
|
+
return readAmount(json);
|
|
32
|
+
} on InvalidPayloadException {
|
|
33
|
+
rethrow; // nunca `catch (e)` amplo nem captura de `Error`
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/// Exemplo: teste unitário com `group`, `setUp` e `expect`.
|
|
2
|
+
///
|
|
3
|
+
/// Em um projeto real o arquivo fica em `test/`, espelhando `lib/`.
|
|
4
|
+
library;
|
|
5
|
+
|
|
6
|
+
import 'package:test/test.dart';
|
|
7
|
+
|
|
8
|
+
import 'entity.dart';
|
|
9
|
+
import 'repository.dart';
|
|
10
|
+
|
|
11
|
+
void main() {
|
|
12
|
+
group('PayOrder', () {
|
|
13
|
+
late InMemoryOrderRepository repository;
|
|
14
|
+
late PayOrder useCase;
|
|
15
|
+
|
|
16
|
+
setUp(() {
|
|
17
|
+
repository = InMemoryOrderRepository();
|
|
18
|
+
useCase = PayOrder(repository);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('marca o pedido como pago e persiste', () async {
|
|
22
|
+
await repository.save(Order(id: '1', total: 10));
|
|
23
|
+
|
|
24
|
+
final paid = await useCase.execute('1');
|
|
25
|
+
|
|
26
|
+
expect(paid.isPaid, isTrue);
|
|
27
|
+
expect((await repository.findById('1'))!.isPaid, isTrue);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('lança OrderNotFoundException quando o pedido não existe', () {
|
|
31
|
+
expect(() => useCase.execute('x'), throwsA(isA<OrderNotFoundException>()));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/// Exemplo: contrato (porta) e implementação, com dependência injetada.
|
|
2
|
+
library;
|
|
3
|
+
|
|
4
|
+
import 'entity.dart';
|
|
5
|
+
|
|
6
|
+
/// Contrato de persistência de pedidos.
|
|
7
|
+
abstract interface class OrderRepository {
|
|
8
|
+
/// Busca o pedido pelo [id]; retorna `null` se não existir.
|
|
9
|
+
Future<Order?> findById(String id);
|
|
10
|
+
|
|
11
|
+
/// Salva o [order].
|
|
12
|
+
Future<void> save(Order order);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// Implementação em memória, útil em testes.
|
|
16
|
+
class InMemoryOrderRepository implements OrderRepository {
|
|
17
|
+
final Map<String, Order> _orders = {};
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
Future<Order?> findById(String id) async => _orders[id];
|
|
21
|
+
|
|
22
|
+
@override
|
|
23
|
+
Future<void> save(Order order) async {
|
|
24
|
+
_orders[order.id] = order;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Caso de uso: paga um pedido existente.
|
|
29
|
+
class PayOrder {
|
|
30
|
+
/// Cria o caso de uso com o [repository] injetado.
|
|
31
|
+
PayOrder(this._repository);
|
|
32
|
+
|
|
33
|
+
final OrderRepository _repository;
|
|
34
|
+
|
|
35
|
+
/// Marca como pago o pedido [id].
|
|
36
|
+
///
|
|
37
|
+
/// Lança [OrderNotFoundException] se o pedido não existir.
|
|
38
|
+
Future<Order> execute(String id) async {
|
|
39
|
+
final order = await _repository.findById(id);
|
|
40
|
+
if (order == null) throw OrderNotFoundException(id);
|
|
41
|
+
final paid = order.markAsPaid();
|
|
42
|
+
await _repository.save(paid);
|
|
43
|
+
return paid;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Erro de domínio: pedido não encontrado.
|
|
48
|
+
class OrderNotFoundException implements Exception {
|
|
49
|
+
/// Cria a exceção para o pedido [id].
|
|
50
|
+
const OrderNotFoundException(this.id);
|
|
51
|
+
|
|
52
|
+
/// Identificador procurado.
|
|
53
|
+
final String id;
|
|
54
|
+
|
|
55
|
+
@override
|
|
56
|
+
String toString() => 'Pedido não encontrado: $id';
|
|
57
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Dart — Checklist de review detalhado
|
|
2
|
+
|
|
3
|
+
- [ ] Regra de negócio em classes; sem funções soltas nem pipelines longos.
|
|
4
|
+
- [ ] Dependências externas atrás de `abstract interface class`, injetadas no construtor.
|
|
5
|
+
- [ ] Campos `final`, construtores `const` onde couber, estado privado encapsulado.
|
|
6
|
+
- [ ] Toda declaração pública com `///` (sem `/** */`, sem `@param`).
|
|
7
|
+
- [ ] Nomes: `UpperCamelCase` (tipos), `lowerCamelCase` (membros e constantes), `snake_case` (arquivos).
|
|
8
|
+
- [ ] Sem `dynamic`, `!` desnecessário, `Function` solto ou `throw` de string.
|
|
9
|
+
- [ ] Sem `catch` de `Error`; `rethrow` preserva o stack trace.
|
|
10
|
+
- [ ] `Future`s aguardados; recursos liberados em `try/finally`.
|
|
11
|
+
- [ ] `dart analyze` limpo, `dart format` aplicado.
|
|
12
|
+
- [ ] Testes em `test/` espelhando `lib/`, com `group`/`setUp`/`expect`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Dart — Documentação com `///` (referência detalhada)
|
|
2
|
+
|
|
3
|
+
Complementa a seção 3 do `SKILL.md`.
|
|
4
|
+
|
|
5
|
+
## Modelo
|
|
6
|
+
|
|
7
|
+
```dart
|
|
8
|
+
/// Calcula o total do pedido.
|
|
9
|
+
///
|
|
10
|
+
/// Soma os itens de [items] e aplica [discount] (entre 0 e 1).
|
|
11
|
+
/// Lança [ArgumentError] se [discount] estiver fora do intervalo.
|
|
12
|
+
double calculateTotal(List<Item> items, {double discount = 0}) { ... }
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Regras rápidas
|
|
16
|
+
|
|
17
|
+
- Primeira linha: frase única, terminada em ponto; depois linha `///` vazia.
|
|
18
|
+
- Propriedade: sintagma nominal. Booleano: "Se ...". Método: verbo na 3ª pessoa.
|
|
19
|
+
- Sem `@param`/`@return`; use prosa e `[nome]`.
|
|
20
|
+
- `///` antes de `@override` e outras anotações.
|
|
21
|
+
- Par getter/setter: documente só o getter.
|
|
22
|
+
- Não documente `@override` sem mudança de comportamento.
|
|
23
|
+
|
|
24
|
+
## Validação
|
|
25
|
+
|
|
26
|
+
`dart analyze` resolve referências entre colchetes; `dart doc` gera a documentação.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Dart — Nomenclatura (referência detalhada)
|
|
2
|
+
|
|
3
|
+
Complementa a seção 2 do `SKILL.md`.
|
|
4
|
+
|
|
5
|
+
## Certo x errado
|
|
6
|
+
|
|
7
|
+
| Evitar | Preferir | Motivo |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `MAX_RETRIES`, `kMaxRetries` | `maxRetries` | Constantes usam `lowerCamelCase` |
|
|
10
|
+
| `IUserRepository` | `UserRepository` | Sem prefixo `I` |
|
|
11
|
+
| `UserRepository.dart` | `user_repository.dart` | Arquivos em `snake_case` |
|
|
12
|
+
| `getTotal()` | `total` (getter) | Propriedade é substantivo, sem `get` |
|
|
13
|
+
| `isNotValid` | `isValid` | Booleano afirmativo |
|
|
14
|
+
| `HTTPClient` | `HttpClient` | Siglas com mais de 2 letras viram palavra |
|
|
15
|
+
| `data`, `tmp`, `x` | `orderTotals` | Nome expressa intenção |
|
|
16
|
+
|
|
17
|
+
## Ordem de imports
|
|
18
|
+
|
|
19
|
+
1. `dart:`
|
|
20
|
+
2. `package:`
|
|
21
|
+
3. relativos
|
|
22
|
+
|
|
23
|
+
Cada grupo em ordem alfabética, separado por linha em branco.
|
|
24
|
+
|
|
25
|
+
## Privacidade
|
|
26
|
+
|
|
27
|
+
O prefixo `_` torna o membro privado à **biblioteca** (arquivo), não à classe.
|