feat: adicionar plugin acidaos e skill prompt-refine

Plugin acidaos (novo):
- rust-dev: desenvolvimento Core em Rust (Axum, crates, debug compiler)
- spoke-dev: desenvolvimento Spokes em Next.js/TypeScript + Storybook
- devops: pipelines Gitea Actions CI/CD (adaptado de GitHub para Gitea)
- docs: rustdoc, TypeDoc, Outline e ADRs

dev-tools:
- prompt-refine: skill genérica de engenharia de prompts para agentes IA

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 22:11:22 +00:00
parent 6b3a6f2698
commit 24b0b68ed0
6 changed files with 1138 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
# Plugin: acidaos
Skills especializadas para desenvolvimento do **AcidaOS** — o sistema operativo de negócio para PMEs da Descomplicar®.
## Arquitectura
O AcidaOS usa uma arquitectura Hub-and-Spoke:
- **Core (Hub):** Rust + Axum — motor de orquestração de agentes, API gRPC/REST interna
- **Spokes:** Next.js/TypeScript — dashboards, UI, aplicações de negócio
## Skills disponíveis
| Skill | Trigger | Descrição |
|-------|---------|-----------|
| `acidaos:rust-dev` | `/rust-dev`, desenvolvimento Core | Desenvolvimento do Core em Rust (Axum, Tokio) |
| `acidaos:spoke-dev` | `/spoke-dev`, desenvolvimento Spokes | Aplicações Next.js e componentes React |
| `acidaos:devops` | `/acidaos-pipeline`, CI/CD | Pipelines Gitea Actions para o AcidaOS |
| `acidaos:docs` | `/acidaos-docs`, documentação técnica | Gerar documentação a partir do código |
## Referências
- Arquitectura: `Hub/01-Planeamento/AcidaOS/Relatorio_Arquitetura_Core.md`
- SPECs: `Hub/01-Planeamento/AcidaOS/acidaos-core/SPECs.md`
- Visão estratégica: `Hub/01-Planeamento/AcidaOS/AcidaOS_Visao-Estrategica.md`
- Repositório: Gitea `acidaos-core`, `acidaos-dashboard`
---
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Data**: 2026-03-12
+316
View File
@@ -0,0 +1,316 @@
---
name: devops
description: CI/CD pipelines para o AcidaOS via Gitea Actions — build, test, deploy para acidaos-core (Rust) e acidaos-dashboard (Next.js). Usar quando "pipeline acidaos", "gitea actions acidaos", "ci cd acidaos", "deploy acidaos", "workflow acidaos".
allowed-tools: Read, Write, Edit, Bash, mcp__gitea__list_repo_action_workflows, mcp__gitea__get_repo_action_workflow, mcp__gitea__create_file, mcp__gitea__update_file, mcp__memory-supabase__search_memories
---
# AcidaOS DevOps — Gitea Actions
Skill para criar e gerir pipelines CI/CD do AcidaOS via **Gitea Actions**.
> **Atenção:** O AcidaOS usa **Gitea Actions**, não GitHub Actions. A sintaxe é compatível mas o runner é self-hosted em `mcp-hub.descomplicar.pt`.
## Contexto
```
Repositórios Gitea:
acidaos-core → Rust Core
acidaos-dashboard → Next.js Dashboard
Runners:
self-hosted @ mcp-hub.descomplicar.pt
Labels: [self-hosted, linux, rust, node]
Deploy target:
EasyPanel (projectName: "descomplicar")
acidaos-core → serviceName: "acidaos-core"
acidaos-dashboard → serviceName: "acidaos-dashboard"
```
## Protocolo Inicial
```
mcp__memory-supabase__search_memories "acidaos devops pipeline"
mcp__gitea__list_repo_action_workflows <repo> # ver workflows existentes
```
---
## Pipelines Disponíveis
### 1. Core Rust — CI Pipeline
**Ficheiro:** `.gitea/workflows/ci.yml`
```yaml
name: AcidaOS Core CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
check:
name: Verificar código
runs-on: [self-hosted, linux, rust]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache Cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Cargo check
run: cargo check --all-features
- name: Clippy
run: cargo clippy --all-features -- -D warnings
- name: Formatação
run: cargo fmt --all -- --check
test:
name: Testes
needs: check
runs-on: [self-hosted, linux, rust]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache Cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Testes unitários
run: cargo test --all-features
- name: Testes de integração
run: cargo test --test '*' --all-features
env:
ACIDAOS_ENV: test
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
security:
name: Auditoria de segurança
runs-on: [self-hosted, linux, rust]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: cargo-audit
run: |
cargo install cargo-audit --quiet
cargo audit
```
---
### 2. Core Rust — Deploy Pipeline
**Ficheiro:** `.gitea/workflows/deploy.yml`
```yaml
name: AcidaOS Core Deploy
on:
push:
branches: [main]
tags: ['v*']
jobs:
deploy:
name: Deploy para EasyPanel
runs-on: [self-hosted, linux, rust]
environment: production
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build release
run: cargo build --release
- name: Build Docker image
run: |
docker build \
-t acidaos-core:${{ gitea.sha }} \
-t acidaos-core:latest \
.
- name: Push para registry
run: |
docker tag acidaos-core:latest \
registry.descomplicar.pt/acidaos/core:latest
docker push registry.descomplicar.pt/acidaos/core:latest
env:
DOCKER_REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
- name: Deploy via EasyPanel API
run: |
curl -X POST \
"https://easypanel.descomplicar.pt/api/deploy" \
-H "Authorization: Bearer ${{ secrets.EASYPANEL_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{
"projectName": "descomplicar",
"serviceName": "acidaos-core",
"image": "registry.descomplicar.pt/acidaos/core:latest"
}'
- name: Verificar health
run: |
sleep 10
curl -f http://acidaos-core.descomplicar.pt/health || exit 1
```
---
### 3. Dashboard Next.js — CI Pipeline
**Ficheiro:** `.gitea/workflows/ci.yml` (no repo acidaos-dashboard)
```yaml
name: AcidaOS Dashboard CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint-typecheck:
name: Lint e TypeCheck
runs-on: [self-hosted, linux, node]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Instalar dependências
run: pnpm install --frozen-lockfile
- name: TypeScript check
run: pnpm tsc --noEmit
- name: ESLint
run: pnpm lint
test:
name: Testes
needs: lint-typecheck
runs-on: [self-hosted, linux, node]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Instalar dependências
run: pnpm install --frozen-lockfile
- name: Testes unitários
run: pnpm test
- name: Build de verificação
run: pnpm build
env:
ACIDAOS_CORE_URL: http://localhost:3001
e2e:
name: Testes E2E
needs: test
runs-on: [self-hosted, linux, node]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Instalar dependências
run: pnpm install --frozen-lockfile
- name: Instalar Playwright
run: pnpm exec playwright install --with-deps chromium
- name: Testes E2E
run: pnpm test:e2e
env:
BASE_URL: http://localhost:3000
ACIDAOS_CORE_URL: http://localhost:3001
- name: Upload relatório E2E
if: failure()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: playwright-report/
```
---
## Gestão via MCP Gitea
```javascript
// Listar workflows de um repo
mcp__gitea__list_repo_action_workflows({ owner: "descomplicar", repo: "acidaos-core" })
// Ver runs recentes
mcp__gitea__list_repo_action_runs({ owner: "descomplicar", repo: "acidaos-core" })
// Desencadear workflow manualmente
mcp__gitea__dispatch_repo_action_workflow({
owner: "descomplicar",
repo: "acidaos-core",
workflow_id: "deploy.yml",
ref: "main"
})
// Ver logs de uma job
mcp__gitea__get_repo_action_job_log_preview({ owner: "descomplicar", repo: "acidaos-core", job_id: <id> })
```
## Segredos necessários (Gitea Secrets)
| Segredo | Usado em | Descrição |
|---------|----------|-----------|
| `TEST_DATABASE_URL` | Core CI | PostgreSQL de teste |
| `REGISTRY_TOKEN` | Core Deploy | Token registry Docker |
| `EASYPANEL_TOKEN` | Core/Dashboard Deploy | Token API EasyPanel |
## Checklist Pipeline Nova
- [ ] Workflow criado em `.gitea/workflows/`
- [ ] Runner labels correctas (`self-hosted, linux, rust` ou `node`)
- [ ] Cache Cargo/pnpm configurado
- [ ] Segredos referenciados (não hardcoded)
- [ ] Health check no deploy
- [ ] Tested com `mcp__gitea__dispatch_repo_action_workflow`
---
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
+191
View File
@@ -0,0 +1,191 @@
---
name: docs
description: Gerar documentação técnica do AcidaOS a partir do código — Rust (rustdoc), TypeScript (TypeDoc), e publicar no Outline. Usar quando "documentação acidaos", "gerar docs", "rustdoc", "typedoc", "acidaos-docs", documentar código do projecto.
allowed-tools: Read, Write, Bash, mcp__gitea__get_file_content, mcp__gitea__get_dir_content, mcp__outline-api__create_document, mcp__outline-api__update_document, mcp__outline-api__search_documents, mcp__memory-supabase__search_memories
---
# AcidaOS Docs
Skill para gerar e publicar documentação técnica do AcidaOS.
## Estratégia de Documentação
| Camada | Ferramenta | Destino |
|--------|-----------|---------|
| API interna Rust | `rustdoc` + comentários `///` | `/docs` no repo |
| Componentes React | TypeDoc + Storybook | Storybook deployed |
| Arquitectura | Mermaid.js diagramas | Outline (Wiki) |
| Endpoints API | OpenAPI/Swagger | Outline (Wiki) |
| Decisões técnicas | ADRs em Markdown | Outline (Wiki) |
## Protocolo
```
mcp__memory-supabase__search_memories "acidaos documentação"
mcp__outline-api__search_documents "acidaos" # ver docs existentes
```
---
## Operações
### 1. Gerar documentação Rust (`rustdoc`)
**Verificar comentários existentes:**
```
mcp__gitea__get_dir_content acidaos-core/src/
```
**Gerar localmente (no container dev):**
```bash
cd /root/Dev/acidaos-core
cargo doc --all-features --no-deps --open
```
**Verificar cobertura de documentação:**
```bash
cargo doc --all-features 2>&1 | grep "warning: missing documentation"
```
**Template comentários Rust:**
```rust
/// # ComponenteX
///
/// Breve descrição em uma linha.
///
/// ## Descrição detalhada
///
/// Explicação mais longa do comportamento e propósito.
///
/// ## Exemplos
///
/// ```rust
/// use acidaos_core::ComponenteX;
///
/// let c = ComponenteX::new("id");
/// assert!(c.is_valid());
/// ```
///
/// ## Erros
///
/// Retorna [`Error::Init`] se a inicialização falhar.
pub struct ComponenteX { ... }
```
---
### 2. Gerar documentação TypeScript (TypeDoc)
**Verificar configuração:**
```
mcp__gitea__get_file_content acidaos-dashboard/typedoc.json
```
**Gerar (no container dev):**
```bash
cd /root/Dev/acidaos-dashboard
pnpm typedoc --out docs/api src/
```
**Template JSDoc para componentes:**
```typescript
/**
* AgentStatusCard — Mostra o estado de um agente AcidaOS
*
* @example
* ```tsx
* <AgentStatusCard
* agentId="agent-123"
* onRefresh={() => refetch()}
* />
* ```
*/
export interface AgentStatusCardProps {
/** ID único do agente no Core */
agentId: string;
/** Callback chamado ao clicar em refrescar */
onRefresh?: () => void;
}
```
---
### 3. Publicar arquitectura no Outline
**Criar/actualizar diagrama de arquitectura:**
```javascript
mcp__outline-api__create_document({
title: "AcidaOS — Arquitectura Core",
text: `
# Arquitectura AcidaOS Core
## Hub-and-Spoke
\`\`\`mermaid
graph TD
A[acidaos-dashboard] -->|API REST| B[AcidaOS Core]
B --> C[Agent Kernel]
B --> D[Security & Sandboxing]
B --> E[Memory Engine]
B --> F[Observability]
\`\`\`
## Componentes
| Componente | Linguagem | Responsabilidade |
|-----------|-----------|-----------------|
| Core | Rust | Orquestração de agentes |
| Dashboard | Next.js | Interface de utilizador |
`,
collectionId: "<acidaos-collection-id>"
})
```
---
### 4. Criar ADR (Architecture Decision Record)
**Template ADR:**
```markdown
# ADR-<NNN>: <Título da Decisão>
**Data:** YYYY-MM-DD
**Estado:** [Proposto | Aceite | Depreciado | Substituído por ADR-NNN]
## Contexto
[Situação que levou à necessidade de tomar esta decisão]
## Opções Consideradas
1. **Opção A** — descrição breve
2. **Opção B** — descrição breve
## Decisão
[Opção escolhida e porquê]
## Consequências
**Positivas:**
- [Consequência positiva]
**Negativas / Trade-offs:**
- [Limitação ou custo]
```
---
## Quality Gate de Documentação
Antes de marcar tarefa como concluída:
- [ ] Rust: zero `missing documentation` warnings em `cargo doc`
- [ ] TypeScript: TypeDoc gera sem erros
- [ ] Novos módulos têm exemplos de uso nos comentários
- [ ] Diagramas Mermaid actualizado se arquitectura mudou
- [ ] ADR criado para decisões técnicas significativas
---
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
+232
View File
@@ -0,0 +1,232 @@
---
name: rust-dev
description: Desenvolvimento do AcidaOS Core em Rust — criar crates, definir endpoints Axum, debugar erros do compilador. Usar quando "rust", "axum", "cargo", "crate", "core", "acidaos core", "rust error", "borrow checker", desenvolvimento do motor central do AcidaOS.
allowed-tools: Read, Write, Edit, Bash, mcp__memory-supabase__search_memories, mcp__gitea__get_file_content, mcp__gitea__create_file, mcp__gitea__update_file
---
# AcidaOS Rust Dev
Skill para desenvolvimento do **Core do AcidaOS** em Rust.
## Contexto do Projecto
```
acidaos-core (Rust)
├── src/
│ ├── api/ ← endpoints Axum (REST/gRPC)
│ ├── kernel/ ← Agent Kernel & Scheduler
│ ├── security/ ← Sandboxing, isolamento WASM
│ ├── memory/ ← Context & Memory Engine
│ ├── registry/ ← Parsers de skills/plugins
│ ├── observability/← Logging, tracing
│ └── ethics/ ← Constitution Engine
├── crates/ ← bibliotecas internas
└── Cargo.toml
```
**Stack:** Rust stable | Axum | Tokio | Serde | Tracing | SQLx | wasmtime
## Protocolo Inicial
```
mcp__memory-supabase__search_memories "acidaos core [componente]"
mcp__gitea__get_file_content acidaos-core/Cargo.toml # verificar dependências actuais
```
---
## Operações
### 1. Criar novo crate (`/rust-create-crate`)
**Input:** Nome do crate e propósito
**Passos:**
1. Criar directório `crates/<nome>/`
2. Gerar `Cargo.toml` com dependências mínimas
3. Criar `src/lib.rs` com estrutura base
4. Adicionar ao workspace `Cargo.toml`
5. Criar `src/error.rs` com tipo de erro custom usando `thiserror`
**Template `Cargo.toml`:**
```toml
[package]
name = "acidaos-<nome>"
version = "0.1.0"
edition = "2021"
description = "<descrição>"
[dependencies]
tracing = "0.1"
serde = { version = "1", features = ["derive"] }
thiserror = "1"
tokio = { version = "1", features = ["full"] }
```
**Template `src/lib.rs`:**
```rust
//! # acidaos-<nome>
//!
//! <Descrição do módulo>
//!
//! ## Exemplo
//! ```rust
//! use acidaos_<nome>::<TipoPrincipal>;
//! ```
mod error;
pub use error::Error;
pub type Result<T> = std::result::Result<T, Error>;
```
**Template `src/error.rs`:**
```rust
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("Erro de inicialização: {0}")]
Init(String),
#[error("Operação não suportada: {0}")]
Unsupported(String),
}
```
---
### 2. Definir endpoint Axum (`/rust-define-api-endpoint`)
**Input:** Definição do endpoint (método, path, request/response types) de uma SPEC.md
**Template de endpoint:**
```rust
use axum::{
extract::{Path, State},
http::StatusCode,
response::Json,
routing::{get, post},
Router,
};
use serde::{Deserialize, Serialize};
use tracing::instrument;
// --- Tipos ---
#[derive(Debug, Deserialize)]
pub struct <NomeRequest> {
// campos do request
}
#[derive(Debug, Serialize)]
pub struct <NomeResponse> {
// campos do response
}
// --- Handler ---
#[instrument(skip(state))]
pub async fn <nome_handler>(
State(state): State<AppState>,
Json(req): Json<<NomeRequest>>,
) -> Result<Json<<NomeResponse>>, StatusCode> {
tracing::info!("Processando <nome>");
// lógica do handler
Ok(Json(<NomeResponse> {
// preencher response
}))
}
// --- Router ---
pub fn <nome>_router() -> Router<AppState> {
Router::new()
.route("/<path>", post(<nome_handler>))
}
```
**Princípios obrigatórios:**
- `#[instrument]` em todos os handlers (observabilidade)
- Erros retornam `StatusCode` ou tipo de erro custom (nunca `.unwrap()`)
- Estado partilhado via `State<AppState>` (não globals)
- Validação de input antes de processamento
---
### 3. Debugar erro do compilador (`/rust-debug-compiler-error`)
**Input:** Output completo de `cargo build` ou `cargo check`
**Protocolo de análise:**
1. **Identificar categoria do erro:**
| Código | Categoria | Solução típica |
|--------|-----------|----------------|
| E0382 | Move após uso | Usar `clone()` ou referências `&` |
| E0502 | Borrow conflict | Reordenar operações, usar `Arc<Mutex<>>` |
| E0308 | Type mismatch | Verificar tipos, usar `.into()` ou cast explícito |
| E0277 | Trait not impl | Implementar trait ou usar tipo diferente |
| E0499 | Multiple mut borrows | Usar `RefCell` ou reestruturar lógica |
2. **Analisar mensagem de erro completa** (incluindo `help:` e `note:`)
3. **Gerar código corrigido** com explicação da causa raiz
4. **Verificar:** `cargo check` passa antes de `cargo build`
**Padrões comuns no AcidaOS Core:**
```rust
// ❌ Move não intencional
let data = fetch_data();
process(data);
log(data); // ERRO: data foi moved
// ✅ Correcto
let data = fetch_data();
process(&data); // ou process(data.clone())
log(&data);
// ❌ Async + lifetime
async fn handler(req: &Request) -> Response { ... } // lifetime issue
// ✅ Correcto — owned ou Arc
async fn handler(req: Arc<Request>) -> Response { ... }
```
---
## Quality Gate
Antes de fazer commit:
```bash
cargo check # zero erros
cargo clippy # zero warnings
cargo test # todos os testes passam
cargo fmt --check # formatação correcta
```
**Standards:**
- Zero `unwrap()` em código de produção — usar `?` ou `expect("mensagem descritiva")`
- Funções async < 50 linhas
- `tracing::instrument` em todas as funções públicas async
- Documentação `///` em todos os tipos e funções públicas
---
## Checklist Entrega
- [ ] `cargo check` sem erros
- [ ] `cargo clippy -- -D warnings` limpo
- [ ] `cargo test` 100% pass
- [ ] Documentação `///` completa
- [ ] Observabilidade: `#[instrument]` nos handlers
- [ ] Sem `.unwrap()` em paths críticos
- [ ] CHANGELOG.md actualizado
---
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos
+239
View File
@@ -0,0 +1,239 @@
---
name: spoke-dev
description: Desenvolvimento de Spokes do AcidaOS em Next.js/TypeScript — criar aplicações Spoke, componentes React com testes e Storybook. Usar quando "spoke", "dashboard acidaos", "next.js acidaos", "componente react acidaos", "ts-create-spoke", "acidaos ui", "acidaos frontend".
allowed-tools: Read, Write, Edit, Bash, mcp__memory-supabase__search_memories, mcp__gitea__get_file_content, mcp__gitea__create_file, mcp__gitea__update_file
---
# AcidaOS Spoke Dev
Skill para desenvolvimento dos **Spokes do AcidaOS** em Next.js/TypeScript.
## Contexto do Projecto
Os Spokes são as aplicações de interface que comunicam com o Core via API interna:
```
acidaos-dashboard (Next.js 15 + App Router)
├── src/
│ ├── app/ ← App Router pages
│ ├── components/ ← Componentes React
│ │ ├── ui/ ← Componentes base (shadcn/ui)
│ │ └── features/ ← Componentes de funcionalidade
│ ├── lib/
│ │ ├── api/ ← Client para AcidaOS Core API
│ │ └── hooks/ ← React hooks custom
│ └── types/ ← TypeScript types partilhados
├── __tests__/ ← Jest + Testing Library
└── .storybook/ ← Storybook
```
**Stack:** Next.js 15 | TypeScript 5 | React 19 | Tailwind CSS | shadcn/ui | Vercel AI SDK | Vitest | Playwright
## Protocolo Inicial
```
mcp__memory-supabase__search_memories "acidaos spoke dashboard [componente]"
mcp__gitea__get_file_content acidaos-dashboard/package.json
```
---
## Operações
### 1. Criar nova aplicação Spoke (`/ts-create-spoke-app`)
**Input:** Nome do Spoke e propósito
**Estrutura a criar:**
```bash
# No container dev (Regra #48)
cd /root/Dev
npx create-next-app@latest acidaos-<nome> \
--typescript \
--tailwind \
--app \
--src-dir \
--import-alias "@/*" \
--no-git
```
**Ficheiros obrigatórios após scaffold:**
`src/lib/api/core-client.ts` — cliente para o Core:
```typescript
/**
* AcidaOS Core API Client
*
* @author Descomplicar® Crescimento Digital
* @link https://descomplicar.pt
*/
const CORE_API_URL = process.env.ACIDAOS_CORE_URL ?? 'http://localhost:3001';
export async function coreRequest<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const res = await fetch(`${CORE_API_URL}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
'X-AcidaOS-Version': '1',
...options?.headers,
},
});
if (!res.ok) {
throw new Error(`Core API error: ${res.status} ${res.statusText}`);
}
return res.json() as Promise<T>;
}
```
`src/types/index.ts` — tipos base:
```typescript
export interface AgentTask {
id: string;
status: 'pending' | 'running' | 'completed' | 'failed';
createdAt: string;
completedAt?: string;
}
export interface CoreHealth {
status: 'healthy' | 'degraded' | 'down';
version: string;
uptime: number;
}
```
---
### 2. Criar componente React (`/ts-create-react-component`)
**Input:** Descrição do componente (nome, props, comportamento)
**Template base — componente:**
`src/components/features/<Nome>/<Nome>.tsx`:
```typescript
/**
* <Nome> — <Descrição curta>
*
* @author Descomplicar® Crescimento Digital
*/
import { type FC } from 'react';
import { cn } from '@/lib/utils';
interface <Nome>Props {
// props do componente
className?: string;
}
export const <Nome>: FC<<Nome>Props> = ({ className }) => {
return (
<div className={cn('', className)}>
{/* conteúdo */}
</div>
);
};
<Nome>.displayName = '<Nome>';
```
**Template — teste (Vitest + Testing Library):**
`src/components/features/<Nome>/<Nome>.test.tsx`:
```typescript
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { <Nome> } from './<Nome>';
describe('<Nome>', () => {
it('renderiza sem erros', () => {
render(<<Nome> />);
// asserção específica ao componente
});
it('aceita className personalizada', () => {
const { container } = render(<<Nome> className="test-class" />);
expect(container.firstChild).toHaveClass('test-class');
});
});
```
**Template — Storybook:**
`src/components/features/<Nome>/<Nome>.stories.tsx`:
```typescript
import type { Meta, StoryObj } from '@storybook/react';
import { <Nome> } from './<Nome>';
const meta: Meta<typeof <Nome>> = {
title: 'Features/<Nome>',
component: <Nome>,
parameters: {
layout: 'centered',
},
};
export default meta;
type Story = StoryObj<typeof <Nome>>;
export const Default: Story = {
args: {},
};
```
**Criar index de exportação:**
`src/components/features/<Nome>/index.ts`:
```typescript
export { <Nome> } from './<Nome>';
export type { <Nome>Props } from './<Nome>';
```
---
## Padrões Obrigatórios
### TypeScript
- `strict: true` em `tsconfig.json` — sem `any` implícito
- Props sempre tipadas com interface exportada
- Hooks custom em `src/lib/hooks/use<Nome>.ts`
- Server Components por defeito; `'use client'` apenas quando necessário
### Performance
- `next/image` para todas as imagens
- `loading="lazy"` em componentes pesados
- `Suspense` boundaries em torno de data-fetching
- Cache de API calls com `unstable_cache` ou React cache
### Segurança
- Nunca expor `ACIDAOS_CORE_URL` no cliente (apenas server-side)
- Sanitizar input do utilizador antes de enviar ao Core
- Usar Next.js Server Actions para mutações
---
## Quality Gate
```bash
pnpm build # zero erros TypeScript
pnpm test # todos os testes passam
pnpm lint # zero erros ESLint
```
## Checklist Entrega
- [ ] Tipos TypeScript sem `any`
- [ ] Testes criados (>80% cobertura)
- [ ] Story Storybook criada
- [ ] `displayName` definido no componente
- [ ] `pnpm build` sem erros
- [ ] Client/Server components correctamente marcados
- [ ] CHANGELOG.md actualizado
---
**Versão**: 1.0.0 | **Autor**: Descomplicar® | **Plugin**: acidaos