From anti-vibe-coding
This skill should be used when the user asks about 'SOLID principles', 'monolith vs microservices', 'CQRS', 'event sourcing', 'REST vs GraphQL', 'tech stack selection', 'architecture decision', 'ADR', 'design patterns', 'Law of Demeter', 'Tell-Don't-Ask', 'composition vs inheritance', 'dependency injection', 'DI', 'IoC container', 'constructor injection', or faces architectural trade-off decisions. Provides senior-level architecture consultation with explicit trade-off analysis.
How this skill is triggered — by the user, by Claude, or both
Slash command
/anti-vibe-coding:architecture [architecture decision or pattern to analyze][architecture decision or pattern to analyze]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
```typescript
__tests__/stack-aware-preface-wire.test.ts__tests__/tracer-bullet.test.tslib/__fixtures__/populated-src/index.tslib/__tests__/architecture-recommendations.test.tslib/architecture-recommendations.tsreferences/api-architecture.mdreferences/cqrs-event-sourcing.mdreferences/dependency-injection.mdreferences/design-principles.mdreferences/monolith-vs-microservices.mdreferences/solid-principles.md// === Telemetria passiva (Plano 03 fase-03) — nao remover sem registrar em MEMORY.md ===
// G5: telemetria SEMPRE ativa, ignora architectureDetectorEnabled
// G7: skill name canonico fixo
import { writeTelemetryStart, writeTelemetryEnd } from '../../lib/telemetry-utils'
import type { TelemetryStart, TelemetryEnd } from '../../lib/telemetry-types'
const __telemetry_skillName = 'architecture'
const __telemetry_fasePipeline = 'architecture'
const __telemetry_startTimestamp = new Date().toISOString()
const __telemetry_startMs = Date.now()
const __telemetry_startEntry: TelemetryStart = {
evento: 'start',
skill_invocada: __telemetry_skillName,
timestamp_inicio: __telemetry_startTimestamp,
profile_arquitetura: 'disabled',
fase_pipeline: __telemetry_fasePipeline,
}
writeTelemetryStart(__telemetry_startEntry)
// === Fim do bloco de inicio ===
// 2026-05-15 (Luiz/dev): v6.3.1 RF-CH-01 fase-07 — migra readArchitectureProfile → readPrefaceContext.
// Lê architectureProfile do manifest via readPrefaceContext (Plano 01 v6.3.0) — UMA leitura.
// Lookup table per-skill mantido.
// G5 do plano02 / CA-12: NUNCA preencher ctx.language ou ctx.framework — D2 ADR-0020 reserva v6.5/v6.6.
// Quando ctx.profile === null: fallback Greenfield/default (CA-04 v6.3.0 preserved).
import { readdirSync } from 'node:fs'
import { join } from 'node:path'
import { readPrefaceContext } from '../lib/preface-context'
import { getRecommendationForProfile } from '../../lib/read-architecture-profile'
import {
ARCHITECTURE_RECOMMENDATIONS,
DEFAULT_RECOMMENDATION_V52,
GREENFIELD_RECOMMENDATION,
isGreenfield,
} from './lib/architecture-recommendations'
const ctx = readPrefaceContext(process.cwd())
const profileName = ctx.profile ?? null
let srcFileCount = 0
try {
srcFileCount = (readdirSync(join(process.cwd(), 'src'), { recursive: true }) as string[])
.filter((f) => /\.(ts|tsx)$/.test(f)).length
} catch {
srcFileCount = 0
}
const recommendation = isGreenfield(profileName, srcFileCount)
? GREENFIELD_RECOMMENDATION
: getRecommendationForProfile(profileName, ARCHITECTURE_RECOMMENDATIONS, DEFAULT_RECOMMENDATION_V52)
Ao produzir recomendações, use recommendation.headline, recommendation.rationale,
recommendation.patterns e recommendation.caveats como insumos textuais adaptativos.
Se profileName for não-nulo, inicie sua resposta com:
"Recomendações para perfil: "
Se profileName for nulo (manifest ausente), comportamento v5.2 intacto — sem preface.
// 2026-05-16 (Luiz/dev): Plano 03 fase-02 — stack-aware-preface (PRD §Mecanismo Skill wire-up, D11).
// G1 do plano: bloco verbatim do Plano 01 fase-04 (security wire). Path fixo .claude/knowledge/INDEX.md (D11).
// CA-09: se INDEX ausente, preface = ''; comportamento da skill = v6.3.1 intacto.
import { getStackKnowledgePreface } from '../security/lib/stack-aware-preface'
const stackKnowledgePreface = getStackKnowledgePreface(process.cwd())
Se stackKnowledgePreface for não-vazio, prepende esta frase ao início da resposta (após o preface profile-aware, se ambos existirem). Se vazio, ignore — comportamento da skill segue do bloco profile-aware-preface acima sem mudança (CA-09).
Operar como consultor senior de arquitetura. O papel e ensinar e orientar decisoes, nao gerar codigo. Analisar trade-offs, questionar premissas e ajudar o desenvolvedor a tomar decisoes informadas.
Para implementacao apos entender o conceito, direcionar para /anti-vibe-coding:tdd-workflow.
Cada topico tem um arquivo de referencia detalhado em
references/. Consultar quando precisar de profundidade.
SOLID sao ALVOS de design, nao regras absolutas. Em projetos pequenos, aplicar tudo pode criar boilerplate desnecessario. A nota pragmatica ao lado de cada principio indica a forca com que deve ser seguido.
Referencia completa:
references/solid-principles.md
| Principio | Nota | Regra de Ouro |
|---|---|---|
| S — Single Responsibility | 7/10 | Definir "responsabilidade" no nivel do dominio, nao granularidade tecnica |
| O — Open/Closed | 8/10 | Aplicar quando if/else cresce a cada feature. NAO aplicar em MVPs |
| L — Liskov Substitution | 10/10 | INVIOLAVEL. Unico principio SOLID que e lei matematica |
| I — Interface Segregation | 5/10 | Aplicar em bibliotecas/SDKs publicos. Cuidado com fragmentacao |
| D — Dependency Inversion | 6.5/10 | Aplicar em boundaries arquiteturais. Pular em scripts simples |
Devo aplicar SOLID aqui?
Projeto pequeno / MVP / prototipo?
SIM → Focar em SRP e LSP. Resto e prematura otimizacao
NAO → Projeto em crescimento / producao?
SIM → Aplicar todos com pragmatismo
L (LSP) → SEMPRE, sem excecao
O (OCP) → Quando switch/if cresce
S (SRP) → Quando classe faz "coisas demais"
D (DIP) → Em boundaries (infra vs dominio)
I (ISP) → Em APIs publicas / bibliotecas
Referencia completa:
references/monolith-vs-microservices.md
"Por que fazer network requests em vez de chamadas de funcao?"
Se nao existe resposta CONCRETA, ficar no monolito.
Precisa escalar?
Monolito com load balancer resolve?
SIM → Ficar no monolito
NAO → Qual parte precisa escalar independentemente?
Parte especifica → Extrair SO esse servico
"Tudo" → Provavelmente nao mediu direito
Referencia completa:
references/cqrs-event-sourcing.md
A pergunta nao e "CQRS e melhor tecnicamente?" mas sim "Meu dominio PRECISA de auditabilidade completa?"
O dominio exige historico completo de mudancas?
NAO → CRUD simples resolve. NAO usar CQRS/ES
SIM → Regulacao exige audit trail?
SIM → Event Sourcing (financeiro, saude, compliance)
NAO → Valor de negocio em "como chegamos nesse estado?"
SIM → Event Sourcing
NAO → CQRS sem Event Sourcing pode bastar
(read/write models separados, sem event store)
OrderCancelled compensa OrderPlacedReferencia completa:
references/api-architecture.md
Quantos front-ends consomem a API?
1-2 → REST (com endpoints especializados se necessario)
3+ → GraphQL PODE fazer sentido
Time tem experiencia com GraphQL?
NAO → REST + BFF (Backend for Frontend)
SIM → Avaliar custo/beneficio
| Aspecto | REST | GraphQL |
|---|---|---|
| Cache | HTTP nativo (CDN, ETags) | Requer solucao custom |
| Curva de aprendizado | Baixa | Media-alta |
| Overfetching | Endpoints especializados | Resolvido nativamente |
| Monitoramento | Maduro | Requer tooling especifico |
| Upload de arquivos | Nativo | Workaround necessario |
| Real-time | WebSockets/SSE | Subscriptions |
REST para a maioria dos endpoints + GraphQL para telas complexas que agregam muitos dados. Nao e tudo ou nada.
Referencia completa:
references/api-architecture.md(secao Stack Selection)
1. ESCOPO → Definir o problema com clareza
2. CORE → Identificar as partes essenciais
3. PESQUISA → Avaliar opcoes maduras para cada componente
4. PoC → Prototipos para validar riscos tecnicos
5. ADR → Documentar a decisao e justificativa
Referencia completa:
references/design-principles.md
| Principio | Regra | Exemplo |
|---|---|---|
| Lei de Demeter | Nao falar com estranhos | order.shippingZip() em vez de order.customer.address.zip |
| Tell-Don't-Ask | Dizer ao objeto O QUE fazer | account.withdraw(amount) em vez de checar balance antes |
| Composicao > Heranca | Preferir protocolos/interfaces | Compor comportamentos em vez de hierarquias profundas |
| Acoplamento Temporal | Gerenciar sequencia internamente | processor.run() em vez de init() → validate() → execute() |
| Pipe Operator | Modelar como transformacoes | `dados |
Referencia completa:
references/dependency-injection.md
| Conceito | Tipo | Pergunta que responde |
|---|---|---|
| DIP (Dependency Inversion Principle) | Principio SOLID | "De QUEM meu codigo deve depender?" → abstracoes, nao detalhes |
| DI (Dependency Injection) | Tecnica / Pattern | "COMO fornecer essas dependencias?" → injecao externa |
DIP e o principio: modulos de alto nivel (core) dependem de abstracoes (interfaces), NAO de modulos de baixo nivel (SDKs, APIs externas). DI e a tecnica que fornece as implementacoes concretas externamente.
Dependencias recebidas como parametros do constructor. Usar SEMPRE como escolha padrao.
class OrderService {
constructor(
private readonly paymentProvider: IPaymentProvider, // interface, nao concreto
private readonly emailService: IEmailService
) {}
}
Vantagens: dependencias visiveis na assinatura, objeto sempre valido apos construcao, facil de testar (passar mocks), imutavel.
Method injection: quando a dependencia varia por CHAMADA, nao por instancia. Property injection: EVITAR. Objeto pode existir em estado invalido.
A classe depende de servico externo (API, banco, email, pagamento)?
SIM → USAR DI + DIP (interface + injecao)
NAO → Precisa ser testada com mocks?
SIM → USAR DI (injetar concreta para substituir em testes)
NAO → A dependencia pode mudar no futuro?
SIM → USAR DI + DIP
NAO → Instanciacao direta (new) esta OK
Regra pragmatica: Aplicar DI/DIP em boundaries arquiteturais (pagamento, email, storage, cache, auth). NAO em utils internas, helpers puros, value objects.
Quantas classes com dependencias?
< 10 → DI manual (constructor injection)
10-50 → DI manual funciona, container e opcional
50+ → Container comecar a fazer sentido
Framework com container nativo (NestJS, Spring, Angular)?
SIM → Usar o container do framework
NAO → Avaliar se a complexidade se justifica
| Anti-Pattern | Problema | Correcao |
|---|---|---|
| Service Locator | Dependencias OCULTAS — classe busca em registro global | Constructor injection — dependencias visiveis na assinatura |
| DI para tudo | Interface + implementacao para funcoes puras que NUNCA vao mudar | Se so existe UMA implementacao possivel, funcao direta. YAGNI |
| Injecao circular | A depende de B, B depende de A | SRP violado — extrair logica compartilhada para terceira classe |
| Salvar detalhes externos no banco | productId do Stripe no banco — banco acoplado ao Stripe | Salvar IDs do DOMINIO, mapeamento para IDs externos na camada de integracao |
Ao analisar uma decisao arquitetural, seguir este template:
Para cada opcao, avaliar:
Documentar a decisao no formato:
# ADR-001: [Titulo da Decisao]
## Status: [Proposta | Aceita | Deprecada | Substituida]
## Contexto: [Qual problema estamos resolvendo?]
## Decisao: [O que decidimos fazer?]
## Alternativas Consideradas: [O que mais avaliamos e por que descartamos?]
## Consequencias: [Positivas e negativas da decisao]
## Data: YYYY-MM-DD
// === Telemetria passiva (Plano 03 fase-03) — registra fim ===
const __telemetry_endEntry: TelemetryEnd = {
evento: 'end',
skill_invocada: __telemetry_skillName,
timestamp_inicio: __telemetry_startTimestamp,
timestamp_fim: new Date().toISOString(),
duracao_ms: Date.now() - __telemetry_startMs,
profile_arquitetura: 'disabled',
fase_pipeline: __telemetry_fasePipeline,
tokens_aproximados_consumidos: 0,
arquivos_lidos: 0,
arquivos_modificados: 0,
sucesso: true,
}
writeTelemetryEnd(__telemetry_endEntry)
// === Fim do bloco de fim ===
npx claudepluginhub luyzkk/anti-vibe-coding --plugin anti-vibe-codingGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.