From b08b7ddd535064f3f7830dc27bcb90a2e3a38e77 Mon Sep 17 00:00:00 2001 From: Rods Date: Fri, 24 Apr 2026 09:13:37 -0300 Subject: [PATCH 1/4] chore: propose centralized AI context structure (mcp/context/) Adds OpenSpec change proposal to create a single source of truth for AI context across Claude Code, Copilot, Cursor, Gemini and Codex. Co-Authored-By: Claude Sonnet 4.6 --- .../centralized-ai-context/.openspec.yaml | 2 + .../changes/centralized-ai-context/design.md | 88 +++++++++++++++++++ .../centralized-ai-context/proposal.md | 31 +++++++ .../centralized-context-structure/spec.md | 30 +++++++ .../specs/community-explainer-docs/spec.md | 30 +++++++ .../specs/per-tool-native-files/spec.md | 34 +++++++ .../changes/centralized-ai-context/tasks.md | 30 +++++++ 7 files changed, 245 insertions(+) create mode 100644 openspec/changes/centralized-ai-context/.openspec.yaml create mode 100644 openspec/changes/centralized-ai-context/design.md create mode 100644 openspec/changes/centralized-ai-context/proposal.md create mode 100644 openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md create mode 100644 openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md create mode 100644 openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md create mode 100644 openspec/changes/centralized-ai-context/tasks.md diff --git a/openspec/changes/centralized-ai-context/.openspec.yaml b/openspec/changes/centralized-ai-context/.openspec.yaml new file mode 100644 index 0000000..9323e24 --- /dev/null +++ b/openspec/changes/centralized-ai-context/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-04-24 diff --git a/openspec/changes/centralized-ai-context/design.md b/openspec/changes/centralized-ai-context/design.md new file mode 100644 index 0000000..6fdf75a --- /dev/null +++ b/openspec/changes/centralized-ai-context/design.md @@ -0,0 +1,88 @@ +## Context + +Hoje o CraftD tem contexto de IA fragmentado: +- `CLAUDE.md` + `.claude/instructions/` → só Claude Code lê +- `.claude/skills/` → só Claude Code conhece +- Nenhum arquivo nativo para Copilot, Cursor, Gemini ou Codex + +O resultado: devs que usam Copilot ou Cursor no mesmo repo trabalham sem as regras arquiteturais do projeto. O padrão que já funciona no Claude Code (arquivo principal referencia instruções detalhadas em subpastas) é o modelo a ser generalizado. + +## Goals / Non-Goals + +**Goals:** +- Criar `mcp/context/` como fonte única de verdade para qualquer ferramenta de IA +- Cada ferramenta tem arquivo nativo leve com essencial inline + referência a `mcp/context/` +- Skills autodescritivas com `name` e `description` que qualquer modelo descobre ao ler +- Comunidade entende o padrão ao abrir qualquer pasta nativa (explicativo em inglês + diagrama) +- Zero infraestrutura — apenas arquivos markdown + +**Non-Goals:** +- MCP Server com processo rodando (futuro, se necessário) +- Garantir comportamento idêntico entre todos os modelos (cada um interpreta à sua maneira) +- Migrar o sistema de skills estruturadas do `.claude/skills/` (formato YAML interno) — apenas criar versões em `mcp/context/skills/` legíveis por qualquer modelo + +## Decisions + +### Estrutura de pastas + +``` +mcp/ + README.md ← explicativo para a comunidade (Mermaid) + context/ + rules.md ← regras arquiteturais (do CLAUDE.md) + module-graph.md ← dependências entre módulos (novo) + android.md ← do .claude/instructions/android-patterns.md + ios.md ← do .claude/instructions/ios-patterns.md + flutter.md ← do .claude/instructions/flutter-patterns.md + skills/ + new-component.md ← como criar novo componente + review-pr.md ← checklist de revisão de PR + run-build.md ← como rodar o build + android-testing.md ← padrões de teste Android + compose-ui.md ← boas práticas Compose +``` + +### Arquivos nativos por ferramenta + +| Ferramenta | Arquivo nativo | Estratégia | +|---|---|---| +| Claude Code | `CLAUDE.md` | Atualizar referências para `mcp/context/` | +| GitHub Copilot | `.github/copilot-instructions.md` | Novo — essencial inline + referência | +| Cursor | `.cursorrules` | Novo — essencial inline + referência | +| Gemini (Google IDX) | `.gemini/context.md` | Novo — essencial inline + referência | +| Codex / OpenAI | `AGENTS.md` | Novo — essencial inline + referência | + +**Decisão:** cada arquivo nativo carrega as 5-8 regras mais críticas inline (garante que qualquer modelo as leia, mesmo sem seguir a referência) e adiciona `For complete rules and skills, read mcp/context/` ao final. + +**Alternativa descartada:** arquivo nativo apenas como apontador. Risco: modelos com contexto limitado ou implementações inconsistentes ignoram a instrução de ir ler outra pasta. + +### Conteúdo das skills em mcp/context/skills/ + +Cada skill é um markdown autodescritivo: + +```markdown +--- +name: new-component +description: Create a new Server Driven UI component in CraftD following + the CraftDBuilder pattern across all platforms +trigger: when user asks to create a new component or builder +--- + +## Steps +... +``` + +O frontmatter `name` + `description` permite que o modelo liste o que sabe fazer antes de ser perguntado. É o padrão que o próprio `.claude/skills/` usa, adaptado para ser legível por qualquer ferramenta. + +### Explicativos para a comunidade + +Cada pasta nativa ganha um arquivo `AI_CONTEXT.md` (ou `README.md` onde faz sentido) em inglês explicando que o conteúdo não é duplicado — há uma fonte central. Inclui diagrama Mermaid mostrando o fluxo. + +**Decisão de nome:** `AI_CONTEXT.md` em vez de `README.md` para não conflitar com READMEs existentes e deixar claro o propósito. + +## Risks / Trade-offs + +- **[Risco] Modelos ignoram a referência a `mcp/context/`** → Mitigado mantendo regras críticas inline em cada arquivo nativo +- **[Risco] `mcp/context/` fica desatualizado** → O nome da pasta (`mcp/`) pode confundir — não é um MCP Server, é contexto. Mitigado com `README.md` explicativo claro +- **[Trade-off] Alguma duplicação intencional** → Regras críticas aparecem tanto no arquivo nativo quanto em `mcp/context/rules.md`. Aceito: o arquivo nativo é o "resumo garantido", o `mcp/context/` é o "detalhe completo" +- **[Risco] `.claude/skills/` e `mcp/context/skills/` coexistem** → As skills em `.claude/skills/` têm formato estruturado para o Claude Code; as de `mcp/context/skills/` são markdown livre para qualquer modelo. Diferentes propósitos, podem coexistir sem conflito diff --git a/openspec/changes/centralized-ai-context/proposal.md b/openspec/changes/centralized-ai-context/proposal.md new file mode 100644 index 0000000..ab3ffa2 --- /dev/null +++ b/openspec/changes/centralized-ai-context/proposal.md @@ -0,0 +1,31 @@ +## Why + +CraftD é um repositório público usado como referência pela comunidade, mas hoje cada ferramenta de IA (Claude Code, Copilot, Cursor, Gemini, Codex) tem seu próprio arquivo de contexto isolado — ou nenhum. Isso significa que regras arquiteturais, padrões de plataforma e skills ficam duplicados, desatualizados ou simplesmente ausentes dependendo da ferramenta usada. O momento é agora porque o ecossistema de AI coding tools convergiu o suficiente para que um padrão de "fonte única de contexto" seja viável e legível por todas as ferramentas. + +## What Changes + +- Criar pasta `mcp/context/` como fonte única de verdade para regras, padrões e skills +- Migrar conteúdo de `.claude/instructions/` (android-patterns, ios-patterns, flutter-patterns) para `mcp/context/` +- Migrar skills de `.claude/skills/` para `mcp/context/skills/` +- Criar arquivos nativos leves para cada ferramenta: `.github/copilot-instructions.md`, `.cursorrules`, `.gemini/context.md`, `AGENTS.md` (Codex) — cada um com regras essenciais inline + referência a `mcp/context/` +- Atualizar `CLAUDE.md` para referenciar `mcp/context/` em vez de `.claude/instructions/` +- Adicionar `.md` explicativo em inglês em cada pasta nativa (`.claude/`, `.github/`) para a comunidade entender a estrutura sem duplicação, com diagrama Mermaid + +## Capabilities + +### New Capabilities + +- `centralized-context-structure`: Estrutura `mcp/context/` como fonte única de contexto AI com regras, padrões por plataforma e skills autodescritivas +- `per-tool-native-files`: Arquivos nativos leves por ferramenta que carregam essencial inline e referenciam `mcp/context/` para detalhes +- `community-explainer-docs`: Documentação explicativa em inglês em cada pasta nativa para a comunidade entender o padrão adotado + +### Modified Capabilities + + + +## Impact + +- **Arquivos novos:** `mcp/context/rules.md`, `mcp/context/android.md`, `mcp/context/ios.md`, `mcp/context/flutter.md`, `mcp/context/module-graph.md`, `mcp/context/skills/` (migração), `.github/copilot-instructions.md`, `.cursorrules`, `.gemini/context.md`, `AGENTS.md`, `mcp/README.md`, `.claude/README.md`, `.github/AI_CONTEXT.md` +- **Arquivos modificados:** `CLAUDE.md` (atualizar referências de `.claude/instructions/` para `mcp/context/`) +- **Sem breaking change:** `.claude/skills/` e `.claude/instructions/` podem coexistir durante migração +- **Sem dependências externas:** apenas arquivos markdown, zero infraestrutura diff --git a/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md b/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md new file mode 100644 index 0000000..b884395 --- /dev/null +++ b/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md @@ -0,0 +1,30 @@ +## ADDED Requirements + +### Requirement: mcp/context/ é a fonte única de verdade para contexto AI +O projeto SHALL manter uma pasta `mcp/context/` na raiz contendo todo o contexto arquitetural, regras e skills do projeto em formato markdown legível por qualquer ferramenta de IA. + +#### Scenario: Desenvolvedor com qualquer ferramenta acessa contexto completo +- **WHEN** um desenvolvedor aponta qualquer ferramenta de IA para `mcp/context/` +- **THEN** a ferramenta tem acesso a regras arquiteturais, padrões por plataforma e skills disponíveis + +#### Scenario: Estrutura de arquivos está presente e organizada +- **WHEN** a pasta `mcp/context/` é inspecionada +- **THEN** contém `rules.md`, `module-graph.md`, `android.md`, `ios.md`, `flutter.md` e pasta `skills/` + +### Requirement: Skills são autodescritivas com frontmatter padronizado +Cada skill em `mcp/context/skills/` SHALL ter frontmatter com `name`, `description` e `trigger` para que qualquer modelo descubra o que pode fazer. + +#### Scenario: Modelo lista skills disponíveis ao ler a pasta +- **WHEN** um modelo lê os arquivos em `mcp/context/skills/` +- **THEN** consegue identificar nome, descrição e quando usar cada skill pelo frontmatter + +#### Scenario: Skill de novo componente está disponível +- **WHEN** desenvolvedor pede para criar um novo componente CraftD em qualquer ferramenta +- **THEN** a ferramenta encontra `mcp/context/skills/new-component.md` com o guia completo + +### Requirement: module-graph.md documenta dependências entre módulos explicitamente +O arquivo `mcp/context/module-graph.md` SHALL documentar as dependências entre módulos de forma explícita, sem exigir leitura do `settings.gradle.kts`. + +#### Scenario: Modelo entende que módulos de plataforma não se dependem +- **WHEN** um modelo lê `mcp/context/module-graph.md` +- **THEN** entende claramente que `craftd-compose`, `craftd-xml`, `ios/` e `flutter/` dependem apenas do `craftd-core` e nunca entre si diff --git a/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md b/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md new file mode 100644 index 0000000..a52f1fc --- /dev/null +++ b/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md @@ -0,0 +1,30 @@ +## ADDED Requirements + +### Requirement: Cada pasta nativa tem documento explicativo em inglês para a comunidade +O projeto SHALL incluir um arquivo `AI_CONTEXT.md` em cada pasta que contém configuração de ferramenta de IA (`.claude/`, `.github/`), e um `README.md` em `mcp/`, explicando em inglês o padrão adotado e por que o conteúdo não é duplicado. + +#### Scenario: Desenvolvedor que clona o repo entende a estrutura sem ler código +- **WHEN** um desenvolvedor abre `.claude/` ou `.github/` no GitHub +- **THEN** encontra `AI_CONTEXT.md` explicando o padrão centralizado com diagrama Mermaid + +#### Scenario: mcp/README.md explica o propósito da pasta +- **WHEN** um desenvolvedor acessa `mcp/` no repositório +- **THEN** encontra `README.md` explicando que é a fonte central de contexto AI, não um MCP Server em execução + +### Requirement: Diagrama Mermaid ilustra o fluxo de contexto entre ferramentas e fonte central +O documento explicativo SHALL incluir um diagrama Mermaid mostrando como cada ferramenta lê seu arquivo nativo e como esse arquivo referencia `mcp/context/`. + +#### Scenario: Diagrama é renderizado corretamente no GitHub +- **WHEN** o arquivo `AI_CONTEXT.md` ou `mcp/README.md` é visualizado no GitHub +- **THEN** o diagrama Mermaid renderiza mostrando o fluxo: ferramentas → arquivos nativos → mcp/context/ + +#### Scenario: Diagrama comunica a ausência de duplicação +- **WHEN** um desenvolvedor lê o diagrama +- **THEN** fica claro que cada ferramenta aponta para a mesma fonte, sem cópias do conteúdo + +### Requirement: Explicativo menciona como replicar o padrão em outros repositórios +O documento `mcp/README.md` SHALL incluir uma nota indicando que a estrutura pode ser copiada para outros repositórios públicos como ponto de partida. + +#### Scenario: Comunidade consegue adotar o padrão no próprio projeto +- **WHEN** um desenvolvedor externo lê `mcp/README.md` +- **THEN** encontra instrução clara de como replicar a estrutura em outro repositório diff --git a/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md b/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md new file mode 100644 index 0000000..e640de1 --- /dev/null +++ b/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md @@ -0,0 +1,34 @@ +## ADDED Requirements + +### Requirement: Cada ferramenta tem arquivo nativo com regras essenciais inline +O projeto SHALL manter um arquivo nativo para cada ferramenta de IA suportada contendo as regras arquiteturais mais críticas diretamente no arquivo (inline), garantindo funcionamento mesmo sem leitura de `mcp/context/`. + +#### Scenario: Copilot funciona sem configuração adicional +- **WHEN** um desenvolvedor abre o projeto com GitHub Copilot +- **THEN** `.github/copilot-instructions.md` é lido automaticamente com as regras críticas do projeto + +#### Scenario: Cursor funciona sem configuração adicional +- **WHEN** um desenvolvedor abre o projeto com Cursor +- **THEN** `.cursorrules` é lido automaticamente com as regras críticas do projeto + +#### Scenario: Claude Code funciona sem configuração adicional +- **WHEN** um desenvolvedor abre o projeto com Claude Code +- **THEN** `CLAUDE.md` é lido automaticamente com as regras críticas e referência a `mcp/context/` + +### Requirement: Arquivos nativos referenciam mcp/context/ para detalhes completos +Todo arquivo nativo SHALL incluir ao final uma instrução explícita para ler `mcp/context/` para regras completas e skills disponíveis. + +#### Scenario: Modelo com suporte a leitura de contexto externo carrega detalhes +- **WHEN** um modelo capaz de ler arquivos externos processa o arquivo nativo +- **THEN** encontra a instrução `For complete rules and skills, read mcp/context/` e carrega o contexto completo + +#### Scenario: Modelo sem suporte a leitura externa ainda funciona +- **WHEN** um modelo ignora a referência a `mcp/context/` +- **THEN** ainda possui as regras críticas inline e pode trabalhar com o projeto corretamente + +### Requirement: Ferramentas suportadas cobrem Claude, Copilot, Cursor, Gemini e Codex +O projeto SHALL ter arquivos nativos para: `CLAUDE.md` (Claude Code), `.github/copilot-instructions.md` (GitHub Copilot), `.cursorrules` (Cursor), `.gemini/context.md` (Gemini/Google IDX), `AGENTS.md` (Codex/OpenAI). + +#### Scenario: Todos os arquivos nativos existem na estrutura do projeto +- **WHEN** a raiz do projeto é inspecionada +- **THEN** todos os cinco arquivos nativos estão presentes com conteúdo válido diff --git a/openspec/changes/centralized-ai-context/tasks.md b/openspec/changes/centralized-ai-context/tasks.md new file mode 100644 index 0000000..648f8a9 --- /dev/null +++ b/openspec/changes/centralized-ai-context/tasks.md @@ -0,0 +1,30 @@ +## 1. Criar estrutura mcp/context/ + +- [ ] 1.1 Criar pasta `mcp/context/` e `mcp/context/skills/` na raiz do projeto +- [ ] 1.2 Criar `mcp/context/rules.md` com as regras arquiteturais do `CLAUDE.md` (seção "Regras arquiteturais — nunca violar" e "Convenções de código") +- [ ] 1.3 Criar `mcp/context/module-graph.md` documentando explicitamente as dependências entre módulos (craftd-core ← compose/xml/ios/flutter, sem dependências cruzadas entre plataformas) +- [ ] 1.4 Criar `mcp/context/android.md` com conteúdo de `.claude/instructions/android-patterns.md` +- [ ] 1.5 Criar `mcp/context/ios.md` com conteúdo de `.claude/instructions/ios-patterns.md` +- [ ] 1.6 Criar `mcp/context/flutter.md` com conteúdo de `.claude/instructions/flutter-patterns.md` + +## 2. Migrar skills para mcp/context/skills/ + +- [ ] 2.1 Criar `mcp/context/skills/new-component.md` com frontmatter (name, description, trigger) e guia de criação de componente CraftD +- [ ] 2.2 Criar `mcp/context/skills/review-pr.md` com frontmatter e checklist de revisão de PR (baseado na seção "Review de PRs" do CLAUDE.md) +- [ ] 2.3 Criar `mcp/context/skills/android-testing.md` com frontmatter e conteúdo de `.claude/skills/android-testing/` +- [ ] 2.4 Criar `mcp/context/skills/compose-ui.md` com frontmatter e conteúdo de `.claude/skills/compose-ui/` +- [ ] 2.5 Criar `mcp/context/skills/run-build.md` com frontmatter e instruções para rodar o build (`./gradlew build` no módulo afetado) + +## 3. Criar arquivos nativos por ferramenta + +- [ ] 3.1 Criar `.github/copilot-instructions.md` com regras críticas inline (arquitetura, nomenclatura, proibições) + referência a `mcp/context/` +- [ ] 3.2 Criar `.cursorrules` com regras críticas inline + referência a `mcp/context/` +- [ ] 3.3 Criar `.gemini/context.md` com regras críticas inline + referência a `mcp/context/` +- [ ] 3.4 Criar `AGENTS.md` (Codex/OpenAI) com regras críticas inline + referência a `mcp/context/` +- [ ] 3.5 Atualizar `CLAUDE.md` para referenciar `mcp/context/` em vez de `.claude/instructions/` nos pontos de plataforma + +## 4. Criar documentação explicativa para a comunidade + +- [ ] 4.1 Criar `mcp/README.md` em inglês explicando o propósito da pasta, com diagrama Mermaid mostrando o fluxo ferramenta → arquivo nativo → mcp/context/ e nota sobre como replicar em outros repositórios +- [ ] 4.2 Criar `.claude/AI_CONTEXT.md` em inglês explicando que `.claude/` é específico do Claude Code e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid +- [ ] 4.3 Criar `.github/AI_CONTEXT.md` em inglês explicando que `copilot-instructions.md` é o arquivo nativo do Copilot e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid From 749bb3704e9af104fbfd649d637f238c6cd10b37 Mon Sep 17 00:00:00 2001 From: Rods Date: Fri, 24 Apr 2026 09:19:33 -0300 Subject: [PATCH 2/4] feat: add centralized AI context structure in mcp/context/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creates a single source of truth for AI context across all tools: - mcp/context/ with rules, module-graph, platform patterns (android/ios/flutter) - mcp/context/skills/ with new-component, review-pr, run-build, android-testing, compose-ui - Native files for Copilot (.github/copilot-instructions.md), Cursor (.cursorrules), Gemini (.gemini/context.md), and Codex (AGENTS.md) — each with critical rules inline + reference to mcp/context/ - Community explainer docs with Mermaid diagrams in .claude/ and .github/ - Updated CLAUDE.md to reference mcp/context/ instead of .claude/instructions/ Co-Authored-By: Claude Sonnet 4.6 --- .claude/AI_CONTEXT.md | 44 +++++++ .claude/settings.local.json | 16 +++ .cursorrules | 36 ++++++ .gemini/context.md | 36 ++++++ .github/AI_CONTEXT.md | 43 +++++++ .github/copilot-instructions.md | 36 ++++++ AGENTS.md | 36 ++++++ CLAUDE.md | 8 +- android_kmp/.claude/settings.local.json | 11 +- mcp/README.md | 65 ++++++++++ mcp/context/android.md | 88 +++++++++++++ mcp/context/flutter.md | 50 ++++++++ mcp/context/ios.md | 44 +++++++ mcp/context/module-graph.md | 53 ++++++++ mcp/context/rules.md | 58 +++++++++ mcp/context/skills/android-testing.md | 65 ++++++++++ mcp/context/skills/compose-ui.md | 116 ++++++++++++++++++ mcp/context/skills/new-component.md | 105 ++++++++++++++++ mcp/context/skills/review-pr.md | 58 +++++++++ mcp/context/skills/run-build.md | 68 ++++++++++ .../changes/centralized-ai-context/tasks.md | 38 +++--- .../.openspec.yaml | 2 - .../design.md | 66 ---------- .../proposal.md | 27 ---- .../specs/generate-tests-trigger/spec.md | 42 ------- .../tasks.md | 25 ---- 26 files changed, 1050 insertions(+), 186 deletions(-) create mode 100644 .claude/AI_CONTEXT.md create mode 100644 .claude/settings.local.json create mode 100644 .cursorrules create mode 100644 .gemini/context.md create mode 100644 .github/AI_CONTEXT.md create mode 100644 .github/copilot-instructions.md create mode 100644 AGENTS.md create mode 100644 mcp/README.md create mode 100644 mcp/context/android.md create mode 100644 mcp/context/flutter.md create mode 100644 mcp/context/ios.md create mode 100644 mcp/context/module-graph.md create mode 100644 mcp/context/rules.md create mode 100644 mcp/context/skills/android-testing.md create mode 100644 mcp/context/skills/compose-ui.md create mode 100644 mcp/context/skills/new-component.md create mode 100644 mcp/context/skills/review-pr.md create mode 100644 mcp/context/skills/run-build.md delete mode 100644 openspec/changes/restrict-generate-tests-to-merged-prs/.openspec.yaml delete mode 100644 openspec/changes/restrict-generate-tests-to-merged-prs/design.md delete mode 100644 openspec/changes/restrict-generate-tests-to-merged-prs/proposal.md delete mode 100644 openspec/changes/restrict-generate-tests-to-merged-prs/specs/generate-tests-trigger/spec.md delete mode 100644 openspec/changes/restrict-generate-tests-to-merged-prs/tasks.md diff --git a/.claude/AI_CONTEXT.md b/.claude/AI_CONTEXT.md new file mode 100644 index 0000000..9edf04d --- /dev/null +++ b/.claude/AI_CONTEXT.md @@ -0,0 +1,44 @@ +# AI Context Structure — Claude Code + +This folder (`.claude/`) contains Claude Code-specific configuration: skills, commands, scripts, and settings. + +The **complete AI context** (architectural rules, platform patterns, available skills) lives in a single central location to avoid duplication across tools: + +``` +📁 mcp/context/ ← single source of truth for all AI tools +``` + +## Why This Structure? + +CraftD uses multiple AI coding tools (Claude Code, GitHub Copilot, Cursor, Gemini, Codex). Instead of maintaining separate context files for each tool — which would quickly diverge — all tools point to the same source. + +```mermaid +graph LR + CLAUDE["Claude Code
CLAUDE.md"] + COPILOT["Copilot
.github/copilot-instructions.md"] + CURSOR["Cursor
.cursorrules"] + OTHER["Other tools..."] + + MCP["📁 mcp/context/
Single Source of Truth"] + + CLAUDE -->|references| MCP + COPILOT -->|references| MCP + CURSOR -->|references| MCP + OTHER -->|references| MCP +``` + +## What Lives Here vs. in mcp/context/ + +| Here (`.claude/`) | In `mcp/context/` | +|---|---| +| Claude Code skills (structured YAML format) | Skills as readable Markdown (any tool) | +| Claude Code commands | Architectural rules | +| Claude Code hooks/settings | Platform patterns (Android, iOS, Flutter) | +| Claude-specific scripts | Module graph | + +## Quick Reference + +- Full rules → `mcp/context/rules.md` +- Module dependencies → `mcp/context/module-graph.md` +- Platform patterns → `mcp/context/android.md`, `ios.md`, `flutter.md` +- Skills (any tool) → `mcp/context/skills/` diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..bd257b4 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,16 @@ +{ + "permissions": { + "allow": [ + "Bash(openspec new:*)", + "Bash(openspec status:*)", + "Bash(openspec instructions:*)", + "Bash(git checkout:*)", + "Bash(git add:*)", + "Bash(git commit -m ':*)", + "Bash(git commit:*)", + "Bash(git push:*)", + "Bash(openspec list:*)", + "Bash(wc:*)" + ] + } +} diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..0dfc232 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,36 @@ +# CraftD — Cursor Rules + +CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android XML, iOS SwiftUI, Flutter). + +## Critical Rules + +1. Platform modules never depend on each other — `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. +2. Every new component implements the platform abstraction — `CraftDBuilder` on Android/KMP, equivalent protocols on iOS and Flutter. +3. `onAction`/fallback always covered, even as a no-op. +4. `commonMain` must have zero platform dependencies — use `expect/actual`. +5. Every new builder must be registered in `CraftDBuilderManager`. +6. External libraries injected via constructor — never coupled directly in the builder. +7. Class names consistent across all platforms (`CraftDImage` everywhere). +8. `CraftD` prefix on all lib classes and files. +9. No hardcoded colors or typography — use `MaterialTheme`. +10. Tests: JUnit4 + MockK, backtick naming. + +## What NOT to Do + +- Do not create components outside `CraftDBuilder` abstraction +- Do not add platform imports in `commonMain` +- Do not create cross-platform module dependencies +- Do not commit `local.properties` or credentials + +## Complete Context and Skills + +Read these files for full rules, platform patterns, and available skills: + +``` +mcp/context/rules.md ← architectural rules +mcp/context/module-graph.md ← module dependencies +mcp/context/android.md ← Android/KMP patterns +mcp/context/ios.md ← iOS patterns +mcp/context/flutter.md ← Flutter patterns +mcp/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui +``` diff --git a/.gemini/context.md b/.gemini/context.md new file mode 100644 index 0000000..7acc1eb --- /dev/null +++ b/.gemini/context.md @@ -0,0 +1,36 @@ +# CraftD — Gemini Context + +CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android XML, iOS SwiftUI, Flutter). + +## Critical Rules + +1. Platform modules never depend on each other — `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. +2. Every new component implements the platform abstraction — `CraftDBuilder` on Android/KMP, equivalent protocols on iOS and Flutter. +3. `onAction`/fallback always covered, even as a no-op. +4. `commonMain` must have zero platform dependencies — use `expect/actual`. +5. Every new builder must be registered in `CraftDBuilderManager`. +6. External libraries injected via constructor — never coupled directly in the builder. +7. Class names consistent across all platforms (`CraftDImage` everywhere). +8. `CraftD` prefix on all lib classes and files. +9. No hardcoded colors or typography — use `MaterialTheme`. +10. Tests: JUnit4 + MockK, backtick naming `` `given X when Y then Z` ``. + +## What NOT to Do + +- Do not create components outside `CraftDBuilder` abstraction +- Do not add platform imports in `commonMain` +- Do not create cross-platform module dependencies +- Do not commit `local.properties` or credentials + +## Complete Context and Skills + +Read these files for full rules, platform patterns, and available skills: + +``` +mcp/context/rules.md ← architectural rules +mcp/context/module-graph.md ← module dependencies +mcp/context/android.md ← Android/KMP patterns +mcp/context/ios.md ← iOS patterns +mcp/context/flutter.md ← Flutter patterns +mcp/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui +``` diff --git a/.github/AI_CONTEXT.md b/.github/AI_CONTEXT.md new file mode 100644 index 0000000..f131bce --- /dev/null +++ b/.github/AI_CONTEXT.md @@ -0,0 +1,43 @@ +# AI Context Structure — GitHub Copilot + +This folder (`.github/`) contains GitHub-specific configuration: workflows, issue templates, and the Copilot native instructions file. + +The **complete AI context** (architectural rules, platform patterns, available skills) lives in a single central location to avoid duplication across tools: + +``` +📁 mcp/context/ ← single source of truth for all AI tools +``` + +## Why This Structure? + +CraftD uses multiple AI coding tools (Claude Code, GitHub Copilot, Cursor, Gemini, Codex). Instead of maintaining separate context files for each tool — which would quickly diverge — all tools point to the same source. + +```mermaid +graph LR + COPILOT["GitHub Copilot
copilot-instructions.md"] + CLAUDE["Claude Code
CLAUDE.md"] + CURSOR["Cursor
.cursorrules"] + OTHER["Other tools..."] + + MCP["📁 mcp/context/
Single Source of Truth"] + + COPILOT -->|references| MCP + CLAUDE -->|references| MCP + CURSOR -->|references| MCP + OTHER -->|references| MCP +``` + +## Files in This Folder + +| File | Purpose | +|---|---| +| `copilot-instructions.md` | Copilot native context — critical rules inline + reference to `mcp/context/` | +| `workflows/` | CI/CD automation (build, test, auto-generate tests) | +| `AI_CONTEXT.md` | This file — explains the AI context structure for the community | + +## Quick Reference + +- Full rules → `mcp/context/rules.md` +- Module dependencies → `mcp/context/module-graph.md` +- Platform patterns → `mcp/context/android.md`, `ios.md`, `flutter.md` +- Skills (any tool) → `mcp/context/skills/` diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..614f9e4 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,36 @@ +# CraftD — GitHub Copilot Instructions + +CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android XML, iOS SwiftUI, Flutter). + +## Critical Rules + +1. **Platform modules never depend on each other.** `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. Never on each other. +2. **Every new component implements the platform abstraction.** On Android/KMP: `CraftDBuilder`. On iOS: Swift protocol equivalent. On Flutter: Dart abstract class equivalent. +3. **`onAction`/fallback always covered** — even as a no-op. +4. **`commonMain` has no platform dependencies** — use `expect/actual` for platform-specific behavior. +5. **New builders must be registered in `CraftDBuilderManager`** of the respective platform. Never create a builder without registering it. +6. **External libraries (Coil, Glide, etc.) must be injected via constructor** — never coupled directly inside the builder. +7. **Class names are consistent across platforms** — `CraftDImage` on Android = `CraftDImage` on iOS and Flutter. +8. **`CraftD` prefix** on all lib classes and files. +9. **No hardcoded colors or typography** — use `MaterialTheme.colorScheme` / `MaterialTheme.typography`. +10. **Tests:** JUnit4 + MockK, backtick naming `` `given X when Y then Z` ``. + +## What NOT to Do + +- Do not create a component outside `CraftDBuilder` abstraction +- Do not add platform imports in `commonMain` +- Do not create cross-platform module dependencies +- Do not commit `local.properties` or credential files + +## Complete Context + +For full architectural rules, platform patterns, module graph, and available skills, read: + +``` +mcp/context/rules.md ← architectural rules and conventions +mcp/context/module-graph.md ← module dependencies +mcp/context/android.md ← Android/KMP patterns +mcp/context/ios.md ← iOS/SwiftUI patterns +mcp/context/flutter.md ← Flutter patterns +mcp/context/skills/ ← available skills (new-component, review-pr, run-build, ...) +``` diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..d1c87f3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,36 @@ +# CraftD — AI Agents Context (Codex / OpenAI) + +CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android XML, iOS SwiftUI, Flutter). + +## Critical Rules + +1. Platform modules never depend on each other — `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. +2. Every new component implements the platform abstraction — `CraftDBuilder` on Android/KMP, equivalent protocols on iOS and Flutter. +3. `onAction`/fallback always covered, even as a no-op. +4. `commonMain` must have zero platform dependencies — use `expect/actual`. +5. Every new builder must be registered in `CraftDBuilderManager`. +6. External libraries injected via constructor — never coupled directly in the builder. +7. Class names consistent across all platforms (`CraftDImage` everywhere). +8. `CraftD` prefix on all lib classes and files. +9. No hardcoded colors or typography — use `MaterialTheme`. +10. Tests: JUnit4 + MockK, backtick naming `` `given X when Y then Z` ``. + +## What NOT to Do + +- Do not create components outside `CraftDBuilder` abstraction +- Do not add platform imports in `commonMain` +- Do not create cross-platform module dependencies +- Do not commit `local.properties` or credentials + +## Complete Context and Skills + +Read these files for full rules, platform patterns, and available skills: + +``` +mcp/context/rules.md ← architectural rules +mcp/context/module-graph.md ← module dependencies +mcp/context/android.md ← Android/KMP patterns +mcp/context/ios.md ← iOS patterns +mcp/context/flutter.md ← Flutter patterns +mcp/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui +``` diff --git a/CLAUDE.md b/CLAUDE.md index fb79905..f6aa65d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -58,11 +58,11 @@ docs/ # documentação do site (MkDocs) ## Contexto por plataforma -Antes de iniciar qualquer task, identifique a plataforma e leia o arquivo correspondente em `.claude/instructions/`: +Antes de iniciar qualquer task, identifique a plataforma e leia o arquivo correspondente em `mcp/context/`: -- Android/KMP → `.claude/instructions/android-patterns.md` -- iOS → `.claude/instructions/ios-patterns.md` -- Flutter → `.claude/instructions/flutter-patterns.md` +- Android/KMP → `mcp/context/android.md` +- iOS → `mcp/context/ios.md` +- Flutter → `mcp/context/flutter.md` Ao gerar um `proposal.md` via `/propose`, detecte a plataforma na descrição do usuário e adicione frontmatter no início do arquivo: diff --git a/android_kmp/.claude/settings.local.json b/android_kmp/.claude/settings.local.json index 71714ea..6f166c4 100644 --- a/android_kmp/.claude/settings.local.json +++ b/android_kmp/.claude/settings.local.json @@ -7,7 +7,16 @@ "Bash(gh pr:*)", "Bash(git merge:*)", "Bash(./gradlew :craftd-core:testDebugUnitTest)", - "Bash(git add:*)" + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(./gradlew :craftd-core:build :craftd-compose:build :craftd-xml:build)", + "Bash(git stash:*)", + "Bash(./gradlew :craftd-core:testReleaseUnitTest)", + "Bash(./gradlew :craftd-core:assembleRelease :craftd-compose:assembleRelease :craftd-xml:assembleRelease)", + "Bash(git push:*)", + "Read(//Users/rodrigo/rep/CraftD/**)", + "Bash(openspec list:*)", + "Bash(./gradlew :app-sample-cmp:assembleDebug)" ] } } diff --git a/mcp/README.md b/mcp/README.md new file mode 100644 index 0000000..142aa29 --- /dev/null +++ b/mcp/README.md @@ -0,0 +1,65 @@ +# AI Context — Centralized Source of Truth + +This folder contains the **single source of truth** for AI context in the CraftD project. + +It is **not** a running MCP Server — it is a collection of Markdown files that any AI tool can read to understand the project's architecture, conventions, and available skills. + +## How It Works + +Each AI tool reads its own native file (which contains the essential rules inline), and that file points here for the complete context. + +```mermaid +graph TD + CC["Claude Code
CLAUDE.md"] + CP["GitHub Copilot
.github/copilot-instructions.md"] + CU["Cursor
.cursorrules"] + GE["Gemini
.gemini/context.md"] + OA["Codex / OpenAI
AGENTS.md"] + + CTX["📁 mcp/context/"] + RULES["rules.md"] + GRAPH["module-graph.md"] + AND["android.md"] + IOS["ios.md"] + FL["flutter.md"] + SK["skills/"] + + CC -->|reads| CTX + CP -->|reads| CTX + CU -->|reads| CTX + GE -->|reads| CTX + OA -->|reads| CTX + + CTX --> RULES + CTX --> GRAPH + CTX --> AND + CTX --> IOS + CTX --> FL + CTX --> SK +``` + +## Files + +| File | Purpose | +|---|---| +| `context/rules.md` | Architectural rules and code conventions | +| `context/module-graph.md` | Explicit module dependencies | +| `context/android.md` | Android / KMP platform patterns | +| `context/ios.md` | iOS / SwiftUI platform patterns | +| `context/flutter.md` | Flutter platform patterns | +| `context/skills/new-component.md` | How to create a new CraftD component | +| `context/skills/review-pr.md` | PR review checklist | +| `context/skills/run-build.md` | How to build and run tests | +| `context/skills/android-testing.md` | Android/KMP testing strategies | +| `context/skills/compose-ui.md` | Compose UI best practices | + +## Replicating This Pattern + +This structure can be copied to any public repository as a starting point for centralized AI context: + +1. Create `mcp/context/` with your project's rules and platform patterns +2. Create a native file for each AI tool you use (see examples in this repo) +3. Each native file: include critical rules inline + point to `mcp/context/` for details +4. Add skills as Markdown files with `name`, `description`, and `trigger` frontmatter + +The native files ensure basic context even if the tool doesn't follow the `mcp/context/` reference. The central folder provides complete context for tools that do. diff --git a/mcp/context/android.md b/mcp/context/android.md new file mode 100644 index 0000000..34456f1 --- /dev/null +++ b/mcp/context/android.md @@ -0,0 +1,88 @@ +# Android / KMP — Platform Instructions + +> Read this file when starting any Android/KMP task. Ignore `ios/` and `flutter/`. + +--- + +## Core Abstractions + +| Class | Role | +|---|---| +| `CraftDBuilder` | Base interface for creating components | +| `CraftDBuilderManager` | Registers and resolves builders by `key` | +| `CraftDynamic` | Main composable that renders the SDUI | +| `SimpleProperties` | Base data model (`key` + `value` JSON) | +| `ActionProperties` | Action data (deeplink + analytics) | +| `CraftDComponentKey` | Enum with built-in component keys | +| `CraftDViewListener` | Action callback for the consumer | + +--- + +## Folder Structure + +### craftd-core (models and abstractions) +``` +commonMain/ + data/ + model/ + base/ → SimpleProperties, SimplePropertiesResponse + action/ → ActionProperties, AnalyticsProperties + [name]/ → [Name]Properties.kt for each component + domain/ → enums and sealed classes (CraftDAlign, CraftDTextStyle) + presentation/ → CraftDViewListener, CraftDComponentKey + extensions/ → extension functions +``` + +### craftd-compose (Compose/KMP implementation) +``` +commonMain/ + builder/ → CraftDBuilder.kt (interface), CraftDBuilderManager.kt + ui/ + [name]/ + CraftD[Name].kt → the @Composable for the component + CraftD[Name]Builder.kt → implements CraftDBuilder + extensions/ → Compose utility functions +``` + +### craftd-xml (View System implementation) +``` +src/main/kotlin/.../ + ui/ + [name]/ + CraftD[Name]Component.kt → custom View + CraftD[Name]ComponentRender.kt → implements CraftDViewRenderer + builder/ + CraftDBuilderManager.kt → getBuilderRenders() +``` + +### Pattern for a new component (example: CraftDFoo) + +1. `craftd-core/commonMain/data/model/foo/FooProperties.kt` — model data class +2. `craftd-compose/commonMain/ui/foo/CraftDFoo.kt` — composable +3. `craftd-compose/commonMain/ui/foo/CraftDFooBuilder.kt` — builder +4. `craftd-xml/src/main/kotlin/.../ui/foo/CraftDFooComponent.kt` — custom View +5. `craftd-xml/src/main/kotlin/.../ui/foo/CraftDFooComponentRender.kt` — render +6. Register in `CraftDBuilderManager` of each module +7. Add to `app-sample-android` (Compose + XML) and to `dynamic.json` + +--- + +## Compose Principles + +- Composables are **stateless** — state comes from the caller (state hoisting) +- Every component exposes `modifier: Modifier = Modifier` +- No hardcoded color or typography values — use `MaterialTheme.colorScheme` and `MaterialTheme.typography` +- Every interactive component: minimum touch target of 48x48dp + +## Build + +- Dependencies always via `libs.versions.toml` — never hardcoded version in `build.gradle.kts` +- Shared configuration across modules goes in a convention plugin in `build-logic/` +- Run `./gradlew build` in `android_kmp/` after each task before marking `[x]` + +## Tests + +- JUnit4 + MockK for Android tests +- `kotlin("test")` + `kotlinx.serialization` + `compose.runtime` for commonTest +- Backtick naming: `` `given X when Y then Z` `` +- Path mirrors source: `src/commonTest/kotlin/...` diff --git a/mcp/context/flutter.md b/mcp/context/flutter.md new file mode 100644 index 0000000..5784b1c --- /dev/null +++ b/mcp/context/flutter.md @@ -0,0 +1,50 @@ +# Flutter — Platform Instructions + +> Read this file when starting any Flutter task. Ignore `android_kmp/` and `ios/`. + +--- + +## Core Abstractions + +| Class | Role | +|---|---| +| `CraftDynamic` | Main widget that renders the SDUI | +| `CraftDViewListener` | Action callback for the consumer | +| `SimpleProperties` | Base data model | +| `ActionProperties` | Action data (deeplink + analytics) | +| `CraftDAlign` | Component alignment | + +--- + +## Folder Structure + +``` +flutter/craftd_widget/ + lib/ + src/ + builder/ → CraftDBuilder (abstract), CraftDBuilderManager + ui/ + [name]/ + craftd_[name].dart → component Widget + craftd_[name]_builder.dart → implements CraftDBuilder + model/ + [name]_properties.dart → model class +``` + +## Pattern for a new component (example: CraftDFoo) + +1. `lib/src/model/foo_properties.dart` — model class +2. `lib/src/ui/foo/craftd_foo.dart` — Widget +3. `lib/src/ui/foo/craftd_foo_builder.dart` — implements CraftDBuilder +4. Register in `CraftDBuilderManager` +5. Add to the Flutter sample app + +## Conventions + +- File names in `snake_case` +- Classes in `PascalCase` with `CraftD` prefix +- External dependencies (e.g., cached_network_image) injected via constructor, never coupled in the builder + +## Reference + +Consult `CraftDButton` / `CraftDButtonBuilder` as the pattern before creating anything new. diff --git a/mcp/context/ios.md b/mcp/context/ios.md new file mode 100644 index 0000000..b49f2dc --- /dev/null +++ b/mcp/context/ios.md @@ -0,0 +1,44 @@ +# iOS / SwiftUI — Platform Instructions + +> Read this file when starting any iOS task. Ignore `android_kmp/` and `flutter/`. + +--- + +## Core Abstractions + +| Class | Role | +|---|---| +| `CraftDBuilder` | Base protocol for creating components | +| `CraftDBuilderManager` | Registers and resolves builders by `key` | +| `CraftDynamic` | Main View that renders the SDUI | +| `SimpleProperties` | Base data model | +| `ActionProperties` | Action data (deeplink + analytics) | +| `CraftDViewListener` | Action callback for the consumer | + +--- + +## Folder Structure + +``` +ios/craftd-swiftui/ + Sources/CraftD/ + builder/ → CraftDBuilder.swift (protocol), CraftDBuilderManager.swift + ui/ + [name]/ + CraftD[Name].swift → SwiftUI View for the component + CraftD[Name]Builder.swift → implements CraftDBuilder + model/ + [Name]Properties.swift → model struct +``` + +## Pattern for a new component (example: CraftDFoo) + +1. `Sources/CraftD/model/FooProperties.swift` — model struct +2. `Sources/CraftD/ui/foo/CraftDFoo.swift` — SwiftUI View +3. `Sources/CraftD/ui/foo/CraftDFooBuilder.swift` — implements CraftDBuilder +4. Register in `CraftDBuilderManager` +5. Add to the iOS sample app + +## Reference + +Consult `CraftDButton` / `CraftDButtonBuilder` as the pattern before creating anything new. diff --git a/mcp/context/module-graph.md b/mcp/context/module-graph.md new file mode 100644 index 0000000..7c44d82 --- /dev/null +++ b/mcp/context/module-graph.md @@ -0,0 +1,53 @@ +# CraftD — Module Dependency Graph + +## Dependency Rules + +All platform modules depend **only** on `craftd-core`. Platform modules **never** depend on each other. + +``` + ┌─────────────────┐ + │ craftd-core │ ← shared models, abstractions (KMP) + │ (commonMain) │ + └────────┬────────┘ + │ depends on + ┌─────────────────┼─────────────────┐ + │ │ │ + ▼ ▼ ▼ + ┌────────────────┐ ┌──────────────┐ ┌─────────────────────┐ + │ craftd-compose │ │ craftd-xml │ │ ios/craftd-swiftui │ + │ (Android/KMP) │ │ (Android) │ │ (Swift) │ + └────────────────┘ └──────────────┘ └─────────────────────┘ + + ┌─────────────────┐ + │flutter/craftd_ │ + │ widget │ + │ (Dart) │ + └─────────────────┘ + + ✗ craftd-compose → craftd-xml FORBIDDEN + ✗ craftd-xml → craftd-compose FORBIDDEN + ✗ ios/ → android_kmp/ FORBIDDEN + ✗ flutter/ → android_kmp/ FORBIDDEN +``` + +## Module Responsibilities + +| Module | Language | Role | +|---|---|---| +| `craftd-core` | Kotlin (KMP) | Models (`XxxProperties`), enums (`CraftDComponentKey`), interfaces (`CraftDBuilder`, `CraftDViewListener`) | +| `craftd-compose` | Kotlin (Compose/KMP) | Composables (`CraftDXxx`), builders (`CraftDXxxBuilder`), `CraftDBuilderManager`, `CraftDynamic` | +| `craftd-xml` | Kotlin (Android) | Custom Views (`CraftDXxxComponent`), renders (`CraftDXxxComponentRender`), XML `CraftDBuilderManager` | +| `ios/craftd-swiftui` | Swift | SwiftUI Views, `CraftDBuilder` protocol, `CraftDBuilderManager`, `CraftDynamic` | +| `flutter/craftd_widget` | Dart | Widgets, `CraftDBuilder` abstract, `CraftDBuilderManager`, `CraftDynamic` | + +## Adding a New Component + +Always follow this order: + +1. **craftd-core** — create `XxxProperties.kt` in `commonMain/data/model/xxx/` +2. **craftd-compose** — create composable + builder, register in `CraftDBuilderManager` +3. **craftd-xml** — create View + render, register in `getBuilderRenders()` +4. **ios/** — create View + builder (Swift), register in `CraftDBuilderManager` +5. **flutter/** — create widget + builder (Dart), register in `CraftDBuilderManager` + +Core must be implemented before any platform module — they all depend on it. diff --git a/mcp/context/rules.md b/mcp/context/rules.md new file mode 100644 index 0000000..b089610 --- /dev/null +++ b/mcp/context/rules.md @@ -0,0 +1,58 @@ +# CraftD — Architectural Rules + +CraftD is a **Server Driven UI** multiplatform library. The server decides which components to render and how; the client (app) only executes. Supports Android Compose, Android XML, KMP Compose Multiplatform, iOS SwiftUI, and Flutter. + +## Module Structure + +``` +android_kmp/ + craftd-core/ # shared models and abstractions (KMP) + commonMain/ # code shared across platforms + androidMain/ # Android-specific implementations + craftd-compose/ # Compose / KMP implementation + craftd-xml/ # View System (XML) implementation + app-sample-android/ # Android sample app + app-sample-cmp/ # KMP Compose sample app + build-logic/ # shared build configuration + +ios/craftd-swiftui/ # iOS library (Swift Package + CocoaPods) +flutter/craftd_widget/ # Flutter library (pub.dev) +docs/ # site documentation (MkDocs) +``` + +## Architectural Rules — Never Violate + +1. **Platform modules do not depend on each other.** `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. Never on each other. + +2. **Every new component implements the platform abstraction.** On Android/KMP: `CraftDBuilder`. On iOS: the Swift equivalent. On Flutter: the Dart equivalent. Never create a standalone component outside this abstraction. + +3. **`onAction` / fallback always covered.** Every component implementation must handle the action callback (`ActionProperties`), even as a no-op. + +4. **`commonMain` is sacred.** Code in `commonMain` cannot have platform dependencies. If different behavior is needed per platform, use `expect/actual`. + +5. **New components follow the existing pattern.** Consult `CraftDButtonBuilder` and `CraftDTextBuilder` as reference implementations before creating anything new. + +6. **Class names are consistent across all platforms.** Example: if a component is called `CraftDImage` on Android, it must be called `CraftDImage` on iOS and Flutter too. + +7. **Every new component must have a unit test** (when possible) and **documentation in `docs/` under the respective platform section**. + +8. **Every change that affects public library behavior** (new component, new parameter, breaking change) must update `docs/how-to-use/` for the corresponding platform: `compose.md`, `view-system.md`, `swift-ui.md`, or `flutter.md`. + +9. **Every new builder must be registered in `CraftDBuilderManager`** of the respective platform. In Compose/KMP: `CraftDComponentKey.X.key to CraftDXBuilder()`. In XML: add the render in `getBuilderRenders()`. Never create a builder without registering it. + +10. **External library dependencies must be abstracted.** Never directly couple a third-party lib (e.g., Coil, Picasso, Glide) inside the builder. Expose an interface/function as a constructor parameter so the consumer injects the implementation. + +## Code Conventions + +- **Kotlin:** follows official Kotlin conventions. Prefer `data class` for models. +- **Component naming:** `CraftD` prefix on everything that is part of the lib (e.g., `CraftDButton`, `CraftDButtonBuilder`). +- **Tests:** JUnit4 + MockK. Backtick naming: `` `given X when Y then Z` ``. Path mirrors source: `src/test/java/...` +- **Commits:** messages in English, semantic (`feat:`, `fix:`, `test:`, `chore:`, `docs:`). + +## What NOT to Do + +- Do not create a component outside the `CraftDBuilder` abstraction (or platform equivalent) +- Do not add platform dependencies in `commonMain` +- Do not create dependencies between platform modules (`craftd-compose` → `craftd-xml`, for example) +- Do not commit `local.properties` or credential files +- Do not use `--no-verify` to bypass CI hooks diff --git a/mcp/context/skills/android-testing.md b/mcp/context/skills/android-testing.md new file mode 100644 index 0000000..cd0e161 --- /dev/null +++ b/mcp/context/skills/android-testing.md @@ -0,0 +1,65 @@ +--- +name: android-testing +description: Testing strategies for Android/KMP in CraftD. Use when creating or reviewing tests. +trigger: when the user asks to write tests, review test files, or fix test compilation errors +--- + +# Android / KMP Testing in CraftD + +## Test Levels + +| Level | Focus | Tools | +|---|---|---| +| Unit | Isolated logic (ViewModels, Repositories, Builders) | JUnit4, MockK | +| Integration | Interaction between components | AndroidX Test | +| Screenshot | Visual UI verification | Roborazzi (runs on JVM, no emulator needed) | + +## CraftD Standard + +- Framework: **JUnit4 + MockK** +- Naming: backtick notation `` `given X when Y then Z` `` +- Path: `src/test/java/...` mirroring the original file's package +- Every new component must have a unit test covering: construction, defaults, `copy()`, `equals/hashCode`, and the builder's `craft()` + +## AI-Generated Tests (CI / Claude API) + +The CI workflow can auto-generate tests via Claude API. These tests **often fail to compile or run** and need review. Common issues: + +### Compilation Errors + +| Problem | Symptom | Fix | +|---|---|---| +| Markdown code fence | File starts with ` ```kotlin ` | Remove ` ```kotlin ` and ` ``` ` from start/end | +| MockK: loose `throws()` | `mockk { throws(...) }` | Use `mockk(); every { mock.prop } throws ...` | +| `apply { val = }` on data class | `copy().apply { valProp = ... }` | `val` is immutable — use `copy(prop = ...)` | +| Non-existent enum | `CraftDAlign.START`, `CraftDTextStyle.REGULAR` | Check the real enum and substitute | +| AbstractMap entries incompatible | Wrong type override for `entries` | Remove the anonymous object if it's dead code | +| `assertNotEquals` for references | `assertNotEquals(a as Any, b as Any)` when `a == b` | Use `assertTrue(a !== b)` | +| Type inference: `assertNotEquals` | Two different types without explicit parameter | `assertNotEquals(a, b)` | + +### Build Gradle Dependencies + +For `androidUnitTest` sourceSet (path `src/test/java/`), ensure: +```kotlin +androidUnitTest.dependencies { + implementation(libs.junit) + implementation(libs.mockk) + implementation(kotlin("test-junit")) +} +``` + +### Runtime Errors + +| Problem | Symptom | Fix | +|---|---|---| +| `@Stable`/`@Immutable`/`@Serializable` annotations | `assertTrue(isStable)` fails at runtime | BINARY retention — not visible via reflection. Remove the test | +| Mock of extension function | `MockKException: Missing mocked calls` | Kotlin extension functions need `mockkStatic`. Alternative: use `ByteArrayInputStream` | +| Jackson `convertValue` with String | `ClassCastException` | `convertValue` doesn't parse JSON strings — remove the test or use `readValue` | +| Jackson `convertValue` with generic List | Returns `List` instead of `List` | Generics are erased at runtime — remove the test | + +## Screenshot Tests (Roborazzi) + +```bash +./gradlew recordRoborazziDebug # record baseline +./gradlew verifyRoborazziDebug # verify regression +``` diff --git a/mcp/context/skills/compose-ui.md b/mcp/context/skills/compose-ui.md new file mode 100644 index 0000000..e91a6fe --- /dev/null +++ b/mcp/context/skills/compose-ui.md @@ -0,0 +1,116 @@ +--- +name: compose-ui +description: Best practices for Compose components in CraftD. Use when writing or reviewing Compose UI. +trigger: when the user asks to create, review, or fix a Compose component in CraftD +--- + +# Creating a Compose Component in CraftD + +## Mandatory Checklist + +- [ ] `XxxProperties` defined in `craftd-core/commonMain` +- [ ] `CraftDComponentKey.XXX_COMPONENT` added to the enum in `craftd-core` +- [ ] `CraftDXxx` composable created in `craftd-compose/commonMain` +- [ ] `CraftDXxxBuilder` created and implements `CraftDBuilder` +- [ ] Builder registered in `CraftDBuilderManager` +- [ ] `onAction`/fallback covered (even as no-op) +- [ ] Unit test in `commonTest` +- [ ] Documentation in `docs/how-to-use/compose.md` + +--- + +## 1. Composable — Standard Signature + +```kotlin +@Composable +fun CraftDXxx( + properties: XxxProperties, + onAction: () -> Unit = {}, + modifier: Modifier = Modifier, +) { ... } +``` + +- `modifier` always as the last optional parameter, applied to the root element +- `onAction` with default `{}` — never omit the parameter +- Composable is **stateless**: state comes from the caller, never internal + +### Conditional `onAction` (when actionProperties can be null) + +```kotlin +val clickableModifier = if (properties.actionProperties != null) { + modifier.clickable { onAction() } +} else modifier +``` + +--- + +## 2. Builder — Standard Structure + +```kotlin +class CraftDXxxBuilder( + override val key: String = CraftDComponentKey.XXX_COMPONENT.key +) : CraftDBuilder { + @Composable + override fun craft(model: SimpleProperties, listener: CraftDViewListener) { + val properties = model.value.convertToElement() + properties?.let { + CraftDXxx( + properties = it, + onAction = { it.actionProperties?.let { action -> listener.invoke(action) } }, + ) + } + } +} +``` + +### Builder with External Dependency (e.g., imageLoader) + +When the component needs a third-party lib (Coil, etc.), receive it via constructor — never couple directly: + +```kotlin +class CraftDXxxBuilder( + private val imageLoader: @Composable (url: String, contentDescription: String?, modifier: Modifier) -> Unit, + override val key: String = CraftDComponentKey.XXX_COMPONENT.key, +) : CraftDBuilder { ... } +``` + +--- + +## 3. Registration in CraftDBuilderManager + +```kotlin +// Internal registration (no external dependency) +CraftDComponentKey.XXX_COMPONENT.key to CraftDXxxBuilder() + +// Builder with external dependency — consumer injects via add() +craftDBuilderManager.add( + CraftDXxxBuilder(imageLoader = { url, desc, mod -> /* Coil, etc. */ }) +) +``` + +--- + +## 4. Theming + +- Use `MaterialTheme.colorScheme` and `MaterialTheme.typography` +- Never hardcode color, font size, or spacing values + +--- + +## 5. Performance + +- `remember` for expensive computations between recompositions +- `derivedStateOf` when state changes frequently but UI updates at a threshold +- Stable lambdas to avoid unnecessary recomposition of children + +--- + +## 6. Preview + +```kotlin +@Preview(showBackground = true) +@Composable +private fun CraftDXxxPreview() { + CraftDXxx(properties = XxxProperties(...)) {} +} +``` diff --git a/mcp/context/skills/new-component.md b/mcp/context/skills/new-component.md new file mode 100644 index 0000000..f978317 --- /dev/null +++ b/mcp/context/skills/new-component.md @@ -0,0 +1,105 @@ +--- +name: new-component +description: Create a new Server Driven UI component in CraftD following the CraftDBuilder pattern across all platforms +trigger: when the user asks to create a new component, builder, or SDUI element +--- + +# Creating a New CraftD Component + +## Reference Implementation + +Always consult `CraftDButtonBuilder` and `CraftDTextBuilder` before starting. They are the canonical examples. + +## Step-by-Step (Android/KMP) + +### 1. craftd-core — model (commonMain) + +``` +android_kmp/craftd-core/src/commonMain/kotlin/.../data/model/[name]/[Name]Properties.kt +``` + +```kotlin +@Serializable +data class [Name]Properties( + val someField: String = "", + val actionProperties: ActionProperties? = null, +) +``` + +### 2. craftd-core — register the key + +Add to `CraftDComponentKey` enum: +```kotlin +[NAME]_COMPONENT("[name]_component") +``` + +### 3. craftd-compose — composable (commonMain) + +``` +android_kmp/craftd-compose/src/commonMain/kotlin/.../ui/[name]/CraftD[Name].kt +``` + +```kotlin +@Composable +fun CraftD[Name]( + properties: [Name]Properties, + onAction: () -> Unit = {}, + modifier: Modifier = Modifier, +) { + // implementation +} +``` + +### 4. craftd-compose — builder (commonMain) + +```kotlin +class CraftD[Name]Builder( + override val key: String = CraftDComponentKey.[NAME]_COMPONENT.key +) : CraftDBuilder { + @Composable + override fun craft(model: SimpleProperties, listener: CraftDViewListener) { + val properties = model.value.convertToElement<[Name]Properties>() + properties?.let { + CraftD[Name]( + properties = it, + onAction = { it.actionProperties?.let { action -> listener.invoke(action) } }, + ) + } + } +} +``` + +### 5. Register in CraftDBuilderManager (Compose) + +```kotlin +CraftDComponentKey.[NAME]_COMPONENT.key to CraftD[Name]Builder() +``` + +### 6. craftd-xml — custom View + render + +Create `CraftD[Name]Component.kt` and `CraftD[Name]ComponentRender.kt`, then register in `getBuilderRenders()`. + +### 7. Build validation + +```bash +cd android_kmp && ./gradlew build +``` + +Fix any compilation errors before proceeding. + +## Checklist + +- [ ] `[Name]Properties` in `craftd-core/commonMain` +- [ ] `CraftDComponentKey.[NAME]_COMPONENT` added to enum +- [ ] `CraftD[Name]` composable created +- [ ] `CraftD[Name]Builder` created and implements `CraftDBuilder` +- [ ] Builder registered in `CraftDBuilderManager` (Compose) +- [ ] `onAction`/fallback covered (even as no-op) +- [ ] XML View + render created and registered +- [ ] Unit tests in `commonTest` +- [ ] Documentation in `docs/how-to-use/compose.md` +- [ ] Sample app updated + +## iOS / Flutter + +Follow the same pattern adapted to each platform. See `mcp/context/ios.md` and `mcp/context/flutter.md` for platform-specific folder structure and conventions. diff --git a/mcp/context/skills/review-pr.md b/mcp/context/skills/review-pr.md new file mode 100644 index 0000000..2e1b1fa --- /dev/null +++ b/mcp/context/skills/review-pr.md @@ -0,0 +1,58 @@ +--- +name: review-pr +description: Review a CraftD pull request checking architectural rules, completeness, tests, and docs +trigger: when the user asks to review a PR, check a pull request, or validate changes +--- + +# CraftD PR Review Checklist + +Use `gh pr review --comment -b ""` for general comments and `gh api` for inline comments. + +## 1. Architectural Rules + +- [ ] Component implements `CraftDBuilder` (Android/KMP), protocol equivalent (iOS), or abstract class (Flutter) +- [ ] No dependency between platform modules (`craftd-compose` → `craftd-xml` is forbidden) +- [ ] `commonMain` has no platform-specific imports or dependencies +- [ ] External libraries (Coil, Glide, etc.) are injected via constructor, not coupled directly in the builder + +## 2. Completeness + +- [ ] Builder registered in `CraftDBuilderManager` of the respective platform +- [ ] `onAction`/fallback covered — even if it's a no-op +- [ ] `XxxProperties` (or equivalent) defined in `craftd-core` +- [ ] `CraftDComponentKey` updated with the new component key + +## 3. Tests + +- [ ] Unit tests present for the new component +- [ ] Test naming uses backtick notation: `` `given X when Y then Z` `` +- [ ] Test path mirrors source path: `src/test/java/...` +- [ ] Tests cover: construction, defaults, `copy()`, `equals/hashCode`, and builder `craft()` + +## 4. Documentation + +- [ ] `docs/how-to-use/` updated for the affected platform (`compose.md`, `view-system.md`, `swift-ui.md`, or `flutter.md`) +- [ ] Sample app updated with the new component + +## 5. Code Standards + +- [ ] `CraftD` prefix on all lib classes and files +- [ ] `modifier: Modifier = Modifier` exposed on composables +- [ ] No hardcoded color, typography, or spacing values +- [ ] Composable is stateless (state hoisting) + +## How to Comment + +```bash +# General PR comment +gh pr review 123 --comment -b "LGTM — all architectural rules followed." + +# Request changes +gh pr review 123 --request-changes -b "Builder not registered in CraftDBuilderManager." + +# Inline comment via API +gh api repos/CodandoTV/CraftD/pulls/123/comments \ + -f body="Missing onAction fallback" \ + -f path="android_kmp/craftd-compose/src/commonMain/..." \ + -f line=42 +``` diff --git a/mcp/context/skills/run-build.md b/mcp/context/skills/run-build.md new file mode 100644 index 0000000..eb9f841 --- /dev/null +++ b/mcp/context/skills/run-build.md @@ -0,0 +1,68 @@ +--- +name: run-build +description: Run the CraftD build and tests for the affected module +trigger: when the user asks to build, compile, run tests, or validate the project +--- + +# Running the CraftD Build + +## Android / KMP + +Always run from the `android_kmp/` directory: + +```bash +cd android_kmp + +# Full build (all modules) +./gradlew build + +# Build a specific module +./gradlew :craftd-core:build +./gradlew :craftd-compose:build +./gradlew :craftd-xml:build + +# Unit tests only +./gradlew testDebugUnitTest + +# Tests for a specific module +./gradlew :craftd-core:testDebugUnitTest +``` + +## When to Run + +Per CLAUDE.md rules: **run `./gradlew build` after every task before marking `[x]`**. Never mark a task complete without a passing build. + +## Common Build Errors + +| Error | Likely Cause | Fix | +|---|---|---| +| `Unresolved reference: XxxProperties` | Model not created in `craftd-core` | Create the `XxxProperties` data class first | +| `Class is not abstract and does not implement abstract member` | Builder missing `craft()` override | Implement `craft()` in the builder | +| `None of the following candidates is applicable` | Wrong import or type mismatch | Check `convertToElement()` generic type | +| `Duplicate key` in `CraftDBuilderManager` | Component key registered twice | Check `CraftDComponentKey` for duplicate values | + +## Screenshot Tests + +```bash +# Record new baseline +./gradlew recordRoborazziDebug + +# Verify no visual regression +./gradlew verifyRoborazziDebug +``` + +## iOS + +```bash +cd ios/craftd-swiftui +swift build +swift test +``` + +## Flutter + +```bash +cd flutter/craftd_widget +flutter pub get +flutter test +``` diff --git a/openspec/changes/centralized-ai-context/tasks.md b/openspec/changes/centralized-ai-context/tasks.md index 648f8a9..02e1d32 100644 --- a/openspec/changes/centralized-ai-context/tasks.md +++ b/openspec/changes/centralized-ai-context/tasks.md @@ -1,30 +1,30 @@ ## 1. Criar estrutura mcp/context/ -- [ ] 1.1 Criar pasta `mcp/context/` e `mcp/context/skills/` na raiz do projeto -- [ ] 1.2 Criar `mcp/context/rules.md` com as regras arquiteturais do `CLAUDE.md` (seção "Regras arquiteturais — nunca violar" e "Convenções de código") -- [ ] 1.3 Criar `mcp/context/module-graph.md` documentando explicitamente as dependências entre módulos (craftd-core ← compose/xml/ios/flutter, sem dependências cruzadas entre plataformas) -- [ ] 1.4 Criar `mcp/context/android.md` com conteúdo de `.claude/instructions/android-patterns.md` -- [ ] 1.5 Criar `mcp/context/ios.md` com conteúdo de `.claude/instructions/ios-patterns.md` -- [ ] 1.6 Criar `mcp/context/flutter.md` com conteúdo de `.claude/instructions/flutter-patterns.md` +- [x] 1.1 Criar pasta `mcp/context/` e `mcp/context/skills/` na raiz do projeto +- [x] 1.2 Criar `mcp/context/rules.md` com as regras arquiteturais do `CLAUDE.md` (seção "Regras arquiteturais — nunca violar" e "Convenções de código") +- [x] 1.3 Criar `mcp/context/module-graph.md` documentando explicitamente as dependências entre módulos (craftd-core ← compose/xml/ios/flutter, sem dependências cruzadas entre plataformas) +- [x] 1.4 Criar `mcp/context/android.md` com conteúdo de `.claude/instructions/android-patterns.md` +- [x] 1.5 Criar `mcp/context/ios.md` com conteúdo de `.claude/instructions/ios-patterns.md` +- [x] 1.6 Criar `mcp/context/flutter.md` com conteúdo de `.claude/instructions/flutter-patterns.md` ## 2. Migrar skills para mcp/context/skills/ -- [ ] 2.1 Criar `mcp/context/skills/new-component.md` com frontmatter (name, description, trigger) e guia de criação de componente CraftD -- [ ] 2.2 Criar `mcp/context/skills/review-pr.md` com frontmatter e checklist de revisão de PR (baseado na seção "Review de PRs" do CLAUDE.md) -- [ ] 2.3 Criar `mcp/context/skills/android-testing.md` com frontmatter e conteúdo de `.claude/skills/android-testing/` -- [ ] 2.4 Criar `mcp/context/skills/compose-ui.md` com frontmatter e conteúdo de `.claude/skills/compose-ui/` -- [ ] 2.5 Criar `mcp/context/skills/run-build.md` com frontmatter e instruções para rodar o build (`./gradlew build` no módulo afetado) +- [x] 2.1 Criar `mcp/context/skills/new-component.md` com frontmatter (name, description, trigger) e guia de criação de componente CraftD +- [x] 2.2 Criar `mcp/context/skills/review-pr.md` com frontmatter e checklist de revisão de PR (baseado na seção "Review de PRs" do CLAUDE.md) +- [x] 2.3 Criar `mcp/context/skills/android-testing.md` com frontmatter e conteúdo de `.claude/skills/android-testing/` +- [x] 2.4 Criar `mcp/context/skills/compose-ui.md` com frontmatter e conteúdo de `.claude/skills/compose-ui/` +- [x] 2.5 Criar `mcp/context/skills/run-build.md` com frontmatter e instruções para rodar o build (`./gradlew build` no módulo afetado) ## 3. Criar arquivos nativos por ferramenta -- [ ] 3.1 Criar `.github/copilot-instructions.md` com regras críticas inline (arquitetura, nomenclatura, proibições) + referência a `mcp/context/` -- [ ] 3.2 Criar `.cursorrules` com regras críticas inline + referência a `mcp/context/` -- [ ] 3.3 Criar `.gemini/context.md` com regras críticas inline + referência a `mcp/context/` -- [ ] 3.4 Criar `AGENTS.md` (Codex/OpenAI) com regras críticas inline + referência a `mcp/context/` -- [ ] 3.5 Atualizar `CLAUDE.md` para referenciar `mcp/context/` em vez de `.claude/instructions/` nos pontos de plataforma +- [x] 3.1 Criar `.github/copilot-instructions.md` com regras críticas inline (arquitetura, nomenclatura, proibições) + referência a `mcp/context/` +- [x] 3.2 Criar `.cursorrules` com regras críticas inline + referência a `mcp/context/` +- [x] 3.3 Criar `.gemini/context.md` com regras críticas inline + referência a `mcp/context/` +- [x] 3.4 Criar `AGENTS.md` (Codex/OpenAI) com regras críticas inline + referência a `mcp/context/` +- [x] 3.5 Atualizar `CLAUDE.md` para referenciar `mcp/context/` em vez de `.claude/instructions/` nos pontos de plataforma ## 4. Criar documentação explicativa para a comunidade -- [ ] 4.1 Criar `mcp/README.md` em inglês explicando o propósito da pasta, com diagrama Mermaid mostrando o fluxo ferramenta → arquivo nativo → mcp/context/ e nota sobre como replicar em outros repositórios -- [ ] 4.2 Criar `.claude/AI_CONTEXT.md` em inglês explicando que `.claude/` é específico do Claude Code e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid -- [ ] 4.3 Criar `.github/AI_CONTEXT.md` em inglês explicando que `copilot-instructions.md` é o arquivo nativo do Copilot e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid +- [x] 4.1 Criar `mcp/README.md` em inglês explicando o propósito da pasta, com diagrama Mermaid mostrando o fluxo ferramenta → arquivo nativo → mcp/context/ e nota sobre como replicar em outros repositórios +- [x] 4.2 Criar `.claude/AI_CONTEXT.md` em inglês explicando que `.claude/` é específico do Claude Code e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid +- [x] 4.3 Criar `.github/AI_CONTEXT.md` em inglês explicando que `copilot-instructions.md` é o arquivo nativo do Copilot e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid diff --git a/openspec/changes/restrict-generate-tests-to-merged-prs/.openspec.yaml b/openspec/changes/restrict-generate-tests-to-merged-prs/.openspec.yaml deleted file mode 100644 index 9323e24..0000000 --- a/openspec/changes/restrict-generate-tests-to-merged-prs/.openspec.yaml +++ /dev/null @@ -1,2 +0,0 @@ -schema: spec-driven -created: 2026-04-24 diff --git a/openspec/changes/restrict-generate-tests-to-merged-prs/design.md b/openspec/changes/restrict-generate-tests-to-merged-prs/design.md deleted file mode 100644 index e52b87c..0000000 --- a/openspec/changes/restrict-generate-tests-to-merged-prs/design.md +++ /dev/null @@ -1,66 +0,0 @@ -## Context - -O workflow `generate-tests.yml` usa `workflow_run` como gatilho, o que faz com que ele execute toda vez que o workflow "Build and Test for PRs" conclui com sucesso — independentemente de haver um merge. Isso significa que a geração de testes (e o custo associado à Claude API) ocorre a cada push em branches com PR aberto. - -O estado atual do gatilho: -```yaml -workflow_run: - workflows: ["Build and Test for PRs"] - types: [completed] -``` - -A mudança substitui esse gatilho por `pull_request` com tipo `closed`, filtrando apenas merges reais. - -## Goals / Non-Goals - -**Goals:** -- Garantir que `generate-tests.yml` rode apenas quando um PR é mergeado no `main` -- Manter o `workflow_dispatch` para acionamento manual com `override_files` -- Simplificar a lógica de contexto eliminando a ramificação `workflow_run` - -**Non-Goals:** -- Não alterar a lógica de geração de testes em si (Python script, Claude API, PR criado) -- Não modificar outros workflows (`pr.yml`) -- Não mudar o comportamento do `workflow_dispatch` - -## Decisions - -### Gatilho: `pull_request` com tipo `closed` + condição `merged` - -**Decisão:** Usar `on: pull_request: types: [closed]` com `if: github.event.pull_request.merged == true` no job. - -**Alternativas consideradas:** -- `push` no branch `main` — funcionaria, mas perderia o número do PR de origem, que é usado no corpo do PR de testes gerados. -- Manter `workflow_run` com filtro extra — não é possível filtrar por merge via `workflow_run`; exigiria lógica de shell para verificar via `gh api`, mais frágil. - -**Rationale:** O evento `pull_request.closed` com `merged == true` é a forma idiomática do GitHub Actions para "PR mergeado". Fornece `github.event.pull_request.number` diretamente, mantendo a rastreabilidade no PR gerado. - -### Base do diff: `github.event.pull_request.base.sha` - -**Decisão:** No step "Check for Kotlin file changes", substituir `origin/main...HEAD` por `${{ github.event.pull_request.base.sha }}...HEAD` quando o gatilho for `pull_request`. - -**Rationale:** Com `pull_request.closed`, o checkout ocorre no merge commit. Usar o SHA base do PR garante que o diff cubra exatamente os arquivos modificados naquele PR — o mesmo conjunto analisado pelo CI. - -### Remoção do step "Resolve trigger context" - -**Decisão:** Remover o step `ctx` que normalizava `head_sha` e `pr_number` entre os dois gatilhos (`workflow_dispatch` vs `workflow_run`). - -**Rationale:** Com apenas `pull_request` e `workflow_dispatch`, os valores são obtidos diretamente: -- `pr_number`: `github.event.pull_request.number` (ou `"manual"` no dispatch) -- `head_sha`: `github.event.pull_request.merge_commit_sha` (ou `github.sha` no dispatch) - -Isso elimina a indireção e simplifica os steps subsequentes. - -## Risks / Trade-offs - -- **[Risco] PRs mergeados em branches que não `main`** → O job pode ser restrito adicionando `if: github.event.pull_request.base.ref == 'main'`. Incluir essa condição como precaução. -- **[Trade-off] Geração só ocorre pós-merge** → Antes, testes podiam ser gerados ainda com o PR aberto (como efeito colateral). Agora é intencional — só pós-merge. Aceito como comportamento desejado. - -## Migration Plan - -1. Editar `.github/workflows/generate-tests.yml`: - - Substituir bloco `workflow_run` por `pull_request: types: [closed]` - - Remover step `Resolve trigger context` - - Atualizar condição `if` do job para verificar `merged == true` e base `main` - - Atualizar referências de `steps.ctx.outputs.*` nos steps seguintes -2. Fazer commit e push — sem necessidade de rollback especial; reverter o arquivo restaura o comportamento anterior. diff --git a/openspec/changes/restrict-generate-tests-to-merged-prs/proposal.md b/openspec/changes/restrict-generate-tests-to-merged-prs/proposal.md deleted file mode 100644 index 084ba72..0000000 --- a/openspec/changes/restrict-generate-tests-to-merged-prs/proposal.md +++ /dev/null @@ -1,27 +0,0 @@ -## Why - -O workflow `generate-tests.yml` dispara a cada commit em qualquer branch porque o gatilho `workflow_run` reage à conclusão de "Build and Test for PRs" independente de o PR ter sido mergeado ou não. Isso gera execuções desnecessárias e custo de API durante o desenvolvimento, quando o ideal é gerar testes apenas uma vez — ao merge no `main`. - -## What Changes - -- Substituir o gatilho `workflow_run` por `pull_request` com o tipo `closed` + filtro `merged == true` -- Remover a lógica de resolução de contexto para o gatilho `workflow_run` (step "Resolve trigger context") -- Ajustar o step "Check for Kotlin file changes" para usar `github.event.pull_request.base.sha` como base do diff em vez de `origin/main` -- Manter o gatilho `workflow_dispatch` inalterado para acionamento manual - -## Capabilities - -### New Capabilities - -- `generate-tests-trigger`: Controle de gatilho do workflow de geração de testes — restringe execução a PRs mergeados no `main` - -### Modified Capabilities - - - -## Impact - -- **Arquivo afetado:** `.github/workflows/generate-tests.yml` -- **Comportamento anterior:** workflow roda a cada push que passe no CI de qualquer branch com PR aberto -- **Comportamento novo:** workflow roda apenas quando um PR é mergeado no `main` -- **Sem impacto** em outros workflows, código da lib ou testes existentes diff --git a/openspec/changes/restrict-generate-tests-to-merged-prs/specs/generate-tests-trigger/spec.md b/openspec/changes/restrict-generate-tests-to-merged-prs/specs/generate-tests-trigger/spec.md deleted file mode 100644 index 78a5c99..0000000 --- a/openspec/changes/restrict-generate-tests-to-merged-prs/specs/generate-tests-trigger/spec.md +++ /dev/null @@ -1,42 +0,0 @@ -## ADDED Requirements - -### Requirement: Workflow executa apenas em PRs mergeados no main -O workflow `generate-tests.yml` SHALL ser acionado automaticamente somente quando um pull request for mergeado na branch `main`. - -#### Scenario: PR mergeado no main dispara o workflow -- **WHEN** um pull request é fechado com `merged == true` e `base.ref == 'main'` -- **THEN** o job `generate-tests` é executado - -#### Scenario: PR fechado sem merge não dispara o workflow -- **WHEN** um pull request é fechado com `merged == false` -- **THEN** o job `generate-tests` NÃO é executado - -#### Scenario: Push em branch sem merge não dispara o workflow -- **WHEN** um commit é feito em qualquer branch sem que haja um merge no main -- **THEN** o job `generate-tests` NÃO é executado - -#### Scenario: PR mergeado em branch que não main não dispara o workflow -- **WHEN** um pull request é mergeado em uma branch diferente de `main` (ex: `develop`) -- **THEN** o job `generate-tests` NÃO é executado - -### Requirement: Workflow_dispatch mantido para acionamento manual -O workflow SHALL continuar suportando acionamento manual via `workflow_dispatch` com o parâmetro opcional `override_files`. - -#### Scenario: Disparo manual sem override roda scan completo -- **WHEN** o workflow é acionado via `workflow_dispatch` sem `override_files` -- **THEN** o job escaneia todos os arquivos `.kt` sem cobertura em `craftd-core` - -#### Scenario: Disparo manual com override_files usa arquivos informados -- **WHEN** o workflow é acionado via `workflow_dispatch` com `override_files` preenchido -- **THEN** o job processa apenas os arquivos listados em `override_files` - -### Requirement: Número do PR de origem preservado no PR gerado -O workflow SHALL incluir o número do PR que disparou a geração no corpo do PR de testes criado automaticamente. - -#### Scenario: PR de testes referencia o PR de origem -- **WHEN** o workflow é disparado por um merge de PR número `N` -- **THEN** o corpo do PR gerado contém `Triggered by PR #N` - -#### Scenario: Disparo manual usa label "manual" -- **WHEN** o workflow é acionado via `workflow_dispatch` -- **THEN** o corpo do PR gerado contém `Triggered by PR #manual` diff --git a/openspec/changes/restrict-generate-tests-to-merged-prs/tasks.md b/openspec/changes/restrict-generate-tests-to-merged-prs/tasks.md deleted file mode 100644 index bff8fe6..0000000 --- a/openspec/changes/restrict-generate-tests-to-merged-prs/tasks.md +++ /dev/null @@ -1,25 +0,0 @@ -## 1. Substituir gatilho do workflow - -- [x] 1.1 Remover o bloco `workflow_run` de `.github/workflows/generate-tests.yml` -- [x] 1.2 Adicionar gatilho `pull_request: types: [closed]` no lugar - -## 2. Atualizar condição do job - -- [x] 2.1 Adicionar condição `if` no job `generate-tests` para verificar `github.event.pull_request.merged == true` -- [x] 2.2 Adicionar filtro `github.event.pull_request.base.ref == 'main'` na condição do job (ou manter para `workflow_dispatch`) - -## 3. Remover e simplificar lógica de contexto - -- [x] 3.1 Remover o step "Resolve trigger context" (`id: ctx`) inteiramente -- [x] 3.2 Atualizar o step "Checkout" para usar `github.event.pull_request.merge_commit_sha` (ou `github.sha` para dispatch) -- [x] 3.3 Atualizar referências `steps.ctx.outputs.pr_number` e `steps.ctx.outputs.head_sha` nos steps seguintes para usar os valores diretos do evento - -## 4. Ajustar diff de Kotlin - -- [x] 4.1 No step "Check for Kotlin file changes", substituir a base do diff de `origin/main...HEAD` por `${{ github.event.pull_request.base.sha }}...HEAD` para o gatilho `pull_request` -- [x] 4.2 Garantir que o modo `workflow_dispatch` continue usando o scan completo (sem base SHA de PR) - -## 5. Validação - -- [x] 5.1 Revisar o YAML final e confirmar que a sintaxe está correta (sem erros de indentação ou referências quebradas) -- [x] 5.2 Confirmar que `pr_number` no body do PR gerado continua referenciando o número correto (ou "manual" para dispatch) From 1c1fa2f678fed78037bfdb7095bafc0459ad2933 Mon Sep 17 00:00:00 2001 From: Rods Date: Fri, 24 Apr 2026 09:32:10 -0300 Subject: [PATCH 3/4] refactor: rename mcp/ to mcp-local/ for clearer intent Better communicates that this is local AI context (not a running MCP Server) while still connecting to the MCP concept. Co-Authored-By: Claude Sonnet 4.6 --- .claude/AI_CONTEXT.md | 16 +++---- .cursorrules | 12 +++--- .gemini/context.md | 12 +++--- .github/AI_CONTEXT.md | 14 +++---- .github/copilot-instructions.md | 12 +++--- AGENTS.md | 12 +++--- CLAUDE.md | 8 ++-- {mcp => mcp-local}/README.md | 8 ++-- {mcp => mcp-local}/context/android.md | 0 {mcp => mcp-local}/context/flutter.md | 0 {mcp => mcp-local}/context/ios.md | 0 {mcp => mcp-local}/context/module-graph.md | 0 {mcp => mcp-local}/context/rules.md | 0 .../context/skills/android-testing.md | 0 .../context/skills/compose-ui.md | 0 .../context/skills/new-component.md | 2 +- .../context/skills/review-pr.md | 0 .../context/skills/run-build.md | 0 .../changes/centralized-ai-context/design.md | 20 ++++----- .../centralized-ai-context/proposal.md | 18 ++++---- .../centralized-context-structure/spec.md | 18 ++++---- .../specs/community-explainer-docs/spec.md | 12 +++--- .../specs/per-tool-native-files/spec.md | 12 +++--- .../changes/centralized-ai-context/tasks.md | 42 +++++++++---------- 24 files changed, 109 insertions(+), 109 deletions(-) rename {mcp => mcp-local}/README.md (89%) rename {mcp => mcp-local}/context/android.md (100%) rename {mcp => mcp-local}/context/flutter.md (100%) rename {mcp => mcp-local}/context/ios.md (100%) rename {mcp => mcp-local}/context/module-graph.md (100%) rename {mcp => mcp-local}/context/rules.md (100%) rename {mcp => mcp-local}/context/skills/android-testing.md (100%) rename {mcp => mcp-local}/context/skills/compose-ui.md (100%) rename {mcp => mcp-local}/context/skills/new-component.md (93%) rename {mcp => mcp-local}/context/skills/review-pr.md (100%) rename {mcp => mcp-local}/context/skills/run-build.md (100%) diff --git a/.claude/AI_CONTEXT.md b/.claude/AI_CONTEXT.md index 9edf04d..caadba4 100644 --- a/.claude/AI_CONTEXT.md +++ b/.claude/AI_CONTEXT.md @@ -5,7 +5,7 @@ This folder (`.claude/`) contains Claude Code-specific configuration: skills, co The **complete AI context** (architectural rules, platform patterns, available skills) lives in a single central location to avoid duplication across tools: ``` -📁 mcp/context/ ← single source of truth for all AI tools +📁 mcp-local/context/ ← single source of truth for all AI tools ``` ## Why This Structure? @@ -19,7 +19,7 @@ graph LR CURSOR["Cursor
.cursorrules"] OTHER["Other tools..."] - MCP["📁 mcp/context/
Single Source of Truth"] + MCP["📁 mcp-local/context/
Single Source of Truth"] CLAUDE -->|references| MCP COPILOT -->|references| MCP @@ -27,9 +27,9 @@ graph LR OTHER -->|references| MCP ``` -## What Lives Here vs. in mcp/context/ +## What Lives Here vs. in mcp-local/context/ -| Here (`.claude/`) | In `mcp/context/` | +| Here (`.claude/`) | In `mcp-local/context/` | |---|---| | Claude Code skills (structured YAML format) | Skills as readable Markdown (any tool) | | Claude Code commands | Architectural rules | @@ -38,7 +38,7 @@ graph LR ## Quick Reference -- Full rules → `mcp/context/rules.md` -- Module dependencies → `mcp/context/module-graph.md` -- Platform patterns → `mcp/context/android.md`, `ios.md`, `flutter.md` -- Skills (any tool) → `mcp/context/skills/` +- Full rules → `mcp-local/context/rules.md` +- Module dependencies → `mcp-local/context/module-graph.md` +- Platform patterns → `mcp-local/context/android.md`, `ios.md`, `flutter.md` +- Skills (any tool) → `mcp-local/context/skills/` diff --git a/.cursorrules b/.cursorrules index 0dfc232..2f49c1a 100644 --- a/.cursorrules +++ b/.cursorrules @@ -27,10 +27,10 @@ CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android Read these files for full rules, platform patterns, and available skills: ``` -mcp/context/rules.md ← architectural rules -mcp/context/module-graph.md ← module dependencies -mcp/context/android.md ← Android/KMP patterns -mcp/context/ios.md ← iOS patterns -mcp/context/flutter.md ← Flutter patterns -mcp/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui +mcp-local/context/rules.md ← architectural rules +mcp-local/context/module-graph.md ← module dependencies +mcp-local/context/android.md ← Android/KMP patterns +mcp-local/context/ios.md ← iOS patterns +mcp-local/context/flutter.md ← Flutter patterns +mcp-local/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui ``` diff --git a/.gemini/context.md b/.gemini/context.md index 7acc1eb..854ec5c 100644 --- a/.gemini/context.md +++ b/.gemini/context.md @@ -27,10 +27,10 @@ CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android Read these files for full rules, platform patterns, and available skills: ``` -mcp/context/rules.md ← architectural rules -mcp/context/module-graph.md ← module dependencies -mcp/context/android.md ← Android/KMP patterns -mcp/context/ios.md ← iOS patterns -mcp/context/flutter.md ← Flutter patterns -mcp/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui +mcp-local/context/rules.md ← architectural rules +mcp-local/context/module-graph.md ← module dependencies +mcp-local/context/android.md ← Android/KMP patterns +mcp-local/context/ios.md ← iOS patterns +mcp-local/context/flutter.md ← Flutter patterns +mcp-local/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui ``` diff --git a/.github/AI_CONTEXT.md b/.github/AI_CONTEXT.md index f131bce..58e6ba0 100644 --- a/.github/AI_CONTEXT.md +++ b/.github/AI_CONTEXT.md @@ -5,7 +5,7 @@ This folder (`.github/`) contains GitHub-specific configuration: workflows, issu The **complete AI context** (architectural rules, platform patterns, available skills) lives in a single central location to avoid duplication across tools: ``` -📁 mcp/context/ ← single source of truth for all AI tools +📁 mcp-local/context/ ← single source of truth for all AI tools ``` ## Why This Structure? @@ -19,7 +19,7 @@ graph LR CURSOR["Cursor
.cursorrules"] OTHER["Other tools..."] - MCP["📁 mcp/context/
Single Source of Truth"] + MCP["📁 mcp-local/context/
Single Source of Truth"] COPILOT -->|references| MCP CLAUDE -->|references| MCP @@ -31,13 +31,13 @@ graph LR | File | Purpose | |---|---| -| `copilot-instructions.md` | Copilot native context — critical rules inline + reference to `mcp/context/` | +| `copilot-instructions.md` | Copilot native context — critical rules inline + reference to `mcp-local/context/` | | `workflows/` | CI/CD automation (build, test, auto-generate tests) | | `AI_CONTEXT.md` | This file — explains the AI context structure for the community | ## Quick Reference -- Full rules → `mcp/context/rules.md` -- Module dependencies → `mcp/context/module-graph.md` -- Platform patterns → `mcp/context/android.md`, `ios.md`, `flutter.md` -- Skills (any tool) → `mcp/context/skills/` +- Full rules → `mcp-local/context/rules.md` +- Module dependencies → `mcp-local/context/module-graph.md` +- Platform patterns → `mcp-local/context/android.md`, `ios.md`, `flutter.md` +- Skills (any tool) → `mcp-local/context/skills/` diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 614f9e4..0164629 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -27,10 +27,10 @@ CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android For full architectural rules, platform patterns, module graph, and available skills, read: ``` -mcp/context/rules.md ← architectural rules and conventions -mcp/context/module-graph.md ← module dependencies -mcp/context/android.md ← Android/KMP patterns -mcp/context/ios.md ← iOS/SwiftUI patterns -mcp/context/flutter.md ← Flutter patterns -mcp/context/skills/ ← available skills (new-component, review-pr, run-build, ...) +mcp-local/context/rules.md ← architectural rules and conventions +mcp-local/context/module-graph.md ← module dependencies +mcp-local/context/android.md ← Android/KMP patterns +mcp-local/context/ios.md ← iOS/SwiftUI patterns +mcp-local/context/flutter.md ← Flutter patterns +mcp-local/context/skills/ ← available skills (new-component, review-pr, run-build, ...) ``` diff --git a/AGENTS.md b/AGENTS.md index d1c87f3..9edf356 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,10 +27,10 @@ CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android Read these files for full rules, platform patterns, and available skills: ``` -mcp/context/rules.md ← architectural rules -mcp/context/module-graph.md ← module dependencies -mcp/context/android.md ← Android/KMP patterns -mcp/context/ios.md ← iOS patterns -mcp/context/flutter.md ← Flutter patterns -mcp/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui +mcp-local/context/rules.md ← architectural rules +mcp-local/context/module-graph.md ← module dependencies +mcp-local/context/android.md ← Android/KMP patterns +mcp-local/context/ios.md ← iOS patterns +mcp-local/context/flutter.md ← Flutter patterns +mcp-local/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui ``` diff --git a/CLAUDE.md b/CLAUDE.md index f6aa65d..ad69afd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -58,11 +58,11 @@ docs/ # documentação do site (MkDocs) ## Contexto por plataforma -Antes de iniciar qualquer task, identifique a plataforma e leia o arquivo correspondente em `mcp/context/`: +Antes de iniciar qualquer task, identifique a plataforma e leia o arquivo correspondente em `mcp-local/context/`: -- Android/KMP → `mcp/context/android.md` -- iOS → `mcp/context/ios.md` -- Flutter → `mcp/context/flutter.md` +- Android/KMP → `mcp-local/context/android.md` +- iOS → `mcp-local/context/ios.md` +- Flutter → `mcp-local/context/flutter.md` Ao gerar um `proposal.md` via `/propose`, detecte a plataforma na descrição do usuário e adicione frontmatter no início do arquivo: diff --git a/mcp/README.md b/mcp-local/README.md similarity index 89% rename from mcp/README.md rename to mcp-local/README.md index 142aa29..2fe50b9 100644 --- a/mcp/README.md +++ b/mcp-local/README.md @@ -16,7 +16,7 @@ graph TD GE["Gemini
.gemini/context.md"] OA["Codex / OpenAI
AGENTS.md"] - CTX["📁 mcp/context/"] + CTX["📁 mcp-local/context/"] RULES["rules.md"] GRAPH["module-graph.md"] AND["android.md"] @@ -57,9 +57,9 @@ graph TD This structure can be copied to any public repository as a starting point for centralized AI context: -1. Create `mcp/context/` with your project's rules and platform patterns +1. Create `mcp-local/context/` with your project's rules and platform patterns 2. Create a native file for each AI tool you use (see examples in this repo) -3. Each native file: include critical rules inline + point to `mcp/context/` for details +3. Each native file: include critical rules inline + point to `mcp-local/context/` for details 4. Add skills as Markdown files with `name`, `description`, and `trigger` frontmatter -The native files ensure basic context even if the tool doesn't follow the `mcp/context/` reference. The central folder provides complete context for tools that do. +The native files ensure basic context even if the tool doesn't follow the `mcp-local/context/` reference. The central folder provides complete context for tools that do. diff --git a/mcp/context/android.md b/mcp-local/context/android.md similarity index 100% rename from mcp/context/android.md rename to mcp-local/context/android.md diff --git a/mcp/context/flutter.md b/mcp-local/context/flutter.md similarity index 100% rename from mcp/context/flutter.md rename to mcp-local/context/flutter.md diff --git a/mcp/context/ios.md b/mcp-local/context/ios.md similarity index 100% rename from mcp/context/ios.md rename to mcp-local/context/ios.md diff --git a/mcp/context/module-graph.md b/mcp-local/context/module-graph.md similarity index 100% rename from mcp/context/module-graph.md rename to mcp-local/context/module-graph.md diff --git a/mcp/context/rules.md b/mcp-local/context/rules.md similarity index 100% rename from mcp/context/rules.md rename to mcp-local/context/rules.md diff --git a/mcp/context/skills/android-testing.md b/mcp-local/context/skills/android-testing.md similarity index 100% rename from mcp/context/skills/android-testing.md rename to mcp-local/context/skills/android-testing.md diff --git a/mcp/context/skills/compose-ui.md b/mcp-local/context/skills/compose-ui.md similarity index 100% rename from mcp/context/skills/compose-ui.md rename to mcp-local/context/skills/compose-ui.md diff --git a/mcp/context/skills/new-component.md b/mcp-local/context/skills/new-component.md similarity index 93% rename from mcp/context/skills/new-component.md rename to mcp-local/context/skills/new-component.md index f978317..dea2fe0 100644 --- a/mcp/context/skills/new-component.md +++ b/mcp-local/context/skills/new-component.md @@ -102,4 +102,4 @@ Fix any compilation errors before proceeding. ## iOS / Flutter -Follow the same pattern adapted to each platform. See `mcp/context/ios.md` and `mcp/context/flutter.md` for platform-specific folder structure and conventions. +Follow the same pattern adapted to each platform. See `mcp-local/context/ios.md` and `mcp-local/context/flutter.md` for platform-specific folder structure and conventions. diff --git a/mcp/context/skills/review-pr.md b/mcp-local/context/skills/review-pr.md similarity index 100% rename from mcp/context/skills/review-pr.md rename to mcp-local/context/skills/review-pr.md diff --git a/mcp/context/skills/run-build.md b/mcp-local/context/skills/run-build.md similarity index 100% rename from mcp/context/skills/run-build.md rename to mcp-local/context/skills/run-build.md diff --git a/openspec/changes/centralized-ai-context/design.md b/openspec/changes/centralized-ai-context/design.md index 6fdf75a..40aedab 100644 --- a/openspec/changes/centralized-ai-context/design.md +++ b/openspec/changes/centralized-ai-context/design.md @@ -10,8 +10,8 @@ O resultado: devs que usam Copilot ou Cursor no mesmo repo trabalham sem as regr ## Goals / Non-Goals **Goals:** -- Criar `mcp/context/` como fonte única de verdade para qualquer ferramenta de IA -- Cada ferramenta tem arquivo nativo leve com essencial inline + referência a `mcp/context/` +- Criar `mcp-local/context/` como fonte única de verdade para qualquer ferramenta de IA +- Cada ferramenta tem arquivo nativo leve com essencial inline + referência a `mcp-local/context/` - Skills autodescritivas com `name` e `description` que qualquer modelo descobre ao ler - Comunidade entende o padrão ao abrir qualquer pasta nativa (explicativo em inglês + diagrama) - Zero infraestrutura — apenas arquivos markdown @@ -19,7 +19,7 @@ O resultado: devs que usam Copilot ou Cursor no mesmo repo trabalham sem as regr **Non-Goals:** - MCP Server com processo rodando (futuro, se necessário) - Garantir comportamento idêntico entre todos os modelos (cada um interpreta à sua maneira) -- Migrar o sistema de skills estruturadas do `.claude/skills/` (formato YAML interno) — apenas criar versões em `mcp/context/skills/` legíveis por qualquer modelo +- Migrar o sistema de skills estruturadas do `.claude/skills/` (formato YAML interno) — apenas criar versões em `mcp-local/context/skills/` legíveis por qualquer modelo ## Decisions @@ -46,17 +46,17 @@ mcp/ | Ferramenta | Arquivo nativo | Estratégia | |---|---|---| -| Claude Code | `CLAUDE.md` | Atualizar referências para `mcp/context/` | +| Claude Code | `CLAUDE.md` | Atualizar referências para `mcp-local/context/` | | GitHub Copilot | `.github/copilot-instructions.md` | Novo — essencial inline + referência | | Cursor | `.cursorrules` | Novo — essencial inline + referência | | Gemini (Google IDX) | `.gemini/context.md` | Novo — essencial inline + referência | | Codex / OpenAI | `AGENTS.md` | Novo — essencial inline + referência | -**Decisão:** cada arquivo nativo carrega as 5-8 regras mais críticas inline (garante que qualquer modelo as leia, mesmo sem seguir a referência) e adiciona `For complete rules and skills, read mcp/context/` ao final. +**Decisão:** cada arquivo nativo carrega as 5-8 regras mais críticas inline (garante que qualquer modelo as leia, mesmo sem seguir a referência) e adiciona `For complete rules and skills, read mcp-local/context/` ao final. **Alternativa descartada:** arquivo nativo apenas como apontador. Risco: modelos com contexto limitado ou implementações inconsistentes ignoram a instrução de ir ler outra pasta. -### Conteúdo das skills em mcp/context/skills/ +### Conteúdo das skills em mcp-local/context/skills/ Cada skill é um markdown autodescritivo: @@ -82,7 +82,7 @@ Cada pasta nativa ganha um arquivo `AI_CONTEXT.md` (ou `README.md` onde faz sent ## Risks / Trade-offs -- **[Risco] Modelos ignoram a referência a `mcp/context/`** → Mitigado mantendo regras críticas inline em cada arquivo nativo -- **[Risco] `mcp/context/` fica desatualizado** → O nome da pasta (`mcp/`) pode confundir — não é um MCP Server, é contexto. Mitigado com `README.md` explicativo claro -- **[Trade-off] Alguma duplicação intencional** → Regras críticas aparecem tanto no arquivo nativo quanto em `mcp/context/rules.md`. Aceito: o arquivo nativo é o "resumo garantido", o `mcp/context/` é o "detalhe completo" -- **[Risco] `.claude/skills/` e `mcp/context/skills/` coexistem** → As skills em `.claude/skills/` têm formato estruturado para o Claude Code; as de `mcp/context/skills/` são markdown livre para qualquer modelo. Diferentes propósitos, podem coexistir sem conflito +- **[Risco] Modelos ignoram a referência a `mcp-local/context/`** → Mitigado mantendo regras críticas inline em cada arquivo nativo +- **[Risco] `mcp-local/context/` fica desatualizado** → O nome da pasta (`mcp/`) pode confundir — não é um MCP Server, é contexto. Mitigado com `README.md` explicativo claro +- **[Trade-off] Alguma duplicação intencional** → Regras críticas aparecem tanto no arquivo nativo quanto em `mcp-local/context/rules.md`. Aceito: o arquivo nativo é o "resumo garantido", o `mcp-local/context/` é o "detalhe completo" +- **[Risco] `.claude/skills/` e `mcp-local/context/skills/` coexistem** → As skills em `.claude/skills/` têm formato estruturado para o Claude Code; as de `mcp-local/context/skills/` são markdown livre para qualquer modelo. Diferentes propósitos, podem coexistir sem conflito diff --git a/openspec/changes/centralized-ai-context/proposal.md b/openspec/changes/centralized-ai-context/proposal.md index ab3ffa2..2886511 100644 --- a/openspec/changes/centralized-ai-context/proposal.md +++ b/openspec/changes/centralized-ai-context/proposal.md @@ -4,19 +4,19 @@ CraftD é um repositório público usado como referência pela comunidade, mas h ## What Changes -- Criar pasta `mcp/context/` como fonte única de verdade para regras, padrões e skills -- Migrar conteúdo de `.claude/instructions/` (android-patterns, ios-patterns, flutter-patterns) para `mcp/context/` -- Migrar skills de `.claude/skills/` para `mcp/context/skills/` -- Criar arquivos nativos leves para cada ferramenta: `.github/copilot-instructions.md`, `.cursorrules`, `.gemini/context.md`, `AGENTS.md` (Codex) — cada um com regras essenciais inline + referência a `mcp/context/` -- Atualizar `CLAUDE.md` para referenciar `mcp/context/` em vez de `.claude/instructions/` +- Criar pasta `mcp-local/context/` como fonte única de verdade para regras, padrões e skills +- Migrar conteúdo de `.claude/instructions/` (android-patterns, ios-patterns, flutter-patterns) para `mcp-local/context/` +- Migrar skills de `.claude/skills/` para `mcp-local/context/skills/` +- Criar arquivos nativos leves para cada ferramenta: `.github/copilot-instructions.md`, `.cursorrules`, `.gemini/context.md`, `AGENTS.md` (Codex) — cada um com regras essenciais inline + referência a `mcp-local/context/` +- Atualizar `CLAUDE.md` para referenciar `mcp-local/context/` em vez de `.claude/instructions/` - Adicionar `.md` explicativo em inglês em cada pasta nativa (`.claude/`, `.github/`) para a comunidade entender a estrutura sem duplicação, com diagrama Mermaid ## Capabilities ### New Capabilities -- `centralized-context-structure`: Estrutura `mcp/context/` como fonte única de contexto AI com regras, padrões por plataforma e skills autodescritivas -- `per-tool-native-files`: Arquivos nativos leves por ferramenta que carregam essencial inline e referenciam `mcp/context/` para detalhes +- `centralized-context-structure`: Estrutura `mcp-local/context/` como fonte única de contexto AI com regras, padrões por plataforma e skills autodescritivas +- `per-tool-native-files`: Arquivos nativos leves por ferramenta que carregam essencial inline e referenciam `mcp-local/context/` para detalhes - `community-explainer-docs`: Documentação explicativa em inglês em cada pasta nativa para a comunidade entender o padrão adotado ### Modified Capabilities @@ -25,7 +25,7 @@ CraftD é um repositório público usado como referência pela comunidade, mas h ## Impact -- **Arquivos novos:** `mcp/context/rules.md`, `mcp/context/android.md`, `mcp/context/ios.md`, `mcp/context/flutter.md`, `mcp/context/module-graph.md`, `mcp/context/skills/` (migração), `.github/copilot-instructions.md`, `.cursorrules`, `.gemini/context.md`, `AGENTS.md`, `mcp/README.md`, `.claude/README.md`, `.github/AI_CONTEXT.md` -- **Arquivos modificados:** `CLAUDE.md` (atualizar referências de `.claude/instructions/` para `mcp/context/`) +- **Arquivos novos:** `mcp-local/context/rules.md`, `mcp-local/context/android.md`, `mcp-local/context/ios.md`, `mcp-local/context/flutter.md`, `mcp-local/context/module-graph.md`, `mcp-local/context/skills/` (migração), `.github/copilot-instructions.md`, `.cursorrules`, `.gemini/context.md`, `AGENTS.md`, `mcp-local/README.md`, `.claude/README.md`, `.github/AI_CONTEXT.md` +- **Arquivos modificados:** `CLAUDE.md` (atualizar referências de `.claude/instructions/` para `mcp-local/context/`) - **Sem breaking change:** `.claude/skills/` e `.claude/instructions/` podem coexistir durante migração - **Sem dependências externas:** apenas arquivos markdown, zero infraestrutura diff --git a/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md b/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md index b884395..2fd1ee7 100644 --- a/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md +++ b/openspec/changes/centralized-ai-context/specs/centralized-context-structure/spec.md @@ -1,30 +1,30 @@ ## ADDED Requirements -### Requirement: mcp/context/ é a fonte única de verdade para contexto AI -O projeto SHALL manter uma pasta `mcp/context/` na raiz contendo todo o contexto arquitetural, regras e skills do projeto em formato markdown legível por qualquer ferramenta de IA. +### Requirement: mcp-local/context/ é a fonte única de verdade para contexto AI +O projeto SHALL manter uma pasta `mcp-local/context/` na raiz contendo todo o contexto arquitetural, regras e skills do projeto em formato markdown legível por qualquer ferramenta de IA. #### Scenario: Desenvolvedor com qualquer ferramenta acessa contexto completo -- **WHEN** um desenvolvedor aponta qualquer ferramenta de IA para `mcp/context/` +- **WHEN** um desenvolvedor aponta qualquer ferramenta de IA para `mcp-local/context/` - **THEN** a ferramenta tem acesso a regras arquiteturais, padrões por plataforma e skills disponíveis #### Scenario: Estrutura de arquivos está presente e organizada -- **WHEN** a pasta `mcp/context/` é inspecionada +- **WHEN** a pasta `mcp-local/context/` é inspecionada - **THEN** contém `rules.md`, `module-graph.md`, `android.md`, `ios.md`, `flutter.md` e pasta `skills/` ### Requirement: Skills são autodescritivas com frontmatter padronizado -Cada skill em `mcp/context/skills/` SHALL ter frontmatter com `name`, `description` e `trigger` para que qualquer modelo descubra o que pode fazer. +Cada skill em `mcp-local/context/skills/` SHALL ter frontmatter com `name`, `description` e `trigger` para que qualquer modelo descubra o que pode fazer. #### Scenario: Modelo lista skills disponíveis ao ler a pasta -- **WHEN** um modelo lê os arquivos em `mcp/context/skills/` +- **WHEN** um modelo lê os arquivos em `mcp-local/context/skills/` - **THEN** consegue identificar nome, descrição e quando usar cada skill pelo frontmatter #### Scenario: Skill de novo componente está disponível - **WHEN** desenvolvedor pede para criar um novo componente CraftD em qualquer ferramenta -- **THEN** a ferramenta encontra `mcp/context/skills/new-component.md` com o guia completo +- **THEN** a ferramenta encontra `mcp-local/context/skills/new-component.md` com o guia completo ### Requirement: module-graph.md documenta dependências entre módulos explicitamente -O arquivo `mcp/context/module-graph.md` SHALL documentar as dependências entre módulos de forma explícita, sem exigir leitura do `settings.gradle.kts`. +O arquivo `mcp-local/context/module-graph.md` SHALL documentar as dependências entre módulos de forma explícita, sem exigir leitura do `settings.gradle.kts`. #### Scenario: Modelo entende que módulos de plataforma não se dependem -- **WHEN** um modelo lê `mcp/context/module-graph.md` +- **WHEN** um modelo lê `mcp-local/context/module-graph.md` - **THEN** entende claramente que `craftd-compose`, `craftd-xml`, `ios/` e `flutter/` dependem apenas do `craftd-core` e nunca entre si diff --git a/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md b/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md index a52f1fc..731d88b 100644 --- a/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md +++ b/openspec/changes/centralized-ai-context/specs/community-explainer-docs/spec.md @@ -7,24 +7,24 @@ O projeto SHALL incluir um arquivo `AI_CONTEXT.md` em cada pasta que contém con - **WHEN** um desenvolvedor abre `.claude/` ou `.github/` no GitHub - **THEN** encontra `AI_CONTEXT.md` explicando o padrão centralizado com diagrama Mermaid -#### Scenario: mcp/README.md explica o propósito da pasta +#### Scenario: mcp-local/README.md explica o propósito da pasta - **WHEN** um desenvolvedor acessa `mcp/` no repositório - **THEN** encontra `README.md` explicando que é a fonte central de contexto AI, não um MCP Server em execução ### Requirement: Diagrama Mermaid ilustra o fluxo de contexto entre ferramentas e fonte central -O documento explicativo SHALL incluir um diagrama Mermaid mostrando como cada ferramenta lê seu arquivo nativo e como esse arquivo referencia `mcp/context/`. +O documento explicativo SHALL incluir um diagrama Mermaid mostrando como cada ferramenta lê seu arquivo nativo e como esse arquivo referencia `mcp-local/context/`. #### Scenario: Diagrama é renderizado corretamente no GitHub -- **WHEN** o arquivo `AI_CONTEXT.md` ou `mcp/README.md` é visualizado no GitHub -- **THEN** o diagrama Mermaid renderiza mostrando o fluxo: ferramentas → arquivos nativos → mcp/context/ +- **WHEN** o arquivo `AI_CONTEXT.md` ou `mcp-local/README.md` é visualizado no GitHub +- **THEN** o diagrama Mermaid renderiza mostrando o fluxo: ferramentas → arquivos nativos → mcp-local/context/ #### Scenario: Diagrama comunica a ausência de duplicação - **WHEN** um desenvolvedor lê o diagrama - **THEN** fica claro que cada ferramenta aponta para a mesma fonte, sem cópias do conteúdo ### Requirement: Explicativo menciona como replicar o padrão em outros repositórios -O documento `mcp/README.md` SHALL incluir uma nota indicando que a estrutura pode ser copiada para outros repositórios públicos como ponto de partida. +O documento `mcp-local/README.md` SHALL incluir uma nota indicando que a estrutura pode ser copiada para outros repositórios públicos como ponto de partida. #### Scenario: Comunidade consegue adotar o padrão no próprio projeto -- **WHEN** um desenvolvedor externo lê `mcp/README.md` +- **WHEN** um desenvolvedor externo lê `mcp-local/README.md` - **THEN** encontra instrução clara de como replicar a estrutura em outro repositório diff --git a/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md b/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md index e640de1..1f007e2 100644 --- a/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md +++ b/openspec/changes/centralized-ai-context/specs/per-tool-native-files/spec.md @@ -1,7 +1,7 @@ ## ADDED Requirements ### Requirement: Cada ferramenta tem arquivo nativo com regras essenciais inline -O projeto SHALL manter um arquivo nativo para cada ferramenta de IA suportada contendo as regras arquiteturais mais críticas diretamente no arquivo (inline), garantindo funcionamento mesmo sem leitura de `mcp/context/`. +O projeto SHALL manter um arquivo nativo para cada ferramenta de IA suportada contendo as regras arquiteturais mais críticas diretamente no arquivo (inline), garantindo funcionamento mesmo sem leitura de `mcp-local/context/`. #### Scenario: Copilot funciona sem configuração adicional - **WHEN** um desenvolvedor abre o projeto com GitHub Copilot @@ -13,17 +13,17 @@ O projeto SHALL manter um arquivo nativo para cada ferramenta de IA suportada co #### Scenario: Claude Code funciona sem configuração adicional - **WHEN** um desenvolvedor abre o projeto com Claude Code -- **THEN** `CLAUDE.md` é lido automaticamente com as regras críticas e referência a `mcp/context/` +- **THEN** `CLAUDE.md` é lido automaticamente com as regras críticas e referência a `mcp-local/context/` -### Requirement: Arquivos nativos referenciam mcp/context/ para detalhes completos -Todo arquivo nativo SHALL incluir ao final uma instrução explícita para ler `mcp/context/` para regras completas e skills disponíveis. +### Requirement: Arquivos nativos referenciam mcp-local/context/ para detalhes completos +Todo arquivo nativo SHALL incluir ao final uma instrução explícita para ler `mcp-local/context/` para regras completas e skills disponíveis. #### Scenario: Modelo com suporte a leitura de contexto externo carrega detalhes - **WHEN** um modelo capaz de ler arquivos externos processa o arquivo nativo -- **THEN** encontra a instrução `For complete rules and skills, read mcp/context/` e carrega o contexto completo +- **THEN** encontra a instrução `For complete rules and skills, read mcp-local/context/` e carrega o contexto completo #### Scenario: Modelo sem suporte a leitura externa ainda funciona -- **WHEN** um modelo ignora a referência a `mcp/context/` +- **WHEN** um modelo ignora a referência a `mcp-local/context/` - **THEN** ainda possui as regras críticas inline e pode trabalhar com o projeto corretamente ### Requirement: Ferramentas suportadas cobrem Claude, Copilot, Cursor, Gemini e Codex diff --git a/openspec/changes/centralized-ai-context/tasks.md b/openspec/changes/centralized-ai-context/tasks.md index 02e1d32..d062d22 100644 --- a/openspec/changes/centralized-ai-context/tasks.md +++ b/openspec/changes/centralized-ai-context/tasks.md @@ -1,30 +1,30 @@ -## 1. Criar estrutura mcp/context/ +## 1. Criar estrutura mcp-local/context/ -- [x] 1.1 Criar pasta `mcp/context/` e `mcp/context/skills/` na raiz do projeto -- [x] 1.2 Criar `mcp/context/rules.md` com as regras arquiteturais do `CLAUDE.md` (seção "Regras arquiteturais — nunca violar" e "Convenções de código") -- [x] 1.3 Criar `mcp/context/module-graph.md` documentando explicitamente as dependências entre módulos (craftd-core ← compose/xml/ios/flutter, sem dependências cruzadas entre plataformas) -- [x] 1.4 Criar `mcp/context/android.md` com conteúdo de `.claude/instructions/android-patterns.md` -- [x] 1.5 Criar `mcp/context/ios.md` com conteúdo de `.claude/instructions/ios-patterns.md` -- [x] 1.6 Criar `mcp/context/flutter.md` com conteúdo de `.claude/instructions/flutter-patterns.md` +- [x] 1.1 Criar pasta `mcp-local/context/` e `mcp-local/context/skills/` na raiz do projeto +- [x] 1.2 Criar `mcp-local/context/rules.md` com as regras arquiteturais do `CLAUDE.md` (seção "Regras arquiteturais — nunca violar" e "Convenções de código") +- [x] 1.3 Criar `mcp-local/context/module-graph.md` documentando explicitamente as dependências entre módulos (craftd-core ← compose/xml/ios/flutter, sem dependências cruzadas entre plataformas) +- [x] 1.4 Criar `mcp-local/context/android.md` com conteúdo de `.claude/instructions/android-patterns.md` +- [x] 1.5 Criar `mcp-local/context/ios.md` com conteúdo de `.claude/instructions/ios-patterns.md` +- [x] 1.6 Criar `mcp-local/context/flutter.md` com conteúdo de `.claude/instructions/flutter-patterns.md` -## 2. Migrar skills para mcp/context/skills/ +## 2. Migrar skills para mcp-local/context/skills/ -- [x] 2.1 Criar `mcp/context/skills/new-component.md` com frontmatter (name, description, trigger) e guia de criação de componente CraftD -- [x] 2.2 Criar `mcp/context/skills/review-pr.md` com frontmatter e checklist de revisão de PR (baseado na seção "Review de PRs" do CLAUDE.md) -- [x] 2.3 Criar `mcp/context/skills/android-testing.md` com frontmatter e conteúdo de `.claude/skills/android-testing/` -- [x] 2.4 Criar `mcp/context/skills/compose-ui.md` com frontmatter e conteúdo de `.claude/skills/compose-ui/` -- [x] 2.5 Criar `mcp/context/skills/run-build.md` com frontmatter e instruções para rodar o build (`./gradlew build` no módulo afetado) +- [x] 2.1 Criar `mcp-local/context/skills/new-component.md` com frontmatter (name, description, trigger) e guia de criação de componente CraftD +- [x] 2.2 Criar `mcp-local/context/skills/review-pr.md` com frontmatter e checklist de revisão de PR (baseado na seção "Review de PRs" do CLAUDE.md) +- [x] 2.3 Criar `mcp-local/context/skills/android-testing.md` com frontmatter e conteúdo de `.claude/skills/android-testing/` +- [x] 2.4 Criar `mcp-local/context/skills/compose-ui.md` com frontmatter e conteúdo de `.claude/skills/compose-ui/` +- [x] 2.5 Criar `mcp-local/context/skills/run-build.md` com frontmatter e instruções para rodar o build (`./gradlew build` no módulo afetado) ## 3. Criar arquivos nativos por ferramenta -- [x] 3.1 Criar `.github/copilot-instructions.md` com regras críticas inline (arquitetura, nomenclatura, proibições) + referência a `mcp/context/` -- [x] 3.2 Criar `.cursorrules` com regras críticas inline + referência a `mcp/context/` -- [x] 3.3 Criar `.gemini/context.md` com regras críticas inline + referência a `mcp/context/` -- [x] 3.4 Criar `AGENTS.md` (Codex/OpenAI) com regras críticas inline + referência a `mcp/context/` -- [x] 3.5 Atualizar `CLAUDE.md` para referenciar `mcp/context/` em vez de `.claude/instructions/` nos pontos de plataforma +- [x] 3.1 Criar `.github/copilot-instructions.md` com regras críticas inline (arquitetura, nomenclatura, proibições) + referência a `mcp-local/context/` +- [x] 3.2 Criar `.cursorrules` com regras críticas inline + referência a `mcp-local/context/` +- [x] 3.3 Criar `.gemini/context.md` com regras críticas inline + referência a `mcp-local/context/` +- [x] 3.4 Criar `AGENTS.md` (Codex/OpenAI) com regras críticas inline + referência a `mcp-local/context/` +- [x] 3.5 Atualizar `CLAUDE.md` para referenciar `mcp-local/context/` em vez de `.claude/instructions/` nos pontos de plataforma ## 4. Criar documentação explicativa para a comunidade -- [x] 4.1 Criar `mcp/README.md` em inglês explicando o propósito da pasta, com diagrama Mermaid mostrando o fluxo ferramenta → arquivo nativo → mcp/context/ e nota sobre como replicar em outros repositórios -- [x] 4.2 Criar `.claude/AI_CONTEXT.md` em inglês explicando que `.claude/` é específico do Claude Code e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid -- [x] 4.3 Criar `.github/AI_CONTEXT.md` em inglês explicando que `copilot-instructions.md` é o arquivo nativo do Copilot e que o contexto completo vive em `mcp/context/`, com diagrama Mermaid +- [x] 4.1 Criar `mcp-local/README.md` em inglês explicando o propósito da pasta, com diagrama Mermaid mostrando o fluxo ferramenta → arquivo nativo → mcp-local/context/ e nota sobre como replicar em outros repositórios +- [x] 4.2 Criar `.claude/AI_CONTEXT.md` em inglês explicando que `.claude/` é específico do Claude Code e que o contexto completo vive em `mcp-local/context/`, com diagrama Mermaid +- [x] 4.3 Criar `.github/AI_CONTEXT.md` em inglês explicando que `copilot-instructions.md` é o arquivo nativo do Copilot e que o contexto completo vive em `mcp-local/context/`, com diagrama Mermaid From 13ff55f3222e4f28e12dc95f1c0a529aebb3f7c9 Mon Sep 17 00:00:00 2001 From: Rods Date: Fri, 24 Apr 2026 13:33:06 -0300 Subject: [PATCH 4/4] refactor: unify AI context into mcp-local/ single source of truth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Flatten mcp-local/context/ → mcp-local/ (remove /context/ layer) - Move platform files into mcp-local/instructions/ - Move architectural rules + conventions into mcp-local/skills/architecture.md - Move all skills into mcp-local/skills/ (android-gradle-logic, android-testing, compose-ui) - Create mcp-local/init.md as shared initializer with session token verification - Slim CLAUDE.md, .gemini/context.md, .github/copilot-instructions.md to identical thin pointers - Replace scattered AI_CONTEXT.md files with single doc_ai_context.md at root - Delete .claude/instructions/ and duplicate CraftD-specific skills from .claude/skills/ Co-Authored-By: Claude Sonnet 4.6 --- .claude/AI_CONTEXT.md | 44 ---- .claude/instructions/android-patterns.md | 88 -------- .claude/instructions/flutter-patterns.md | 50 ----- .claude/instructions/ios-patterns.md | 44 ---- .claude/skills/android-testing/SKILL.md | 64 ------ .claude/skills/compose-ui/SKILL.md | 115 ---------- .gemini/context.md | 42 +--- .github/AI_CONTEXT.md | 43 ---- .github/copilot-instructions.md | 42 +--- CLAUDE.md | 200 +----------------- doc_ai_context.md | 52 +++++ mcp-local/init.md | 167 +++++++++++++++ .../{context => instructions}/android.md | 0 .../{context => instructions}/flutter.md | 0 mcp-local/{context => instructions}/ios.md | 0 mcp-local/{context => }/module-graph.md | 0 .../skills/android-gradle-logic.md | 0 .../{context => }/skills/android-testing.md | 0 .../rules.md => skills/architecture.md} | 40 ++-- mcp-local/{context => }/skills/compose-ui.md | 0 .../{context => }/skills/new-component.md | 0 mcp-local/{context => }/skills/review-pr.md | 0 mcp-local/{context => }/skills/run-build.md | 0 23 files changed, 262 insertions(+), 729 deletions(-) delete mode 100644 .claude/AI_CONTEXT.md delete mode 100644 .claude/instructions/android-patterns.md delete mode 100644 .claude/instructions/flutter-patterns.md delete mode 100644 .claude/instructions/ios-patterns.md delete mode 100644 .claude/skills/android-testing/SKILL.md delete mode 100644 .claude/skills/compose-ui/SKILL.md delete mode 100644 .github/AI_CONTEXT.md create mode 100644 doc_ai_context.md create mode 100644 mcp-local/init.md rename mcp-local/{context => instructions}/android.md (100%) rename mcp-local/{context => instructions}/flutter.md (100%) rename mcp-local/{context => instructions}/ios.md (100%) rename mcp-local/{context => }/module-graph.md (100%) rename .claude/skills/android-gradle-logic/SKILL.md => mcp-local/skills/android-gradle-logic.md (100%) rename mcp-local/{context => }/skills/android-testing.md (100%) rename mcp-local/{context/rules.md => skills/architecture.md} (74%) rename mcp-local/{context => }/skills/compose-ui.md (100%) rename mcp-local/{context => }/skills/new-component.md (100%) rename mcp-local/{context => }/skills/review-pr.md (100%) rename mcp-local/{context => }/skills/run-build.md (100%) diff --git a/.claude/AI_CONTEXT.md b/.claude/AI_CONTEXT.md deleted file mode 100644 index caadba4..0000000 --- a/.claude/AI_CONTEXT.md +++ /dev/null @@ -1,44 +0,0 @@ -# AI Context Structure — Claude Code - -This folder (`.claude/`) contains Claude Code-specific configuration: skills, commands, scripts, and settings. - -The **complete AI context** (architectural rules, platform patterns, available skills) lives in a single central location to avoid duplication across tools: - -``` -📁 mcp-local/context/ ← single source of truth for all AI tools -``` - -## Why This Structure? - -CraftD uses multiple AI coding tools (Claude Code, GitHub Copilot, Cursor, Gemini, Codex). Instead of maintaining separate context files for each tool — which would quickly diverge — all tools point to the same source. - -```mermaid -graph LR - CLAUDE["Claude Code
CLAUDE.md"] - COPILOT["Copilot
.github/copilot-instructions.md"] - CURSOR["Cursor
.cursorrules"] - OTHER["Other tools..."] - - MCP["📁 mcp-local/context/
Single Source of Truth"] - - CLAUDE -->|references| MCP - COPILOT -->|references| MCP - CURSOR -->|references| MCP - OTHER -->|references| MCP -``` - -## What Lives Here vs. in mcp-local/context/ - -| Here (`.claude/`) | In `mcp-local/context/` | -|---|---| -| Claude Code skills (structured YAML format) | Skills as readable Markdown (any tool) | -| Claude Code commands | Architectural rules | -| Claude Code hooks/settings | Platform patterns (Android, iOS, Flutter) | -| Claude-specific scripts | Module graph | - -## Quick Reference - -- Full rules → `mcp-local/context/rules.md` -- Module dependencies → `mcp-local/context/module-graph.md` -- Platform patterns → `mcp-local/context/android.md`, `ios.md`, `flutter.md` -- Skills (any tool) → `mcp-local/context/skills/` diff --git a/.claude/instructions/android-patterns.md b/.claude/instructions/android-patterns.md deleted file mode 100644 index 9f4cb72..0000000 --- a/.claude/instructions/android-patterns.md +++ /dev/null @@ -1,88 +0,0 @@ -# Android / KMP — Instruções de plataforma - -> Leia este arquivo ao iniciar qualquer task Android/KMP. Ignore `ios/` e `flutter/`. - ---- - -## Abstrações principais - -| Classe | Papel | -|---|---| -| `CraftDBuilder` | Interface base para criar componentes | -| `CraftDBuilderManager` | Registra e resolve builders pelo `key` | -| `CraftDynamic` | Composable principal que renderiza o SDUI | -| `SimpleProperties` | Modelo base de dados (`key` + `value` JSON) | -| `ActionProperties` | Dados de ação (deeplink + analytics) | -| `CraftDComponentKey` | Enum com as chaves de componentes built-in | -| `CraftDViewListener` | Callback de ações para o consumidor | - ---- - -## Estrutura de pastas - -### craftd-core (modelos e abstrações) -``` -commonMain/ - data/ - model/ - base/ → SimpleProperties, SimplePropertiesResponse - action/ → ActionProperties, AnalyticsProperties - [name]/ → [Name]Properties.kt para cada componente - domain/ → enums e sealed classes (CraftDAlign, CraftDTextStyle) - presentation/ → CraftDViewListener, CraftDComponentKey - extensions/ → funções de extensão -``` - -### craftd-compose (implementação Compose/KMP) -``` -commonMain/ - builder/ → CraftDBuilder.kt (interface), CraftDBuilderManager.kt - ui/ - [name]/ - CraftD[Name].kt → o @Composable do componente - CraftD[Name]Builder.kt → implementa CraftDBuilder - extensions/ → funções utilitárias Compose -``` - -### craftd-xml (implementação View System) -``` -src/main/kotlin/.../ - ui/ - [name]/ - CraftD[Name]Component.kt → custom View - CraftD[Name]ComponentRender.kt → implementa CraftDViewRenderer - builder/ - CraftDBuilderManager.kt → getBuilderRenders() -``` - -### Padrão por novo componente (exemplo: CraftDFoo) - -1. `craftd-core/commonMain/data/model/foo/FooProperties.kt` — data class do modelo -2. `craftd-compose/commonMain/ui/foo/CraftDFoo.kt` — composable -3. `craftd-compose/commonMain/ui/foo/CraftDFooBuilder.kt` — builder -4. `craftd-xml/src/main/kotlin/.../ui/foo/CraftDFooComponent.kt` — custom View -5. `craftd-xml/src/main/kotlin/.../ui/foo/CraftDFooComponentRender.kt` — render -6. Registrar no `CraftDBuilderManager` de cada módulo -7. Adicionar ao `app-sample-android` (Compose + XML) e ao `dynamic.json` - ---- - -## Princípios Compose - -- Composables **stateless** — estado vem do caller (state hoisting) -- Todo componente expõe `modifier: Modifier = Modifier` -- Sem valores hardcoded de cor ou tipografia — usar `MaterialTheme.colorScheme` e `MaterialTheme.typography` -- Todo componente interativo: touch target mínimo de 48x48dp - -## Build - -- Dependências sempre via `libs.versions.toml` — nunca versão hardcoded no `build.gradle.kts` -- Configuração compartilhada entre módulos vai em convention plugin no `build-logic/` -- Rodar `./gradlew build` em `android_kmp/` após cada task antes de marcar `[x]` - -## Testes - -- JUnit4 + MockK para testes Android -- `kotlin("test")` + `kotlinx.serialization` + `compose.runtime` para commonTest -- Nomenclatura em backtick: `` `given X when Y then Z` `` -- Path espelha o source: `src/commonTest/kotlin/...` diff --git a/.claude/instructions/flutter-patterns.md b/.claude/instructions/flutter-patterns.md deleted file mode 100644 index ff654b4..0000000 --- a/.claude/instructions/flutter-patterns.md +++ /dev/null @@ -1,50 +0,0 @@ -# Flutter — Instruções de plataforma - -> Leia este arquivo ao iniciar qualquer task Flutter. Ignore `android_kmp/` e `ios/`. - ---- - -## Abstrações principais - -| Classe | Papel | -|---|---| -| `CraftDynamic` | Widget principal que renderiza o SDUI | -| `CraftDViewListener` | Callback de ações para o consumidor | -| `SimpleProperties` | Modelo base de dados | -| `ActionProperties` | Dados de ação (deeplink + analytics) | -| `CraftDAlign` | Alinhamento de componentes | - ---- - -## Estrutura de pastas - -``` -flutter/craftd_widget/ - lib/ - src/ - builder/ → CraftDBuilder (abstract), CraftDBuilderManager - ui/ - [name]/ - craftd_[name].dart → Widget do componente - craftd_[name]_builder.dart → implementa CraftDBuilder - model/ - [name]_properties.dart → classe do modelo -``` - -## Padrão por novo componente (exemplo: CraftDFoo) - -1. `lib/src/model/foo_properties.dart` — classe do modelo -2. `lib/src/ui/foo/craftd_foo.dart` — Widget -3. `lib/src/ui/foo/craftd_foo_builder.dart` — implementa CraftDBuilder -4. Registrar no `CraftDBuilderManager` -5. Adicionar ao sample app Flutter - -## Convenções - -- Nomes de arquivos em `snake_case` -- Classes em `PascalCase` com prefixo `CraftD` -- Dependências externas (ex: cached_network_image) injetadas via construtor, nunca acopladas no builder - -## Referência - -Consultar `CraftDButton` / `CraftDButtonBuilder` como padrão antes de criar algo novo. diff --git a/.claude/instructions/ios-patterns.md b/.claude/instructions/ios-patterns.md deleted file mode 100644 index edbc3f5..0000000 --- a/.claude/instructions/ios-patterns.md +++ /dev/null @@ -1,44 +0,0 @@ -# iOS / SwiftUI — Instruções de plataforma - -> Leia este arquivo ao iniciar qualquer task iOS. Ignore `android_kmp/` e `flutter/`. - ---- - -## Abstrações principais - -| Classe | Papel | -|---|---| -| `CraftDBuilder` | Protocol base para criar componentes | -| `CraftDBuilderManager` | Registra e resolve builders pelo `key` | -| `CraftDynamic` | View principal que renderiza o SDUI | -| `SimpleProperties` | Modelo base de dados | -| `ActionProperties` | Dados de ação (deeplink + analytics) | -| `CraftDViewListener` | Callback de ações para o consumidor | - ---- - -## Estrutura de pastas - -``` -ios/craftd-swiftui/ - Sources/CraftD/ - builder/ → CraftDBuilder.swift (protocol), CraftDBuilderManager.swift - ui/ - [name]/ - CraftD[Name].swift → SwiftUI View do componente - CraftD[Name]Builder.swift → implementa CraftDBuilder - model/ - [Name]Properties.swift → struct do modelo -``` - -## Padrão por novo componente (exemplo: CraftDFoo) - -1. `Sources/CraftD/model/FooProperties.swift` — struct do modelo -2. `Sources/CraftD/ui/foo/CraftDFoo.swift` — SwiftUI View -3. `Sources/CraftD/ui/foo/CraftDFooBuilder.swift` — implementa CraftDBuilder -4. Registrar no `CraftDBuilderManager` -5. Adicionar ao sample app iOS - -## Referência - -Consultar `CraftDButton` / `CraftDButtonBuilder` como padrão antes de criar algo novo. \ No newline at end of file diff --git a/.claude/skills/android-testing/SKILL.md b/.claude/skills/android-testing/SKILL.md deleted file mode 100644 index 2c83d67..0000000 --- a/.claude/skills/android-testing/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: android-testing -description: Testing strategies for Android/KMP. Use when creating or reviewing tests no CraftD. ---- - -# Android Testing Strategies - -## Níveis de teste - -| Nível | Foco | Ferramentas | -|---|---|---| -| Unit | Lógica isolada (ViewModels, Repositories, Builders) | JUnit4, MockK | -| Integration | Interação entre componentes | AndroidX Test | -| Screenshot | Verificação visual de UI | Roborazzi (roda na JVM, sem emulador) | - -## Padrão no CraftD - -- Framework: **JUnit4 + MockK** -- Nomenclatura: backtick notation `` `given X when Y then Z` `` -- Path: `src/test/java/...` espelhando o pacote do arquivo original -- Todo novo componente deve ter teste unitário cobrindo: construção, defaults, `copy()`, `equals/hashCode`, e o `craft()` do builder - -## Testes gerados por IA (CI / Claude API) - -O workflow de CI pode gerar testes automaticamente via Claude API. Esses testes **frequentemente falham ao compilar ou rodar** e precisam de revisão. Checklist de problemas recorrentes: - -### Erros de compilação - -| Problema | Sintoma | Fix | -|---|---|---| -| Code fence markdown | Arquivo começa com ` ```kotlin ` | Remover ` ```kotlin ` e ` ``` ` do início/fim | -| MockK: `throws()` solto | `mockk { throws(...) }` | Usar `mockk(); every { mock.prop } throws ...` | -| `apply { val = }` em data class | `copy().apply { valProp = ... }` | `val` não é mutável — usar `copy(prop = ...)` | -| Enum inexistente | `CraftDAlign.START`, `CraftDTextStyle.REGULAR` | Verificar o enum real e substituir | -| AbstractMap entries incompat. | Override de `entries` com tipo errado | Remover o objeto anônimo se for código morto | -| `assertNotEquals` para ref. | `assertNotEquals(a as Any, b as Any)` quando `a == b` | Usar `assertTrue(a !== b)` | -| Type inference: `assertNotEquals` | Dois tipos diferentes sem parâmetro explícito | `assertNotEquals(a, b)` | - -### Erros de dependências em `build.gradle.kts` - -Para o sourceSet `androidUnitTest` (path `src/test/java/`), garantir: -```kotlin -androidUnitTest.dependencies { - implementation(libs.junit) - implementation(libs.mockk) - implementation(kotlin("test-junit")) -} -``` - -### Erros de runtime - -| Problema | Sintoma | Fix | -|---|---|---| -| Anotações `@Stable`/`@Immutable`/`@Serializable` | `assertTrue(isStable)` falha em runtime | Retenção BINARY — não visível via reflection. Remover o teste | -| Mock de extension function | `MockKException: Missing mocked calls` em `every { stream.bufferedReader() }` | Extension functions Kotlin precisam de `mockkStatic`. Alternativa: usar `ByteArrayInputStream` | -| Jackson `convertValue` com String | `ClassCastException` ao tentar `jsonString.convertToVO()` | `convertValue` não parseia JSON string — remover o teste ou usar `readValue` | -| Jackson `convertValue` com List genérica | Retorna `List` em vez de `List` | Genéricos apagados em runtime — remover o teste | - -## Screenshot tests (Roborazzi) - -```bash -./gradlew recordRoborazziDebug # grava baseline -./gradlew verifyRoborazziDebug # verifica regressão -``` diff --git a/.claude/skills/compose-ui/SKILL.md b/.claude/skills/compose-ui/SKILL.md deleted file mode 100644 index abdccaf..0000000 --- a/.claude/skills/compose-ui/SKILL.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -name: compose-ui -description: Boas práticas para Composables no CraftD. Use ao escrever ou revisar componentes Compose. ---- - -# Criando um componente Compose no CraftD - -## Checklist obrigatório - -- [ ] `XxxProperties` definido em `craftd-core/commonMain` -- [ ] `CraftDComponentKey.XXX_COMPONENT` adicionado ao enum em `craftd-core` -- [ ] Composable `CraftDXxx` criado em `craftd-compose/commonMain` -- [ ] `CraftDXxxBuilder` criado e implementa `CraftDBuilder` -- [ ] Builder registrado no `CraftDBuilderManager` -- [ ] `onAction`/fallback coberto (mesmo que seja no-op) -- [ ] Teste unitário em `commonTest` -- [ ] Documentação em `docs/how-to-use/compose.md` - ---- - -## 1. Composable — assinatura padrão - -```kotlin -@Composable -fun CraftDXxx( - properties: XxxProperties, - onAction: () -> Unit = {}, - modifier: Modifier = Modifier, -) { ... } -``` - -- `modifier` sempre como último parâmetro opcional, aplicado no elemento raiz -- `onAction` com default `{}` — nunca omitir o parâmetro -- Composable é **stateless**: estado vem do caller, nunca interno - -### `onAction` condicional (quando actionProperties pode ser null) - -```kotlin -val clickableModifier = if (properties.actionProperties != null) { - modifier.clickable { onAction() } -} else modifier -``` - ---- - -## 2. Builder — estrutura padrão - -```kotlin -class CraftDXxxBuilder( - override val key: String = CraftDComponentKey.XXX_COMPONENT.key -) : CraftDBuilder { - @Composable - override fun craft(model: SimpleProperties, listener: CraftDViewListener) { - val properties = model.value.convertToElement() - properties?.let { - CraftDXxx( - properties = it, - onAction = { it.actionProperties?.let { action -> listener.invoke(action) } }, - ) - } - } -} -``` - -### Builder com dependência externa (ex: imageLoader) - -Quando o componente precisa de lib de terceiro (Coil, etc.), recebe via construtor — nunca acopla diretamente: - -```kotlin -class CraftDXxxBuilder( - private val imageLoader: @Composable (url: String, contentDescription: String?, modifier: Modifier) -> Unit, - override val key: String = CraftDComponentKey.XXX_COMPONENT.key, -) : CraftDBuilder { ... } -``` - ---- - -## 3. Registro no CraftDBuilderManager - -```kotlin -// Registro interno (sem dependência externa) -CraftDComponentKey.XXX_COMPONENT.key to CraftDXxxBuilder() - -// Builder com dependência externa — consumidor injeta via add() -craftDBuilderManager.add( - CraftDXxxBuilder(imageLoader = { url, desc, mod -> /* Coil, etc. */ }) -) -``` - ---- - -## 4. Theming - -- Usar `MaterialTheme.colorScheme` e `MaterialTheme.typography` -- Nunca valores hardcoded de cor, tamanho de fonte ou espaçamento - ---- - -## 5. Performance - -- `remember` para computações caras entre recomposições -- `derivedStateOf` quando estado muda frequentemente mas UI atualiza em threshold -- Lambdas estáveis para evitar recomposição desnecessária de filhos - ---- - -## 6. Preview - -```kotlin -@Preview(showBackground = true) -@Composable -private fun CraftDXxxPreview() { - CraftDXxx(properties = XxxProperties(...)) {} -} -``` diff --git a/.gemini/context.md b/.gemini/context.md index 854ec5c..7501063 100644 --- a/.gemini/context.md +++ b/.gemini/context.md @@ -1,36 +1,14 @@ -# CraftD — Gemini Context +# CraftD — Gemini -CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android XML, iOS SwiftUI, Flutter). +> Start every session by reading `mcp-local/init.md`. -## Critical Rules +## Context Files -1. Platform modules never depend on each other — `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. -2. Every new component implements the platform abstraction — `CraftDBuilder` on Android/KMP, equivalent protocols on iOS and Flutter. -3. `onAction`/fallback always covered, even as a no-op. -4. `commonMain` must have zero platform dependencies — use `expect/actual`. -5. Every new builder must be registered in `CraftDBuilderManager`. -6. External libraries injected via constructor — never coupled directly in the builder. -7. Class names consistent across all platforms (`CraftDImage` everywhere). -8. `CraftD` prefix on all lib classes and files. -9. No hardcoded colors or typography — use `MaterialTheme`. -10. Tests: JUnit4 + MockK, backtick naming `` `given X when Y then Z` ``. - -## What NOT to Do - -- Do not create components outside `CraftDBuilder` abstraction -- Do not add platform imports in `commonMain` -- Do not create cross-platform module dependencies -- Do not commit `local.properties` or credentials - -## Complete Context and Skills - -Read these files for full rules, platform patterns, and available skills: - -``` -mcp-local/context/rules.md ← architectural rules -mcp-local/context/module-graph.md ← module dependencies -mcp-local/context/android.md ← Android/KMP patterns -mcp-local/context/ios.md ← iOS patterns -mcp-local/context/flutter.md ← Flutter patterns -mcp-local/context/skills/ ← skills: new-component, review-pr, run-build, android-testing, compose-ui ``` +mcp-local/init.md ← initializer: project overview, tasks, agents, CI, review +mcp-local/module-graph.md ← module dependency graph +mcp-local/instructions/android.md ← Android/KMP patterns +mcp-local/instructions/ios.md ← iOS/SwiftUI patterns +mcp-local/instructions/flutter.md ← Flutter patterns +mcp-local/skills/ ← skills: architecture, compose-ui, android-testing, android-gradle-logic, ... +``` \ No newline at end of file diff --git a/.github/AI_CONTEXT.md b/.github/AI_CONTEXT.md deleted file mode 100644 index 58e6ba0..0000000 --- a/.github/AI_CONTEXT.md +++ /dev/null @@ -1,43 +0,0 @@ -# AI Context Structure — GitHub Copilot - -This folder (`.github/`) contains GitHub-specific configuration: workflows, issue templates, and the Copilot native instructions file. - -The **complete AI context** (architectural rules, platform patterns, available skills) lives in a single central location to avoid duplication across tools: - -``` -📁 mcp-local/context/ ← single source of truth for all AI tools -``` - -## Why This Structure? - -CraftD uses multiple AI coding tools (Claude Code, GitHub Copilot, Cursor, Gemini, Codex). Instead of maintaining separate context files for each tool — which would quickly diverge — all tools point to the same source. - -```mermaid -graph LR - COPILOT["GitHub Copilot
copilot-instructions.md"] - CLAUDE["Claude Code
CLAUDE.md"] - CURSOR["Cursor
.cursorrules"] - OTHER["Other tools..."] - - MCP["📁 mcp-local/context/
Single Source of Truth"] - - COPILOT -->|references| MCP - CLAUDE -->|references| MCP - CURSOR -->|references| MCP - OTHER -->|references| MCP -``` - -## Files in This Folder - -| File | Purpose | -|---|---| -| `copilot-instructions.md` | Copilot native context — critical rules inline + reference to `mcp-local/context/` | -| `workflows/` | CI/CD automation (build, test, auto-generate tests) | -| `AI_CONTEXT.md` | This file — explains the AI context structure for the community | - -## Quick Reference - -- Full rules → `mcp-local/context/rules.md` -- Module dependencies → `mcp-local/context/module-graph.md` -- Platform patterns → `mcp-local/context/android.md`, `ios.md`, `flutter.md` -- Skills (any tool) → `mcp-local/context/skills/` diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0164629..051e28e 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,36 +1,14 @@ -# CraftD — GitHub Copilot Instructions +# CraftD — GitHub Copilot -CraftD is a **Server Driven UI** multiplatform library (Android Compose, Android XML, iOS SwiftUI, Flutter). +> Start every session by reading `mcp-local/init.md`. -## Critical Rules +## Context Files -1. **Platform modules never depend on each other.** `craftd-compose`, `craftd-xml`, `ios/`, and `flutter/` depend only on `craftd-core`. Never on each other. -2. **Every new component implements the platform abstraction.** On Android/KMP: `CraftDBuilder`. On iOS: Swift protocol equivalent. On Flutter: Dart abstract class equivalent. -3. **`onAction`/fallback always covered** — even as a no-op. -4. **`commonMain` has no platform dependencies** — use `expect/actual` for platform-specific behavior. -5. **New builders must be registered in `CraftDBuilderManager`** of the respective platform. Never create a builder without registering it. -6. **External libraries (Coil, Glide, etc.) must be injected via constructor** — never coupled directly inside the builder. -7. **Class names are consistent across platforms** — `CraftDImage` on Android = `CraftDImage` on iOS and Flutter. -8. **`CraftD` prefix** on all lib classes and files. -9. **No hardcoded colors or typography** — use `MaterialTheme.colorScheme` / `MaterialTheme.typography`. -10. **Tests:** JUnit4 + MockK, backtick naming `` `given X when Y then Z` ``. - -## What NOT to Do - -- Do not create a component outside `CraftDBuilder` abstraction -- Do not add platform imports in `commonMain` -- Do not create cross-platform module dependencies -- Do not commit `local.properties` or credential files - -## Complete Context - -For full architectural rules, platform patterns, module graph, and available skills, read: - -``` -mcp-local/context/rules.md ← architectural rules and conventions -mcp-local/context/module-graph.md ← module dependencies -mcp-local/context/android.md ← Android/KMP patterns -mcp-local/context/ios.md ← iOS/SwiftUI patterns -mcp-local/context/flutter.md ← Flutter patterns -mcp-local/context/skills/ ← available skills (new-component, review-pr, run-build, ...) ``` +mcp-local/init.md ← initializer: project overview, tasks, agents, CI, review +mcp-local/module-graph.md ← module dependency graph +mcp-local/instructions/android.md ← Android/KMP patterns +mcp-local/instructions/ios.md ← iOS/SwiftUI patterns +mcp-local/instructions/flutter.md ← Flutter patterns +mcp-local/skills/ ← skills: architecture, compose-ui, android-testing, android-gradle-logic, ... +``` \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index ad69afd..a328868 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,194 +1,14 @@ -# CraftD — Claude Instructions +# CraftD — Claude Code -## O que é o projeto +> Start every session by reading `mcp-local/init.md`. If the file was fully read, the session token at the end will be present — confirm it before responding. -CraftD é uma biblioteca de **Server Driven UI** multiplatforma. O servidor decide quais componentes renderizar e como; o cliente (app) apenas executa. Suporta: +## Context Files -- Android Compose (`android_kmp/craftd-compose`) -- Android View System / XML (`android_kmp/craftd-xml`) -- KMP Compose Multiplatform (`android_kmp/craftd-compose` via commonMain) -- iOS SwiftUI (`ios/craftd-swiftui`) -- Flutter (`flutter/craftd_widget`) - ---- - -## Estrutura de módulos - -``` -android_kmp/ - craftd-core/ # modelos e abstrações compartilhadas (KMP) - commonMain/ # código compartilhado entre plataformas - androidMain/ # implementações Android-específicas - craftd-compose/ # implementação Compose / KMP - craftd-xml/ # implementação View System (XML) - app-sample-android/ # app de exemplo Android - app-sample-cmp/ # app de exemplo KMP Compose - build-logic/ # configuração de build compartilhada - -ios/craftd-swiftui/ # biblioteca iOS (Swift Package + CocoaPods) -flutter/craftd_widget/ # biblioteca Flutter (pub.dev) -docs/ # documentação do site (MkDocs) ``` - ---- - -## Regras arquiteturais — nunca violar - -1. **Módulos de plataforma não dependem uns dos outros.** `craftd-compose`, `craftd-xml`, `ios/` e `flutter/` dependem apenas do `craftd-core`. Jamais entre si. - -2. **Todo novo componente implementa a abstração do platform.** No Android/KMP é `CraftDBuilder`. No iOS é o equivalente Swift. No Flutter é o equivalente Dart. Nunca criar componente avulso fora dessa abstração. - -3. **`onAction` / fallback sempre coberto.** Toda implementação de componente deve tratar o callback de ação (`ActionProperties`), mesmo que seja um no-op. - -4. **`commonMain` é sagrado.** Código em `commonMain` não pode ter dependências de plataforma. Se precisar de comportamento diferente por plataforma, usa `expect/actual`. - -5. **Novos componentes seguem o padrão existente.** Consultar `CraftDButtonBuilder` e `CraftDTextBuilder` como referência de implementação antes de criar algo novo. - -6. **Nomes de classes são consistentes entre todas as plataformas.** Ex: se um componente se chama `CraftDImage` no Android, deve se chamar `CraftDImage` em iOS e Flutter também. - -7. **Todo novo componente deve ter teste unitário** (quando possível) e **documentação em `docs/` na seção da respectiva plataforma**. - -8. **Toda mudança que afeta comportamento público da lib** (novo componente, novo parâmetro, breaking change) deve atualizar `docs/how-to-use/` da plataforma correspondente: `compose.md`, `view-system.md`, `swift-ui.md` ou `futter.md`. - -9. **Todo novo builder deve ser registrado no `CraftDBuilderManager`** da respectiva plataforma. No Compose/KMP: `CraftDComponentKey.X.key to CraftDXBuilder()`. No XML: adicionar o render em `getBuilderRenders()`. Nunca criar um builder sem registrá-lo. - -10. **Dependências de bibliotecas externas devem ser abstraídas.** Nunca acoplar diretamente uma lib de terceiro (ex: Coil, Picasso, Glide) dentro do builder. Expor uma interface/função como parâmetro do construtor para que o consumidor injete a implementação. - ---- - -## Contexto por plataforma - -Antes de iniciar qualquer task, identifique a plataforma e leia o arquivo correspondente em `mcp-local/context/`: - -- Android/KMP → `mcp-local/context/android.md` -- iOS → `mcp-local/context/ios.md` -- Flutter → `mcp-local/context/flutter.md` - -Ao gerar um `proposal.md` via `/propose`, detecte a plataforma na descrição do usuário e adicione frontmatter no início do arquivo: - -``` ---- -platform: android # mencionou android / compose / xml / kmp -platform: ios # mencionou ios / swiftui / swift -platform: flutter # mencionou flutter / dart -platform: all # multiplatforma ou não ficou claro ---- -``` - -Ao iniciar `/apply`, leia o campo `platform:` do `proposal.md` da change e carregue o arquivo de instructions correspondente antes de qualquer outra leitura. - ---- - -## Convenções de código - -- **Kotlin:** segue as convenções oficiais do Kotlin. Prefere `data class` para modelos. -- **Nomenclatura de componentes:** prefixo `CraftD` em tudo que é parte da lib (ex: `CraftDButton`, `CraftDButtonBuilder`). -- **Testes:** JUnit4 + MockK. Nomenclatura em backtick: `` `given X when Y then Z` ``. Path espelha o source: `src/test/java/...` -- **Commits:** mensagens em inglês, semânticas (`feat:`, `fix:`, `test:`, `chore:`, `docs:`). - ---- - -## Implementação de tasks - -Ao concluir cada task de um `tasks.md`: -1. Implemente o código da task -2. Rode `./gradlew build` no módulo afetado (`android_kmp/`) -3. Corrija erros de compilação se houver -4. Só então marque `[x]` no `tasks.md` - -Nunca marcar `[x]` antes do build passar. - -### Orquestração com agents para componentes Android/KMP - -Ao aplicar uma change que adiciona um novo componente Android/KMP (detectável pela estrutura das tasks: core → compose/xml → docs/sample), usar agents paralelos com worktrees isoladas seguindo estas rodadas: - -**Rodada 1** — sequencial (core é dependência das demais): -- Agent Core → tasks de `craftd-core` (model, enum, key) - -**Rodada 2** — paralelo (após Rodada 1 mergeada): -- Agent Compose → tasks de `craftd-compose` (composable, builder, registro, testes) -- Agent XML → tasks de `craftd-xml` (render, registro) - -**Rodada 3** — sequencial (após Rodada 2): -- Agent Docs/Sample → tasks de documentação e sample app - -**Rodada 4** — revisor (após Rodada 3): -- Agent Revisor → revisa todo o código produzido seguindo as regras de review do CLAUDE.md. Não faz build — cada agent já validou o seu. - -Cada agent roda em worktree isolada (`isolation: "worktree"`) e valida o build antes de marcar `[x]`. - -### Custo de contexto — diretrizes para agents - -**Escopo de plataforma — ignorar pastas irrelevantes:** -- Tasks Android/KMP → ignorar `ios/` e `flutter/` -- Tasks iOS → ignorar `android_kmp/` e `flutter/` -- Tasks Flutter → ignorar `android_kmp/` e `ios/` - -Nunca ler, listar ou referenciar arquivos fora da plataforma da task em execução. - -**Quando NÃO usar agent (fazer inline):** -- Rodada 3 (Docs/Sample) e Rodada 4 (Revisor) — edições simples, o overhead do agent supera o benefício -- Qualquer task com menos de 10 arquivos a editar e sem necessidade de build isolado - -**Quando usar agent com worktree:** -- Rodadas 1 e 2 — compilação isolada necessária, risco de conflito entre módulos paralelos - -**Como montar o prompt de um agent:** -- Passar os caminhos exatos dos arquivos relevantes -- Incluir o trecho de código de referência (ex: o builder existente que deve ser replicado) -- Nunca escrever "leia o projeto e implemente" — especificar o quê e onde - -**Modelo por tipo de tarefa:** -- Edições mecânicas (JSON, doc, registro simples): usar `model: "haiku"` -- Lógica, compilação e decisões arquiteturais: Sonnet (default) - -Após cada mudança de estado relevante (agent iniciado, concluído ou com erro), exibir tabela de progresso: - -| Agent | Status | Tasks | -|---|---|---| -| Agent Core | ✓ Completo | 1.x | -| Agent Compose | ⟳ Rodando | 2.x | -| Agent XML | ⏳ Aguardando | 3.x | - -Ícones: `⟳` rodando, `✓` completo, `⏳` aguardando, `✗` erro. - -Durante a execução, reportar progresso no formato: - -``` -[Agent Core] ✓ 1.1 IMAGE_COMPONENT adicionado -[Agent Core] ✓ 1.2 CraftDContentScale criado -[Agent Compose] ⟳ 2.2 Criando CraftDImage composable... -[Agent XML] ⟳ 3.1 Criando CraftDImageComponent... -[Agent Compose] ✓ 2.2 CraftDImage composable criado -``` - -Usar `⟳` para em progresso e `✓` para concluído. Reportar a cada task iniciada e concluída. - ---- - -## CI / automação - -- **`pr.yml`** — build e testes, dispara em todo PR -- **`generate-tests.yml`** — gera testes unitários automaticamente via Claude API para `.kt` modificados, abre PR separado. Só roda após `pr.yml` passar. Não roda em PRs de bots. - -## Review de PRs - -Quando um PR for publicado ou quando solicitado, revisar usando `gh pr review` verificando: - -1. **Regras arquiteturais** — componente implementa `CraftDBuilder` (ou equivalente), sem dependência entre módulos de plataforma, `commonMain` sem deps de plataforma -2. **Completude** — builder registrado no `CraftDBuilderManager`, `onAction`/fallback coberto, `ImageProperties` (ou equivalente) no `craftd-core` -3. **Testes** — testes unitários presentes e com nomenclatura correta em backtick -4. **Docs** — `docs/how-to-use/` atualizado para a plataforma afetada -5. **Padrão de código** — prefixo `CraftD`, `Modifier` exposto, sem valores hardcoded de cor/tipografia - -Usar `gh pr review --comment -b ""` para comentários gerais e `gh api` para comentários em linha específicos. - ---- - -## O que não fazer - -- Não criar componente fora da abstração `CraftDBuilder` (ou equivalente de plataforma) -- Não adicionar dependência de plataforma em `commonMain` -- Não criar dependência entre módulos de plataforma (`craftd-compose` → `craftd-xml`, por exemplo) -- Não commitar `local.properties` nem arquivos de credenciais -- Não usar `--no-verify` para burlar hooks de CI +mcp-local/init.md ← initializer: project overview, tasks, agents, CI, review +mcp-local/module-graph.md ← module dependency graph +mcp-local/instructions/android.md ← Android/KMP patterns +mcp-local/instructions/ios.md ← iOS/SwiftUI patterns +mcp-local/instructions/flutter.md ← Flutter patterns +mcp-local/skills/ ← skills: architecture, compose-ui, android-testing, android-gradle-logic, ... +``` \ No newline at end of file diff --git a/doc_ai_context.md b/doc_ai_context.md new file mode 100644 index 0000000..94093f9 --- /dev/null +++ b/doc_ai_context.md @@ -0,0 +1,52 @@ +# AI Context Structure + +CraftD uses multiple AI coding tools (Claude Code, GitHub Copilot, Gemini, Cursor, etc.). Instead of maintaining separate context files for each tool — which would quickly diverge — all tools point to the same source. + +``` +📁 mcp-local/ ← single source of truth for all AI tools +``` + +```mermaid +graph LR + CLAUDE["Claude Code
CLAUDE.md"] + COPILOT["GitHub Copilot
.github/copilot-instructions.md"] + GEMINI["Gemini
.gemini/context.md"] + OTHER["Other tools..."] + + MCP["📁 mcp-local/
Single Source of Truth"] + + CLAUDE -->|references| MCP + COPILOT -->|references| MCP + GEMINI -->|references| MCP + OTHER -->|references| MCP +``` + +## mcp-local/ structure + +``` +mcp-local/ + init.md ← initializer: read this first every session + module-graph.md ← module dependency graph + instructions/ + android.md ← Android/KMP patterns + ios.md ← iOS/SwiftUI patterns + flutter.md ← Flutter patterns + skills/ + architecture.md ← architectural rules and code conventions + compose-ui.md ← Compose component checklist and patterns + android-testing.md ← Android/KMP testing strategies + android-gradle-logic.md ← build-logic and version catalog + new-component.md ← step-by-step for new components + review-pr.md ← PR review checklist + run-build.md ← how to run builds per platform +``` + +## Tool-specific config + +| Location | Tool | Purpose | +|---|---|---| +| `CLAUDE.md` | Claude Code | Entry point → points to `mcp-local/` | +| `.gemini/context.md` | Gemini | Entry point → points to `mcp-local/` | +| `.github/copilot-instructions.md` | GitHub Copilot | Entry point → points to `mcp-local/` | +| `.claude/skills/` | Claude Code | Native skills (openspec-propose, apply, explore, archive) | +| `.github/skills/` | GitHub Copilot | Native skills (openspec-propose, apply, explore, archive) | diff --git a/mcp-local/init.md b/mcp-local/init.md new file mode 100644 index 0000000..3727b36 --- /dev/null +++ b/mcp-local/init.md @@ -0,0 +1,167 @@ +# CraftD — Initializer + +Read this file at the start of every session before doing anything else. + +--- + +## What is CraftD + +CraftD is a **Server Driven UI** multiplatform library. The server decides which components to render and how; the client (app) only executes. Supports: + +- Android Compose (`android_kmp/craftd-compose`) +- Android View System / XML (`android_kmp/craftd-xml`) +- KMP Compose Multiplatform (`android_kmp/craftd-compose` via commonMain) +- iOS SwiftUI (`ios/craftd-swiftui`) +- Flutter (`flutter/craftd_widget`) + +## Module Structure + +``` +android_kmp/ + craftd-core/ # shared models and abstractions (KMP) + commonMain/ # code shared across platforms + androidMain/ # Android-specific implementations + craftd-compose/ # Compose / KMP implementation + craftd-xml/ # View System (XML) implementation + app-sample-android/ # Android sample app + app-sample-cmp/ # KMP Compose sample app + build-logic/ # shared build configuration + +ios/craftd-swiftui/ # iOS library (Swift Package + CocoaPods) +flutter/craftd_widget/ # Flutter library (pub.dev) +docs/ # site documentation (MkDocs) +``` + +Full module dependency graph → `mcp-local/module-graph.md` + +--- + +## Loading Platform Context + +Before starting any task, identify the platform and read the corresponding file: + +- Android/KMP → `mcp-local/instructions/android.md` +- iOS → `mcp-local/instructions/ios.md` +- Flutter → `mcp-local/instructions/flutter.md` + +Ignore folders outside the platform of the current task: +- Android/KMP tasks → ignore `ios/` and `flutter/` +- iOS tasks → ignore `android_kmp/` and `flutter/` +- Flutter tasks → ignore `android_kmp/` and `ios/` + +When generating a `proposal.md` via `/propose`, detect the platform and add frontmatter: + +``` +--- +platform: android # android / compose / xml / kmp mentioned +platform: ios # ios / swiftui / swift mentioned +platform: flutter # flutter / dart mentioned +platform: all # multiplatform or unclear +--- +``` + +When starting `/apply`, read the `platform:` field from the change's `proposal.md` and load the corresponding instructions file before any other read. + +--- + +## Implementing Tasks + +When completing each task from a `tasks.md`: + +1. Implement the task code +2. Run `./gradlew build` in the affected module (`android_kmp/`) +3. Fix any compilation errors +4. Only then mark `[x]` in `tasks.md` + +Never mark `[x]` before the build passes. + +--- + +## Agent Orchestration (Android/KMP components) + +When applying a change that adds a new Android/KMP component (detectable by the task structure: core → compose/xml → docs/sample), use parallel agents with isolated worktrees: + +**Round 1** — sequential (core is a dependency of everything else): +- Agent Core → `craftd-core` tasks (model, enum, key) + +**Round 2** — parallel (after Round 1 is merged): +- Agent Compose → `craftd-compose` tasks (composable, builder, registration, tests) +- Agent XML → `craftd-xml` tasks (render, registration) + +**Round 3** — sequential (after Round 2): +- Agent Docs/Sample → documentation and sample app tasks + +**Round 4** — reviewer (after Round 3): +- Agent Reviewer → reviews all produced code against the rules in `mcp-local/skills/architecture.md`. No build — each agent already validated theirs. + +Each agent runs in an isolated worktree (`isolation: "worktree"`) and validates the build before marking `[x]`. + +### When NOT to use an agent (do inline): +- Rounds 3 and 4 — simple edits, agent overhead outweighs the benefit +- Any task with fewer than 10 files to edit and no need for isolated build + +### When to use an agent with worktree: +- Rounds 1 and 2 — isolated compilation needed, risk of conflict between parallel modules + +### How to write an agent prompt: +- Pass the exact file paths of relevant files +- Include the reference code snippet (e.g., the existing builder to replicate) +- Never write "read the project and implement" — specify what and where + +### Model by task type: +- Mechanical edits (JSON, doc, simple registration): use `model: "haiku"` +- Logic, compilation, and architectural decisions: Sonnet (default) + +### Progress reporting + +After each relevant state change (agent started, completed, or errored), show a progress table: + +| Agent | Status | Tasks | +|---|---|---| +| Agent Core | ✓ Complete | 1.x | +| Agent Compose | ⟳ Running | 2.x | +| Agent XML | ⏳ Waiting | 3.x | + +Icons: `⟳` running, `✓` complete, `⏳` waiting, `✗` error. + +During execution, report progress as: + +``` +[Agent Core] ✓ 1.1 IMAGE_COMPONENT added +[Agent Core] ✓ 1.2 CraftDContentScale created +[Agent Compose] ⟳ 2.2 Creating CraftDImage composable... +[Agent XML] ⟳ 3.1 Creating CraftDImageComponent... +[Agent Compose] ✓ 2.2 CraftDImage composable created +``` + +Report at each task started and completed. + +--- + +## CI / Automation + +- **`pr.yml`** — build and tests, triggers on every PR +- **`generate-tests.yml`** — auto-generates unit tests via Claude API for modified `.kt` files, opens a separate PR. Only runs after `pr.yml` passes. Does not run on bot PRs. + +--- + +## PR Review + +When a PR is published or when requested, review using `gh pr review` checking: + +1. **Architectural rules** — component implements `CraftDBuilder` (or equivalent), no dependency between platform modules, `commonMain` without platform deps +2. **Completeness** — builder registered in `CraftDBuilderManager`, `onAction`/fallback covered, properties model in `craftd-core` +3. **Tests** — unit tests present with correct backtick naming +4. **Docs** — `docs/how-to-use/` updated for the affected platform +5. **Code standard** — `CraftD` prefix, `Modifier` exposed, no hardcoded color/typography values + +Use `gh pr review --comment -b ""` for general comments and `gh api` for inline comments. + +--- + +╔══════════════════════════════════╗ +║ SESSION TOKEN: READY ║ +╚══════════════════════════════════╝ + +You reached the end of init.md. +Reply with the token above before starting any task. diff --git a/mcp-local/context/android.md b/mcp-local/instructions/android.md similarity index 100% rename from mcp-local/context/android.md rename to mcp-local/instructions/android.md diff --git a/mcp-local/context/flutter.md b/mcp-local/instructions/flutter.md similarity index 100% rename from mcp-local/context/flutter.md rename to mcp-local/instructions/flutter.md diff --git a/mcp-local/context/ios.md b/mcp-local/instructions/ios.md similarity index 100% rename from mcp-local/context/ios.md rename to mcp-local/instructions/ios.md diff --git a/mcp-local/context/module-graph.md b/mcp-local/module-graph.md similarity index 100% rename from mcp-local/context/module-graph.md rename to mcp-local/module-graph.md diff --git a/.claude/skills/android-gradle-logic/SKILL.md b/mcp-local/skills/android-gradle-logic.md similarity index 100% rename from .claude/skills/android-gradle-logic/SKILL.md rename to mcp-local/skills/android-gradle-logic.md diff --git a/mcp-local/context/skills/android-testing.md b/mcp-local/skills/android-testing.md similarity index 100% rename from mcp-local/context/skills/android-testing.md rename to mcp-local/skills/android-testing.md diff --git a/mcp-local/context/rules.md b/mcp-local/skills/architecture.md similarity index 74% rename from mcp-local/context/rules.md rename to mcp-local/skills/architecture.md index b089610..2fe5726 100644 --- a/mcp-local/context/rules.md +++ b/mcp-local/skills/architecture.md @@ -1,24 +1,10 @@ -# CraftD — Architectural Rules +--- +name: architecture +description: CraftD architectural rules and code conventions. Use when reviewing, designing, or implementing any component across platforms. +trigger: when the user asks about architecture, rules, conventions, or what is/isn't allowed in the codebase +--- -CraftD is a **Server Driven UI** multiplatform library. The server decides which components to render and how; the client (app) only executes. Supports Android Compose, Android XML, KMP Compose Multiplatform, iOS SwiftUI, and Flutter. - -## Module Structure - -``` -android_kmp/ - craftd-core/ # shared models and abstractions (KMP) - commonMain/ # code shared across platforms - androidMain/ # Android-specific implementations - craftd-compose/ # Compose / KMP implementation - craftd-xml/ # View System (XML) implementation - app-sample-android/ # Android sample app - app-sample-cmp/ # KMP Compose sample app - build-logic/ # shared build configuration - -ios/craftd-swiftui/ # iOS library (Swift Package + CocoaPods) -flutter/craftd_widget/ # Flutter library (pub.dev) -docs/ # site documentation (MkDocs) -``` +# CraftD — Architectural Rules & Conventions ## Architectural Rules — Never Violate @@ -42,13 +28,6 @@ docs/ # site documentation (MkDocs) 10. **External library dependencies must be abstracted.** Never directly couple a third-party lib (e.g., Coil, Picasso, Glide) inside the builder. Expose an interface/function as a constructor parameter so the consumer injects the implementation. -## Code Conventions - -- **Kotlin:** follows official Kotlin conventions. Prefer `data class` for models. -- **Component naming:** `CraftD` prefix on everything that is part of the lib (e.g., `CraftDButton`, `CraftDButtonBuilder`). -- **Tests:** JUnit4 + MockK. Backtick naming: `` `given X when Y then Z` ``. Path mirrors source: `src/test/java/...` -- **Commits:** messages in English, semantic (`feat:`, `fix:`, `test:`, `chore:`, `docs:`). - ## What NOT to Do - Do not create a component outside the `CraftDBuilder` abstraction (or platform equivalent) @@ -56,3 +35,10 @@ docs/ # site documentation (MkDocs) - Do not create dependencies between platform modules (`craftd-compose` → `craftd-xml`, for example) - Do not commit `local.properties` or credential files - Do not use `--no-verify` to bypass CI hooks + +## Code Conventions + +- **Kotlin:** follows official Kotlin conventions. Prefer `data class` for models. +- **Component naming:** `CraftD` prefix on everything that is part of the lib (e.g., `CraftDButton`, `CraftDButtonBuilder`). +- **Tests:** JUnit4 + MockK. Backtick naming: `` `given X when Y then Z` ``. Path mirrors source: `src/test/java/...` +- **Commits:** messages in English, semantic (`feat:`, `fix:`, `test:`, `chore:`, `docs:`). \ No newline at end of file diff --git a/mcp-local/context/skills/compose-ui.md b/mcp-local/skills/compose-ui.md similarity index 100% rename from mcp-local/context/skills/compose-ui.md rename to mcp-local/skills/compose-ui.md diff --git a/mcp-local/context/skills/new-component.md b/mcp-local/skills/new-component.md similarity index 100% rename from mcp-local/context/skills/new-component.md rename to mcp-local/skills/new-component.md diff --git a/mcp-local/context/skills/review-pr.md b/mcp-local/skills/review-pr.md similarity index 100% rename from mcp-local/context/skills/review-pr.md rename to mcp-local/skills/review-pr.md diff --git a/mcp-local/context/skills/run-build.md b/mcp-local/skills/run-build.md similarity index 100% rename from mcp-local/context/skills/run-build.md rename to mcp-local/skills/run-build.md