From e0874596f7dbd0eb08c824860d12813fa9aad51f Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Fri, 21 Aug 2026 20:21:58 -0300 Subject: [PATCH] chore: reduce token overhead in agent workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Drop model-selection skill (dead, pool is dormant) - Drop PNG rendering from UI planning (HTML-only, no pnpm ui-draft:render) - Trim code-simplification: 331→~150 lines, Python/React examples moved to reference/ - Compress engineering-brief.md: remove redundant 'Pinhos do repo' (alwaysApply rules) - Deduplicate capture-review-debts: reference decision-quality.md instead of re-explaining - Create concise-output skill (35 lines) to enforce terse agent output - Trim all 99 skill descriptions to ≤1 sentence - Split AGENTS.md into layers: core (73 lines, always) + campaign/public/infra (on-demand) - Decompose plan-issue: exploration sub-agent + parallel plan-writers + register sub-agent - Decompose work-issue: exploration sub-agent + plan-writer + 2 parallel reviewers + debt sub-agent - Update agent-work-issue to match sub-agent pattern --- .agents/skills/37signals-way/SKILL.md | 2 +- .agents/skills/agent-pool/SKILL.md | 2 +- .agents/skills/agent-work-issue/SKILL.md | 104 ++++---- .../skills/api-and-interface-design/SKILL.md | 2 +- .agents/skills/blue-ocean-strategy/SKILL.md | 2 +- .../browser-testing-with-devtools/SKILL.md | 2 +- .agents/skills/capture-review-debts/SKILL.md | 35 +-- .agents/skills/ci-cd-and-automation/SKILL.md | 2 +- .agents/skills/clean-architecture/SKILL.md | 2 +- .agents/skills/clean-code/SKILL.md | 2 +- .../skills/code-review-and-quality/SKILL.md | 2 +- .agents/skills/code-simplification/SKILL.md | 239 ++---------------- .../reference/language-guide.md | 103 ++++++++ .agents/skills/cold-start-problem/SKILL.md | 2 +- .agents/skills/concise-output/SKILL.md | 27 ++ .agents/skills/contagious/SKILL.md | 2 +- .agents/skills/context-engineering/SKILL.md | 2 +- .agents/skills/continuous-discovery/SKILL.md | 2 +- .agents/skills/create-app/SKILL.md | 2 +- .agents/skills/create-business/SKILL.md | 2 +- .agents/skills/create-website/SKILL.md | 2 +- .agents/skills/cro-methodology/SKILL.md | 2 +- .agents/skills/crossing-the-chasm/SKILL.md | 2 +- .agents/skills/ddia-systems/SKILL.md | 2 +- .../debugging-and-error-recovery/SKILL.md | 2 +- .../skills/deprecation-and-migration/SKILL.md | 2 +- .../skills/design-code-architecture/SKILL.md | 2 +- .../skills/design-everyday-things/SKILL.md | 2 +- .agents/skills/design-sprint/SKILL.md | 2 +- .../skills/documentation-and-adrs/SKILL.md | 2 +- .agents/skills/domain-driven-design/SKILL.md | 2 +- .../skills/doubt-driven-development/SKILL.md | 2 +- .agents/skills/drive-motivation/SKILL.md | 2 +- .agents/skills/engineering-audit/SKILL.md | 2 +- .../skills/frontend-ui-engineering/SKILL.md | 2 +- .../git-workflow-and-versioning/SKILL.md | 2 +- .../good-strategy-bad-strategy/SKILL.md | 2 +- .agents/skills/grow-app/SKILL.md | 2 +- .agents/skills/grow-business/SKILL.md | 2 +- .agents/skills/grow-website/SKILL.md | 2 +- .../skills/high-output-management/SKILL.md | 2 +- .agents/skills/high-perf-browser/SKILL.md | 2 +- .agents/skills/hooked-ux/SKILL.md | 2 +- .../skills/hundred-million-offers/SKILL.md | 2 +- .agents/skills/idea-refine/SKILL.md | 2 +- .agents/skills/impeccable/SKILL.md | 2 +- .agents/skills/improve-app/SKILL.md | 2 +- .agents/skills/improve-business/SKILL.md | 2 +- .agents/skills/improve-code-quality/SKILL.md | 2 +- .agents/skills/improve-retention/SKILL.md | 2 +- .agents/skills/improve-website/SKILL.md | 2 +- .../incremental-implementation/SKILL.md | 2 +- .agents/skills/influence-psychology/SKILL.md | 2 +- .agents/skills/inspired-product/SKILL.md | 2 +- .agents/skills/interview-me/SKILL.md | 2 +- .agents/skills/ios-hig-design/SKILL.md | 2 +- .agents/skills/jobs-to-be-done/SKILL.md | 2 +- .agents/skills/lean-analytics/SKILL.md | 2 +- .agents/skills/lean-startup/SKILL.md | 2 +- .agents/skills/lean-ux/SKILL.md | 2 +- .agents/skills/local-database/SKILL.md | 2 +- .agents/skills/made-to-stick/SKILL.md | 2 +- .agents/skills/microinteractions/SKILL.md | 2 +- .agents/skills/model-selection/SKILL.md | 92 ------- .agents/skills/mom-test/SKILL.md | 2 +- .agents/skills/monetizing-innovation/SKILL.md | 2 +- .agents/skills/negotiation/SKILL.md | 2 +- .../SKILL.md | 2 +- .agents/skills/obviously-awesome/SKILL.md | 2 +- .agents/skills/one-page-marketing/SKILL.md | 2 +- .agents/skills/payload-migrations/SKILL.md | 2 +- .../skills/performance-optimization/SKILL.md | 2 +- .agents/skills/plan-issue/SKILL.md | 194 ++++++-------- .../skills/plan-issue/intention-template.md | 15 +- .agents/skills/plan-issue/skills-map.md | 2 +- .agents/skills/plan-issue/ui-draft-html.md | 41 +-- .../planning-and-task-breakdown/SKILL.md | 2 +- .agents/skills/pragmatic-programmer/SKILL.md | 2 +- .agents/skills/predictable-revenue/SKILL.md | 2 +- .agents/skills/project-status/SKILL.md | 2 +- .agents/skills/rebase-on-main/SKILL.md | 2 +- .agents/skills/refactoring-patterns/SKILL.md | 2 +- .agents/skills/refactoring-ui/SKILL.md | 2 +- .agents/skills/release-it/SKILL.md | 2 +- .agents/skills/remove-technical-debt/SKILL.md | 2 +- .agents/skills/scorecard-marketing/SKILL.md | 2 +- .../skills/security-and-hardening/SKILL.md | 2 +- .agents/skills/shipping-and-launch/SKILL.md | 2 +- .../software-design-philosophy/SKILL.md | 2 +- .../skills/source-driven-development/SKILL.md | 2 +- .../skills/spec-driven-development/SKILL.md | 2 +- .../skills/steve-jobs-design-review/SKILL.md | 2 +- .agents/skills/storybrand-messaging/SKILL.md | 2 +- .agents/skills/system-design/SKILL.md | 2 +- .agents/skills/team-topologies/SKILL.md | 2 +- .../skills/test-driven-development/SKILL.md | 2 +- .agents/skills/top-design/SKILL.md | 2 +- .agents/skills/traction-eos/SKILL.md | 2 +- .agents/skills/using-agent-skills/SKILL.md | 2 +- .agents/skills/ux-heuristics/SKILL.md | 2 +- .agents/skills/web-typography/SKILL.md | 2 +- .agents/skills/work-issue/SKILL.md | 175 ++++++++----- .../skills/work-issue/engineering-brief.md | 8 - .../skills/work-issue/execution-pipeline.md | 5 +- .../skills/working-with-legacy-code/SKILL.md | 2 +- .agents/skills/worktree-next-issue/SKILL.md | 2 +- AGENTS-campaign.md | 76 ++++++ AGENTS-infra.md | 27 ++ AGENTS-public.md | 43 ++++ AGENTS.md | 134 +--------- package.json | 1 - scripts/lib/agent-forgejo.mjs | 4 +- scripts/render-ui-draft.mjs | 52 ---- 113 files changed, 673 insertions(+), 890 deletions(-) create mode 100644 .agents/skills/code-simplification/reference/language-guide.md create mode 100644 .agents/skills/concise-output/SKILL.md delete mode 100644 .agents/skills/model-selection/SKILL.md create mode 100644 AGENTS-campaign.md create mode 100644 AGENTS-infra.md create mode 100644 AGENTS-public.md delete mode 100644 scripts/render-ui-draft.mjs diff --git a/.agents/skills/37signals-way/SKILL.md b/.agents/skills/37signals-way/SKILL.md index 7a848045..1dc97f99 100644 --- a/.agents/skills/37signals-way/SKILL.md +++ b/.agents/skills/37signals-way/SKILL.md @@ -1,6 +1,6 @@ --- name: 37signals-way -description: 'Build lean, opinionated products using the 37signals philosophy from "Getting Real", "Rework", and "Shape Up". Use when the user mentions "Getting Real", "Rework", "Shape Up", "37signals", "Basecamp method", "six-week cycles", "fixed time variable scope", "appetite vs estimates", "betting table", "breadboarding", "fat marker sketch", "build less", "underdo the competition", "opinionated software", "we have too many meetings", "how do we ship faster", or "stop overbuilding". Also trigger when cutting scope to ship sooner, running a small team, or avoiding long-term roadmaps. Covers shaping, betting, building, and the art of saying no. For MVP validation, see lean-startup. For design sprints, see design-sprint.' +description: 'Build lean products using 37signals philosophy: appetite, build less, shaped work.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/agent-pool/SKILL.md b/.agents/skills/agent-pool/SKILL.md index 2f94c523..c4f5fc96 100644 --- a/.agents/skills/agent-pool/SKILL.md +++ b/.agents/skills/agent-pool/SKILL.md @@ -1,6 +1,6 @@ --- name: agent-pool -description: >- +description: 'Opera e monitora o pool de agentes Cursor Cloud do Teqo.' Opera e monitora o pool de agentes Cursor Cloud do Teqo (supervisor remoto determinístico em Forgejo Actions). Ao invocar: SEMPRE status + fila elegível primeiro; NUNCA liga o pool sem confirmação explícita do usuário. Usar quando diff --git a/.agents/skills/agent-work-issue/SKILL.md b/.agents/skills/agent-work-issue/SKILL.md index 8157a8c6..a0b917b7 100644 --- a/.agents/skills/agent-work-issue/SKILL.md +++ b/.agents/skills/agent-work-issue/SKILL.md @@ -1,22 +1,17 @@ --- name: agent-work-issue -description: >- - Executa uma Issue já claimada de ponta a ponta para workers do agent pool: - Plan mode → plano de implementação (engenharia deliberada a partir da - intenção) → execução → /simplify → capture-review-debts → PR Ready em main - com auto-merge. Use quando o pool spawna um worker, quando a Issue já está - in-progress, ou quando o usuário pedir /agent-work-issue. +description: 'Execute a claimed Issue end-to-end autonomously: plan → execute → simplify → PR.' disable-model-invocation: true --- # Agent work-issue (autônomo) -Conduz **uma** Issue já claimada do plano de implementação ao merge em `main`. É o contrato dos workers do **agent pool** (Cursor Cloud, autônomo). O fluxo humano supervisionado é `work-issue` — skill própria, com gate humano no impl plan e contexto de Issue vindo da sessão. +Conduz **uma** Issue já claimada do plano de implementação ao merge em `main`. Contrato dos workers do agent pool. **Proibido:** DB de prod / `ALLOW_REMOTE_DB`; merge sem CI green; editar outras Issues `in-progress`; pular `/simplify`; entregar Draft ou sem auto-merge. -**Fonte de produto:** plano de intenção (`docs/plans/.md`) + body da Issue. -**Fonte de engenharia:** o `*-impl.md` que **você** cria — não o plano de intenção. +**Fonte de produto:** plano de intenção (`docs/plans/.md`) + body da Issue. +**Fonte de engenharia:** o `*-impl.md` que **você** cria. ## Relação com outras skills @@ -24,18 +19,27 @@ Conduz **uma** Issue já claimada do plano de implementação ao merge em `main` | ----- | ----- | | `plan-issue` | Intenção (já feita) | | **`agent-work-issue` (esta)** | Impl plan → execução → simplify → débitos → PR | -| `work-issue` | Humano: Issue já claimada → impl plan → **pausa humana** → execução → simplify → débitos → PR | +| `work-issue` | Humano: impl plan → **pausa humana** → execução → simplify → débitos → PR | + +## Decomposição em sub-agentes + +Mesmo padrão de `work-issue` — sub-agentes para fases pesadas: + +- **Explorador** (código) → findings +- **Escritor** (impl plan) → plano +- **2 Revisores** (paralelo: estrutural + qualidade) → achados do simplify +- **Capturador** (débitos) → tabela de triage ## Checklist ``` - [ ] 0. Prep: `pnpm i` se preciso; Cloud → §Prep Cloud (sem Docker) -- [ ] 1. Sessão: rename_chat + open_resource na intenção -- [ ] 2. Modelo: spawn do pool já fixou (`model:` da Issue) — sem comparação -- [ ] 3. Plan mode → plano de implementação (`*-impl.md`) -- [ ] 4. Executar o impl plan (schema/server → UI → e2e local afetado → gates) -- [ ] 5. /simplify → fixes; capture-review-debts (modo autônomo) -- [ ] 6. PR Ready `--base main` (GitHub) + auto-merge nativo — `pnpm push -u origin HEAD` → `node scripts/github-pr.mjs` (ou `ManagePullRequest` `draft: false` no Cloud) +- [ ] 1. Sessão: rename_chat + open_resource + carregar camada AGENTS +- [ ] 2. Plan mode → dispatch explorador + escritor → impl plan +- [ ] 3. Executar (main agent iterativo) +- [ ] 4. Dispatch 2 revisores paralelos → simplify +- [ ] 5. Dispatch capturador → triage de débitos +- [ ] 6. PR Ready + auto-merge ``` ## Passo 0 — Prep @@ -50,50 +54,48 @@ Não use `pnpm db:start`. Postgres via `.cursor/environment.json`. `gate:fast` / ## Passo 1 — Sessão (Issue já claimada) -**Não** rode `pnpm agent:claim` — o pool (ou o claim pré-sessão do humano — hoje `pnpm agent:claim` manual; OPS33 via `worktree next`) já claimou. +**Não** rode `pnpm agent:claim`. -1. `rename_chat` → `# — ` (padrão canônico; truncar só o título). +1. `rename_chat` → `# — `. 2. `open_resource` no plano de intenção (`docs/plans/.md`). +3. Carregar camada AGENTS: se toca `/campanha`, leia `AGENTS-campaign.md`. Se site público, `AGENTS-public.md`. Se deploy/CI, `AGENTS-infra.md`. -## Passo 2 — Modelo +## Passo 2 — Plano de implementação -O spawn do pool já fixou o modelo (`model:` da Issue — ver `model-selection`); não há comparação assimétrica a fazer: +1. `SwitchMode` → `plan`. +2. Dispatch sub-agente **explorador** com plano de intenção + `engineering-brief.md` + `codebase-map.mdc`. Receba findings (≤25 linhas). +3. Dispatch sub-agente **escritor** com plano + findings + `implementation-template.md` + `decision-quality.md`. Receba impl plan. +4. Crie `docs/plans/-impl.md`. Marque `aprovado`. +5. `SwitchMode` → `agent`. -- Fallback do pool (slug inválido → `composer-2.5`) pode deixar a sessão **mais fraca** que o declarado → informa e segue -- Ausente → o pool spawna no default `composer-2.5`; segue +**Divergência material de produto:** pare, comente na Issue, flip para `blocked`. -## Passo 3 — Plano de implementação (Plan mode) +## Passo 3 — Executar -1. `SwitchMode` → `plan` (explique: deliberar engenharia a partir da intenção). -2. Leia [engineering-brief.md](../work-issue/engineering-brief.md) e aplique skills/princípios sob demanda. -3. Explore o código o bastante para **reavaliar** a “Direção no codebase” da intenção — você **deve** escolher a melhor abordagem maintainable, mesmo que difira da hipótese do plano de intenção, desde que o **aceite de produto** se mantenha. -4. Escreva `docs/plans/-impl.md` via [implementation-template.md](../work-issue/implementation-template.md). Qualidade: [decision-quality.md](../work-issue/decision-quality.md) ≥4/5. -5. Em autonomia: marque Status `aprovado` e **siga sem pausa**. (Em `work-issue`, o humano confirma antes.) - -**Divergência material de produto** (aceite/persona/lockdown da intenção não cabem na abordagem): pare, comente na Issue, flip para `blocked` se pool — não invente produto novo. - -## Passo 4 — Executar - -`SwitchMode` → `agent` se ainda estiver em plan. Siga a mecânica de -[`../work-issue/execution-pipeline.md`](../work-issue/execution-pipeline.md) -(executar → simplify → fechar em main), com os deltas do ator pool: +Siga `execution-pipeline.md` com deltas do pool: - **Branch:** `agent/-` (worktrees Cursor podem já ter criado). -- **E2E local afetado (OPS72):** mesmo passo discricionário do ator humano - (rodar os e2e criados + da mesma superfície — ver `execution-pipeline.md`); - **worktree com browsers Playwright** → rode; **Cursor Cloud sem browsers** → - registre a justificativa no fechamento e siga — o CI de PR roda o blast - radius quando o diff classifica `selected`; em diff high-risk (`full`) o PR - não roda e2e e a rede final é o `verify` do deploy. -- **UI:** shape → craft → critique → polish (harden/optimize só sob gatilho). -- **`capture-review-debts`:** **autônomo** — só `expensive_lock` com score ≥4 - (Issues novas com `depends: []` se necessário); score ≤3 / - cheap_polish / defer_trigger → defer com gatilho no `*-impl.md` ou descarte — - **não** polua a fila. -- **Cloud:** PR via `ManagePullRequest` com `draft: false` no **GitHub** - (repo/PR agora no GitHub; o tracker de Issues segue no Forgejo — OPS71); - Prep Cloud no Passo 0. +- **E2E local afetado (OPS72):** discricionário (Cloud sem browsers → registre justificativa). +- **UI:** shape → craft → critique → polish. +- **`capture-review-debts`:** autônomo — só `expensive_lock` com score ≥4; resto → defer/descarte. +- **Cloud:** PR via `ManagePullRequest` com `draft: false` no GitHub. + +## Passo 4 — Simplify (2 sub-agentes paralelos) + +Dispatche os dois revisores com o diff: +- **Revisor estrutural:** Dependency Rule, module boundaries, abstractions, duplication, type honesty +- **Revisor de qualidade:** naming, function size, dead code, complexity, conventions + +Aplique fixes que preservem comportamento. + +## Passo 5 — Débitos (sub-agente) + +Dispatche capturador com achados + regras de `capture-review-debts`. Receba triage. Registre/absorva/defira/descarte. + +## Passo 6 — Fechar + +PR Ready `--base main` (GitHub) + auto-merge nativo — `pnpm push -u origin HEAD` → `node scripts/github-pr.mjs` (ou `ManagePullRequest` `draft: false` no Cloud). ## Resumo final -Issue · impl plan (abordagem escolhida + rejeitadas) · o que divergiu da hipótese de direção · simplify + débitos registrados/deferidos · PR + estado do merge. +Issue · impl plan · simplify + débitos · PR + merge. diff --git a/.agents/skills/api-and-interface-design/SKILL.md b/.agents/skills/api-and-interface-design/SKILL.md index 012c8b68..3c56c3c1 100644 --- a/.agents/skills/api-and-interface-design/SKILL.md +++ b/.agents/skills/api-and-interface-design/SKILL.md @@ -1,6 +1,6 @@ --- name: api-and-interface-design -description: Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend. +description: 'Guide stable API and interface design.' --- # API and Interface Design diff --git a/.agents/skills/blue-ocean-strategy/SKILL.md b/.agents/skills/blue-ocean-strategy/SKILL.md index 2486dc92..551f6db9 100644 --- a/.agents/skills/blue-ocean-strategy/SKILL.md +++ b/.agents/skills/blue-ocean-strategy/SKILL.md @@ -1,6 +1,6 @@ --- name: blue-ocean-strategy -description: 'Create uncontested market space using value innovation instead of competing head-to-head. Use when the user mentions "blue ocean", "red ocean", "strategy canvas", "ERRC framework", "value innovation", "non-customers", "buyer utility map", "the market is too crowded", "how do we stand out", or "escape the price war". Also trigger when exploring a new market category, or finding underserved or non-customers. Covers the Four Actions Framework, Six Paths, buyer utility map, and value-cost trade-offs. For real strategy formulation and bad-strategy detection, see good-strategy-bad-strategy. For tech adoption strategy, see crossing-the-chasm. For product positioning, see obviously-awesome.' +description: 'Create uncontested market space using value innovation.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/browser-testing-with-devtools/SKILL.md b/.agents/skills/browser-testing-with-devtools/SKILL.md index 9864d272..aa5c8621 100644 --- a/.agents/skills/browser-testing-with-devtools/SKILL.md +++ b/.agents/skills/browser-testing-with-devtools/SKILL.md @@ -1,6 +1,6 @@ --- name: browser-testing-with-devtools -description: Tests in real browsers via Chrome DevTools MCP. Use when building or debugging anything that runs in a browser. Use when you need to inspect the DOM, capture console errors, analyze network requests, profile performance, or verify visual output with real runtime data. Requires the chrome-devtools MCP server to be configured. +description: 'Test in real browsers via Chrome DevTools MCP.' --- # Browser Testing with DevTools diff --git a/.agents/skills/capture-review-debts/SKILL.md b/.agents/skills/capture-review-debts/SKILL.md index f9558703..a7626c04 100644 --- a/.agents/skills/capture-review-debts/SKILL.md +++ b/.agents/skills/capture-review-debts/SKILL.md @@ -1,6 +1,6 @@ --- name: capture-review-debts -description: Use when the user asks to register leftover /simplify or /impeccable findings as trackable GitHub Issues, harvest session review debts, triage post-simplify or post-critique follow-ups, or says "registra os débitos", "o que ficou do simplify", "coloca como issue o que o critique apontou", "harvest debts". +description: 'Triage simplify/impeccable findings into tracked GitHub Issues.' --- # Capturar débitos de /simplify e /impeccable em Issues @@ -56,35 +56,12 @@ Contra o repositório **antes** de pontuar: ## Passo 3 — Pontuar e decidir destino -Para cada candidato restante, atribua **importância** (1–5) com estes âncoras Teqo: +Aplique [decision-quality.md](../work-issue/decision-quality.md) para: +- **Score** (1–5) com âncoras de Teqo (feature bloqueada = 5, rename de pureza = 1) +- **Tipo de decisão:** expensive_lock / cheap_polish / defer_trigger +- **Destino:** registrar / absorver / descartar / defer / já_resolvido -| Score | Quando | -| ----- | ------------------------------------------------------------------------------------------- | -| 5 | Bloqueia feature dependente, hot path em produção, P0/P1 critique aberto, risco access/LGPD | -| 4 | Perf/DRY com ≥3 call sites ou custo herdado por A5/B3/E4/lista de núcleos | -| 3 | UX P2 acionável (Alex/Casey/Lia), DRY claro 2 call sites, a11y outline | -| 2 | Higiene/naming, polish cosmético, P3 critique | -| 1 | Preferência de estilo, rename de pureza, micro-otimização sem evidência | - -**Bump caro de reverter:** access/LGPD/schema/unicidade/hot path → piso de score **4–5**, mesmo que o simplify tenha rotulado como “nice cleanup”. - -**Tipo de decisão** (obrigatório — uma coluna na triage): - -| Tipo | Exemplos | Destino típico | -| ------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -| **expensive_lock** | access, Consent, uniqueness, write skew | registrar / absorver (nunca descartar por score baixo artificial) | -| **cheap_polish** | copy, motion, rename, P3 | descartar ou já_resolvido | -| **defer_trigger** | DRY <3 call sites, abstração prematura | **não registrar** como epic — anotar gatilho (`quando 3º bulk path`, `quando B3`) no plano-pai ou em Explicitamente fora | - -**Destino** (escolha exatamente um): - -| Destino | Critério | -| ---------------- | --------------------------------------------------------------------------------------------------------------------- | -| **registrar** | Score ≥3 **e** não coberto **e** tipo ≠ defer_trigger puro; cabe num plano próprio ou lote mesclado | -| **absorver** | Score ≥3 mas é fase natural de um plano/`escala-dry-pos-*`/UX já existente | -| **descartar** | Score ≤2 **ou** rename de pureza **ou** "nice to have" sem dono **ou** skip explícito do simplify **ou** cheap_polish | -| **defer** | Tipo defer_trigger: não cria ID novo; registra gatilho no plano-pai / Explicitamente fora | -| **já_resolvido** | Feito no cleanup da sessão | +**Bump caro de reverter:** access/LGPD/schema/unicidade/hot path → piso de score **4–5**, mesmo que o simplify tenha rotulado como "nice cleanup". Preferir **defer+gatilho** a **registrar** para DRY prematuro — alinha a YAGNI / deep modules e aos precedentes `escala-dry-pos-*`. diff --git a/.agents/skills/ci-cd-and-automation/SKILL.md b/.agents/skills/ci-cd-and-automation/SKILL.md index 118456fc..dc7d37d2 100644 --- a/.agents/skills/ci-cd-and-automation/SKILL.md +++ b/.agents/skills/ci-cd-and-automation/SKILL.md @@ -1,6 +1,6 @@ --- name: ci-cd-and-automation -description: Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines. Use when you need to automate quality gates, configure test runners in CI, or establish deployment strategies. +description: 'Automate CI/CD pipeline setup and deployment strategies.' --- # CI/CD and Automation diff --git a/.agents/skills/clean-architecture/SKILL.md b/.agents/skills/clean-architecture/SKILL.md index a95fdf86..11ebaacc 100644 --- a/.agents/skills/clean-architecture/SKILL.md +++ b/.agents/skills/clean-architecture/SKILL.md @@ -1,6 +1,6 @@ --- name: clean-architecture -description: 'Structure software around the Dependency Rule: source code dependencies point inward from frameworks to use cases to entities. Use when the user mentions "architecture layers", "dependency rule", "ports and adapters (hexagonal)", "onion architecture", "screaming architecture", "where should business logic go", "decouple from the database", "swap the framework without a rewrite", or "keep business rules independent". Also trigger when deciding which layer code belongs in, isolating core logic from infrastructure, defining module boundaries, or debating whether the framework should call your code or the reverse. Covers component principles, boundaries, and SOLID. For code-level quality, see clean-code. For domain modeling, see domain-driven-design.' +description: 'Structure software with the Dependency Rule: entities ← use cases ← frameworks.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/clean-code/SKILL.md b/.agents/skills/clean-code/SKILL.md index 84a8a50f..041ea743 100644 --- a/.agents/skills/clean-code/SKILL.md +++ b/.agents/skills/clean-code/SKILL.md @@ -1,6 +1,6 @@ --- name: clean-code -description: 'Write readable, maintainable code through disciplined naming, small functions, and clean error handling. Use when the user mentions "clean up this code", "this function is too long", "code smells", "naming conventions", "boy scout rule", "single responsibility", or "unit test quality". Also trigger when reviewing a pull request for readability, untangling a messy function, debating comment styles, or improving error-handling patterns. Covers SRP, comment discipline, formatting, and unit testing. For refactoring techniques, see refactoring-patterns. For architecture and dependency rules, see clean-architecture.' +description: 'Write readable, maintainable code through naming, small functions, clean error handling.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/code-review-and-quality/SKILL.md b/.agents/skills/code-review-and-quality/SKILL.md index 01c4ebe0..af491c9e 100644 --- a/.agents/skills/code-review-and-quality/SKILL.md +++ b/.agents/skills/code-review-and-quality/SKILL.md @@ -1,6 +1,6 @@ --- name: code-review-and-quality -description: Conducts multi-axis code review. Use before merging any change. Use when reviewing code written by yourself, another agent, or a human. Use when you need to assess code quality across multiple dimensions before it enters the main branch. +description: 'Conduct multi-axis code review before merging.' --- # Code Review and Quality diff --git a/.agents/skills/code-simplification/SKILL.md b/.agents/skills/code-simplification/SKILL.md index 239b2848..367a95d9 100644 --- a/.agents/skills/code-simplification/SKILL.md +++ b/.agents/skills/code-simplification/SKILL.md @@ -1,102 +1,49 @@ --- name: code-simplification -description: Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read, maintain, or extend than it should be. Use when reviewing code that has accumulated unnecessary complexity. +description: 'Simplify code for clarity without changing behavior.' --- # Code Simplification -> Inspired by the [Claude Code Simplifier plugin](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/code-simplifier/agents/code-simplifier.md). Adapted here as a model-agnostic, process-driven skill for any AI coding agent. - -## Overview - -Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass a simple test: "Would a new team member understand this faster than the original?" +Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass: "Would a new team member understand this faster than the original?" ## When to Use - After a feature is working and tests pass, but the implementation feels heavier than it needs to be - During code review when readability or complexity issues are flagged - When you encounter deeply nested logic, long functions, or unclear names -- When refactoring code written under time pressure - When consolidating related logic scattered across files -- After merging changes that introduced duplication or inconsistency **When NOT to use:** - Code is already clean and readable — don't simplify for the sake of it - You don't understand what the code does yet — comprehend before you simplify - The code is performance-critical and the "simpler" version would be measurably slower -- You're about to rewrite the module entirely — simplifying throwaway code wastes effort ## The Five Principles ### 1. Preserve Behavior Exactly -Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it. +Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. ``` ASK BEFORE EVERY CHANGE: → Does this produce the same output for every input? → Does this maintain the same error behavior? -→ Does this preserve the same side effects and ordering? → Do all existing tests still pass without modification? ``` ### 2. Follow Project Conventions -Simplification means making code more consistent with the codebase, not imposing external preferences. Before simplifying: - -``` -1. Read CLAUDE.md / project conventions -2. Study how neighboring code handles similar patterns -3. Match the project's style for: - - Import ordering and module system - - Function declaration style - - Naming conventions - - Error handling patterns - - Type annotation depth -``` - -Simplification that breaks project consistency is not simplification — it's churn. +Simplification means making code more consistent with the codebase, not imposing external preferences. Match the project's style for imports, naming, error handling, and type annotations. Simplification that breaks project consistency is not simplification — it's churn. ### 3. Prefer Clarity Over Cleverness -Explicit code is better than compact code when the compact version requires a mental pause to parse. - -```typescript -// UNCLEAR: Dense ternary chain -const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active'; - -// CLEAR: Readable mapping -function getStatusLabel(item: Item): string { - if (item.isNew) return 'New'; - if (item.isUpdated) return 'Updated'; - if (item.isArchived) return 'Archived'; - return 'Active'; -} -``` - -```typescript -// UNCLEAR: Chained reduces with inline logic -const result = items.reduce((acc, item) => ({ - ...acc, - [item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 } -}), {}); - -// CLEAR: Named intermediate step -const countById = new Map(); -for (const item of items) { - countById.set(item.id, (countById.get(item.id) ?? 0) + 1); -} -``` +Explicit code is better than compact code when the compact version requires a mental pause to parse. Dense ternaries, chained reduces with inline logic, and single-letter variables obscure intent — replace with readable equivalents. ### 4. Maintain Balance -Simplification has a failure mode: over-simplification. Watch for these traps: - -- **Inlining too aggressively** — removing a helper that gave a concept a name makes the call site harder to read -- **Combining unrelated logic** — two simple functions merged into one complex function is not simpler -- **Removing "unnecessary" abstraction** — some abstractions exist for extensibility or testability, not complexity -- **Optimizing for line count** — fewer lines is not the goal; easier comprehension is +Simplification has a failure mode: over-simplification. Don't inline so aggressively you remove a helper that gave a concept a name. Don't combine two simple functions into one complex one. Don't remove abstractions that exist for extensibility or testability. Fewer lines is not the goal; easier comprehension is. ### 5. Scope to What Changed @@ -106,16 +53,15 @@ Default to simplifying recently modified code. Avoid drive-by refactors of unrel ### Step 1: Understand Before Touching (Chesterton's Fence) -Before changing or removing anything, understand why it exists. This is Chesterton's Fence: if you see a fence across a road and don't understand why it's there, don't tear it down. First understand the reason, then decide if the reason still applies. +Before changing or removing anything, understand why it exists. If you see a fence across a road and don't understand why it's there, don't tear it down. ``` BEFORE SIMPLIFYING, ANSWER: - What is this code's responsibility? - What calls it? What does it call? - What are the edge cases and error paths? -- Are there tests that define the expected behavior? -- Why might it have been written this way? (Performance? Platform constraint? Historical reason?) -- Check git blame: what was the original context for this code? +- Why might it have been written this way? +- Check git blame: what was the original context? ``` If you can't answer these, you're not ready to simplify. Read more context first. @@ -124,39 +70,22 @@ If you can't answer these, you're not ready to simplify. Read more context first Scan for these patterns — each one is a concrete signal, not a vague smell: -**Structural complexity:** - | Pattern | Signal | Simplification | |---------|--------|----------------| -| Deep nesting (3+ levels) | Hard to follow control flow | Extract conditions into guard clauses or helper functions | +| Deep nesting (3+ levels) | Hard to follow control flow | Extract into guard clauses or helper functions | | Long functions (50+ lines) | Multiple responsibilities | Split into focused functions with descriptive names | -| Nested ternaries | Requires mental stack to parse | Replace with if/else chains, switch, or lookup objects | +| Nested ternaries | Requires mental stack to parse | Replace with if/else chains or lookup objects | | Boolean parameter flags | `doThing(true, false, true)` | Replace with options objects or separate functions | -| Repeated conditionals | Same `if` check in multiple places | Extract to a well-named predicate function | - -**Naming and readability:** - -| Pattern | Signal | Simplification | -|---------|--------|----------------| -| Generic names | `data`, `result`, `temp`, `val`, `item` | Rename to describe the content: `userProfile`, `validationErrors` | -| Abbreviated names | `usr`, `cfg`, `btn`, `evt` | Use full words unless the abbreviation is universal (`id`, `url`, `api`) | -| Misleading names | Function named `get` that also mutates state | Rename to reflect actual behavior | -| Comments explaining "what" | `// increment counter` above `count++` | Delete the comment — the code is clear enough | -| Comments explaining "why" | `// Retry because the API is flaky under load` | Keep these — they carry intent the code can't express | - -**Redundancy:** - -| Pattern | Signal | Simplification | -|---------|--------|----------------| +| Generic names | `data`, `result`, `temp`, `val` | Rename to describe content: `userProfile`, `errors` | +| Comments explaining "what" | `// increment counter` above `count++` | Delete — the code is clear enough | +| Comments explaining "why" | `// Retry because the API is flaky` | Keep — they carry intent the code can't express | | Duplicated logic | Same 5+ lines in multiple places | Extract to a shared function | -| Dead code | Unreachable branches, unused variables, commented-out blocks | Remove (after confirming it's truly dead) | -| Unnecessary abstractions | Wrapper that adds no value | Inline the wrapper, call the underlying function directly | -| Over-engineered patterns | Factory-for-a-factory, strategy-with-one-strategy | Replace with the simple direct approach | -| Redundant type assertions | Casting to a type that's already inferred | Remove the assertion | +| Dead code | Unreachable branches, unused variables | Remove after confirming it's truly dead | +| Redundant type assertions | Casting to an already-inferred type | Remove the assertion | ### Step 3: Apply Changes Incrementally -Make one simplification at a time. Run tests after each change. **Submit refactoring changes separately from feature or bug fix changes.** A PR that refactors and adds a feature is two PRs — split them. +Make one simplification at a time. Run tests after each change. **Submit refactoring changes separately from feature or bug fix changes.** ``` FOR EACH SIMPLIFICATION: @@ -166,145 +95,29 @@ FOR EACH SIMPLIFICATION: 4. If tests fail → revert and reconsider ``` -Avoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it. - -**The Rule of 500:** If a refactoring would touch more than 500 lines, invest in automation (codemods, sed scripts, AST transforms) rather than making the changes by hand. Manual edits at that scale are error-prone and exhausting to review. +**The Rule of 500:** If a refactoring would touch more than 500 lines, invest in automation (codemods, AST transforms) rather than making the changes by hand. ### Step 4: Verify the Result -After all simplifications, step back and evaluate the whole: - ``` COMPARE BEFORE AND AFTER: - Is the simplified version genuinely easier to understand? -- Did you introduce any new patterns inconsistent with the codebase? +- Did you introduce patterns inconsistent with the codebase? - Is the diff clean and reviewable? - Would a teammate approve this change? ``` If the "simplified" version is harder to understand or review, revert. Not every simplification attempt succeeds. -## Language-Specific Guidance - -### TypeScript / JavaScript - -```typescript -// SIMPLIFY: Unnecessary async wrapper -// Before -async function getUser(id: string): Promise { - return await userService.findById(id); -} -// After -function getUser(id: string): Promise { - return userService.findById(id); -} - -// SIMPLIFY: Verbose conditional assignment -// Before -let displayName: string; -if (user.nickname) { - displayName = user.nickname; -} else { - displayName = user.fullName; -} -// After -const displayName = user.nickname || user.fullName; - -// SIMPLIFY: Manual array building -// Before -const activeUsers: User[] = []; -for (const user of users) { - if (user.isActive) { - activeUsers.push(user); - } -} -// After -const activeUsers = users.filter((user) => user.isActive); - -// SIMPLIFY: Redundant boolean return -// Before -function isValid(input: string): boolean { - if (input.length > 0 && input.length < 100) { - return true; - } - return false; -} -// After -function isValid(input: string): boolean { - return input.length > 0 && input.length < 100; -} -``` - -### Python - -```python -# SIMPLIFY: Verbose dictionary building -# Before -result = {} -for item in items: - result[item.id] = item.name -# After -result = {item.id: item.name for item in items} - -# SIMPLIFY: Nested conditionals with early return -# Before -def process(data): - if data is not None: - if data.is_valid(): - if data.has_permission(): - return do_work(data) - else: - raise PermissionError("No permission") - else: - raise ValueError("Invalid data") - else: - raise TypeError("Data is None") -# After -def process(data): - if data is None: - raise TypeError("Data is None") - if not data.is_valid(): - raise ValueError("Invalid data") - if not data.has_permission(): - raise PermissionError("No permission") - return do_work(data) -``` - -### React / JSX - -```tsx -// SIMPLIFY: Verbose conditional rendering -// Before -function UserBadge({ user }: Props) { - if (user.isAdmin) { - return Admin; - } else { - return User; - } -} -// After -function UserBadge({ user }: Props) { - const variant = user.isAdmin ? 'admin' : 'default'; - const label = user.isAdmin ? 'Admin' : 'User'; - return {label}; -} - -// SIMPLIFY: Prop drilling through intermediate components -// Before — consider whether context or composition solves this better. -// This is a judgment call — flag it, don't auto-refactor. -``` - ## Common Rationalizations | Rationalization | Reality | |---|---| -| "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change. | -| "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. | -| "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused. | -| "The types make it self-documenting" | Types document structure, not intent. A well-named function explains *why* better than a type signature explains *what*. | -| "This abstraction might be useful later" | Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed. | -| "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure. | -| "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. | +| "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. | +| "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. | +| "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions. | +| "The types make it self-documenting" | Types document structure, not intent. A well-named function explains *why*. | +| "This abstraction might be useful later" | Don't preserve speculative abstractions. Remove it and re-add when needed. | ## Red Flags @@ -313,8 +126,6 @@ function UserBadge({ user }: Props) { - Renaming things to match your preferences rather than project conventions - Removing error handling because "it makes the code cleaner" - Simplifying code you don't fully understand -- Batching many simplifications into one large, hard-to-review commit -- Refactoring code outside the scope of the current task without being asked ## Verification @@ -325,7 +136,5 @@ After completing a simplification pass: - [ ] Linter/formatter passes (no style regressions) - [ ] Each simplification is a reviewable, incremental change - [ ] The diff is clean — no unrelated changes mixed in -- [ ] Simplified code follows project conventions (checked against CLAUDE.md or equivalent) - [ ] No error handling was removed or weakened - [ ] No dead code was left behind (unused imports, unreachable branches) -- [ ] A teammate or review agent would approve the change as a net improvement diff --git a/.agents/skills/code-simplification/reference/language-guide.md b/.agents/skills/code-simplification/reference/language-guide.md new file mode 100644 index 00000000..8e974938 --- /dev/null +++ b/.agents/skills/code-simplification/reference/language-guide.md @@ -0,0 +1,103 @@ +# Language-Specific Simplification Examples + +Load this file on-demand when the target code uses a specific language. Teqo is TypeScript-only; Python is included for general reference. + +## TypeScript / JavaScript + +```typescript +// SIMPLIFY: Unnecessary async wrapper +// Before +async function getUser(id: string): Promise { + return await userService.findById(id); +} +// After +function getUser(id: string): Promise { + return userService.findById(id); +} + +// SIMPLIFY: Manual array building → filter +// Before +const activeUsers: User[] = []; +for (const user of users) { + if (user.isActive) activeUsers.push(user); +} +// After +const activeUsers = users.filter((u) => u.isActive); + +// SIMPLIFY: Verbose conditional assignment +// Before +let displayName: string; +if (user.nickname) { + displayName = user.nickname; +} else { + displayName = user.fullName; +} +// After +const displayName = user.nickname || user.fullName; + +// SIMPLIFY: Redundant boolean return +// Before +function isValid(input: string): boolean { + if (input.length > 0 && input.length < 100) return true; + return false; +} +// After +function isValid(input: string): boolean { + return input.length > 0 && input.length < 100; +} +``` + +## Python + +```python +# SIMPLIFY: Verbose dictionary building +# Before +result = {} +for item in items: + result[item.id] = item.name +# After +result = {item.id: item.name for item in items} + +# SIMPLIFY: Nested conditionals with early return +# Before +def process(data): + if data is not None: + if data.is_valid(): + if data.has_permission(): + return do_work(data) + else: + raise PermissionError("No permission") + else: + raise ValueError("Invalid data") + else: + raise TypeError("Data is None") +# After +def process(data): + if data is None: + raise TypeError("Data is None") + if not data.is_valid(): + raise ValueError("Invalid data") + if not data.has_permission(): + raise PermissionError("No permission") + return do_work(data) +``` + +## React / JSX + +```tsx +// SIMPLIFY: Verbose conditional rendering +// Before +function UserBadge({ user }: Props) { + if (user.isAdmin) { + return Admin; + } else { + return User; + } +} +// After +function UserBadge({ user }: Props) { + const variant = user.isAdmin ? 'admin' : 'default'; + const label = user.isAdmin ? 'Admin' : 'User'; + return {label}; +} +``` diff --git a/.agents/skills/cold-start-problem/SKILL.md b/.agents/skills/cold-start-problem/SKILL.md index ac44a85c..3b7ae0d1 100644 --- a/.agents/skills/cold-start-problem/SKILL.md +++ b/.agents/skills/cold-start-problem/SKILL.md @@ -1,6 +1,6 @@ --- name: cold-start-problem -description: 'Start and scale networked products using Andrew Chen''s "The Cold Start Problem" framework for network effects. Use when the user mentions "network effects", "chicken and egg", "cold start", "two-sided marketplace", "atomic network", "hard side", "liquidity", "critical mass", "invite-only launch", "how do I get my first users", or "the marketplace has no buyers or sellers". Also trigger when launching a marketplace, social, or collaboration product that is worthless without other users, deciding launch sequencing and seeding tactics, or diagnosing stalled network growth at scale. Covers the five stages: cold start, tipping point, escape velocity, hitting the ceiling, and the moat. For word-of-mouth virality, see contagious. For habit-driven retention, see hooked-ux.' +description: 'Start and scale networked products using Andrew Chen's cold-start framework.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/concise-output/SKILL.md b/.agents/skills/concise-output/SKILL.md new file mode 100644 index 00000000..c8394353 --- /dev/null +++ b/.agents/skills/concise-output/SKILL.md @@ -0,0 +1,27 @@ +--- +name: concise-output +description: 'Force concise agent output to reduce token waste.' + Forces concise agent output. Reduces token waste from verbose responses, + unnecessary preambles, and repeated context. Use at session start or + before any skill that produces long output. +--- + +# Concise Output Protocol + +## Rules (always apply) + +1. **≤3 sentences** per response unless the user asks for detail. +2. **Never repeat** what you just read — state only new information or decisions. +3. **No preambles** — skip "Here is...", "Let me...", "I will..." — go straight to the answer. +4. **Code in code blocks** — don't write prose to describe code. +5. **Extract, don't paste** — when reporting tool results, show only relevant lines. +6. **Batch tool calls** — multiple `read`/`grep` calls in one message, not round-tripping. +7. **Show edits only** — when editing, show the changed lines with context, not the full file. +8. **No summary** at the end of a task unless explicitly asked. + +## In skills + +When a skill instructs verbose output (tables, multi-section reports), apply these overrides: +- Tables: max 5 rows unless the user asked for comprehensive coverage +- Reports: lead with the conclusion, details on request +- Checklists: only show items that need attention, skip passed items diff --git a/.agents/skills/contagious/SKILL.md b/.agents/skills/contagious/SKILL.md index a33b5dd7..d1edb72f 100644 --- a/.agents/skills/contagious/SKILL.md +++ b/.agents/skills/contagious/SKILL.md @@ -1,6 +1,6 @@ --- name: contagious -description: 'Engineer word-of-mouth and virality using the STEPPS framework (Social Currency, Triggers, Emotion, Public, Practical Value, Stories). Use when the user mentions "go viral", "word of mouth", "shareable content", "social currency", "why people share", "referral program", "nobody is sharing it", or "make this spread". Also trigger when designing shareable features, crafting social campaigns, or building products that spread through peer recommendation. Covers environmental triggers and high-arousal emotional content. For sticky messaging, see made-to-stick. For persuasion tactics, see influence-psychology.' +description: 'Engineer word-of-mouth and virality using the STEPPS framework.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/context-engineering/SKILL.md b/.agents/skills/context-engineering/SKILL.md index 3429079f..be1f4ae9 100644 --- a/.agents/skills/context-engineering/SKILL.md +++ b/.agents/skills/context-engineering/SKILL.md @@ -1,6 +1,6 @@ --- name: context-engineering -description: Optimizes agent context setup. Use when starting a new session, when agent output quality degrades, when switching between tasks, or when you need to configure rules files and context for a project. +description: 'Optimize agent context setup for better output quality.' --- # Context Engineering diff --git a/.agents/skills/continuous-discovery/SKILL.md b/.agents/skills/continuous-discovery/SKILL.md index f945139c..d570d6cf 100644 --- a/.agents/skills/continuous-discovery/SKILL.md +++ b/.agents/skills/continuous-discovery/SKILL.md @@ -1,6 +1,6 @@ --- name: continuous-discovery -description: 'Build a weekly cadence of customer touchpoints using Opportunity Solution Trees, assumption mapping, and interview snapshots. Use when the user mentions "continuous discovery", "opportunity solution tree", "weekly interviews", "assumption testing", "discovery habits", "product trio", "outcome-based roadmap", "how do I talk to customers regularly", "we keep building things nobody uses", or "connect research to the roadmap". Also trigger when setting up regular customer feedback loops, prioritizing which experiments to run, or tying discovery insights to delivery work. Covers experience mapping, co-creation, and prioritizing opportunities. For interview technique, see mom-test. For team structure, see inspired-product.' +description: 'Build a weekly cadence of customer touchpoints and research.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/create-app/SKILL.md b/.agents/skills/create-app/SKILL.md index 5ed8d58f..6e457db9 100644 --- a/.agents/skills/create-app/SKILL.md +++ b/.agents/skills/create-app/SKILL.md @@ -1,6 +1,6 @@ --- name: create-app -description: 'Guided journey from a raw app idea to a validated, cleanly architected first version that ships on a sustainable cadence. Orchestrates ten skills phase by phase - lean-startup, design-sprint, clean-architecture, domain-driven-design, clean-code, pragmatic-programmer, system-design, ios-hig-design, 37signals-way, software-design-philosophy - asking the user questions at every decision point and recording results in the project docs/ folder (PRODUCT.md, ARCHITECTURE.md, EXPERIMENTS.md, CREATE-APP-PLAN.md) so the journey resumes across sessions. Use when the user wants to build a new app, validate an idea before writing code, architect an MVP that will not need a rewrite, or says ''help me build my app the right way''. App already exists: use improve-app or grow-app. Business idea not yet validated: run create-business first. Marketing site only: use create-website. Architecture-only question: design-code-architecture. For one framework in isolation, invoke that skill directly.' +description: 'Guided journey from app idea to validated, architected first version.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/create-business/SKILL.md b/.agents/skills/create-business/SKILL.md index 127efde8..a151d81b 100644 --- a/.agents/skills/create-business/SKILL.md +++ b/.agents/skills/create-business/SKILL.md @@ -1,6 +1,6 @@ --- name: create-business -description: 'Guided journey from raw idea to a validated, positioned, priced business with a chosen beachhead. Orchestrates ten skills phase by phase - jobs-to-be-done, mom-test, design-sprint, lean-startup, good-strategy-bad-strategy, blue-ocean-strategy, obviously-awesome, hundred-million-offers, monetizing-innovation, crossing-the-chasm - asking the user questions at every decision point and recording results in the project docs/ folder (CUSTOMER.md, POSITIONING.md, OFFER.md, CREATE-BUSINESS-PLAN.md) so the journey resumes across sessions. Use when the user wants to start a new business, validate a startup idea, find product-market fit before building, or says ''I have an idea for a company''. Do not use once the business has paying customers: use grow-business to add revenue and customers, or improve-business to fix strategy and operations. For building the product itself use create-app or create-website. For one framework in isolation, invoke that skill directly.' +description: 'Guided journey from raw idea to validated, positioned business.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/create-website/SKILL.md b/.agents/skills/create-website/SKILL.md index e09c0d95..ffed703c 100644 --- a/.agents/skills/create-website/SKILL.md +++ b/.agents/skills/create-website/SKILL.md @@ -1,6 +1,6 @@ --- name: create-website -description: 'Guided journey from a blank page to a live, high-converting website, built message-first, then design, then conversion. Orchestrates ten skills phase by phase - one-page-marketing, storybrand-messaging, made-to-stick, top-design, web-typography, refactoring-ui, ux-heuristics, cro-methodology, scorecard-marketing, steve-jobs-design-review - asking the user questions at every decision point and recording results in the project docs/ folder (POSITIONING.md, WEBSITE.md, DESIGN.md, CREATE-WEBSITE-PLAN.md) so the journey resumes across sessions. Use when the user wants to build a new website or landing page from scratch, turn a validated idea into a page that converts, or says ''build me a landing page for my SaaS''. Site already exists: use improve-website to fix conversion/UX or grow-website for more traffic; building a software product, not a marketing site: use create-app; no positioning yet: run create-business first or the positioning phase here. For one framework in isolation, invoke that skill directly.' +description: 'Guided journey from blank page to live, high-converting website.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/cro-methodology/SKILL.md b/.agents/skills/cro-methodology/SKILL.md index cb780af4..03c407dd 100644 --- a/.agents/skills/cro-methodology/SKILL.md +++ b/.agents/skills/cro-methodology/SKILL.md @@ -1,6 +1,6 @@ --- name: cro-methodology -description: 'Audit websites and landing pages for conversion issues and design evidence-based A/B tests. Use when the user mentions "landing page isnt converting", "conversion rate", "A/B test", "why visitors leave", "objection handling", "bounce rate", "conversion funnel", "increase signups", or "people add to cart but dont buy". Also trigger when diagnosing why signups are low, designing experiment hypotheses, or auditing checkout flows for friction points. Covers funnel mapping, persuasion assets, and objection/counter-objection frameworks. For overall marketing strategy, see one-page-marketing. For usability issues, see ux-heuristics.' +description: 'Audit websites for conversion issues and design A/B tests.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/crossing-the-chasm/SKILL.md b/.agents/skills/crossing-the-chasm/SKILL.md index 9e0ed5de..1480785a 100644 --- a/.agents/skills/crossing-the-chasm/SKILL.md +++ b/.agents/skills/crossing-the-chasm/SKILL.md @@ -1,6 +1,6 @@ --- name: crossing-the-chasm -description: 'Navigate the technology adoption lifecycle from early adopters to mainstream market. Use when the user mentions "crossing the chasm", "beachhead segment", "whole product", "early adopters vs mainstream", "tech go-to-market", "bowling pin strategy", "technology adoption lifecycle", "pragmatist buyers", "growth stalled after early adopters", or "our go-to-market plan". Also trigger when planning go-to-market for a technical product. Covers the D-Day analogy, bowling-pin strategy, the tornado, and positioning against incumbents. For product positioning, see obviously-awesome. For new market creation, see blue-ocean-strategy.' +description: 'Navigate the technology adoption lifecycle from early to mainstream market.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/ddia-systems/SKILL.md b/.agents/skills/ddia-systems/SKILL.md index beb1d22c..13f3cd3a 100644 --- a/.agents/skills/ddia-systems/SKILL.md +++ b/.agents/skills/ddia-systems/SKILL.md @@ -1,6 +1,6 @@ --- name: ddia-systems -description: 'Design data systems by understanding storage engines, replication, partitioning, transactions, and consistency models. Use when the user mentions "database choice", "which database should I use", "SQL or NoSQL", "replication lag", "partitioning strategy", "consistency vs availability", "stream processing", "ACID transactions", "eventual consistency", "my queries are slow at scale", or "data is inconsistent across replicas". Also trigger when choosing a datastore, designing data pipelines, or debugging distributed-system consistency issues. Covers data models, batch/stream processing, and distributed consensus. For system design, see system-design. For resilience, see release-it.' +description: 'Design data systems: storage engines, replication, partitioning, consistency.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/debugging-and-error-recovery/SKILL.md b/.agents/skills/debugging-and-error-recovery/SKILL.md index 03775802..8327a7dc 100644 --- a/.agents/skills/debugging-and-error-recovery/SKILL.md +++ b/.agents/skills/debugging-and-error-recovery/SKILL.md @@ -1,6 +1,6 @@ --- name: debugging-and-error-recovery -description: Guides systematic root-cause debugging. Use when tests fail, builds break, behavior doesn't match expectations, or you encounter any unexpected error. Use when you need a systematic approach to finding and fixing the root cause rather than guessing. +description: 'Guide systematic root-cause debugging.' --- # Debugging and Error Recovery diff --git a/.agents/skills/deprecation-and-migration/SKILL.md b/.agents/skills/deprecation-and-migration/SKILL.md index 765bdde6..64943b55 100644 --- a/.agents/skills/deprecation-and-migration/SKILL.md +++ b/.agents/skills/deprecation-and-migration/SKILL.md @@ -1,6 +1,6 @@ --- name: deprecation-and-migration -description: Manages deprecation and migration. Use when removing old systems, APIs, or features. Use when migrating users from one implementation to another. Use when deciding whether to maintain or sunset existing code. +description: 'Manage deprecation and migration of systems.' --- # Deprecation and Migration diff --git a/.agents/skills/design-code-architecture/SKILL.md b/.agents/skills/design-code-architecture/SKILL.md index 9324abc4..d2a0e641 100644 --- a/.agents/skills/design-code-architecture/SKILL.md +++ b/.agents/skills/design-code-architecture/SKILL.md @@ -1,6 +1,6 @@ --- name: design-code-architecture -description: 'Guided journey from an app idea to a deliberate architecture: boundaries, domain model, data decisions, and resilience, making only the expensive-to-reverse decisions and deferring the rest. Orchestrates eight skills phase by phase - clean-architecture, domain-driven-design, system-design, ddia-systems, software-design-philosophy, release-it, pragmatic-programmer, 37signals-way - asking the user questions at every decision point and recording results in the project docs/ folder (ARCHITECTURE.md, RELIABILITY.md, DESIGN-CODE-ARCHITECTURE-PLAN.md) so the journey resumes across sessions. Use when the user wants to design a new app''s architecture, choose boundaries and a domain model before building, decide monolith versus microservices, or says ''how should I structure this app''. If a codebase already exists, use remove-technical-debt (aged) or improve-code-quality (fresh prototype); if the idea is not validated, run create-business or create-app first. For one framework in isolation, invoke that skill directly.' +description: 'Guided journey from app idea to deliberate architecture.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/design-everyday-things/SKILL.md b/.agents/skills/design-everyday-things/SKILL.md index 83cd4052..a2218f45 100644 --- a/.agents/skills/design-everyday-things/SKILL.md +++ b/.agents/skills/design-everyday-things/SKILL.md @@ -1,6 +1,6 @@ --- name: design-everyday-things -description: 'Apply foundational design principles: affordances, signifiers, constraints, feedback, and conceptual models. Use when the user mentions "why is this confusing", "affordance", "error prevention", "discoverability", "human-centered design", "mental model", "mapping", "seven stages of action", "users keep making mistakes", "this is unintuitive", or "people cant figure out how to use it". Also trigger when reducing product complexity or feature creep. Covers the gulfs of execution and evaluation. For usability scoring, see ux-heuristics. For iOS-specific patterns, see ios-hig-design.' +description: 'Apply affordances, signifiers, constraints, feedback, and conceptual models.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/design-sprint/SKILL.md b/.agents/skills/design-sprint/SKILL.md index e8f4d92f..3950688e 100644 --- a/.agents/skills/design-sprint/SKILL.md +++ b/.agents/skills/design-sprint/SKILL.md @@ -1,6 +1,6 @@ --- name: design-sprint -description: 'Run a structured 5-day process to prototype, test, and validate product ideas with real users. Use when the user mentions "design sprint", "validate before we build", "rapid prototype", "test with users", or "should we build this". Also trigger when a team is stuck in endless debate over a high-stakes product decision, or wants to de-risk a costly idea before investing in development. Covers mapping, sketching, deciding, prototyping, and testing across Monday-Friday. For ongoing experimentation and MVPs, see lean-startup. For customer job analysis, see jobs-to-be-done. For non-leading user interviews, see mom-test.' +description: 'Run a structured 5-day process to prototype and validate product ideas.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/documentation-and-adrs/SKILL.md b/.agents/skills/documentation-and-adrs/SKILL.md index 7faf52c9..fd5bf35d 100644 --- a/.agents/skills/documentation-and-adrs/SKILL.md +++ b/.agents/skills/documentation-and-adrs/SKILL.md @@ -1,6 +1,6 @@ --- name: documentation-and-adrs -description: Records decisions and documentation. Use when making architectural decisions, changing public APIs, shipping features, or when you need to record context that future engineers and agents will need to understand the codebase. +description: 'Record decisions, ADRs, and documentation for future context.' --- # Documentation and ADRs diff --git a/.agents/skills/domain-driven-design/SKILL.md b/.agents/skills/domain-driven-design/SKILL.md index 7ee50a23..b1a59647 100644 --- a/.agents/skills/domain-driven-design/SKILL.md +++ b/.agents/skills/domain-driven-design/SKILL.md @@ -1,6 +1,6 @@ --- name: domain-driven-design -description: 'Model software around the business domain using bounded contexts, aggregates, and ubiquitous language. Use when the user mentions "domain modeling", "bounded context", "aggregate root", "ubiquitous language", "anti-corruption layer", "context mapping", "domain events", "strategic design", "the code doesnt match the business", or "how do we split this big system". Also trigger when breaking a monolith into services, defining service boundaries, or aligning code structure with business processes. Covers entities vs value objects, domain events, and context mapping strategies. For architecture layers, see clean-architecture. For complexity, see software-design-philosophy.' +description: 'Model software with bounded contexts, aggregates, and ubiquitous language.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/doubt-driven-development/SKILL.md b/.agents/skills/doubt-driven-development/SKILL.md index f5bc53d0..1755558e 100644 --- a/.agents/skills/doubt-driven-development/SKILL.md +++ b/.agents/skills/doubt-driven-development/SKILL.md @@ -1,6 +1,6 @@ --- name: doubt-driven-development -description: Subjects every non-trivial decision to a fresh-context adversarial review before it stands. Use when correctness matters more than speed, when working in unfamiliar code, when stakes are high (production, security-sensitive logic, irreversible operations), or any time a confident output would be cheaper to verify now than to debug later. +description: 'Adversarial review before acting when correctness matters.' --- # Doubt-Driven Development diff --git a/.agents/skills/drive-motivation/SKILL.md b/.agents/skills/drive-motivation/SKILL.md index b8fbc582..5a7a29a8 100644 --- a/.agents/skills/drive-motivation/SKILL.md +++ b/.agents/skills/drive-motivation/SKILL.md @@ -1,6 +1,6 @@ --- name: drive-motivation -description: 'Design motivation systems using Autonomy, Mastery, and Purpose (AMP) for products and teams. Use when the user mentions "intrinsic motivation", "gamification isnt working", "rewards arent working", "autonomy", "mastery", "purpose-driven", "my team is disengaged", or "how do I motivate people". Also trigger when designing onboarding progression, fixing broken gamification, or building team structures that sustain high performance. Covers why carrot-and-stick fails and how to build progress systems. For habit-forming product loops, see hooked-ux. For retention behavior design, see improve-retention.' +description: 'Design motivation systems using Autonomy, Mastery, Purpose (AMP).' license: MIT metadata: author: wondelai diff --git a/.agents/skills/engineering-audit/SKILL.md b/.agents/skills/engineering-audit/SKILL.md index e34fc061..ec59bd10 100644 --- a/.agents/skills/engineering-audit/SKILL.md +++ b/.agents/skills/engineering-audit/SKILL.md @@ -1,6 +1,6 @@ --- name: engineering-audit -description: Runs a Pass-style engineering audit of the Teqo codebase — code smells, drift from documented patterns, and consolidation of near-duplicate components/hooks/functions/modules — producing a findings ledger and a remediation plan (read-only on code during the sweep; sign-off interativo = apresentação prévia; autônomo = PR Ready + auto-merge dos artefatos; remediações P0/P1 e guardrails de agent-miss na mesma sessão). Use when the user asks for an engineering audit, code-smell sweep, architecture drift check, deduplication/consolidation pass, "Pass 3", "auditoria de engenharia", "varredura de code smells", "consolidação de duplicações", or to plan fixes against the repo's highest engineering standards. +description: 'Run a Pass-style engineering audit of the Teqo codebase.' --- # Engineering Audit (Pass N) diff --git a/.agents/skills/frontend-ui-engineering/SKILL.md b/.agents/skills/frontend-ui-engineering/SKILL.md index ad64ed29..030ccf67 100644 --- a/.agents/skills/frontend-ui-engineering/SKILL.md +++ b/.agents/skills/frontend-ui-engineering/SKILL.md @@ -1,6 +1,6 @@ --- name: frontend-ui-engineering -description: Builds production-quality, accessible, responsive user-facing UIs. Use when building or modifying interfaces and pages, creating components, implementing layouts, meeting WCAG accessibility requirements, managing state, or when the output needs to look and feel production-quality rather than AI-generated. +description: 'Build production-quality, accessible, responsive UIs.' --- # Frontend UI Engineering diff --git a/.agents/skills/git-workflow-and-versioning/SKILL.md b/.agents/skills/git-workflow-and-versioning/SKILL.md index 6b33aefe..918024e1 100644 --- a/.agents/skills/git-workflow-and-versioning/SKILL.md +++ b/.agents/skills/git-workflow-and-versioning/SKILL.md @@ -1,6 +1,6 @@ --- name: git-workflow-and-versioning -description: Structures git workflow practices. Use when making any code change. Use when committing, branching, resolving conflicts, or when you need to organize work across multiple parallel streams. Use when cutting a release, choosing a semantic version bump, tagging, or writing a changelog. +description: 'Structure git workflow: commits, branches, semver, releases.' --- # Git Workflow and Versioning diff --git a/.agents/skills/good-strategy-bad-strategy/SKILL.md b/.agents/skills/good-strategy-bad-strategy/SKILL.md index 4f01c0c4..6cb32192 100644 --- a/.agents/skills/good-strategy-bad-strategy/SKILL.md +++ b/.agents/skills/good-strategy-bad-strategy/SKILL.md @@ -1,6 +1,6 @@ --- name: good-strategy-bad-strategy -description: 'Formulate and audit real strategy using Richard Rumelt''s "Good Strategy Bad Strategy": an honest diagnosis, a guiding policy, and coherent action instead of goals, vision, and wishful thinking. Use when the user mentions "good strategy bad strategy", "strategy kernel", "diagnosis guiding policy coherent action", "our strategy is just goals", "strategic planning", "mission vs strategy", "annual plan", or "is this actually a strategy". Also trigger when auditing a strategy doc or pitch deck for fluff, turning a goal list into real strategy, formulating strategy for a product or company, or finding leverage and proximate objectives. Covers the kernel of strategy, bad-strategy detection, and sources of power. For product positioning, see obviously-awesome. For uncontested markets, see blue-ocean-strategy.' +description: 'Formulate strategy using Rumelt's kernel: diagnosis, policy, action.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/grow-app/SKILL.md b/.agents/skills/grow-app/SKILL.md index 96a3eceb..ce865e90 100644 --- a/.agents/skills/grow-app/SKILL.md +++ b/.agents/skills/grow-app/SKILL.md @@ -1,6 +1,6 @@ --- name: grow-app -description: 'Guided journey from an app people sign up for and then quietly abandon to a sealed retention engine with a habit loop, an activated first run, and one metric the whole team trusts. Orchestrates eight skills phase by phase - hooked-ux, improve-retention, continuous-discovery, lean-ux, inspired-product, lean-analytics, microinteractions, drive-motivation - asking the user questions at every decision point and recording results in the project docs/ folder (PRODUCT.md, METRICS.md, GROW-APP-PLAN.md) so the journey resumes across sessions. Use when the user wants to lift activation and retention, design a habit loop, fix a leaky onboarding funnel, or says ''users sign up then disappear''. Do not use to fix broken UX or performance that no engagement mechanic can paper over - run improve-app first; if there is no app yet, use create-app. For one framework in isolation, invoke that skill directly.' +description: 'Transform an abandoned app into a retention engine with habit loops.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/grow-business/SKILL.md b/.agents/skills/grow-business/SKILL.md index 3b1ebeae..a55da541 100644 --- a/.agents/skills/grow-business/SKILL.md +++ b/.agents/skills/grow-business/SKILL.md @@ -1,6 +1,6 @@ --- name: grow-business -description: 'Guided journey from a business with lucky months to a repeatable growth engine that produces a forecast. Orchestrates nine skills phase by phase - one-page-marketing, hundred-million-offers, predictable-revenue, contagious, influence-psychology, crossing-the-chasm, cold-start-problem, lean-analytics, negotiation - asking the user questions at every decision point and recording results in the project docs/ folder (MARKETING.md, OFFER.md, METRICS.md, GROW-BUSINESS-PLAN.md) so the journey resumes across sessions. Use when the user wants to build a marketing and sales system, manufacture predictable pipeline, engineer word-of-mouth and referrals, or says ''revenue is real but lumpy and I need growth that repeats''. If the offer, retention, or operations underneath are broken, run improve-business first; with no paying customers yet, start with create-business; when the product itself must carry the growth loops, use grow-app. For one framework in isolation, invoke that skill directly.' +description: 'Build a repeatable growth engine with predictable pipeline.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/grow-website/SKILL.md b/.agents/skills/grow-website/SKILL.md index 0c67b300..0d6d493a 100644 --- a/.agents/skills/grow-website/SKILL.md +++ b/.agents/skills/grow-website/SKILL.md @@ -1,6 +1,6 @@ --- name: grow-website -description: 'Guided journey from a website with traffic it under-converts to a research-driven growth engine that captures more leads, persuades more buyers, sells a sharper offer, and earns referrals. Orchestrates eight skills phase by phase - cro-methodology, scorecard-marketing, storybrand-messaging, made-to-stick, influence-psychology, hundred-million-offers, contagious, one-page-marketing - asking the user questions at every decision point and recording results in the project docs/ folder (WEBSITE.md, OFFER.md, MARKETING.md, GROW-WEBSITE-PLAN.md) so the journey resumes across sessions. Use when the user wants to raise conversion on a site that already has traffic, capture more leads, sharpen a weak offer, add referral loops, or says ''my site gets visitors but nobody buys''. If a broken funnel or usability friction is the real blocker, run improve-website first; if there is no site yet, use create-website. For one framework in isolation, invoke that skill directly.' +description: 'Turn a website into a research-driven growth engine.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/high-output-management/SKILL.md b/.agents/skills/high-output-management/SKILL.md index 30976da3..33fabfab 100644 --- a/.agents/skills/high-output-management/SKILL.md +++ b/.agents/skills/high-output-management/SKILL.md @@ -1,6 +1,6 @@ --- name: high-output-management -description: 'Manage for output using Grove''s "High Output Management": a manager''s output is their organization''s output, raised by high-leverage activities. Use when the user mentions "high output management", "managerial leverage", "one-on-ones", "1:1 agenda", "OKRs", "performance review", "task-relevant maturity", "delegation", "meeting overload", "new manager", "how do I run a 1:1", or "just got promoted to manager". Also trigger when structuring a manager''s calendar and meeting cadence, designing team metrics, running planning, coaching delegation, or preparing performance reviews. Covers leverage, production principles, meetings as the medium of management, decisions, OKRs, and task-relevant maturity. For intrinsic motivation, see drive-motivation. For a company operating system, see traction-eos.' +description: 'Manage for output using Grove's High Output Management principles.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/high-perf-browser/SKILL.md b/.agents/skills/high-perf-browser/SKILL.md index 7ae6e321..0c0bc104 100644 --- a/.agents/skills/high-perf-browser/SKILL.md +++ b/.agents/skills/high-perf-browser/SKILL.md @@ -1,6 +1,6 @@ --- name: high-perf-browser -description: 'Optimize web performance through network protocols, resource loading, and browser rendering internals. Use when the user mentions "my site is slow", "Core Web Vitals", "HTTP/2 or HTTP/3", "resource hints", "network latency", "render blocking", "TCP/TLS optimization", "service worker", "Cache-Control or caching strategy", or "critical rendering path". Also trigger when diagnosing slow page loads, optimizing time to first byte, choosing between WebSocket and SSE, or reducing bundle sizes. For UI visual performance, see refactoring-ui. For font loading, see web-typography.' +description: 'Optimize web performance: protocols, resource loading, rendering.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/hooked-ux/SKILL.md b/.agents/skills/hooked-ux/SKILL.md index b7f31826..08c8190c 100644 --- a/.agents/skills/hooked-ux/SKILL.md +++ b/.agents/skills/hooked-ux/SKILL.md @@ -1,6 +1,6 @@ --- name: hooked-ux -description: 'Design habit-forming product loops using the Hook Model (Trigger, Action, Variable Reward, Investment). Use when the user mentions "users arent coming back", "habit formation", "engagement loops", "habit zone", or "the manipulation matrix". Also trigger when designing notification or re-engagement strategies, building streaks or progress systems, or analyzing why users stop after signup. Covers ethics evaluation and onboarding for habits. For friction reduction and B=MAP, see improve-retention. For viral sharing, see contagious.' +description: 'Design habit-forming product loops using the Hook Model.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/hundred-million-offers/SKILL.md b/.agents/skills/hundred-million-offers/SKILL.md index 9dd465be..216931e7 100644 --- a/.agents/skills/hundred-million-offers/SKILL.md +++ b/.agents/skills/hundred-million-offers/SKILL.md @@ -1,6 +1,6 @@ --- name: hundred-million-offers -description: 'Create irresistible offers using the Value Equation, bonus stacking, risk-reversing guarantees, and ethical scarcity. Use when the user mentions "grand slam offer", "make my offer more compelling", "what bonuses should I add", "guarantee strategy", "offer naming", or "people say its too expensive". Also trigger when packaging a product for higher perceived value, justifying premium pricing instead of discounting, designing a money-back guarantee, or structuring tiers to maximize conversions. Covers the MAGIC naming formula and starving-crowd targeting. For product positioning, see obviously-awesome. For outbound sales, see predictable-revenue.' +description: 'Create irresistible offers using the Value Equation and bonus stacking.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/idea-refine/SKILL.md b/.agents/skills/idea-refine/SKILL.md index 38955e89..1fa0c7a9 100644 --- a/.agents/skills/idea-refine/SKILL.md +++ b/.agents/skills/idea-refine/SKILL.md @@ -1,6 +1,6 @@ --- name: idea-refine -description: Refines raw ideas into sharp, actionable concepts through structured divergent and convergent thinking. Use when an idea is still vague, when you need to stress-test assumptions before committing to a plan, or when you want to expand options before converging on one. Triggers on "ideate", "refine this idea", or "stress-test my plan". +description: 'Refine raw ideas through structured divergent and convergent thinking.' --- # Idea Refine diff --git a/.agents/skills/impeccable/SKILL.md b/.agents/skills/impeccable/SKILL.md index de54a3ae..c016743c 100644 --- a/.agents/skills/impeccable/SKILL.md +++ b/.agents/skills/impeccable/SKILL.md @@ -1,6 +1,6 @@ --- name: impeccable -description: Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks. +description: 'Design award-winning, immersive frontend interfaces with extreme craft.' version: 4.0.4 --- diff --git a/.agents/skills/improve-app/SKILL.md b/.agents/skills/improve-app/SKILL.md index 6aec9b8c..37879487 100644 --- a/.agents/skills/improve-app/SKILL.md +++ b/.agents/skills/improve-app/SKILL.md @@ -1,6 +1,6 @@ --- name: improve-app -description: 'Guided journey from a shipped app that works but feels rough to a product that fits the job, flows without friction, reads clearly, and persuades honestly. Orchestrates nine skills phase by phase - jobs-to-be-done, ux-heuristics, design-everyday-things, refactoring-ui, microinteractions, made-to-stick, influence-psychology, high-perf-browser, steve-jobs-design-review - asking the user questions at every decision point and recording results in the project docs/ folder (CUSTOMER.md, DESIGN.md, POSITIONING.md, IMPROVE-APP-PLAN.md) so the journey resumes across sessions. Use when the user wants to fix a clunky product, cut UX friction, sharpen in-app copy and prompts, or says ''the app works but feels rough''. Do not use for code, tests, or production hardening - use improve-code-quality (fresh prototype) or remove-technical-debt (aged codebase); no app yet, create-app; needs growth loops, grow-app; marketing-site friction, improve-website. For one framework in isolation, invoke that skill directly.' +description: 'Fix a clunky product: cut UX friction, sharpen copy, add delight.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/improve-business/SKILL.md b/.agents/skills/improve-business/SKILL.md index 85e5fd11..59bfb74a 100644 --- a/.agents/skills/improve-business/SKILL.md +++ b/.agents/skills/improve-business/SKILL.md @@ -1,6 +1,6 @@ --- name: improve-business -description: 'Guided journey from a stalled, plateaued business to one with an honest diagnosis, a working operating rhythm, and offers repriced to real value. Orchestrates eight skills phase by phase - good-strategy-bad-strategy, traction-eos, high-output-management, team-topologies, drive-motivation, lean-analytics, negotiation, monetizing-innovation - asking the user questions at every decision point and recording results in the project docs/ folder (STRATEGY.md, OPERATIONS.md, METRICS.md, IMPROVE-BUSINESS-PLAN.md) so the journey resumes across sessions. Use when the user wants to fix a business that has plateaued, diagnose why growth stalled, tighten strategy and execution, re-motivate a team, or says ''revenue is flat and I do not know why''. Starting from scratch with no customers: use create-business. Once the fundamentals work and the goal is expansion: use grow-business. When the product itself drags the business down: use improve-app. For one framework in isolation, invoke that skill directly.' +description: 'Diagnose a stalled business and tighten strategy and operations.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/improve-code-quality/SKILL.md b/.agents/skills/improve-code-quality/SKILL.md index 694385b8..2e5f17bd 100644 --- a/.agents/skills/improve-code-quality/SKILL.md +++ b/.agents/skills/improve-code-quality/SKILL.md @@ -1,6 +1,6 @@ --- name: improve-code-quality -description: 'Guided journey from a working-but-untested vibe-coded prototype to a production-ready product with tests, clean structure, a business-rules boundary, and resilience at scale. Orchestrates nine skills phase by phase - working-with-legacy-code, clean-code, refactoring-patterns, software-design-philosophy, clean-architecture, pragmatic-programmer, release-it, system-design, ddia-systems - asking the user questions at every decision point and recording results in the project docs/ folder (TESTING.md, TECH-DEBT.md, RELIABILITY.md, IMPROVE-CODE-QUALITY-PLAN.md) so the journey resumes across sessions. Use when the user wants to harden an AI-generated prototype, add tests before refactoring, make code safe to change, or says ''this works on my machine but I am scared to touch it''. For a large aged codebase, use remove-technical-debt; to decide structure before building, use design-code-architecture; for a product and UX pass, use improve-app. For one framework in isolation, invoke that skill directly.' +description: 'Harden a vibe-coded prototype into production-ready code with tests.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/improve-retention/SKILL.md b/.agents/skills/improve-retention/SKILL.md index 7ec75a60..b3123847 100644 --- a/.agents/skills/improve-retention/SKILL.md +++ b/.agents/skills/improve-retention/SKILL.md @@ -1,6 +1,6 @@ --- name: improve-retention -description: 'Diagnose and fix retention problems using behavior design (B=MAP). Use when the user mentions "users sign up but dont stick around", "activation rate", "onboarding friction", "retention metrics", "why users dont complete", "churn analysis", or "aha moment". Also trigger when analyzing cohort retention curves, designing activation milestones, reducing time-to-value for new users, or investigating why users quit after their first session. Covers the Ability Chain, prompt design, and tiny behaviors that compound. For habit loops and variable rewards, see hooked-ux. For intrinsic motivation, see drive-motivation.' +description: 'Diagnose and fix retention problems using behavior design (B=MAP).' license: MIT metadata: author: wondelai diff --git a/.agents/skills/improve-website/SKILL.md b/.agents/skills/improve-website/SKILL.md index 1c80b5c6..32a19f65 100644 --- a/.agents/skills/improve-website/SKILL.md +++ b/.agents/skills/improve-website/SKILL.md @@ -1,6 +1,6 @@ --- name: improve-website -description: 'Guided journey from a live website that underperforms to a prioritized, evidence-backed backlog of conversion, usability, message, and speed fixes - each shipped as a testable experiment. Orchestrates eight skills phase by phase - cro-methodology, ux-heuristics, refactoring-ui, web-typography, storybrand-messaging, high-perf-browser, made-to-stick, design-everyday-things - asking the user questions at every decision point and recording results in the project docs/ folder (WEBSITE.md, DESIGN.md, EXPERIMENTS.md, IMPROVE-WEBSITE-PLAN.md) so the journey resumes across sessions. Use when the user wants to fix a landing page that isn''t converting, diagnose why visitors leave, audit for clarity and usability, or says ''the homepage feels off but a redesign didn''t help''. Do not use with no site yet - use create-website; if it converts but needs more traffic or leads, grow-website; if the friction is in a product app, not the marketing site, improve-app. For one framework in isolation, invoke that skill directly.' +description: 'Fix a landing page that isn't converting with evidence-backed experiments.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/incremental-implementation/SKILL.md b/.agents/skills/incremental-implementation/SKILL.md index 3caa0c46..dfcecd73 100644 --- a/.agents/skills/incremental-implementation/SKILL.md +++ b/.agents/skills/incremental-implementation/SKILL.md @@ -1,6 +1,6 @@ --- name: incremental-implementation -description: Delivers changes incrementally. Use when implementing any feature or change that touches more than one file. Use when you're about to write a large amount of code at once, or when a task feels too big to land in one step. +description: 'Deliver changes incrementally, one step at a time.' --- # Incremental Implementation diff --git a/.agents/skills/influence-psychology/SKILL.md b/.agents/skills/influence-psychology/SKILL.md index e8741733..b423dfeb 100644 --- a/.agents/skills/influence-psychology/SKILL.md +++ b/.agents/skills/influence-psychology/SKILL.md @@ -1,6 +1,6 @@ --- name: influence-psychology -description: 'Apply the seven principles of ethical persuasion (reciprocity, commitment, social proof, authority, liking, scarcity, unity) to product design, copy, and sales. Use when the user mentions "social proof", "persuasive copy", "why users dont convert", "ethical persuasion", "reciprocity", "scarcity tactics", "commitment and consistency", "shared identity", "in-group", "make my copy more persuasive", "increase trust", or "get more people to say yes". Also trigger when designing testimonial sections, crafting urgency messaging, or improving trust signals on landing pages. Covers the principles, when each applies, and ethical limits. For deal negotiation tactics, see negotiation. For viral word-of-mouth, see contagious.' +description: 'Apply seven principles of ethical persuasion to product design.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/inspired-product/SKILL.md b/.agents/skills/inspired-product/SKILL.md index 56f5b502..4a268261 100644 --- a/.agents/skills/inspired-product/SKILL.md +++ b/.agents/skills/inspired-product/SKILL.md @@ -1,6 +1,6 @@ --- name: inspired-product -description: 'Build empowered product teams using discovery and delivery dual-track. Use when the user mentions "product discovery", "empowered teams", "feature factory", "opportunity assessment", "product vision", "product strategy", "what should we build", or "our roadmap is just a feature list". Also trigger when restructuring teams away from output-driven models, or deciding what to build next based on outcomes. Covers discovery techniques, team structure, opportunity assessment, vision/strategy, and continuous delivery. For customer interviews, see mom-test. For ongoing discovery systems, see continuous-discovery.' +description: 'Build empowered product teams using discovery and delivery dual-track.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/interview-me/SKILL.md b/.agents/skills/interview-me/SKILL.md index de5e3aff..814fd95d 100644 --- a/.agents/skills/interview-me/SKILL.md +++ b/.agents/skills/interview-me/SKILL.md @@ -1,6 +1,6 @@ --- name: interview-me -description: Extracts what the user actually wants instead of what they think they should want. Achieves this through one-question-at-a-time interview until ~95% confidence about the underlying intent. Use when an ask is underspecified ("build me X" without "for whom" or "why now"), when the user explicitly invokes ("interview me", "grill me", "are we sure?", "stress-test my thinking"), or when you catch yourself silently filling in ambiguous requirements before any plan, spec, or code exists. +description: 'Extract what the user actually wants through one-question-at-a-time interview.' --- # Interview Me diff --git a/.agents/skills/ios-hig-design/SKILL.md b/.agents/skills/ios-hig-design/SKILL.md index f823aeb7..46d22c97 100644 --- a/.agents/skills/ios-hig-design/SKILL.md +++ b/.agents/skills/ios-hig-design/SKILL.md @@ -1,6 +1,6 @@ --- name: ios-hig-design -description: 'Design native iOS interfaces following Apple Human Interface Guidelines. Use when the user mentions "iPhone app", "iPad layout", "SwiftUI", "UIKit", "Dynamic Island", "safe areas", "HIG compliance", "SF Symbols", "haptic feedback", "iOS accessibility", "make my app feel native", or "follow Apple design guidelines". Also trigger when building tab bars, navigation stacks, sheets, or modals for iOS, implementing dark mode, or adapting layouts across screen sizes. Covers navigation patterns, accessibility, SF Symbols, and platform conventions. For general UI polish, see refactoring-ui. For affordance design, see design-everyday-things.' +description: 'Design native iOS interfaces following Apple HIG.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/jobs-to-be-done/SKILL.md b/.agents/skills/jobs-to-be-done/SKILL.md index 8bcb37af..6e4df256 100644 --- a/.agents/skills/jobs-to-be-done/SKILL.md +++ b/.agents/skills/jobs-to-be-done/SKILL.md @@ -1,6 +1,6 @@ --- name: jobs-to-be-done -description: 'Discover what customers truly need by analyzing the "job" they hire your product to do. Use when the user mentions "customer discovery", "why customers churn", "what job does this solve", "competing against luck", "product-market fit", "switching behavior", "milkshake moment", or "functional vs emotional jobs". Also trigger when investigating why users choose competitors, designing features around real customer needs, or reframing a value proposition. Covers JTBD interviews, competition analysis, and jobs-oriented roadmaps. For product positioning, see obviously-awesome. For rapid validation, see design-sprint. For non-leading interview technique, see mom-test.' +description: 'Discover what customers truly need by analyzing the job they hire your product to do.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/lean-analytics/SKILL.md b/.agents/skills/lean-analytics/SKILL.md index 7eab6a6a..dc0f680a 100644 --- a/.agents/skills/lean-analytics/SKILL.md +++ b/.agents/skills/lean-analytics/SKILL.md @@ -1,6 +1,6 @@ --- name: lean-analytics -description: 'Choose and audit startup metrics using Croll and Yoskovitz''s "Lean Analytics". Use when the user mentions "what metrics should we track", "KPIs", "north star metric", "One Metric That Matters (OMTM)", "vanity metrics", "analytics dashboard", "DAU/MAU", "churn benchmark", or "measure product-market fit". Also trigger when choosing metrics for a startup or feature, auditing a dashboard for vanity metrics, setting metric targets and baselines, or instrumenting a product by business model and stage. Covers good-vs-vanity metrics, the One Metric That Matters, metrics by business model, the five startup stages, and benchmarks. For the build-measure-learn loop, see lean-startup. For fixing activation and retention, see improve-retention.' +description: 'Choose and audit startup metrics using Lean Analytics.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/lean-startup/SKILL.md b/.agents/skills/lean-startup/SKILL.md index aa35a366..a2330e7f 100644 --- a/.agents/skills/lean-startup/SKILL.md +++ b/.agents/skills/lean-startup/SKILL.md @@ -1,6 +1,6 @@ --- name: lean-startup -description: 'Design MVPs, validated learning experiments, and pivot-or-persevere decisions using Build-Measure-Learn. Use when the user mentions "MVP scope", "validated learning", "pivot or persevere", "vanity metrics", "test assumptions", "innovation accounting", "build-measure-learn", "minimum viable experiment", "should we pivot", "test a business idea cheaply", or "build the smallest version first". Also trigger when deciding what to include in a first version, measuring startup progress, or evaluating whether to change direction on a product bet. Covers innovation accounting and actionable metrics. For 5-day prototype testing, see design-sprint. For customer motivation analysis, see jobs-to-be-done.' +description: 'Design MVPs and validated learning experiments using Build-Measure-Learn.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/lean-ux/SKILL.md b/.agents/skills/lean-ux/SKILL.md index a130889f..aacd77ed 100644 --- a/.agents/skills/lean-ux/SKILL.md +++ b/.agents/skills/lean-ux/SKILL.md @@ -1,6 +1,6 @@ --- name: lean-ux -description: 'Apply lean thinking to UX: hypothesis-driven design, collaborative sketching, and rapid experiments instead of heavy deliverables. Use when the user mentions "Lean UX", "design hypothesis", "outcome over output", "design studio method", "assumption mapping", "lightweight research", "too much design documentation", or "get the team designing together". Also trigger when reducing design-documentation overhead, getting cross-functional teams to co-design, or running fast usability experiments. Covers hypothesis statements, MVPs for UX, and cross-functional collaboration. For Build-Measure-Learn, see lean-startup. For usability audits, see ux-heuristics.' +description: 'Apply lean thinking to UX: hypothesis-driven design and rapid experiments.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/local-database/SKILL.md b/.agents/skills/local-database/SKILL.md index 6c9514bf..f9acb0b9 100644 --- a/.agents/skills/local-database/SKILL.md +++ b/.agents/skills/local-database/SKILL.md @@ -1,6 +1,6 @@ --- name: local-database -description: Set up, refresh, and safely use the Teqo local Postgres database, and copy production content locally with `pnpm db:pull`. Use when starting local development, when the local database is empty or stale, when preparing the test database, or when the user mentions the local DB, docker-compose, db:pull, or seeding local data. Enforces that local development and tests never touch the production Neon database. +description: 'Set up and safely use the Teqo local Postgres database.' --- # Teqo Local Database diff --git a/.agents/skills/made-to-stick/SKILL.md b/.agents/skills/made-to-stick/SKILL.md index 9beea35a..6f0b9575 100644 --- a/.agents/skills/made-to-stick/SKILL.md +++ b/.agents/skills/made-to-stick/SKILL.md @@ -1,6 +1,6 @@ --- name: made-to-stick -description: 'Craft messages that are understood, remembered, and drive action using the SUCCESs checklist (Simple, Unexpected, Concrete, Credible, Emotional, Stories). Use when the user mentions "make it memorable", "no one remembers our pitch", "tagline", "value proposition", "why the message isnt landing", "curse of knowledge", or "concrete language". Also trigger when writing a pitch deck, simplifying a complex product explanation, or making a presentation more compelling. Covers the six SUCCESs traits and the curse of knowledge. For narrative brand frameworks, see storybrand-messaging. For viral sharing, see contagious.' +description: 'Craft messages that are understood, remembered, and drive action (SUCCESs).' license: MIT metadata: author: wondelai diff --git a/.agents/skills/microinteractions/SKILL.md b/.agents/skills/microinteractions/SKILL.md index 38ea3e5a..41a683b4 100644 --- a/.agents/skills/microinteractions/SKILL.md +++ b/.agents/skills/microinteractions/SKILL.md @@ -1,6 +1,6 @@ --- name: microinteractions -description: 'Design the small details -- triggers, rules, feedback, loops and modes -- that separate good products from great ones. Use when the user mentions "microinteraction", "button feedback", "loading state", "toggle design", "animation detail", "state transitions", "input feedback", "the interface feels dead", "make the UI feel responsive", or "add polish to interactions". Also trigger when designing form-validation responses, progress indicators, confirmation dialogs, or any element where the user expects immediate feedback. Covers trigger design, state rules, feedback mechanisms, and progressive loops. For overall UI polish, see refactoring-ui. For affordance design, see design-everyday-things.' +description: 'Design small details: triggers, rules, feedback, loops, and modes.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/model-selection/SKILL.md b/.agents/skills/model-selection/SKILL.md deleted file mode 100644 index eb4372c7..00000000 --- a/.agents/skills/model-selection/SKILL.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -name: model-selection -description: >- - Escolhe o modelo (e o nível de raciocínio/effort) com melhor custo/valor - para cada classe de tarefa do Teqo, e despacha subagentes já no modelo certo - via o parâmetro `model` da tool Task. Cardápio único Cursor (Composer 2.5, - Grok 4.5, Kimi K3 Low). Toda Issue declara `model:` único. Usar ao sugerir - modelo em plan-issue, ao despachar subagentes, antes de /simplify, ou quando - o usuário perguntar "qual modelo usar". ---- - -# Seleção de modelo × effort - -**Um cardápio para `model:` (Cursor):** - -Dois eixos, nesta ordem: **(1) classe da tarefa → família de modelo**, **(2) se Grok → effort**. Preço e contexto compram capacidade; effort compra deliberação. **Não pule o eixo 2** — High não é o default automático. - -## Tabela canônica (2026-08-10) — `model:` - -| Prioridade | Família | Slug `model:` | Quando | -| ---------- | ------- | ------------- | ------ | -| 1 (default) | **Composer 2.5** | `composer-2.5` | Features, chores simples, fixes localizados, docs leves — sempre que couber | -| 2 | **Grok 4.5** | `cursor-grok-4.5-low` \| `cursor-grok-4.5-medium` \| `cursor-grok-4.5-high` | Precisa de deliberação além do Composer (abaixo) | -| 3 | **Kimi K3 Low** | `kimi-k3-low` | Só na **fase de execução** de issues bipartidas (refactor grande / simplify / migrations+RBAC de blast radius alto), depois de um plano fechado | - -**Removidos** desta skill (não usar como 1ª escolha nem fallback documentado): Kimi K2.7, Haiku, GLM, Gemini, Luna. O pool mapeia os slugs `model:` para a API Cloud (`grok-4.5`+`effort`, `kimi-k3`+`reasoning`); slug desconhecido → fallback `composer-2.5`. - -### Quando sair do Composer → Grok (eixo 1) - -Suba para Grok só se **pelo menos um** for verdade: - -- design / approach **não óbvio** (várias opções plausíveis, trade-offs reais); -- **discovery** de produto ou síntese de evidência (entrevistas, jargão, ilhas novas); -- **multi-domínio** (auth+schema+UI, Consent/LGPD, paradigm/skills com julgamento); -- critique visual / harvest de guardrails onde o critério é qualitativo. - -Se o caminho está no plano e é execução mecânica → **fique em Composer** (ou Kimi na exec bipartida). - -### Effort Grok (eixo 2) — escolha explícita - -Depois de escolher Grok, **obrigatório** pickar um effort. Escreva o slug completo na Issue (`model: cursor-grok-4.5-…`). - -| Effort | Slug `model:` | Nome no produto / Task | Quando | -| ------ | ------------- | ---------------------- | ------ | -| **Low** | `cursor-grok-4.5-low` | Cursor Grok 4.5 · Effort Low | Já é Grok-class, mas o trabalho é **mecânico com leve julgamento**: reescrever skills/docs após decisão travada, cutover de strings/base branch, bookkeeping que Composer erra por falta de contexto do paradigma. **Não** use Low para Prettier/merge puro — isso é Composer. | -| **Medium** | `cursor-grok-4.5-medium` | Cursor Grok 4.5 · Effort Medium | **Discovery / análise moderada**, critique/polish visual, harvest de padrões → guardrail, glossário a partir de evidência, chores de processo com trade-offs claros. Default quando Grok cabe e **não** é multi-domínio de alto risco. | -| **High** | `cursor-grok-4.5-high` | Cursor Grok 4.5 · Effort High | **Multi-domínio ou design não óbvio** com custo de falha alto: fundações (auth/sessão/schema), Consent/LGPD, plan half de bipartição, arquitetura nova. | - -**Proibido:** sufixo `-fast` em qualquer slug (`composer-2.5-fast`, `cursor-grok-4.5-high-fast`, …). O pool **pina `fast=false`** em todo spawn cuja família Cloud exponha o param `fast` (Composer, Grok, …). Só omitir o param **não basta**: a API Create-Agent resolve o default da variante, que hoje é `fast=true` (`composer-2.5-fast` no usage dashboard). Se a Issue trouxer `-fast`, o resolver remove o sufixo, resolve a base + `fast=false` e emite warn. - -**Heurística anti-viés:** se você ia marcar High por hábito, pergunte "a falha é cara **e** o desenho é aberto?". Se só uma das duas → Medium (ou Low). Se nenhuma → Composer. - -### Pool × API Cloud - -| Slug `model:` | API `model.id` | params | -| ------------- | -------------- | ------ | -| `cursor-grok-4.5-low` | `grok-4.5` | `effort=low`, `fast=false` | -| `cursor-grok-4.5-medium` | `grok-4.5` | `effort=medium`, `fast=false` | -| `cursor-grok-4.5-high` | `grok-4.5` | `effort=high`, `fast=false` | -| `kimi-k3-low` | `kimi-k3` | `reasoning=low` | -| `composer-2.5` | `composer-2.5` | `fast=false` | - -## Issues muito complexas - -O plano de **implementação** nasce em `work-issue` / `agent-work-issue` (`*-impl.md`), não em `plan-issue`. Preferir **uma** Issue de intenção + Grok no `model:` quando a deliberação de engenharia for cara. - -Bipartir (`{id}-plan` Grok High → `{id}-exec` `kimi-k3-low`) só sob pedido explícito ou blast radius extremo (refactor repo-wide / simplify amplo). Não despachar Kimi K3 Low sem plano de implementação fechado. - -## Regras - -1. **Composer 2.5 é o default.** Se a tarefa cabe nele, não suba de modelo. -2. **Grok exige effort explícito** (`-low` / `-medium` / `-high` no slug). Não deixe `cursor-grok-4.5` sem sufixo; não use High como coringa. -3. **Toda Issue declara `model:` único** (slug Cursor conforme a tabela). Issue sem `model:` está incompleta. -4. **Nunca `-fast`.** Nem em Issue, nem em `Task.model`, nem sob pedido — recusar e usar o slug sem `-fast`. -5. **Kimi K3 Low só na exec bipartida** (ou quando a Issue já declara `kimi-k3-low` após um plan). -6. **Nunca economizar em:** migrations (história congelada), access control (`overrideAccess: false`), Consent/LGPD — se for uma Issue só disso e complexa, bipartir (plan Grok High → exec K3). -7. **Usuário pediu modelo específico:** a escolha dele vence (exceto `-fast`, sempre recusado); avise uma vez se houver desperdício claro. - -## Como aplicar - -- **Frontmatter da Issue:** `model:` único (slug Cursor). No `plan-issue`, sugerir um slug completo com effort; no pool, o spawn usa exatamente o `model:`. -- **Subagentes (`Task.model`):** prefira o slug da Issue quando o enum do produto listar (`composer-2.5`, `cursor-grok-4.5-high`, `kimi-k3-low`, …). **Nunca** escolha variantes `-fast` do enum. Se a Issue é `-low`/`-medium` e o enum não tem o slug, use `inherit` (sessão já no effort certo) ou `cursor-grok-4.5-high` só se a subtarefa for a parte difícil — **não** "promova" a Issue inteira para High. -- **Sessão principal:** o agente não troca o próprio modelo. No `work-issue` (máquina do humano) o modelo é fixo por ambiente — a skill não verifica `model:` (ver gates). No pool, o spawn já fixa o modelo da Issue. -- **Pool:** `POOL_DEFAULT_MODEL_SLUG` = `composer-2.5`; `resolvePoolModel` mapeia os slugs canônicos → API e **sempre** inclui `fast=false` quando o modelo Cloud aceita o param (senão o dashboard fatura `*-fast`). - -## Gates por fluxo - -- **`/simplify`:** herda o modelo da sessão. Preferir sessão em Kimi K3 Low **só** quando houver Issue de exec bipartida; caso contrário Composer ou Grok (effort pela tabela) conforme complexidade. -- **`work-issue`:** **não verifica modelo** — a sessão nasce no modelo fixo do ambiente (máquina do humano: DeepSeek V4 Flash). `model:` da Issue é metadata consultiva (o pool spawna nele; o claim brief o imprime). -- **`agent-work-issue`:** pool já fixou o modelo no spawn; sessão mais forte → informa e segue. -- **`plan-issue`:** sugere via esta tabela (slug único completo com effort); bipartição só sob blast radius extremo / pedido explícito. -- ~~`agent-pool` smoke~~ — **dormente (OPS65)**: workflow removido; pool morto. diff --git a/.agents/skills/mom-test/SKILL.md b/.agents/skills/mom-test/SKILL.md index a29e6592..e162e41d 100644 --- a/.agents/skills/mom-test/SKILL.md +++ b/.agents/skills/mom-test/SKILL.md @@ -1,6 +1,6 @@ --- name: mom-test -description: 'Talk to customers without leading them using Mom Test rules: discuss their life not your idea, ask about specifics in the past, and talk less. Use when the user mentions "customer interviews", "validate my idea", "users say they want it but dont buy", "leading questions", "The Mom Test", "customer feedback bias", or "interview script". Also trigger when preparing user-research questions, interpreting ambiguous feedback, or designing customer-discovery that avoids false positives. Covers commitment and advancement, avoiding compliments, and extracting signal from noise. For product-market fit, see jobs-to-be-done. For rapid prototype testing, see design-sprint.' +description: 'Talk to customers without leading them using Mom Test rules.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/monetizing-innovation/SKILL.md b/.agents/skills/monetizing-innovation/SKILL.md index 242fa6eb..5bd92ee5 100644 --- a/.agents/skills/monetizing-innovation/SKILL.md +++ b/.agents/skills/monetizing-innovation/SKILL.md @@ -1,6 +1,6 @@ --- name: monetizing-innovation -description: 'Design products and pricing around validated willingness to pay, from Ramanujam & Tacke''s "Monetizing Innovation". Use when the user mentions "pricing", "how much should we charge", "willingness to pay", "pricing page", "packaging", "freemium vs free trial", "are we leaving money on the table", "nobody buys at this price", "price increase", or "good-better-best". Also trigger when designing or auditing pricing and packaging, validating willingness to pay before building, segmenting customers by value, or choosing between subscription, usage-based, and freemium models. Covers price-before-product, willingness-to-pay talks, the four failures (feature shock, minivation, hidden gem, undead), leader/filler/killer packaging, and behavioral pricing. For offers and guarantees, see hundred-million-offers. For what customers value, see jobs-to-be-done.' +description: 'Design products and pricing around validated willingness to pay.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/negotiation/SKILL.md b/.agents/skills/negotiation/SKILL.md index ca0df49b..b662c6ea 100644 --- a/.agents/skills/negotiation/SKILL.md +++ b/.agents/skills/negotiation/SKILL.md @@ -1,6 +1,6 @@ --- name: negotiation -description: 'Prepare and execute negotiations using tactical empathy, calibrated questions, and the Ackerman method. Use when the user mentions "salary negotiation", "contract terms", "handling objections", "mirroring and labeling", "difficult conversation", "deal terms", "BATNA", "anchoring", "how do I ask for a raise", "get a better deal", or "they wont budge on price". Also trigger when preparing for a vendor negotiation, resolving a pricing dispute, or navigating a high-stakes conversation where both sides need to feel heard. Covers accusation audits, Black Swan discovery, and the "Thats Right" technique. For persuasion in product and marketing, see influence-psychology.' +description: 'Prepare and execute negotiations using tactical empathy and Ackerman method.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/observability-and-instrumentation/SKILL.md b/.agents/skills/observability-and-instrumentation/SKILL.md index c1513871..606fdfa9 100644 --- a/.agents/skills/observability-and-instrumentation/SKILL.md +++ b/.agents/skills/observability-and-instrumentation/SKILL.md @@ -1,6 +1,6 @@ --- name: observability-and-instrumentation -description: Instruments code so production behavior is visible and diagnosable. Use when adding logging, metrics, tracing, or alerting. Use when shipping any feature that runs in production and you need evidence it works. Use when production issues are reported but you can't tell what happened from the available data. +description: 'Instrument code so production behavior is visible and diagnosable.' --- # Observability and Instrumentation diff --git a/.agents/skills/obviously-awesome/SKILL.md b/.agents/skills/obviously-awesome/SKILL.md index 6e585935..adc9e4ab 100644 --- a/.agents/skills/obviously-awesome/SKILL.md +++ b/.agents/skills/obviously-awesome/SKILL.md @@ -1,6 +1,6 @@ --- name: obviously-awesome -description: 'Define product positioning by mapping competitive alternatives, unique attributes, and best-fit customers to the right market category. Use when the user mentions "positioning", "competitive alternatives", "how to position", "market category", "positioning canvas", "repositioning", "category creation", "what category are we in", or "why prospects dont get what we do". Also trigger when launching a new product, entering a crowded market, or diagnosing why prospects dont grasp the product''s value. Covers the positioning canvas and team workshops. For customer jobs analysis, see jobs-to-be-done. For go-to-market, see crossing-the-chasm.' +description: 'Define product positioning with competitive alternatives and category.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/one-page-marketing/SKILL.md b/.agents/skills/one-page-marketing/SKILL.md index e386d79a..17ad2cfa 100644 --- a/.agents/skills/one-page-marketing/SKILL.md +++ b/.agents/skills/one-page-marketing/SKILL.md @@ -1,6 +1,6 @@ --- name: one-page-marketing -description: 'Build a complete marketing plan covering the full customer journey from stranger to raving fan. Use when the user mentions "marketing plan", "marketing strategy", "target market", "USP", "lead nurture", "customer lifetime value", "PVP Index", or "I dont know where to start with marketing". Also trigger when building a marketing plan from scratch, choosing acquisition channels, or designing end-to-end customer-lifecycle campaigns. Covers the PVP Index, channel selection, and advocacy systems. For brand messaging, see storybrand-messaging. For conversion optimization, see cro-methodology.' +description: 'Build a complete marketing plan covering the full customer journey.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/payload-migrations/SKILL.md b/.agents/skills/payload-migrations/SKILL.md index 3cdf6971..6605ca16 100644 --- a/.agents/skills/payload-migrations/SKILL.md +++ b/.agents/skills/payload-migrations/SKILL.md @@ -1,6 +1,6 @@ --- name: payload-migrations -description: Create, apply, and deploy Payload schema migrations for the Teqo project (Postgres, push disabled). Use when changing any collection/global/field config, adding indexes or enums, reconciling schema drift, writing a data migration, or when the user mentions migrations, migrate:create, or applying schema changes to production. Explains how migrations reach the production Neon database on deploy. +description: 'Create, apply, and deploy Payload schema migrations for Teqo.' --- # Teqo Payload Migrations diff --git a/.agents/skills/performance-optimization/SKILL.md b/.agents/skills/performance-optimization/SKILL.md index d4c1b9fc..0a5704f9 100644 --- a/.agents/skills/performance-optimization/SKILL.md +++ b/.agents/skills/performance-optimization/SKILL.md @@ -1,6 +1,6 @@ --- name: performance-optimization -description: Optimizes application performance across frontend, backend, queries, and databases. Use when performance requirements exist, when you suspect performance regressions, when Core Web Vitals or load times need improvement, when N+1 query patterns need fixing, or when profiling reveals bottlenecks. +description: 'Optimize application performance across frontend, backend, queries.' --- # Performance Optimization diff --git a/.agents/skills/plan-issue/SKILL.md b/.agents/skills/plan-issue/SKILL.md index 7b77cb8c..90aacba1 100644 --- a/.agents/skills/plan-issue/SKILL.md +++ b/.agents/skills/plan-issue/SKILL.md @@ -1,166 +1,134 @@ --- name: plan-issue -description: >- - Transforma ideias humanas em Issues do GitHub + planos de intenção em - docs/plans/ (persona, fluxo, objetivo, direção suave no código — sem - decisões duras de engenharia). Se o item muda UI, apresenta no gate um - rascunho visual HTML+Tailwind (PNG embutido no plano de intenção). Divide - o pedido nas menores tarefas que ainda fazem sentido. Use quando o usuário - pedir /plan-issue, planejar features, fatiar um pedido em Issues, ou - registrar trabalho novo na fila. +description: 'Turn human ideas into tracked GitHub Issues with intention plans and UI drafts.' disable-model-invocation: true --- # Planejar Issues (intenção, não engenharia) -Esta skill transforma ideias soltas em: (1) um **plano de intenção** em `docs/plans/.md` por item, e (2) uma **Issue rastreável no GitHub** (`pnpm agent:register`, frontmatter `id/depends/serializes/priority/model`). As Issues do GitHub (`github.com/fsolla/teqo/issues`) são a fonte canônica de spec/status/deps/prio/modelo — `docs/roadmap.md` é legado congelado e **nunca** é editado aqui. +Transforma ideias soltas em: (1) um **plano de intenção** em `docs/plans/.md` por item, e (2) uma **Issue rastreável no GitHub** (`pnpm agent:register`, frontmatter `id/depends/serializes/priority/model`). -## Ciclo de vida (obrigatório) +## Ciclo de vida ```text -rascunho local (Issue: —) - → GATE (Passo 5) + confirmação explícita do lote - → register com --plan → Issue NÃO claimável (blocked; script enforça) - → commit + PR dos planos (Related #N, nunca Closes) - → merge em main - → promote blocked→ready (`pnpm agent:ready` + Action OPS18 — dual, idempotente) - → fila / pool +parse (main agent) + → exploration sub-agent (findings per idea) + → plan-writing sub-agents (parallel, 1 per idea) + → GATE (main agent) + confirmação explícita + → register sub-agent → PR → merge → promote ``` **Regras duras:** -1. **Nada no Forgejo antes do gate.** Antes da confirmação explícita do Passo 5: proibido `pnpm agent:register`, criar Issue/PR / push de PR de planos. Planos locais (`Issue: —`) ok. -2. **Confirmação = OK ao overview do lote** (ex. “confirma”, “pode registrar”). “Ok” ambíguo no meio da edição **não** dispara o Passo 6. -3. **Register com `--plan` não nasce `ready`.** O script aplica `blocked` automaticamente quando `--plan` está presente (`--blocked` explícito ainda vale para chores sem plano). Sem `--plan` (chore body-only / `file-miss`), pode nascer `ready`. -4. **Promote só depois do plano em `main`.** Nunca flipar para `ready` com o PR ainda aberto — isso recria a race de claim. Caminhos: (A) `pnpm agent:ready -- --issue N` no fim do Passo 6 após merge; (B) Action determinística no merge que lê `Related #N` (OPS18). Ambos idempotentes. -5. **Planos de Issues `in-progress` / `done` / `in-prod` são imutáveis.** Não editar `docs/plans/.md` nem o body de intenção dessas Issues. Refino → **plano + Issue novos** (sucessor; `depends` no pai se fizer sentido). Enquanto a Issue ainda é só `blocked`/`ready` (sem claim), editar o mesmo plano ainda é barato. +1. **Nada no Forgejo antes do gate.** Antes da confirmação: proibido `pnpm agent:register`, criar Issue/PR. +2. **Register com `--plan` nasce `blocked`.** Promote só depois do plano em `main`. +3. **Planos de Issues `in-progress`/`done`/`in-prod` são imutáveis.** +4. **Rascunho UI (obrigatório se muda UI):** HTML+Tailwind commitado no repo. Classe A/sem UI → sem rascunho. -**Rascunho UI (obrigatório se muda UI):** itens com superfície Impeccable **B / C / D** (ou qualquer mudança do que o usuário vê/toca) devem ter um **rascunho HTML+Tailwind** (renderizado em PNG e commitado em `docs/plans/`) no gate — ver [ui-draft-html.md](ui-draft-html.md). Classe A / sem UI → sem rascunho. +## Decomposição em sub-agentes -## Divisão com as skills de execução +Cada fase pesada é delegada a um sub-agente com contexto mínimo. O agente principal orquestra. -| Skill | Papel | -| ----- | ----- | -| **`plan-issue` (esta)** | Intenção humana: o quê / para quem / por quê / outcome. Direção suave no codebase. **Proibido** travar schema, signatures, migrations, abstrações ou “Abordagem” de engenharia. | -| **`work-issue`** | Humano supervisiona: Issue já claimada (claim fora da skill) → plano de **implementação** (Plan mode) → **pausa** para confirmação → executa. | -| **`agent-work-issue`** | Pool / autonomia: Issue já claimada → plano de implementação → executa sem pausa → `/simplify` → `capture-review-debts` → PR Ready + auto-merge. | +### Sub-agente: Explorador -Aqui **não** se implementa código de produto, **não** se escreve plano de implementação, **não** se roda Impeccable craft/critique/polish. O rascunho UI/UX (HTML+Tailwind) é artefato do **gate de intenção**, não entrega de app. +**Quando:** Passo 3, para cada batch de ideias. +**Input:** lista de ideias parseadas + `AGENTS.md` (core) + `codebase-map.mdc` +**Task:** Para cada ideia, encontrar: arquivos relevantes existentes, sobreposição com trabalho entregue, área provável no codebase. **Não escrever planos nem tomar decisões.** +**Output:** ≤15 linhas por ideia (achados concisos). -**Shaping (não tour):** aplique [shaping.md](shaping.md) em silêncio — appetite, fatia mínima útil, rabbit holes de produto, self-score ≥4 antes de gravar. +### Sub-agente: Escritor de plano -**Dados (intenção):** se o item envolve números/KPIs/mapas, aplique [data-presentation.md](data-presentation.md) só até “quem decide o quê com este dado”. A **forma** (chart/mapa/KPI) fica para o plano de implementação. +**Quando:** Passo 3, paralelo (1 sub-agente por ideia). +**Input:** UMA ideia + achados do explorador + `intention-template.md` + `shaping.md` (+ `ui-draft-html.md` se UI) +**Task:** Escrever `docs/plans/.md` conforme o template. **Não registrar Issues nem criar arquivos — só produzir o conteúdo do plano.** +**Output:** conteúdo markdown do plano. + +### Sub-agente: Registrador + +**Quando:** Passo 5, após confirmação do gate. +**Input:** planos aprovados + IDs reservados +**Task:** Rodar `pnpm agent:register` para cada plano. Atualizar headers `Issue: #N`. Criar PR `Related #N`. +**Output:** Issues registradas + links de PR. ## Checklist ``` -- [ ] 1. Parse do lote + dedup (intra-lote, Issues existentes, docs/plans, roadmap legacy) -- [ ] 2. Reserva de IDs de uma vez por trilha (roadmap legacy + issuesById()) -- [ ] 3. Por item (ordem topológica): classificar → fatiar → explorar só o suficiente → intenção completa -- [ ] 4. Sugestão de modelo × effort via model-selection (uma linha por item) -- [ ] 5. GATE: overview do lote + rascunho UI/UX (se muda UI) + esboços de fluxo → confirmar/iterar (PARAR aqui até o humano confirmar; sem Issue/PR) -- [ ] 6. Registro: `agent:register` (`--plan` → `blocked`) → PR `Related #N` → merge → `pnpm agent:ready` +- [ ] 1. Parse do lote + dedup + carregar camada AGENTS +- [ ] 2. Reserva de IDs +- [ ] 3. Dispatch sub-agente explorador → receber findings +- [ ] 4. Dispatch sub-agentes escritores (paralelo) → receber planos +- [ ] 5. GATE: overview + rascunho UI (se muda UI) → confirmar +- [ ] 6. Dispatch sub-agente registrador → PR → merge → promote ``` ## Passo 1 — Parse e dedup -1. **Separe os itens.** Entrada pode ser 1 ideia ou N. Se ambíguo, assuma a leitura mais provável e liste — a confirmação vai no gate. -2. **Fatia mínima útil.** Prefira várias Issues pequenas a um epic. Cada item deve caber num appetite curto e entregar um outcome verificável sozinho. Mesclar só quando separar criaria trabalho inútil (mesmo fluxo, mesma persona, mesma superfície sem valor incremental). -3. **Dedup intra-lote:** mesclar | absorver (fase de plano existente, sem ID novo) | manter separados com `depends`. -4. **Dedup contra o existente:** `pnpm issue all` + `issuesById()` + grep em `docs/plans/*.md` e `docs/roadmap.md` (legado). +1. **Separe os itens.** Entrada pode ser 1 ideia ou N. Se ambíguo, assuma a leitura mais provável. +2. **Carregar camada AGENTS relevante:** se qualquer item toca `/campanha`, leia `AGENTS-campaign.md`. Se toca site público, leia `AGENTS-public.md`. Se toca deploy/CI, leia `AGENTS-infra.md`. +3. **Fatia mínima útil.** Prefira várias Issues pequenas a um epic. +4. **Dedup intra-lote:** mesclar | absorver | manter separados com `depends`. +5. **Dedup contra o existente:** `pnpm issue all` + `issuesById()` + grep em `docs/plans/*.md`. - Já coberto / entregue → apontar e não criar. - - Issue **`in-progress` / `done` / `in-prod`:** **não** editar o plano dela — se a intenção mudou, item **sucessor** (plano + Issue novos). - - Issue só `blocked` / `ready` (ainda não claimada): pode editar o plano existente (fase de plano) sem ID novo. - - Novo → seguir. + - Issue `in-progress`/`done`/`in-prod`: não editar — item sucessor se mudou. + - Issue `blocked`/`ready` (não claimada): pode editar o plano existente. ## Passo 2 — Reserva de IDs -Último ID por trilha (A/B/C/D/E) via roadmap legacy + `issuesById()`; distribua **antes** de escrever planos. Fora de trilha: prefixos `O0+`, `FD+`, `RS+`, `OPS+` ou trilha temática mais próxima. +Último ID por trilha (A/B/C/D/E) via roadmap legacy + `issuesById()`. Distribua antes de escrever planos. -## Passo 3 — Por item: intenção completa +## Passo 3 — Explorar + escrever planos (sub-agentes) -Ordem topológica (dependente cita ID do dependido). Por item: +### 3a. Dispatch sub-agente explorador -1. **Tipo** +Monte o task prompt do explorador com: +- Lista das ideias parseadas (título + 1-linha de intenção) +- Referência: `AGENTS.md` (core) + `codebase-map.mdc` +- Instrução: "Para cada ideia, encontre arquivos relevantes, sobreposição com trabalho entregue, área provável. ≤15 linhas por ideia. Não escreva planos." -| Tipo | Destino | -| ---- | ------- | -| Feature `/campanha` ou site com escopo próprio | `kind:feature` + plano de intenção | -| Chore / débito pequeno | `kind:chore` + plano curto (ou body se trivial) | -| Défice do fluxo de agentes | `pnpm agent:file-miss` (`kind:agent-miss`) — não aqui | -| Bloqueio externo (jurídico/LGPD) | `blocked` + `needs:consent`/`needs:migration`; texto no lote jurídico existente | -| Decisão de NÃO fazer | Comentário/doc, não Issue | +Aguarde o output. Valide que é conciso e factual. -2. **Explorar o código o mínimo** — só para apontar **direção** (rotas/pastas/domínios prováveis) e evitar duplicar algo já entregue. Não inventar signatures, collections novas como decisão travada, nem diagramas de componentes. -3. **Superfície UI (A–D)** como dica para quem for executar — não semear brief Impeccable completo. Classe **B/C/D** (ou qualquer mudança de UI): criar **rascunho HTML+Tailwind** ([ui-draft-html.md](ui-draft-html.md)) **antes do gate**, renderizar o PNG (`pnpm ui-draft:render`) e embutir no plano; ASCII no plano fica opcional. Classe **A** / sem UI: sem rascunho. -4. **Dados (intenção)** ou `Dados: N/A`. -5. **Posicionamento:** `P0..P3`, `depends`, appetite, janela eleitoral se relevante, `serializes` se tocar recurso compartilhado — nomeie o registro exato (ex. `serializes: 'docs/plans/'`, `serializes: 'docs/changelog/'` — migrations **não** serializam, AGENT-OPS). Sem detalhar a migration. -6. **Plano de intenção** em `docs/plans/.md` via [intention-template.md](intention-template.md), com campo **Rascunho UI** preenchido (path do `.html` + PNGs embutidos, ou `N/A`). Self-score ≥4/5 ([shaping.md](shaping.md)). +### 3b. Classificar e reservar IDs -### O que é proibido no plano de intenção +Para cada ideia, classifique (feature/chore/bloqueio/não-fazer) e atribua ID. -- Decisões de schema / collection / unicidade / Consent key concreta como “travadas” -- Assinaturas de funções, nomes de arquivos novos obrigatórios, mermaid de arquitetura de solução -- “Abordagem proposta” com componentes e migration nomeada -- Fases de implementação verificáveis com quota de engenharia -- Forçar o executor a uma única forma técnica +### 3c. Dispatch sub-agentes escritores (paralelo) -### O que é obrigatório +Para cada ideia, monte o task prompt do escritor com: +- **Uma** ideia (título + intenção completa + tipo + ID) +- Achados do explorador para essa ideia +- Templates: `intention-template.md`, `shaping.md` +- Se UI: `ui-draft-html.md` +- Se dados: `data-presentation.md` +- Instrução: "Escreva `docs/plans/.md` conforme o template. Output: conteúdo markdown." -- Intenção do humano (problema/oportunidade) -- Persona(s) e fluxo desejado (job / outcome) -- Critérios de aceite em linguagem de produto -- Appetite e fora de escopo (produto) -- **Direção provável no codebase** (pastas/rotas/domínios — hipotética, revisável) -- Questões em aberto com **Opções + Recomendação de produto** (não de engenharia) -- **Se muda UI:** rascunho UI/UX (HTML+Tailwind → PNG) no gate ([ui-draft-html.md](ui-draft-html.md)) + PNG embutido no plano +Dispatche todos os escritores em paralelo (Task tool). Cada um retorna o conteúdo do plano. -## Passo 4 — Modelo × effort +### 3d. Self-score e revisão -Skill `model-selection`. Registre no cabeçalho (`Model:`) e no gate. +O agente principal: +1. Valida cada plano contra `shaping.md` (self-score ≥4) +2. Aplica melhorias se necessário +3. Cria os arquivos `docs/plans/.md` no disco +4. Se UI: cria `docs/plans/-ui-draft.html` (sub-agente ou inline) -- Default: `composer-2.5` -- Grok com effort explícito quando discovery/multi-domínio / falha cara de **produto** -- Não crie par `{id}-plan` / `{id}-exec` por default — o plano de implementação nasce em `work-issue` / `agent-work-issue`. Reserve bipartição só para blast radius extremo (refactor repo-wide) se o humano pedir. +## Passo 4 — GATE -## Passo 5 — GATE +Antes de criar Issues: -Antes de criar Issues **ou** abrir PR de planos: +- Overview: ID, título, prio, depends, appetite, link do plano +- Para cada item UI: aponte o link do `.html` fonte +- Perguntas acumuladas, recomendação de produto primeiro -- Overview: ID, título, prio, depends, appetite, modelo, link do plano local -- **Para cada item que muda UI:** mostre as imagens do rascunho (PNGs embutidos no plano) + link do `.html` fonte — este é o rascunho visual a validar -- Esboço textual de fluxo só se ajudar; não substitui o rascunho quando há UI -- Perguntas acumuladas numa rodada, recomendação de produto primeiro +**Pare e espere.** Itere até confirmação explícita do lote. -**Pare e espere.** Itere (incluindo o rascunho — HTML → re-render do PNG, se houver UI) até confirmação explícita do lote (não basta um “ok” solto durante a edição). Só então Passo 6. +## Passo 5 — Registro (sub-agente registrador) -## Passo 6 — Registro (não claimável até plano em `main`) +Após confirmação, dispatche o sub-agente registrador com: +- Lista de planos aprovados + IDs +- Instrução: rodar `pnpm agent:register` para cada um, criar PR `Related #N`, aguardar merge, rodar `pnpm agent:ready` -Ordem obrigatória (OPS17): - -1. **Register** (com `--model`; com `--plan` o script nasce `blocked` — não precisa `--blocked` extra): - -```bash -pnpm agent:register -- --id --title "" --prio \ - --depends --kind --plan docs/plans/.md \ - --model -``` - -Sem `--plan`: nasce `ready` (use `--blocked` só se quiser não-claimável sem plano). - -2. Atualize `Issue: #N` (e status) no plano local. -3. Commit + **`pnpm push`** + PR **Ready** `--base main` com **`Related #N`** (nunca `Closes #N` em PR só de `docs/plans/` — `plans-only-closes`). -4. Auto-merge via safety net (`agent-pr-ready-automerge.yml` — o rollup `CI (PR) / checks` verde mergea por rebase); espere o merge em `main`. -5. **Promote** com o script (idempotente se já `ready`; só Issues `blocked` + link `docs/plans/`, sem gates humanos `needs:*` nem `in-progress`/`done`/`in-prod`): - -```bash -pnpm agent:ready -- --issue -``` - -A Action de merge (`plan-issue-ready-on-main-merge.yml`, OPS18) é safety net se este passo falhar — não pule o promote do agente no caminho feliz. - -**NÃO faz:** editar `docs/roadmap.md`; implementar código; claim; escrever `*-impl.md`; editar plano de Issue `in-progress`/`done`/`in-prod`; marcar `ready` antes do plano em `main`; registrar/abrir PR antes do gate. +O agente principal validação o resultado e reporta o resumo. ## Resumo final -Tabela do lote + mesclados/absorvidos/descartados + decisões de produto assumidas _(validar)_ + o que o gate decidiu + Issues `#N` + PRs de plano. +Tabela do lote + mesclados/absorvidos/descartados + Issues `#N` + PRs de plano. diff --git a/.agents/skills/plan-issue/intention-template.md b/.agents/skills/plan-issue/intention-template.md index 15143fbc..f6dd6538 100644 --- a/.agents/skills/plan-issue/intention-template.md +++ b/.agents/skills/plan-issue/intention-template.md @@ -11,9 +11,8 @@ Status: rascunho Atualizado em: Issue: # (após `pnpm agent:register`; senão "—") Priority: -Model: Impeccable: — -Rascunho UI: -ui-draft.html + PNG embutido abaixo> +Rascunho UI: -ui-draft.html> Appetite: Responsável: — @@ -31,7 +30,7 @@ Responsável: — ### Esboço de fluxo (B/C/D) + Omitir se A / sem UI. O artefato obrigatório do gate para UI é o HTML+Tailwind commitado — ver ui-draft-html.md. --> \```text [início] → … → [outcome] @@ -39,11 +38,11 @@ Responsável: — ### Rascunho UI (B/C/D) - + -![Rascunho UI — ](-ui-draft-.png) +- Rascunho UI (gate): `docs/plans/-ui-draft.html` ## Objetivo e aceite @@ -96,6 +95,6 @@ Notas: - Alvo: ~60–100 linhas. Mais que isso costuma significar engenharia vazando para a intenção. - Classe **A:** `Impeccable: A — N/A`; `Rascunho UI: N/A`; omita esboço de fluxo. -- Classe **B/C/D:** rascunho HTML+Tailwind obrigatório no gate ([ui-draft-html.md](ui-draft-html.md)); renderize com `pnpm ui-draft:render` e embuta o PNG no plano. +- Classe **B/C/D:** rascunho HTML+Tailwind obrigatório no gate ([ui-draft-html.md](ui-draft-html.md)); commite o `.html` no repo. - Não rode `/impeccable` aqui. - Self-score shaping ≥4/5 antes de gravar. diff --git a/.agents/skills/plan-issue/skills-map.md b/.agents/skills/plan-issue/skills-map.md index 5b8dcf7b..fa0dd26b 100644 --- a/.agents/skills/plan-issue/skills-map.md +++ b/.agents/skills/plan-issue/skills-map.md @@ -39,7 +39,7 @@ No Teqo: **idea-refine / interview** antes se vago; **spec + plan + tasks** = es `frontend-ui-engineering`, `security-and-hardening`, `performance-optimization`, `code-review-and-quality`, `code-simplification`, `observability-and-instrumentation`, `shipping-and-launch`, `ci-cd-and-automation`, `git-workflow-and-versioning`, `deprecation-and-migration`, `debugging-and-error-recovery`, `browser-testing-with-devtools` — entram em `work-issue` / gates do repo, não no registro da Issue. -**Exceção de superfície:** o **rascunho UI/UX do gate** — HTML+Tailwind renderizado em PNG (`pnpm ui-draft:render`), [ui-draft-html.md](ui-draft-html.md) — é usado no `plan-issue` só quando o item muda UI. Não é implementação de `/campanha` nem substituto de Impeccable. +**Exceção de superfície:** o **rascunho UI/UX do gate** — HTML+Tailwind commitado no repo ([ui-draft-html.md](ui-draft-html.md)) — é usado no `plan-issue` só quando o item muda UI. Não é implementação de `/campanha` nem substituto de Impeccable. ## Precedência quando conflita diff --git a/.agents/skills/plan-issue/ui-draft-html.md b/.agents/skills/plan-issue/ui-draft-html.md index e4f7b46e..d91f0d2e 100644 --- a/.agents/skills/plan-issue/ui-draft-html.md +++ b/.agents/skills/plan-issue/ui-draft-html.md @@ -1,12 +1,12 @@ # Rascunho UI/UX do gate (plan-issue) -Quando o item **muda UI** (classe Impeccable **B / C / D**, ou qualquer superfície que o usuário vê/toca), o gate **obrigatoriamente** apresenta um **rascunho visual** da intenção — não ASCII sozinho, não wireframe de implementação. O meio é **HTML + Tailwind**, renderizado em PNG e **commitado no repo Teqo** junto do plano. (Substitui o antigo Cursor canvas, que vivia fora do repo em `~/.cursor/projects//canvases/`, só renderizava no IDE de quem planejou e apodrecia.) +Quando o item **muda UI** (classe Impeccable **B / C / D**, ou qualquer superfície que o usuário vê/toca), o gate **obrigatoriamente** apresenta um **rascunho visual** da intenção — não ASCII sozinho, não wireframe de implementação. O meio é **HTML + Tailwind**, commitado no repo Teqo junto do plano. ## Para que serve — e para que NÃO serve Serve para **colaborar visualmente com o humano** e fechar **layout, espaçamentos e tamanhos**: hierarquia, zonas, CTAs, densidade, medidas reais. É a linguagem do gate para "é isso que o usuário vê/toca". -**NÃO é** implementação da feature, **NÃO é** protótipo funcional, **NÃO é** entrega de app, **NÃO é** decisão de engenharia. Quem executa (`work-issue` / `agent-work-issue`) constrói a partir do plano; o rascunho é descartável como fonte e imutável como registro (o PNG aprovado). +**NÃO é** implementação da feature, **NÃO é** protótipo funcional, **NÃO é** entrega de app, **NÃO é** decisão de engenharia. Quem executa (`work-issue` / `agent-work-issue`) constrói a partir do plano; o rascunho é descartável como fonte e imutável como registro. ## O que o rascunho DEVE ter (fidelidade mínima) @@ -24,7 +24,7 @@ Serve para **colaborar visualmente com o humano** e fechar **layout, espaçament 4. **Zero mock de dados.** Sem KPIs realistas, nomes reais, números de votos — placeholders óbvios ou barras cinza. 5. **Zero decisão de engenharia.** Sem schema, migration, nomes de arquivos obrigatórios, assinaturas — o rascunho mostra superfície, não solução. -## Como fazer (artefatos no repo) +## Como fazer (artefato no repo) 1. **Escreva** `docs/plans/-ui-draft.html` — um arquivo por item, autossuficiente: @@ -40,41 +40,24 @@ Serve para **colaborar visualmente com o humano** e fechar **layout, espaçament

Persona/job em uma linha + cenas abaixo

-
…
-
…
-
…
+
… desktop …
+
… mobile …
+
… vazio …
``` - - Tailwind **v4** (`@tailwindcss/browser@4`) — mesma major do app (4.1.x). Requer rede apenas na hora de renderizar, nunca no artefato. - - **Cada cena que vira imagem: `
`** (rótulo kebab, ex. `mobile`, `desktop-vazio`). Sem `data-shot`, o script captura a página inteira. - - O arquivo **é commitado** com o plano: o rascunho aprovado vira registro permanente do aceite (o PR revisa HTML + PNG; ninguém depende do IDE de quem planejou). - -2. **Renderize:** - -```bash -pnpm ui-draft:render docs/plans/-ui-draft.html -``` - - → `docs/plans/-ui-draft-.png` (uma por cena `data-shot`) ou `docs/plans/-ui-draft.png` (full-page). Usa o Chromium do Playwright já instalado no repo; nunca toca no banco. - -3. **Embute no plano e commite:** - -```markdown -![Rascunho UI — mobile](-ui-draft-mobile.png) -``` + - Tailwind **v4** (`@tailwindcss/browser@4`) — mesma major do app (4.1.x). Requer rede apenas na hora de renderizar no browser. + - O arquivo **é commitado** com o plano: o rascunho aprovado vira registro permanente do aceite visual. ## Relação com o plano em `docs/plans/` - Campo **Rascunho UI:** no cabeçalho: `docs/plans/-ui-draft.html` (ou `N/A — sem UI`). -- PNGs embutidos no corpo do plano (secção "Rascunho UI (gate)"). -- Esboço ASCII no markdown vira **opcional** (backup textual); o PNG é o artefato do gate. -- **É commitado com o plano** (muda o default antigo de "artefato de sessão, fora do repo"): o PNG aprovado é o registro do aceite visual e viaja com a Issue. +- Link do `.html` no corpo do plano (secção "Rascunho UI (gate)"). +- Esboço ASCII no markdown vira **opcional** (backup textual). +- **É commitado com o plano**: o HTML aprovado é o registro do aceite visual e viaja com a Issue. ## Gate -Antes de `pnpm agent:register`, mostre o overview do lote **e** as imagens do rascunho (PNGs embutidos no plano — o humano vê no chat e no PR) + link do `.html` fonte. Itere: **editar HTML → re-renderizar (`pnpm ui-draft:render`) → atualizar PNGs** até confirmação explícita. Só então registre a Issue. - -Legado: os antigos `plan--ui-draft.canvas.tsx` (Cursor) continuam válidos como histórico de planos passados — nenhum rascunho novo usa canvas. +Antes de `pnpm agent:register`, mostre o overview do lote **e** o link do `.html` fonte — o humano abre no browser para validar. Itere: **editar HTML** até confirmação explícita. Só então registre a Issue. diff --git a/.agents/skills/planning-and-task-breakdown/SKILL.md b/.agents/skills/planning-and-task-breakdown/SKILL.md index 0225a5f2..9297efe5 100644 --- a/.agents/skills/planning-and-task-breakdown/SKILL.md +++ b/.agents/skills/planning-and-task-breakdown/SKILL.md @@ -1,6 +1,6 @@ --- name: planning-and-task-breakdown -description: Breaks work into ordered tasks. Use when you have a spec or clear requirements and need to break work into implementable tasks. Use when a task feels too large to start, when you need to estimate scope, or when parallel work is possible. +description: 'Break work into ordered, implementable tasks.' --- # Planning and Task Breakdown diff --git a/.agents/skills/pragmatic-programmer/SKILL.md b/.agents/skills/pragmatic-programmer/SKILL.md index f655e320..65a973f6 100644 --- a/.agents/skills/pragmatic-programmer/SKILL.md +++ b/.agents/skills/pragmatic-programmer/SKILL.md @@ -1,6 +1,6 @@ --- name: pragmatic-programmer -description: 'Apply meta-principles of software craftsmanship: DRY, orthogonality, tracer bullets, and design by contract. Use when the user mentions "best practices", "pragmatic approach", "broken windows", "tracer bullet", "software craftsmanship", "avoid technical debt", "code ownership", or "how do I become a better developer". Also trigger when evaluating build-vs-buy decisions, designing estimation approaches, or choosing between reversible and irreversible architectural decisions. Covers estimation, domain languages, and reversibility. For code-level quality, see clean-code. For refactoring techniques, see refactoring-patterns.' +description: 'Apply DRY, orthogonality, tracer bullets, and design by contract.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/predictable-revenue/SKILL.md b/.agents/skills/predictable-revenue/SKILL.md index d06bbde5..d54b31d5 100644 --- a/.agents/skills/predictable-revenue/SKILL.md +++ b/.agents/skills/predictable-revenue/SKILL.md @@ -1,6 +1,6 @@ --- name: predictable-revenue -description: 'Build a scalable outbound B2B sales machine with specialized roles (SDR, AE, CSM). Use when the user mentions "outbound sales", "Cold Calling 2.0", "cold email sequences", "sales pipeline", "SDR process", "sales development", "build an outbound sales team", or "fill my pipeline". Also trigger when setting up a B2B SaaS sales team from scratch or building a lead-qualification framework to improve close rates. Covers the three lead types (seeds/nets/spears), role specialization, the referral-email method, ANUM qualification, and pipeline math. For offer design, see hundred-million-offers. For persuasion science, see influence-psychology.' +description: 'Build a scalable outbound B2B sales machine.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/project-status/SKILL.md b/.agents/skills/project-status/SKILL.md index e33a5506..946656b4 100644 --- a/.agents/skills/project-status/SKILL.md +++ b/.agents/skills/project-status/SKILL.md @@ -1,6 +1,6 @@ --- name: project-status -description: Apresenta o estado do projeto Teqo a partir das Issues do GitHub rastreáveis — overview (estado/prio/kind), fila atual na ordem do agent:claim com o modelo de cada item, grafo mermaid de dependências, bloqueios com motivo e sugestões de consolidação (merge/break-down). Read-only; NUNCA modifica Issues, em particular nunca toca Issues in-progress. Usar quando o usuário pedir status/visão geral do projeto, "como está o projeto", "qual a fila", "o que está bloqueado", "mostra o grafo", ou perguntar o que dá para consolidar. +description: 'Show Teqo project status from trackable GitHub Issues.' --- # Status do projeto (read-only) diff --git a/.agents/skills/rebase-on-main/SKILL.md b/.agents/skills/rebase-on-main/SKILL.md index ddb8e64f..15e18adf 100644 --- a/.agents/skills/rebase-on-main/SKILL.md +++ b/.agents/skills/rebase-on-main/SKILL.md @@ -1,6 +1,6 @@ --- name: rebase-on-main -description: >- +description: 'Sync current branch with latest origin/main via fetch + rebase.' Sync the current feature branch with latest origin/main via fetch + rebase, then resolve conflicts intelligently. Auto-handles a dirty tree (commit WIP or stash+pop — no asking). Use after /simplify & /impeccable and before diff --git a/.agents/skills/refactoring-patterns/SKILL.md b/.agents/skills/refactoring-patterns/SKILL.md index a5f58c29..b532adbd 100644 --- a/.agents/skills/refactoring-patterns/SKILL.md +++ b/.agents/skills/refactoring-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: refactoring-patterns -description: 'Apply named refactoring transformations to improve code structure without changing behavior. Use when the user mentions "refactor this", "code smells", "extract method", "replace conditional", "technical debt", "move method", "inline variable", "decompose conditional", or "clean up this messy code". Also trigger when cleaning up legacy code, preparing code for new features by restructuring, or identifying which transformation fits a specific code smell. Covers smell-driven refactoring, safe transformation sequences, and testing guards. For code-quality foundations, see clean-code. For managing complexity, see software-design-philosophy.' +description: 'Apply named refactoring transformations to improve code structure.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/refactoring-ui/SKILL.md b/.agents/skills/refactoring-ui/SKILL.md index 8182b304..aa18bc01 100644 --- a/.agents/skills/refactoring-ui/SKILL.md +++ b/.agents/skills/refactoring-ui/SKILL.md @@ -1,6 +1,6 @@ --- name: refactoring-ui -description: 'Audit and fix visual hierarchy, spacing, color, and depth in web UIs. Use when the user mentions "my UI looks off" (or amateur/unprofessional), "fix the design", "Tailwind styling", "color palette", "visual hierarchy", "design system", "spacing scale", or "component styling". Also trigger when building consistent design tokens, creating dark mode themes, improving data-visualization clarity, or polishing UI details before launch. Covers grayscale-first workflow, constrained design scales, shadows, and component styling. For typeface selection, see web-typography. For usability audits, see ux-heuristics.' +description: 'Audit and fix visual hierarchy, spacing, color, and depth in web UIs.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/release-it/SKILL.md b/.agents/skills/release-it/SKILL.md index b0837fba..22acbfa1 100644 --- a/.agents/skills/release-it/SKILL.md +++ b/.agents/skills/release-it/SKILL.md @@ -1,6 +1,6 @@ --- name: release-it -description: 'Build production-ready systems with stability patterns: circuit breakers, bulkheads, timeouts, and retry logic. Use when the user mentions "production outage", "circuit breaker", "deployment pipeline", "chaos engineering", "retry storm", "health checks", "my service keeps crashing", "prevent cascading failures", or "make it resilient". Also trigger when designing resilient microservices, planning zero-downtime deployments, or capacity-planning for peak load. Covers stability patterns, capacity planning, deploy/release decoupling, and observability. For data systems, see ddia-systems. For system architecture, see system-design.' +description: 'Build production-ready systems: circuit breakers, bulkheads, retries.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/remove-technical-debt/SKILL.md b/.agents/skills/remove-technical-debt/SKILL.md index a8ce9299..845988c4 100644 --- a/.agents/skills/remove-technical-debt/SKILL.md +++ b/.agents/skills/remove-technical-debt/SKILL.md @@ -1,6 +1,6 @@ --- name: remove-technical-debt -description: 'Guided journey from a large aged codebase everyone fears to touch to one that is safe to change, legible, bounded, and resilient - paid down in place without a rewrite. Orchestrates eight skills phase by phase - working-with-legacy-code, refactoring-patterns, clean-code, software-design-philosophy, clean-architecture, pragmatic-programmer, release-it, domain-driven-design - asking the user questions at every decision point and recording results in the project docs/ folder (TESTING.md, TECH-DEBT.md, REMOVE-TECHNICAL-DEBT-PLAN.md) so the journey resumes across sessions. Use when the user wants to tame a legacy codebase, pay down technical debt safely, avoid a big-bang rewrite, or says ''we are afraid to touch this code''. For a fresh prototype or vibe-coded app going to production, use improve-code-quality; for greenfield structure, use design-code-architecture; for a product-and-UX pass rather than code-only, use improve-app. For one framework in isolation, invoke that skill directly.' +description: 'Tame a legacy codebase: safe, in-place debt reduction without rewrite.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/scorecard-marketing/SKILL.md b/.agents/skills/scorecard-marketing/SKILL.md index 2d455cc8..7437d88f 100644 --- a/.agents/skills/scorecard-marketing/SKILL.md +++ b/.agents/skills/scorecard-marketing/SKILL.md @@ -1,6 +1,6 @@ --- name: scorecard-marketing -description: 'Build quiz and assessment funnels that generate qualified leads at 30-50% conversion. Use when the user mentions "quiz funnel", "scorecard", "lead magnet", "score-based segmentation", or "lead qualification". Also trigger when designing self-assessment tools, building calculators or graders for marketing, or creating personalized result pages that drive conversions. Covers concept hooks, question design, dynamic results by tier, and automated follow-up sequences. For landing page conversion, see cro-methodology. For full marketing plans, see one-page-marketing.' +description: 'Build quiz and assessment funnels for qualified leads.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/security-and-hardening/SKILL.md b/.agents/skills/security-and-hardening/SKILL.md index 2ddd1352..afe98049 100644 --- a/.agents/skills/security-and-hardening/SKILL.md +++ b/.agents/skills/security-and-hardening/SKILL.md @@ -1,6 +1,6 @@ --- name: security-and-hardening -description: Hardens code against vulnerabilities. Use when handling user input, authentication, data storage, or external integrations. Use when building any feature that accepts untrusted data, manages user sessions, or interacts with third-party services. +description: 'Harden code against vulnerabilities in input, auth, storage.' --- # Security and Hardening diff --git a/.agents/skills/shipping-and-launch/SKILL.md b/.agents/skills/shipping-and-launch/SKILL.md index d679f3cc..50df0f03 100644 --- a/.agents/skills/shipping-and-launch/SKILL.md +++ b/.agents/skills/shipping-and-launch/SKILL.md @@ -1,6 +1,6 @@ --- name: shipping-and-launch -description: Prepares production launches. Use when preparing to deploy to production. Use when you need a pre-launch checklist, when setting up monitoring, when planning a staged rollout, or when you need a rollback strategy. +description: 'Prepare production launches with monitoring and rollback strategy.' --- # Shipping and Launch diff --git a/.agents/skills/software-design-philosophy/SKILL.md b/.agents/skills/software-design-philosophy/SKILL.md index 0a8c1720..d1c6456b 100644 --- a/.agents/skills/software-design-philosophy/SKILL.md +++ b/.agents/skills/software-design-philosophy/SKILL.md @@ -1,6 +1,6 @@ --- name: software-design-philosophy -description: 'Manage software complexity through deep modules, information hiding, and strategic programming. Use when the user mentions "module design", "API too complex", "shallow class", "complexity budget", "strategic vs tactical", "deep module", "information leakage", "pass-through method", "this code is over-engineered", or "simplify this design". Also trigger when reviewing an interface for simplicity, evaluating whether an abstraction is pulling its weight, deciding whether a comment is worth writing, or choosing between general-purpose and special-purpose approaches. Covers deep vs shallow modules, red flags for complexity, and comments as design documentation. For code quality, see clean-code. For architecture boundaries, see clean-architecture.' +description: 'Manage complexity through deep modules, information hiding, strategic programming.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/source-driven-development/SKILL.md b/.agents/skills/source-driven-development/SKILL.md index 9ef02877..d0119484 100644 --- a/.agents/skills/source-driven-development/SKILL.md +++ b/.agents/skills/source-driven-development/SKILL.md @@ -1,6 +1,6 @@ --- name: source-driven-development -description: Grounds every implementation decision in official documentation. Use when you want authoritative, source-cited code free from outdated patterns. Use when building with any framework or library where correctness matters. +description: 'Ground every implementation decision in official documentation.' --- # Source-Driven Development diff --git a/.agents/skills/spec-driven-development/SKILL.md b/.agents/skills/spec-driven-development/SKILL.md index 569d2232..14f08cd3 100644 --- a/.agents/skills/spec-driven-development/SKILL.md +++ b/.agents/skills/spec-driven-development/SKILL.md @@ -1,6 +1,6 @@ --- name: spec-driven-development -description: Creates specs before coding. Use when starting a new project, feature, or significant change and no specification exists yet. Use when requirements are unclear, ambiguous, or only exist as a vague idea. +description: 'Create specs before coding for unclear or ambiguous requirements.' --- # Spec-Driven Development diff --git a/.agents/skills/steve-jobs-design-review/SKILL.md b/.agents/skills/steve-jobs-design-review/SKILL.md index 5f430a91..43645f39 100644 --- a/.agents/skills/steve-jobs-design-review/SKILL.md +++ b/.agents/skills/steve-jobs-design-review/SKILL.md @@ -1,6 +1,6 @@ --- name: steve-jobs-design-review -description: 'Review designs, products, and features with Steve Jobs'' standards: ruthless simplicity, focus, and end-to-end excellence. Use when the user mentions "Steve Jobs review", "design review", "product review", "what would Steve do", "insanely great", "this feels too complicated", "too many features", "product taste", "saying no", or "is this good enough to ship". Also trigger when critiquing a UI, feature, or roadmap for focus and simplicity, cutting scope to the essential, or pressure-testing the whole experience from first run to daily use. Covers the simplicity audit, the no list, design-is-how-it-works, end-to-end ownership, demo culture, and a Jobs-style review protocol with binary verdicts. For visual design fundamentals, see refactoring-ui. For usability audits, see ux-heuristics. For detail polish, see microinteractions.' +description: 'Review designs with Steve Jobs' standards: simplicity, focus, excellence.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/storybrand-messaging/SKILL.md b/.agents/skills/storybrand-messaging/SKILL.md index 5ae7111a..23fb6408 100644 --- a/.agents/skills/storybrand-messaging/SKILL.md +++ b/.agents/skills/storybrand-messaging/SKILL.md @@ -1,6 +1,6 @@ --- name: storybrand-messaging -description: 'Clarify brand messaging using narrative structure that positions the customer as hero. Use when the user mentions "brand message", "website copy", "elevator pitch", "one-liner", "brand script", "StoryBrand framework", "customer as hero", or "my messaging isnt resonating". Also trigger when rewriting homepage copy, crafting email nurture sequences, or creating consistent messaging across sales and marketing collateral. Covers landing page copy, marketing collateral, and consistent communication. For memorable messaging, see made-to-stick. For product positioning, see obviously-awesome.' +description: 'Clarify brand messaging using narrative structure.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/system-design/SKILL.md b/.agents/skills/system-design/SKILL.md index 68eaabe9..82b344c4 100644 --- a/.agents/skills/system-design/SKILL.md +++ b/.agents/skills/system-design/SKILL.md @@ -1,6 +1,6 @@ --- name: system-design -description: 'Design scalable distributed systems using structured approaches for load balancing, caching, database scaling, and message queues. Use when the user mentions "system design", "scale this", "high availability", "rate limiter", "design a URL shortener", "design Twitter", "design Uber", "design a news feed", "system design interview", "capacity planning", or "distributed architecture". Also trigger when estimating infrastructure requirements, choosing between microservices and monoliths, or designing for millions of concurrent users. Covers common system designs (TinyURL, feeds, chat) and back-of-the-envelope estimation. For data fundamentals, see ddia-systems. For resilience, see release-it.' +description: 'Design scalable distributed systems: load balancing, caching, scaling.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/team-topologies/SKILL.md b/.agents/skills/team-topologies/SKILL.md index 4a6b9a0f..a57ff978 100644 --- a/.agents/skills/team-topologies/SKILL.md +++ b/.agents/skills/team-topologies/SKILL.md @@ -1,6 +1,6 @@ --- name: team-topologies -description: 'Organize business and technology teams for fast flow using Skelton & Pais''s "Team Topologies". Use when the user mentions "team topologies", "Conway''s law", "platform team", "stream-aligned team", "team boundaries", "cognitive load", "how should we split teams", "who owns this service", "team dependencies", or "reorg". Also trigger when reorganizing engineering teams, aligning team and service boundaries, splitting a monolith and deciding ownership, reducing cross-team handoffs, or designing an internal platform. Covers the four team types, three interaction modes, the inverse Conway maneuver, and fracture planes. For bounded contexts, see domain-driven-design. For dependency direction in code, see clean-architecture.' +description: 'Organize teams for fast flow using Team Topologies.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/test-driven-development/SKILL.md b/.agents/skills/test-driven-development/SKILL.md index a0c9944d..eb9e0f93 100644 --- a/.agents/skills/test-driven-development/SKILL.md +++ b/.agents/skills/test-driven-development/SKILL.md @@ -1,6 +1,6 @@ --- name: test-driven-development -description: Drives development with tests. Use when implementing any logic, fixing any bug, or changing any behavior. Use when you need to prove that code works, when a bug report arrives, or when you're about to modify existing functionality. +description: 'Drive development with tests: RED-GREEN-REFACTOR.' --- # Test-Driven Development diff --git a/.agents/skills/top-design/SKILL.md b/.agents/skills/top-design/SKILL.md index 3af95853..81aa6215 100644 --- a/.agents/skills/top-design/SKILL.md +++ b/.agents/skills/top-design/SKILL.md @@ -1,6 +1,6 @@ --- name: top-design -description: 'Create award-winning, immersive web experiences at the level of Awwwards-featured agencies. Use when the user mentions "Awwwards quality", "make my site stunning", "scroll animations", "parallax storytelling", "cinematic web design", "portfolio site", or "brand experience". Also trigger when elevating a standard landing page into a memorable digital experience. Covers dramatic typography, purposeful motion, scroll-based composition, and performance-optimized animation. For foundational UI, see refactoring-ui. For type selection, see web-typography.' +description: 'Create award-winning, immersive web experiences at Awwwards level.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/traction-eos/SKILL.md b/.agents/skills/traction-eos/SKILL.md index 69f5cb59..b7e5fc8f 100644 --- a/.agents/skills/traction-eos/SKILL.md +++ b/.agents/skills/traction-eos/SKILL.md @@ -1,6 +1,6 @@ --- name: traction-eos -description: 'Implement the Entrepreneurial Operating System (EOS) to align vision and execution across a company. Use when the user mentions "EOS", "Entrepreneurial Operating System", "V/TO", "quarterly rocks", "Level 10 meetings", "accountability chart", "IDS process", "my company feels chaotic", "we keep having the same problems", or "get the whole team aligned". Also trigger when a growing company needs meeting structure, goal-setting frameworks, or a systematic way to solve recurring organizational issues. Covers the six EOS components: Vision, People, Data, Issues, Process, Traction. For team motivation design, see drive-motivation. For lean experimentation, see lean-startup.' +description: 'Implement the Entrepreneurial Operating System for alignment.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/using-agent-skills/SKILL.md b/.agents/skills/using-agent-skills/SKILL.md index 975fb5c2..d802e0b4 100644 --- a/.agents/skills/using-agent-skills/SKILL.md +++ b/.agents/skills/using-agent-skills/SKILL.md @@ -1,6 +1,6 @@ --- name: using-agent-skills -description: Discovers and invokes agent skills. Use when starting a session or when you need to discover which skill applies to the current task. This is the meta-skill that governs how all other skills are discovered and invoked. +description: 'Discover and invoke agent skills.' --- # Using Agent Skills diff --git a/.agents/skills/ux-heuristics/SKILL.md b/.agents/skills/ux-heuristics/SKILL.md index 63e6db1c..194c5f9a 100644 --- a/.agents/skills/ux-heuristics/SKILL.md +++ b/.agents/skills/ux-heuristics/SKILL.md @@ -1,6 +1,6 @@ --- name: ux-heuristics -description: 'Evaluate and improve interface usability using heuristic analysis. Use when the user mentions "usability audit", "users are confused", "form usability", "navigation problems", "Nielsen heuristics", "cognitive walkthrough", or "is this easy to use". Also trigger when reviewing a design for usability issues, improving form-completion rates, or evaluating information architecture and navigation. Covers Krug''s laws, Nielsen''s 10 heuristics, severity ratings, dark-pattern recognition, and accessibility. For visual design fixes, see refactoring-ui. For conversion-focused audits, see cro-methodology.' +description: 'Evaluate and improve interface usability using heuristic analysis.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/web-typography/SKILL.md b/.agents/skills/web-typography/SKILL.md index 275761a8..09d4b0a3 100644 --- a/.agents/skills/web-typography/SKILL.md +++ b/.agents/skills/web-typography/SKILL.md @@ -1,6 +1,6 @@ --- name: web-typography -description: 'Select, pair, and implement typefaces for web projects. Use when the user mentions "font pairing", "which typeface", "line height", "responsive typography", "web font loading", "type hierarchy", "variable fonts", "FOUT/FOIT", "typographic scale", or "the text is hard to read". Also trigger when choosing between system fonts and web fonts, optimizing font-loading performance, or designing readable long-form content. Covers readability evaluation, CSS implementation, and performance optimization. For overall UI design systems, see refactoring-ui. For dramatic typographic experiences, see top-design.' +description: 'Select, pair, and implement typefaces for web projects.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/work-issue/SKILL.md b/.agents/skills/work-issue/SKILL.md index f8636c16..2a92748c 100644 --- a/.agents/skills/work-issue/SKILL.md +++ b/.agents/skills/work-issue/SKILL.md @@ -1,42 +1,78 @@ --- name: work-issue -description: >- - Executa uma Issue já claimada de ponta a ponta com supervisão humana no - plano: o contexto da sessão identifica a Issue (sem claim), Plan mode com - plano de implementação, pausa para confirmação humana, depois execução → - /simplify → capture-review-debts autônomo (o agente decide o que registrar - e o que descartar) → PR Ready em main com auto-merge. Use quando o usuário - pedir /work-issue, quiser supervisionar a abordagem de engenharia, ou - trabalhar uma Issue com gate humano antes do código. +description: 'Execute a claimed Issue end-to-end with human supervision on the impl plan.' disable-model-invocation: true --- # Work-issue (humano supervisiona) -Fluxo próprio do humano na sua máquina, com a sessão aberta no worktree da -Issue. A sessão **já nasce no contrato**: Issue claimada, worktree correto, -branch correta, modelo fixo do ambiente — o claim é feito **fora da skill** -(hoje: `pnpm agent:claim` manual antes da sessão; OPS33: o `worktree next` -claima). A skill assume isso e vai direto ao trabalho — **nenhum passo de -claim/ambiente/modelo** (só a validação de contexto do Passo 1). +Executa uma Issue já claimada de ponta a ponta com supervisão humana. A sessão nasce no contrato: Issue claimada, worktree correto, branch correta. -O pool tem a skill irmã `agent-work-issue` (workers Cursor Cloud, autônoma) — -não é base nem filha desta. Os materiais compartilhados vivem aqui como -referência: `engineering-brief.md`, `implementation-template.md`, -`decision-quality.md`, `execution-pipeline.md` (mecânica de execução → -fechamento, com deltas por ator). +**Proibido:** DB de prod; merge sem CI green; editar outras Issues `in-progress`; pular a pausa do impl plan; Draft / sem auto-merge. -**Proibido:** DB de prod; merge sem CI green; editar outras Issues `in-progress`; -pular a pausa do impl plan; Draft / sem auto-merge. +## Decomposição em sub-agentes + +Fases pesadas são delegadas a sub-agentes com contexto mínimo. O agente principal orquestra. + +### Sub-agente: Explorador de código + +**Quando:** Passo 3a, antes de escrever o plano. +**Input:** plano de intenção + `engineering-brief.md` + `codebase-map.mdc` +**Task:** Explorar o codebase para esta feature. Encontrar: padrões existentes para reutilizar, implementações similares, arquivos afetados, rabbit holes potenciais. **Não escrever código nem planos.** +**Output:** ≤25 linhas de achados concisos. + +### Sub-agente: Escritor de plano de implementação + +**Quando:** Passo 3b, após o explorador. +**Input:** plano de intenção + achados do explorador + `implementation-template.md` + `decision-quality.md` +**Task:** Escrever `docs/plans/-impl.md` conforme o template. Incluir: abordagem recomendada + alternativas rejeitadas + fases + riscos. Self-score decision-quality ≥4/5. +**Output:** conteúdo markdown do plano. + +### Sub-agente: Revisor estrutural + +**Quando:** Passo 5, reviewer 1 (paralelo). +**Input:** diff da sessão + princípios de `code-simplification` +**Task:** Revisar o diff para conformidade arquitetural: +- Violações da Dependency Rule (lib→utilities→components→app) +- Violações de boundary de módulo (lógica na camada errada) +- Abstrações prematuras (abstrações novas para <3 call sites) +- Duplicação entre módulos +- Violações de type honesty +- Conformidade de padrões de access/transaction +**Output:** lista de achados com file:line e severidade. + +### Sub-agente: Revisor de qualidade + +**Quando:** Passo 5, reviewer 2 (paralelo). +**Input:** diff da sessão + princípios de `code-simplification` +**Task:** Revisar o diff para qualidade de código: +- Clareza de nomes (nomes descrevem o que o código faz?) +- Tamanho/complexidade de funções (funções longas, nesting profundo) +- Código morto (imports não usados, branches inacessíveis) +- Type assertions redundantes +- Complexidade desnecessária (poderia ser mais simples sem mudar comportamento) +- Convenções do projeto +**Output:** lista de achados com file:line e severidade. + +### Sub-agente: Capturador de débitos + +**Quando:** Passo 6, após simplify. +**Input:** achados da sessão + regras de triagem de `capture-review-debts` +**Task:** Triagem: score (1-5), tipo (expensive_lock/cheap_polish/defer_trigger), destino (registrar/absorver/defer/descartar/já_resolvido). **Output:** tabela de triage. ## Checklist ``` - [ ] 0. Prep: `pnpm i` se preciso -- [ ] 1. Contexto: Issue do prompt/`$ARGUMENTS` da sessão (ausente → UMA pergunta com validação; nunca claim) -- [ ] 2. Abrir o plano de intenção do body da Issue (`Plano: docs/plans/...`; sem link → body é spec) -- [ ] 3. Plan mode → escrever `docs/plans/-impl.md` → **PARAR e confirmar com o humano** -- [ ] 4. Após “ok”: Passo 4 (execução → e2e local afetado → /simplify → débitos autônomos → PR, via `execution-pipeline.md`) +- [ ] 1. Contexto: validar Issue + carregar camada AGENTS +- [ ] 2. Ler plano de intenção do body da Issue +- [ ] 3a. Dispatch sub-agente explorador → receber findings +- [ ] 3b. Dispatch sub-agente escritor → receber impl plan +- [ ] 3c. GATE humano: apresentar plano → pausa → confirmação +- [ ] 4. Executar (main agent iterativo) +- [ ] 5. Dispatch 2 sub-agentes revisores (paralelo) → receber achados +- [ ] 6. Dispatch sub-agente capturador → receber triage +- [ ] 7. PR → merge ``` ## Passo 1 — Contexto da sessão @@ -60,57 +96,68 @@ resto (fonte única é a Issue, nunca um brief duplicado). - **Modelo: não verifique.** `model:` da Issue é metadata consultiva (o pool spawna nele; o claim brief o imprime). A sessão da máquina do humano é sempre o modelo fixo do ambiente (DeepSeek V4 Flash). +- **Carregar camada AGENTS:** se toca `/campanha`, leia `AGENTS-campaign.md`. Se site público, `AGENTS-public.md`. Se deploy/CI, leia `AGENTS-infra.md`. ## Passo 2 — Intenção -O path do plano de intenção vem do **body da Issue** (`Plano: [docs/plans/.md]` — -mesmo contrato de `extractPlanPath` do prompt do pool). Sem plano linkado → o body -é a spec. Abra e leia. +O path do plano vem do body da Issue (`Plano: docs/plans/...`). Sem link → body é spec. Abra e leia. -## Passo 3 — Plano de implementação + GATE humano +## Passo 3 — Plano de implementação + GATE -Plan mode: `SwitchMode` → `plan` (deliberar engenharia a partir da intenção). +### 3a. Dispatch sub-agente explorador -1. Leia `engineering-brief.md` e aplique skills/princípios sob demanda. -2. Explore o código o bastante para **reavaliar** a "Direção no codebase" da - intenção — você **deve** escolher a melhor abordagem maintainable, mesmo que - difira da hipótese do plano de intenção, desde que o **aceite de produto** se - mantenha. -3. Escreva `docs/plans/-impl.md` via `implementation-template.md`. - Qualidade: `decision-quality.md` ≥4/5. -4. Apresente no chat: abordagem recomendada, opções rejeitadas, fases, riscos, - o que diverge da hipótese de direção da intenção. -5. **Pare.** Não escreva código de feature até confirmação explícita ("ok", - "pode executar", "aprovado", …). -6. Se o humano pedir mudança de abordagem → revise o `*-impl.md` e reapresente. -7. Confirmação → marque Status `aprovado` no impl plan → `SwitchMode` `agent` → - continue. +Monte o task prompt: +- Plano de intenção (conteúdo completo) +- `engineering-brief.md` (invariantes + skills sob demanda) +- `codebase-map.mdc` (direção de dependência + onde vive o quê) +- Instrução: "Encontre arquivos relevantes, padrões existentes, rabbit holes. ≤25 linhas. Não escreva código nem planos." -Divergência material de produto (aceite/persona/lockdown da intenção não cabem): -pare e **pergunte ao humano** — ele decide entre item sucessor ou `blocked`; -nunca invente produto novo. +Aguarde o output. + +### 3b. Dispatch sub-agente escritor + +Monte o task prompt: +- Plano de intenção + achados do explorador +- `implementation-template.md` + `decision-quality.md` +- Instrução: "Escreva `docs/plans/-impl.md`. Abordagem + alternativas rejeitadas + fases + riscos." + +Aguarde o output. Crie o arquivo `docs/plans/-impl.md`. + +### 3c. GATE humano + +Apresente no chat: +- Abordagem recomendada + opções rejeitadas +- Fases, riscos, divergências da hipótese de direção + +**Pare.** Não escreva código até confirmação explícita. + +Divergência material de produto → pare, pergunte ao humano. ## Passo 4 — Executar -`SwitchMode` → `agent` se ainda estiver em plan. Siga a mecânica de -[`execution-pipeline.md`](execution-pipeline.md) (executar → simplify → -fechar em main), com os deltas do ator humano: +`SwitchMode` → `agent`. Siga `execution-pipeline.md`: -- **Branch:** `-` do worktree — nunca crie branch nova na sessão. -- **E2E local afetado (OPS72, discricionário):** antes do push, rode - localmente os e2e que você **criou** + os da **mesma superfície afetada** — - você decide quais (`pnpm test:e2e:affected` ou specs diretas). Não está no - `gate:push`; ver a seção "E2E local afetado" do `execution-pipeline.md` - (incl. a limitação da #72: `--no-deps` + projetos paralelos → `--workers=1` - ou a cadeia padrão de projetos). +- **Branch:** `-` do worktree — nunca crie branch nova. +- **E2E local afetado (OPS72):** discricionário — rode os e2e criados + mesma superfície. - **UI:** shape → craft → critique → polish. -- **`capture-review-debts`:** **autônomo** — colha, dedupe, pontue e **decida - você mesmo o destino** (registrar/absorver/deferir/descartar) pela triage - da própria skill, **sem pausa para o humano**; registre via - `agent:register` / `agent:file-miss` (Issues novas com `depends` no pai se - necessário) e resuma o que registrou vs descartou no fechamento. +- **Gates:** `pnpm gate:fast` na iteração; entrega com `pnpm push`. + +## Passo 5 — Simplify (2 sub-agentes paralelos) + +Dispatche os dois revisores em paralelo com o diff da sessão + princípios de `code-simplification`. Cada um retorna lista de achados. + +Aplique fixes pontuais que preservem comportamento. + +## Passo 6 — Capture debts (sub-agente) + +Dispatche o capturador com os achados do simplify + sessão + regras de `capture-review-debts`. Receba a tabela de triage. + +Aplique: registre o aprovado, absorva em plano existente, defira com gatilho, descarte o resto. + +## Passo 7 — Fechar em main + +Siga `execution-pipeline.md`: changelog → `pnpm push` → PR no GitHub `--base main` com `Closes #N` → auto-merge → CI. ## Resumo final -Issue (contexto da sessão) · impl plan (abordagem + rejeitadas + divergências da -hipótese) · simplify + débitos registrados/deferidos · PR + estado do merge. +Issue · impl plan · simplify + débitos · PR + merge. diff --git a/.agents/skills/work-issue/engineering-brief.md b/.agents/skills/work-issue/engineering-brief.md index 3e3d822d..4e09b0a7 100644 --- a/.agents/skills/work-issue/engineering-brief.md +++ b/.agents/skills/work-issue/engineering-brief.md @@ -2,14 +2,6 @@ Leia o que for relevante **antes** de travar a abordagem no `*-impl.md`. Não invoque jornadas inteiras de skills — aplique o princípio no momento da decisão. -## Pinos do repo (sempre) - -- `.agents/rules/codebase-map.mdc` — direção `lib/` → `utilities/` → `components/` → `app/`; dono da feature -- `.agents/rules/engineering-standards.mdc` — gates, type honesty, client boundary, caching ladder, access -- `.agents/rules/security-critical.mdc` — quando tocar access/Local API/overrideAccess -- `AGENTS.md` — auth campanha, Consent fail-closed, transactions, naming, DB local -- `docs/ARCHITECTURE.md` — se a mudança cruza verticais ou modelo de domínio - ## Skills sob demanda (não tour) | Situação | Skill / princípio | diff --git a/.agents/skills/work-issue/execution-pipeline.md b/.agents/skills/work-issue/execution-pipeline.md index 899ecd2c..cb209ca9 100644 --- a/.agents/skills/work-issue/execution-pipeline.md +++ b/.agents/skills/work-issue/execution-pipeline.md @@ -50,8 +50,9 @@ antes do deploy**. ## /simplify + débitos -1. Rode o comando `/simplify` completo (3 reviewers paralelos via Task, - read-only) no diff da sessão. +1. Rode o comando `/simplify` completo (2 reviewers paralelos via Task — + revisor estrutural + revisor de qualidade, ver `work-issue` SKILL.md) + no diff da sessão. 2. Aplique fixes pontuais que preservem comportamento. 3. Rode `capture-review-debts` no modo do ator (ver deltas). Nunca edite a Issue `in-progress` atual para absorver débitos. diff --git a/.agents/skills/working-with-legacy-code/SKILL.md b/.agents/skills/working-with-legacy-code/SKILL.md index b009c838..7cd1f48f 100644 --- a/.agents/skills/working-with-legacy-code/SKILL.md +++ b/.agents/skills/working-with-legacy-code/SKILL.md @@ -1,6 +1,6 @@ --- name: working-with-legacy-code -description: 'Safely change and test untested codebases using Feathers'' "Working Effectively with Legacy Code". Use when the user mentions "legacy code", "no tests", "untested codebase", "how do I test this", "seams", "characterization tests", "golden master", "sprout method", "afraid to change this code", "monster method", "dependency breaking", or "inherited a messy codebase". Also trigger when changing code without tests safely, getting a class under test when constructors, statics, or singletons block it, adding features to tangled modules, or planning incremental test coverage for an old codebase. Covers the legacy-code change algorithm, seams, characterization tests, sprout/wrap, and dependency-breaking techniques. For refactoring code that already has tests, see refactoring-patterns. For day-to-day code quality, see clean-code.' +description: 'Safely change and test untested codebases using Feathers' methods.' license: MIT metadata: author: wondelai diff --git a/.agents/skills/worktree-next-issue/SKILL.md b/.agents/skills/worktree-next-issue/SKILL.md index 9d3a2929..8d954c3a 100644 --- a/.agents/skills/worktree-next-issue/SKILL.md +++ b/.agents/skills/worktree-next-issue/SKILL.md @@ -1,6 +1,6 @@ --- name: worktree-next-issue -description: >- +description: 'Claim the next Issue and provision a deterministic worktree.' Claima deterministicamente a próxima Issue da fila (ou a direcionada com --issue N), cria o worktree git dela a partir de main com branch legível no formato - (ex. C15-fullcalendar-em-campanha-agenda, slug pt-BR diff --git a/AGENTS-campaign.md b/AGENTS-campaign.md new file mode 100644 index 00000000..79d61d03 --- /dev/null +++ b/AGENTS-campaign.md @@ -0,0 +1,76 @@ +# Campaign domain (AGENTS layer — load when touching `/campanha`) + +## Campaign auth (`/campanha`) + +The internal `/campanha` area is gated by its own authentication, deliberately kept **isolated from the Payload admin (`/admin`)** so a campaign session and an admin session can coexist in the same browser. + +- **`campaignUser` collection** (`src/collections/CampaignUser.ts`) — a separate Payload auth collection with `name`, optional contact `phone`, and required `role`: `coordinator` ("Coordenador Geral"), `advisor` ("Assessor"), `candidate` ("Candidato"), or `leader` ("Liderança" — default and least privilege). Staff may sign in by email; leadership accounts use the normalized 11-digit phone as `username`. It is not `users`: `admin.user` remains `users`, so campaign users cannot log into `/admin`. Its static `auth.tokenExpiration` is the 14-day ceiling because Payload's Local API does not accept a per-login TTL and `useSessions` (enabled) stores/prunes sessions using that configured expiry. +- **Isolated session cookie `campaign-token`.** The flow sets its own httpOnly cookie named `campaign-token` (constant `CAMPAIGN_TOKEN_COOKIE` in `src/utilities/campaignAuth.ts`), scoped to `path: '/campanha'`, `sameSite: 'lax'`, and `secure` only in production. It is deliberately NOT the default `payload-token` cookie — using a distinct name + path is what lets a campaign session and a Payload admin session live side by side without clobbering each other. Login defaults to **8 hours**; checking "Lembrar de mim neste dispositivo" opts into **14 days**. `setCampaignAuthCookie` owns the invariant JWT `exp` = cookie `maxAge`: it re-signs the Payload token to 8 hours with `jwtSign` or keeps the original 14-day token. Password-reset and invite login paths omit the opt-in and therefore stay at 8 hours. +- **Session verification — `getCampaignUser()`** (`src/utilities/campaignAuth.ts`). Reads the `campaign-token` cookie, calls `payload.auth({ headers })`, accepts only `user.collection === 'campaignUser'`, then reloads that document by ID. The fresh read makes role downgrades effective immediately instead of trusting a stale JWT role. +- **Login/logout server actions** (`src/app/(campaign)/campanha/actions/auth.ts`). `loginCampaign` validates input with `campaignLoginSchema` (`src/lib/schemas/campaign-login.ts`), calls `payload.login({ collection: 'campaignUser' })`, chooses the 8-hour / 14-day TTL, and — because the Local API returns a token WITHOUT setting a cookie — calls `setCampaignAuthCookie` before redirecting to `/campanha`. `logoutCampaign` authenticates the current token and delegates revocation of its `_sid` to Payload's public transactional `logoutOperation`, then clears the cookie (`maxAge: 0`) and redirects to `/campanha/login`; malformed tokens or database failures never prevent local cookie/PWA cleanup. +- **Route layout.** The route group's root layout `src/app/(campaign)/layout.tsx` renders the ``/`` with `data-theme="campaign"`. The public login lives at `src/app/(campaign)/campanha/login/` (`page.tsx` + client `LoginForm.tsx`). Everything gated sits in the `(app)` group, whose layout (`src/app/(campaign)/campanha/(app)/layout.tsx`) calls `getCampaignUser()` and `redirect('/campanha/login')` when there is no session — that layout is the barrier. +- **Biometric login (WebAuthn, B40 — 2026-07-28).** A second way into the same session, never a second session: the biometric path ends at the same `setCampaignAuthCookie` with the 14-day TTL (enrolling the device _is_ the trust opt-in), and the password path is untouched. Credentials live in `campaignWebAuthnCredential` (owner-only access in `src/utilities/access/webauthnCredentials.ts`; `update` is denied to users because the signature counter and `lastUsedAt` are written with `overrideAccess: true` inside the transaction). Four anonymous-or-authenticated JSON routes sit in `src/app/(campaign)/campanha/webauthn/` — deliberately **outside `(app)`**, since two of them run before there is a session and the cookie's `/campanha` path already covers them. **No `Consent` key, and this is not an art. 11 question:** the OS never releases the fingerprint, so what we store is a public key. + - **There is no password-less login in Payload 3.82.0.** `loginOperation` requires `password`. `issueCampaignWebAuthnSession` (`src/utilities/campaignWebAuthnSession.ts`) mints the session from public exports only: `payload.db.findOne` → `checkLoginPermission` → `addSessionToUser` (`payload/shared`) → `getFieldsToSign` + `jwtSign`. **Never load the user with `payload.findByID` here.** `addSessionToUser` read-modify-writes the _whole_ user document, so a doc that passed through `CampaignUser`'s `afterRead` `removePrivateAuthFields` would be written back without `sessions` or `email` — logging the user out of every other device — and with `avatar` expanded into an object. `user.updatedAt = null` is set for the same reason Payload's own login does it. The mint runs inside `withPayloadTransaction` under `campaign-webauthn-session:{userId}`, because rewriting the whole `sessions` array makes two concurrent logins lose one. + - **RP ID must match the host that served the page.** `getCampaignWebAuthnRelyingParty` derives `rpID`/`origin` from `getCampaignInviteBaseURL`, _and_ compares the request's host against it — returning `null` when they differ, which hides the button. Without that comparison a preview served from a different host resolves the canonical origin successfully and the browser throws `SecurityError` mid-ceremony. + - **The challenge cookie must carry the library's own challenge.** It is an HMAC-signed httpOnly cookie (5 min, single-use, path `/campanha`, precedent `supporterImportToken.ts`) — but store the exact base64url string `generateRegistrationOptions`/`generateAuthenticationOptions` returned. Generating our own alongside theirs makes every `register` answer 400. + - **Deleting a `campaignUser` needs the cascade in a hook.** Payload emits `ON DELETE SET NULL` for the required `user` relationship, which cannot apply to a `NOT NULL` column; `CampaignUser` has a `beforeDelete` that removes the user's credentials in the same transaction. E2E uses a CDP virtual authenticator (`WebAuthn.addVirtualAuthenticator`, `transport: 'internal'`), which also makes `isUserVerifyingPlatformAuthenticatorAvailable()` answer `true`. +- **Migrations.** `20260716_010420_add_campaign_user` created the auth collection; `20260728_041958_add_campaign_webauthn_credentials` added the WebAuthn credential table; the unpublished 2026-07-17 campaign chain was consolidated into `20260718_010733_consolidate_campaign_schema`, which adds role/username auth, contact phone, and the remaining final campaign schema. + +## Campaign Municípios model (2026-07-23 remodel) + +`/campanha` is organized around `municipality` ("Município") — the campaign's PREDEFINED operational territory. Deployed to production on 2026-07-23 (destructive remodel migrations applied via the Vercel build). Master plan: `docs/plans/remodelagem-municipios.md` (supersedes `docs/plans/remodelagem-pracas.md`). + +- **Município definition:** 435 seeded rows — one per Bahia municipality (416), except Salvador (19 zone municipalities, ZE 1–19); Camaçari is a single whole municipality (ZE 170/171 aggregated). Canonical catalog: `src/lib/municipalityCatalog.ts` (`tests/fixtures/municipality-catalog.snapshot.json`). Seeded by migration `20260723_200000_remodel_municipalities` (+ reconcile `20260723_202000_reconcile_municipality_remodel`). Geography is admin-only; staff edit strategy fields and the coordinator assigns `advisors`. +- **Collections (admin group `Campanha`):** `municipality`, `leadership`, `votePledge`, `organization`, `stateDeputy` (dobradinhas), `campaignDemand`, `allocationDecision`, `municipalityUpdate`, `campaignInvite`, `campaignWebAuthnCredential` (biometric login — see "Campaign auth"), `supporter`, `activity`. **Global** (same admin group): `campaignGoals` (E8 "conta da cadeira" — `stateGoal` sets the optimistic suggested-goal scenario, `margin` the pessimistic haircut; `read` = admin/staff, `update` = admin/`isCampaignUnrestricted`; no `afterChange` hook — nothing caches it). +- **Engagement level (E14):** `municipality.engagementLevel` (`n0…n4`, staff-only, no default) is the campaign's declared investment in the município — N0 monitorar … N4 investimento pleno. Only `isCampaignUnrestricted` actors move it, every move needs a rationale plus the signals that would reverse it, and the move writes an `allocationDecision` (`outcome: 'movimento'`) in the same transaction under an advisory lock. Hysteresis rules are pure (`src/lib/engagementLevel.ts`) and shared by client and server; the override is recorded with the rules it contradicted. Null means "Sem nível" — the triage queue, not a missing value to backfill. +- **Roles:** `coordinator` ("Coordenador Geral") and `candidate` ("Candidato", unrestricted visibility via `isCampaignUnrestricted`) see/manage everything staff sees; `advisor` ("Assessor") is scoped to `municipality.advisors`; `leader` ("Liderança") is **lockdown** — home is the supporter contact tool only (`LeaderContactsPanel`, `source: lideranca`), reads only supporters they created (`createdBy`), no municipalities/leaderships/pledges/demands/plans/election data. +- **Vote pledge asymmetry:** staff declare `declaredVotes` and record `estimatedVotes` (pessimistic/central/optimistic); leaders never see estimates. Aggregates use `estimated[S] ?? declared`, default `central` (`src/utilities/votePledgeData.ts`). +- **Demandas:** staff-only create/read (`canCreateCampaignDemand`); optional `leadership` provenance selected by staff. Escalated decisions: coordinator **or** candidate. +- **Dobradinhas:** `stateDeputy` entity + `municipality.stateDeputies` / `leadership.stateDeputies` hasMany; UI at `/campanha/dobradinhas`. +- **Map:** staff dashboard (`/campanha`) loads `MunicipalityMapPanel`; `/campanha/municipios` is list/overview only. **Keyed by "map key", not `ibgeCode`** (B8 F2, 2026-07-26): `mapKeyForMunicipality` returns the `municipalitySlug` for `kind === 'zona'` and the `ibgeCode` otherwise, so each of Salvador's 19 ZE is painted, hovered and opened on its own from `bahia-municipality-zones.topo.json`. Every bundle field follows that key (`municipalitiesByMapKey`, `territorialClassByMapKey`, `projectedValidVotesByMapKey`, `valuesByYear`, …) and each key maps to exactly one catalog entry, so rollups assign instead of accumulating. Salvador's **municipal** polygon is still drawn, underneath, as a non-interactive base with no data (`baseKeys` in `BahiaMap`) — two independently simplified meshes do not close on the same coastline, and deleting it opened a gap in the state outline; being out of the key index, it cannot double-count or steal a hover. Feature→key resolution is `featureMapKey` (`municipalitySlug ?? codarea ?? code`) — the three are **mutually exclusive** on the committed meshes, so it is a lookup over distinct names and not a precedence rule; the zone mesh also carries the city's `ibgeCode`, which is deliberately **not** a key property because all 19 zones share it. Since B8+ that contract is exercised on **real features of all three meshes** in `tests/int/bahiaGeometries.int.spec.ts` — over the full 417 / 27 / 19, not on hand-written literals and not on one city feature repeated per zone — and a failure of the zone chunk **degrades instead of killing the map**: `loadLayerFeatures` catches it and paints the state without the ZE (Salvador falls back to its non-interactive base polygon, not to an aggregated one — the bundle is keyed by slug), while `status === 'error'` stays reserved for the municipal mesh. **`competitiveRank` is still per city:** the TSE artifact only carries `federalRankByIbgeCode`, so all 19 zones share the city's placement — which is what the lege... (line truncated to 2000 chars) +- **URLs:** `/campanha/municipios[/slug]`, `/campanha/dobradinhas`, `/campanha/liderancas[/id]`, `/campanha/organizacoes[/slug]`, `/campanha/demandas[/slug]`, `/campanha/atividades[/slug]`, `/campanha/atividades/giros` (compositor de giro, staff), `/campanha/apoiadores`, `/campanha/assessores` (coordinator/candidate), `/campanha/conceitos` (staff glossary), `/campanha/perfil`. + +## Campaign supporters (C2) + +Nominal supporter registry backing the campaign's base of declared supporters (roadmap item C2; engineering ready and merged to `main` on 2026-07-18, production-blocked on the legal batch). One collection in admin group `Campanha`: + +- **`supporter`** (`src/collections/Supporter.ts`) — join `Contact`↔campaign with **optional `municipality`**. Fields include `source` (`import_csv | manual | convite | evento | lideranca` for leader-created rows). +- **Consent by stable key.** `campaignConsent.ts` was generalized to `getConsentByKey` / `requireConsentByKey` (fail-closed). The two keys are `apoiador-cadastro` (declared support) and `apoiador-intencao-voto` (vote intention — highlighted, separate consent). The app fails closed if either key is missing — same pattern as `lideranca-autopreenchimento`. +- **Access.** `coordinator`/`candidate` see/manage all; `advisor` sees supporters of administered municipalities; `leader` may create supporters in linked municipalities and read only rows they created (`createdBy`); supporters without a municipality remain `coordinator`-only. Delete is admin-only. +- **Server actions** (`src/app/(campaign)/campanha/actions/supporter.ts`): `createSupporter`, `setSupporterVoteIntention`, `previewSupporterImport` / `confirmSupporterImport` (CSV, `coordinator`-only, transactional with `req: { transactionID }`, dedup by phone via `contactPhoneInvariant`), and `removeSupporterData` (deletes the `supporter`; anonymizes/clears `Contact` PII only if no other join — `leadership`/`signature`/`subscription`/other `supporter` — references it). +- **UI** `/campanha/apoiadores` — list with KPIs (total / "Certo + Tende" / "Indecisos"), filters (vote intention, territory), detail with LGPD consent block + vote-intention segmented control (disabled until consent) + minimal share kit (`wa.me` + copy text), and a 3-step CSV import wizard (Upload → Preview → Confirm). Phone is required in v1. +- **C6 scale layer (merged to `main` 2026-07-19).** CSV import up to 5000 rows now completes in one transaction: `confirmSupporterImportRecord` acquires all phone advisory locks, then `bulkInsertSupporterImport` (`src/utilities/supporterImportBulk.ts`) inserts contacts + supporters via `payload.db.drizzle` on the Payload transaction session (`getPostgresTransactionDatabase`) in 500-row chunks with `ON CONFLICT DO NOTHING` on `(contact_id, municipality_id)`. `Contact.enforceUniqueContactPhone` honors `context.skipContactPhoneInvariant` **fail-closed** (only inside an active `req.transactionID`), so the bulk path skips the per-row re-check while the single-create path is unchanged. Preview no longer round-trips the full `ok` set: `previewSupporterImportText` stages it in `supporterImportBatch` (`src/collections/SupporterImportBatch.ts`, admin-hidden, `coordinator`/admin only, migration `20260719_011015_add_supporter_import_batch`) and returns an HMAC-SHA256 single-use `importToken` (10-min TTL, actor-bound, `src/utilities/supporterImportToken.ts`); `confirmSupporterImportRecord` verifies the token and consumes the batch (delete after commit). The list KPI is a single `COUNT(*) FILTER` aggregate (`src/utilities/supporterListOverviewAggregate.ts`) mirroring `buildSupporterListWhere` + the access constraint, replacing 3× `payload.count`. Shared shells — `campaignListUrl.ts`, `CampaignListPagination`, `campaignFormFields.ts`, `mapCampaignFormActionError.ts` — replace the three per-list pagination components and the duplicated form-error ladders. Scale/DRY follow-ups from the `/simplify` pass are registered as **C8** (`docs/plans/escala-dry-pos-c6.md`). +- **Mandatory production blocker:** do not import real supporter data or capture vote intention until electoral counsel documents the LGPD art. 11 basis (vote intention is sensitive data), approves the versioned consent texts, and an admin creates `Consent.key = 'apoiador-cadastro'` and `Consent.key = 'apoiador-intencao-voto'`. The app intentionally fails closed when these keys are absent. + +## Campaign activities (C3, renamed by C13) + +Mobilization events / agenda backing the campaign's field operations (roadmap item C3; implemented and merged to `main` on 2026-07-18). **Renamed "Plano de Ação" → "Atividade" on 2026-07-25 (C13)**: the collection slug is `activity`, the route is `/campanha/atividades`, and the vocabulary guard in `tests/unit/codebaseConventions.unit.spec.ts` now fails the build on `actionPlan` / `plano de ação` / `/campanha/planos` anywhere in `src`, `tests` or `scripts` (migrations excluded — frozen history). One collection in admin group `Campanha`: + +- **`activity`** (`src/collections/Activity.ts`) — a calendarizable action/event (caminhada, comício, etc.) anchored on ONE `municipality`, with task checklist, update feed and result record. Fields: `title`, canonical immutable `slug`, `kind` / `status` enums in pt-BR, `startAt` (required beyond `rascunho`), `municipality` (required) + free-text `locality`, `organizations` (hasMany — supporting orgs), `advisors` (staff responsible; ex-`coordinators`), `deputyPresent` (checkbox "Deputado presente"), `responsible` → `Contact`, `leadership` optional, `tasks`/`updates` arrays (derived fields server-side), and the action result: `resultSummary` + `resultMedia` (upload → `media`) + derived `resultRecordedBy/At` — queryable history for future activities in the same município. No `Consent` (internal staff data). +- **Access.** `coordinator` everything; `advisor` where listed in `advisors` OR the activity's `municipality` is administered (may create, auto-included); `leader` has no access (lockdown). +- **UI** `/campanha/atividades` — list with tabs Próximos (default) / Todos / Realizados / Rascunhos, filters (kind, municipality), cards with kind/status badge + date/time + município + "Resp:" + task progress + "Deputado presente"; detail with tabs Visão geral / Tarefas / Atualizações (`/campanha/atividades/[slug]`, create at `/campanha/atividades/nova`); result form appears for staff when the activity is `realizado`. + +## Campaign map geometries (B2) + +Static Bahia map foundation for future Leaflet surfaces (roadmap B2; UI is B3). No migration, collection, Consent, or server action — same static-data pattern as `bahiaTerritories` / `bahiaTseZones`. + +- **Artifacts (committed):** `src/lib/geometries/bahia-municipalities.topo.json` (~132 KB; Topology object `municipalities`, 417 features, `properties: { codarea, name }`), `src/lib/geometries/bahia-identity-territories.topo.json` (~15 KB; object `territories`, 27 features, `properties: { code, name }`) and — since B8 F2 (2026-07-26) — `src/lib/geometries/bahia-municipality-zones.topo.json` (**~7.7 KB** since B8+ recalibrated it; object `municipalityZones`, **19** features, `properties: { municipalitySlug, name, ibgeCode }`), the Salvador ZE mesh. +- **Code table:** `src/lib/bahiaMunicipalityCodes.ts` — canonical municipality name → IBGE 7-digit `codarea`, plus `codeForMunicipality` / `municipalityForCode`. Fixture `tests/fixtures/bahia-municipality-codes.official.json` + int tests for bijection/coverage. +- **Runtime helpers:** `src/lib/bahiaGeometries.ts` — typed topologies, feature arrays and `getMunicipalityFeature`. TopoJSON→GeoJSON decode is LAZY (dynamic import via `loadMunicipalityGeometryModule` / `loadMunicipalityZoneGeometryModule`; B5 F1 done) — the default `/campanha` server graph never pays it. Shared feature types live in `bahiaGeometriesTypes.ts`: `BahiaFeature

` is the one spelling of `Feature`, `BahiaMeshFeature` is what the map layer receives from any of the three meshes, and geometry math (point-in-polygon, centroid, area, bounds — all built on the exported `polygonRingsOf`) takes **`PolygonalFeature`**, which declares the actual requirement instead of dragging `GeoJsonProperties` (i.e. `any`) through the signature. +- **Territory polygons:** dissolved from IBGE municipality meshes via `bahiaIdentityTerritoryRecords` (`topojson` `merge`), not the IDE Bahia shapefile (IDE remains provenance/validation reference only). +- **Rebuild (Salvador zones):** `pnpm build:municipality-zone-geometries` (`scripts/build-municipality-zone-geometries.mjs`; `--report` reconciles without writing) downloads IBGE `BA_bairros_CD2022.zip` from geoftp, parses the shapefile with **`shpjs`** (devDependency — that cut is SHP-only, SIRGAS 2000), keeps `CD_MUN === '2927408'` (170 polygons) and dissolves neighbourhood→zone against **TRE-BA RA 02/2017** (`municipalityZoneNeighborhoods.ts`). Reconciliation is **curated data in the script header**, not cleverer matching: an alias table, a table for TRE neighbourhoods with no polygon of their own (the build refuses a merge that would cross zones), and a table for the one neighbourhood the resolution splits mid-street (it goes whole to one ZE — the neighbourhood is the atom). The 5 polygons the resolution never names are assigned by **longest shared boundary**, a rule validated against the 4 it names under another label. The build fails on an orphan polygon or a TRE neighbourhood with no polygon, so 170/170 → 19/19 is an invariant, not a hope. Same cache dir and the same "**does not touch the database**" guarantee as the sibling below. +- **Rebuild:** `pnpm build:geometries` (`scripts/build-bahia-geometries.mjs`) downloads IBGE Malhas (qualidade intermediaria) + Localidades, reconciles names with `canonicalizeMunicipalityName`, simplifies/quantizes, emits the artifacts above. Cache under `data/geometries/` (gitignored; override with `GEOMETRIES_CACHE_DIR`). **Does not touch the database** — no `assertLocalDatabase` / no prod-DB risk. Not part of `pnpm build` or `pnpm dev`. Details: `docs/plans/mapa-bahia-geometrias.md`. Scale/DRY follow-ups from `/simplify`: `docs/plans/escala-dry-pos-b2.md` (B5). + +## Election baseline data (TSE 2022) + +Public TSE 2022 results back the electoral baseline (roadmap items A3 + A4). Three collections in admin group `Dados Eleitorais`: `electionTally` (per city×zone totals: eligible voters, turnout, valid/blank/null votes), `electionCandidateVote` (nominal votes per candidate×city×zone), and `electionCandidate` (candidate registry with a cross-year `identityKey` hash — no CPF or voter ID is ever persisted). Read access requires an authenticated `campaignUser` or `users` account (`canReadElectionData`); writes are Payload-admin-only, and the import runs via CLI with `overrideAccess: true`. Since the Município remodel, the consumers are `municipalityElectoralBaseline.ts` (per-municipality series/turnout), `municipalityCandidateComparison.ts` (multi-candidate table) and `municipalityMapData.ts` (map, incl. the diverging compare mode); ticket roles live in `BASELINE_TICKET_2022`. Seeds cover 2014/2018/2022 (E2 extended the original 2022-only A3 scope). Two caching layers sit on top (2026-07-23 hardening): the immutable Solla/valid-votes series per municipality ships as a committed artifact — `pnpm build:election-aggregates` → `src/lib/electionAggregates/bahia-federal-baseline.json`, loader `src/lib/bahiaElectionAggregates.ts`, snapshot-tested against `municipalityCatalog` — so the map/dashboard never query these collections for historical years; and the elections-tab loaders (`municipalityElectoralBaseline`, `municipalityCandidateComparison`, `electionCandidateOptions`) are wrapped in `unstable_cache` under the `election-tse` tag (bust via `POST /api/revalidate?tag=election-tse` after re-seeding). + +The artifact is at **v3**: v2 added E8's `campoFederalVotesByYear` / `federalTallyByYear` / `majoritarian2022`, and B13 (2026-07-26) added `federalRankByIbgeCode` — the candidate's placement among **every** federal-deputy candidate with votes > 0 in that geography, per year, keyed by IBGE code (417 codes; Salvador's 19 zone slugs sum to the whole city, which is what the map draws) and read through `getFederalCompetitiveRank`. A geography where he had no votes gets no entry, never `rank: 0`. Its input is `loadFederalVotesByCityZoneAndCandidate` in `municipalityElectoralBaseline.ts` — the sibling of `loadCampoFederalVotesByCityZone`, same statewide scan, **CLI/build-time only**. The file is 623 KB against the 700 KB budget asserted in `tests/unit/bahiaElectionAggregates.unit.spec.ts`; anything new that would blow it needs a real measurement, not a bumped constant. Rank exists only by IBGE code — add a per-slug variant when the dossier or E11 actually needs one. + +`pnpm db:seed:tse` (`scripts/seed-tse-results.mjs`) downloads the TSE open-data zips (provenance URLs + SHA-256 in the script header), parses the Bahia scope, and imports via `payload.db.drizzle` in a transaction — idempotent by replace-per-scope `(year, office, turn)`, only `voteType: 'nominal'` rows in v1. It refuses a non-local `DATABASE_URL` (same guard family as the other seeds; override with `ALLOW_REMOTE_DB=true`) and caches downloads under `data/tse/` (gitignored). No revalidate step is needed: campaign pages are dynamic with auth, not ISR-cached. + +## Campaign supporters — LGPD blocker + +**Mandatory production blocker:** do not insert real leadership/support data or enable invites until electoral counsel documents the LGPD art. 11 basis, approves the specific versioned consent text, and an admin creates it with exactly `Consent.key = 'lideranca-autopreenchimento'`. The app intentionally fails closed when this key is absent. + +**2026-07-23 remodel (DEPLOYED to production 2026-07-23): "Município" is the operational unit** (it replaced "Praça", which replaced "Núcleo Eleitoral"). Municípios are PREDEFINED (seeded, geography read-only): 435 rows — one per Bahia municipality (416), except Salvador (19 zone Municípios, ZE 1–19); Camaçari is a single whole municipality (ZE 170/171 aggregated); shared/leaky TSE zones are cut at the municipal boundary. Code identifier: `municipality`. Leaderships are one record per person (`contact` UNIQUE) linked to N municipalities and N organizations; vote pledges are per leadership×municipality with `declaredVotes` (staff-entered, leader-visible) vs `estimatedVotes` (three scenarios, staff-only, hidden from the leader). Campaign production data was reset by the remodel migrations (public-site data untouched). Master plan: `docs/plans/remodelagem-municipios.md` (supersedes `remodelagem-pracas.md`). Details: "Campaign Municípios model" below. diff --git a/AGENTS-infra.md b/AGENTS-infra.md new file mode 100644 index 00000000..493e2201 --- /dev/null +++ b/AGENTS-infra.md @@ -0,0 +1,27 @@ +# Infrastructure layer (AGENTS layer — load when touching deploy, CI, or local dev) + +## Deploy & CI + +Production is self-hosted on the homeserver (`jorgesolla1313.com.br`, behind the Cloudflare tunnel; container/database `teqo-1313`/`teqo_1313`). **There is no Vercel deploy anymore** — the Vercel deploy job, `vercel-promote.yml`, the Vercel scripts/`vercel.json` and the `VERCEL_*` repo secrets were removed in OPS50 (2026-08-17). **CI/PR/deploy live on GitHub Actions (OPS71, 2026-08-19); the ISSUE TRACKER stays on the Forgejo** (`git.solla.dev/fsolla/teqo` — labels, claims, `pnpm issue`/`agent:*` and the post-merge flips all keep talking to the Forgejo API; GitHub is only the Actions host). The PR CI (`ci-pr.yml`, job único `checks` — OPS62) runs the same cascade as always (guards → lint → format → typecheck → knip → cycles → unit → int → build → e2e selected/afetado, skips via `ci-scope.mjs`); its check-run `CI (PR) / checks` is the required check of `main`. **There is NO main verifier (`ci.yml`) anymore**: publishing is a **manual `workflow_dispatch`** (`.github/workflows/deploy.yml`) with two jobs — `verify` (hosted `ubuntu-latest`, suíte **full** incl. e2e full) → `deploy` (`needs: [verify]`, `runs-on: [self-hosted, homeserver]`): the GitHub self-hosted runner ON the homeserver executes `scripts/deploy-homeserver.sh` **locally** (no SSH; outbound-only runner, works behind the tunnel; the hosted job never touches the homeserver). The remote Docker deployment is gone; the production container runs the monolith directly. The Docker Compose file is used ONLY for local dev databases. The `run-deploy.yml` (OPS38/OPS46) was deleted in OPS71. There is no `run-deploy.yml` or equivalent in GitHub Actions — deploy is `deploy.yml` only. + +**Guarding `pnpm push` (OPS24+):** every PR push goes through `scripts/git-push.mjs`, which runs `ensure-repo-deps` (install + Husky in worktrees — OPS51), then `gate:push` (the pre-push hook), which chains `gate:ci` — a serialized mirror of the CI `checks` job (**without e2e**: OPS72 moved e2e to an explicit skill step) — plus the `docs-guards` (changelog append-only, aggregation sync, conflict markers — OPS63; the rewrite escape stays in CI only). The hook blocks `git push` on failure; escape: `git push --no-verify` (WIP only). There is no YAML `push` gate — the hook is the gate. **CI red on your PR is yours**, even pre-existing or infra — "out of feature scope" is not a stop condition (policy "Dono do PR, dono do CI" in `docs/AGENT-OPS.md`). + +## Database & local development + +- Local dev runs against a local Docker Postgres (`pnpm db:start`). To copy production content locally, use `pnpm db:pull` (`scripts/db-pull.mjs`): it only reads prod, only writes local, and excludes supporter PII (`contact`/`signature`/`subscription` row data). +- `pnpm db:doctor` diagnoses local database connectivity for the dev AND test targets: it names who holds the port, points at exited/crash-looping containers, and flags Postgres containers sharing one data volume (two postmasters on one PGDATA corrupt the WAL — this destroyed the local cluster's checkpoint on 2026-07-25; the canonical setup is ONE compose container on 5432 hosting `teqo` + `teqo_test`). `pnpm dev` runs the same preflight via `guard-dev-db` and refuses to start with a named remedy instead of a later ECONNREFUSED. `db:start`/`db:stop` pin the compose project with `-p teqo`, so they always target that ONE container even from a worktree directory. **`db:start` is idempotent (OPS37):** with `teqo-postgres-1` up and healthy it is a no-op — a plain `compose up` from another worktree would recreate the shared container and kill every live dev/e2e connection (the compose file's relative `./docker/postgres/init` bind mount makes the config hash differ per worktree); apply a real config/image change on purpose with `pnpm db:start --force-recreate`. +- **Per-worktree environments (`pnpm worktree next`, 2026-08-08; default-go 2026-08-10):** parallel agents each get a deterministic isolated env — no fighting over port 3000, the shared `teqo_test`, or a second Postgres container. **`next` claims BEFORE creating the worktree (OPS33, 2026-08-10):** the same queue/order and optimistic lock as `pnpm agent:claim` (shared `claimIssue` in `scripts/lib/agent-github.mjs`); a failed claim prints the reason and stops with no orphan worktree; `--issue ` claims the directed issue (`ready`) or **reopens** an already-claimed one (`in-progress`, no re-claim, worktree reuse stays idempotent); the claim brief is printed and the output warns "já claimada — não rodar `pnpm agent:claim"` (`plan`/`new`/`kill` never touch Issues; the pool's coordinated `claimIssueForPool` is untouched). `worktree next [--issue N] [--stay]` provisions: a dev-server port `3100+slot` (slot = numeric part of the issue code, capped at 999 with hash fallback, bumped on collision among live worktrees), plus dedicated databases `teqo_wt` (dev) and `teqo_wt_test` (tests) created on the shared container with the full migration chain AND the minimal seed applied (`pnpm migrate` + `pnpm db:seed:minimal` per database — OPS28 parity: CI runs the same pair before e2e, so a worktree's `pnpm test:e2e` mirrors CI instead of failing on seed-dependent specs; the seed is idempotent and local-guarded, and `--no-migrate` skips both); writes `.env.local` + `.env.test.local` (gitignored, marker `# teqo worktree env (generated by pnpm worktree next)`; manual envs are never overwritten) and copies `PAYLOAD_SECRET`/`S3_*` (all-or-nothing)/VAPID from the main repo — plus the gitignored `.opencode/secrets/*` (e.g. `penpot-token`, referenced by the worktree's `opencode.json` MCP config), without which opencode refuses to launch ("bad file reference" for the dangling `{file:…}`). **`next`/`plan`/`new` print `cd

` as the last line BY DEFAULT** — the caller applies it... (line truncated to 2000 chars) +- To (repopulate news content, `pnpm db:seed:posts` fetches articles live from jorgesolla.com.br into the LOCAL db (same non-local `DATABASE_URL` guard as `pnpm dev`). It writes from a CLI process outside the deployed runtime, so after seeding — or after ANY direct-DB change — you must bust the production `posts` cache via `POST /api/revalidate`. See "Posts & Tags" in `AGENTS-public.md`. +- To (re)populate the TSE 2022 election baseline, `pnpm db:seed:tse` downloads TSE open data and imports the Bahia scope into the LOCAL db (same guard). Since the 2026-07-23 hardening, elections-tab reads are cached under the `election-tse` tag — after re-seeding a database the deployed app reads, bust it via `POST /api/revalidate?tag=election-tse`. See "Election baseline data" in `AGENTS-campaign.md`. + +## Local verification and deploy checklist + +1. Confirm `DATABASE_URL` is `postgresql://teqo:teqo@localhost:5432/teqo` and `.env.test` points to `teqo_test`; never use the homeserver prod DB for development, tests, E2E, or local builds. In a provisioned worktree (`pnpm worktree next`) the values come from its `.env.local` / `.env.test.local` (`teqo_wt` / `teqo_wt_test`, dev port `3100+slot`) — read them there instead of assuming the main-repo names. +2. Run `pnpm db:start`, `pnpm migrate:status`, and `DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm migrate:status`; every migration must show `Ran: Yes`. +3. Run `pnpm generate:types`, `pnpm generate:importmap` when components changed — **com as envs `S3_*` setadas (valores dummy ok) enquanto o plugin `s3Storage` for condicional: sem elas o importMap fica órfão do `S3ClientUploadHandler` e o admin abre em branco em produção (OPS69, P0 em 2026-08-19)** —, `pnpm exec tsc --noEmit`, `pnpm lint` (zero warnings — the script enforces `--max-warnings=0`), `pnpm format:check` (Prettier is the formatting authority; `pnpm format` fixes), `pnpm exec knip` (dead files/dependencies are CI-blocking; delete what your change orphaned), `pnpm check:cycles` (madge — zero circular imports), `pnpm test` (unit + int), and `pnpm build` against the local database. Payload CLI scripts (`migrate`, `generate:*`, `payload`) and the build migrate step use `--conditions=react-server` so `server-only` modules load correctly outside Next.js. **Política de e2e (OPS72):** o e2e **não roda no gate local** (`gate:push`) — é passo **explícito da skill** (`work-issue`/`agent-work-issue`): antes do push o agente roda localmente os e2e que **criou** + os da **mesma superfície afetada** — **discricionário** (o agente decide quais; ferramenta: `pnpm test:e2e:affected`, espelho local do classifier — gera `--no-deps` para runs filtrados, S6-FOLLOWUP: no dev mode a cadeia de dependencies dos projects arrasta os arquivos das dependências via closure; filtros manuais locais: `pnpm test:e2e --no-deps -- ` ou `--no-deps --project=`; limitação #72: `--no-deps` + projetos paralelos colide no `seedTestUser` → `--workers=1` ou a cadeia padrão de projetos). O **CI de PR roda apenas o blast radius** (modo `selected` via `ci-scope.mjs` — **nunca `full`**; diff high-risk classifica `full` e o PR simplesmente não roda e2e). O e2e **full** roda no `verify` do deploy manual (gateia merge e deploy — rede de segurança final antes de publicar). + - Never run `knip --fix` blind: when knip's module graph is incomplete (it still cannot load `payload.config.ts` — ledgered as P3), `--fix` deletes exports that migrations/tests still reference. Verify each removal (e.g. `git grep -w `) before deleting. + - Run gate commands bare — never piped (`pnpm test | tail` swallows the exit code, and a real failure was masked exactly this way during Pass 2). Large outputs are captured by the terminal; read them from there. +4. Scan every edited runtime source file with Aikido and resolve new findings before handoff. Do not expand hardening work into unrelated pre-existing findings without an explicit scope change. +5. Review production environment variables and migration SQL before deploy; `pnpm build` applies pending migrations to the deployed database automatically. **`NEXT_PUBLIC_SITE_URL` (ex.: `https://jorgesolla1313.com.br`) é obrigatória em Production** — sem ela, `getCampaignInviteBaseURL()` lança em runtime e o fluxo de convites/webauthn/link de import da agenda falha com mensagem genérica (C98, 2026-08-09: produção ficou sem a env e "gerar link" do feed quebrava; o preview tinha a de stage). +6. **Mandatory production blocker:** do not insert real leadership/support data or enable invites until electoral counsel documents the LGPD art. 11 basis, approves the specific versioned consent text, and an admin creates it with exactly `Consent.key = 'lideranca-autopreenchimento'`. The app intentionally fails closed when this key is absent. +7. **Remodel deploy (historical — applied to production 2026-07-23):** the destructive remodel chain (`20260721_020109_remodel_municipalities` → `20260723_200000_remodel_municipalities` + `20260723_202000_reconcile_municipality_remodel`) already ran in production via the Vercel build: campaign vertical reset, 435 municípios seeded, public-site data untouched. Treat any future destructive migration the same way — review its SQL before the first production build that includes it. diff --git a/AGENTS-public.md b/AGENTS-public.md new file mode 100644 index 00000000..9de940da --- /dev/null +++ b/AGENTS-public.md @@ -0,0 +1,43 @@ +# Public site domain (AGENTS layer — load when touching `(frontend)`) + +## Posts & Tags (news / publications) + +The public news/publications system is backed by two collections (both in the `Publicações` admin group) plus the helpers in `src/utilities/posts.ts`. + +- **`post`** (`src/collections/Post.ts`) — fields: `title`, `slug` (unique, indexed, auto-slugified from `title` when left empty), `type` (select enum `noticia|campanha|artigo|evento`), `category` (required single relationship → `tag`), `tags` (`hasMany` relationship → `tag`), `subtitle`, `coverImage` (upload → `media`), `publishedDate`, `body` (richText). Has drafts/versions (`schedulePublish`, `maxPerDoc: 5`). +- **`tag`** (`src/collections/Tag.ts`) — fields: `name`, `slug` (unique, indexed, auto-slugified from `name`), and `hidden` (checkbox, admin label "Esconder", default `false`). Tags are the shared taxonomy for both `post.category` and `post.tags`. + +**Tags are a taxonomy, not a person record.** The `Contact` convention applies to _people_; `tag` is publication metadata (categories + a visibility control flag), so post/tag relations do not touch `Contact`. Don't fold taxonomy into `Contact` or vice-versa. + +**Electoral visibility control (`hidden` + fail-closed `isPostVisible`).** Marking a tag `hidden` hides every post that references it — as `category` or in `tags` — with a single toggle. This exists so campaign / pre-candidacy content (tagged `eleitoral`) can be pulled from the public site during the electoral period. `isPostVisible(post)` (`src/utilities/posts.ts`) returns true only when the post is `published` AND none of its related tags (`category` + `tags`) is `hidden`. It **fails closed**: an unpopulated relation (a bare numeric id) is treated as hiding, so callers must fetch with `depth >= 1`. Every public read filters through `getVisiblePosts()`, which applies this predicate to the cached published list. + +**URLs and Portuguese SEO values.** The canonical article path is `/[type]/[category]/[slug]` (e.g. `/noticia/saude/`), with `/[type]` and `/[type]/[category]` listing routes and the home "Últimas notícias" list. The `type` enum values (`noticia|campanha|artigo|evento`) and tag/category slugs (`saude`, `eleitoral`, …) are deliberately Portuguese for SEO and are **data, not identifiers** — never translate them (see the naming-conventions bullet above). The route folders are `[type]/[category]/[slug]` (English param keys); the article route redirects any stale/mismatched URL to the canonical path derived from the post's _current_ `type` + category slug. Article pages emit JSON-LD (`Article`) and Open Graph metadata. + +**Caching (mixed ISR, `posts` tag).** Public reads go through the `unstable_cache` wrappers in `src/utilities/posts.ts` (`getCachedPublishedPosts`, `getCachedPostBySlug`), all tagged `posts`. The routes set `export const dynamicParams = true` and build `generateStaticParams` from `getVisiblePosts()`: known paths are statically generated, unknown ones render on demand, and everything stays cached until the `posts` tag is busted. `revalidatePostsListing()` (`src/utilities/documents.ts`) is `revalidateTag('posts')` (the listing tag is `` `${collection}s` `` → `posts`), so one call busts the home page, every listing route, and every article route at once. + +**Self-revalidation on admin edits.** Both collections have an `afterChange` hook. `post` busts its own document tag + the `posts` listing on every publish/update (skipping only the initial draft that the admin create view generates during render). `tag` is broader: on change it re-reads every post referencing that tag (as `category` or in `tags`, passing `req` for transaction safety) and revalidates each one plus the listing — so flipping `hidden` is reflected on the site immediately. + +**Seeding news content (`pnpm db:seed:posts`).** `scripts/seed-posts.mjs` (loaded via `scripts/seed-loader.mjs`) fetches ~43 articles live from jorgesolla.com.br (WordPress REST API, with an HTML-crawl fallback), imports them as `type: 'noticia'` published posts, converts the WP HTML body to Payload Lexical, and uploads cover images through the configured media storage (Garage S3 when the `S3_*` envs are set — the adapter overwrites the deterministic `.` key natively, no pre-delete needed; local disk otherwise). The taxonomy (categories + the `eleitoral` control tag, and the per-slug classification) is hardcoded in the script; it reads/writes the `hidden` flag. It is **idempotent by slug** (existing posts are skipped; tags/media are reused by slug/filename) and reuses the same non-local `DATABASE_URL` guard as `pnpm dev` (override only with `ALLOW_REMOTE_DB=true`). `pnpm db:seed:posts --dry-run` is the plan-only pre-flight (fetches, resolves covers, reports what WOULD be created — no writes). **Since OPS60, sync with the `S3_*` envs set also requires explicit bucket-write intent: `SEED_MEDIA_CONFIRM=1`** (fail-closed, same `isTruthyEnv` pattern as `MEDIA_RECOVER_CONFIRM`; without it the sync refuses with exit 1 before any write — the `S3_*` envs alone must never arm a bucket write, since a worktree with a prod-credentials copy running sync against a local DB would write covers to the prod bucket). `--dry-run` stays flag-free. The OPS58 runbook documents the production sync (post-merge, homeserver, stack env, dry-run → sync → bust `posts` cache → verify) — copy it for future syncs (see `docs/plans/ops58-sincronizar-posts-prod-impl.md`). + +### Revalidating after a manual/direct DB change + +Admin edits made through the deployed app self-revalidate via the `afterChange` hooks above. But any write that does **not** go through the deployed Payload runtime — direct SQL, `pnpm db:seed:posts`, a DB restore / `db:pull` — will **not** bust production's frozen `posts` cache. (Even when such a write triggers the hook, its `revalidateTag('posts')` runs in that CLI/local process and cannot touch the deployed server's cache.) The pages keep serving stale content until the tag is busted. + +Bust it with the secured endpoint (`src/app/(frontend)/api/revalidate/route.ts`): + +```bash +# News (`posts` tag — default) +curl -X POST "https:///api/revalidate" \ + -H "x-revalidate-secret: $REVALIDATE_SECRET" + +# Privacy policy global after Onda 0 migration/seed (`global_privacy-policy`) +curl -X POST "https:///api/revalidate?tag=global_privacy-policy" \ + -H "x-revalidate-secret: $REVALIDATE_SECRET" +``` + +- **Auth:** send the secret via `x-revalidate-secret` or `Authorization: Bearer `; it is compared to `REVALIDATE_SECRET` with a constant-time check. +- `REVALIDATE_SECRET` must be set in the **production** env (and in your local env if you want to test the endpoint). It is documented in `.env.example`. +- **Tag:** optional `?tag=` query or JSON body `{ "tag": "..." }` (query wins). Allowlist: `posts` (default), `global_privacy-policy`, `election-tse` (bust after re-running `pnpm db:seed:tse` so the cached elections-tab reads refresh), `municipality-catalog` (bust after a migration/seed that adds or renames a município so chip indexes and `unstable_cache` loaders refresh), `social-feed` (bust after a direct-DB write to the `social-feed-settings` global — e.g. an admin-less seed of the YouTube/Instagram feed config; admin edits self-revalidate). Unknown tag → `400`. +- **Instagram sync status (S11):** the global's `instagramSyncStatus` jsonb (hidden) is written by the render path, by `afterChange` (re-sync only when IG credentials changed), and by the admin button `POST /api/social-feed/sync` (admin session via `payload.auth` + same-origin guard); the `InstagramSyncStatusPanel` ui field renders it. Runbook de credenciais: `docs/ops/instagram-feed-token-runbook.md`. +- **Responses:** `200 { revalidated: true, tag: '...' }` on success; `401` if the secret is missing/wrong; `500` if `REVALIDATE_SECRET` is not configured on the server. +- This POST is the required last step of the post-seed / direct-DB-change runbook. diff --git a/AGENTS.md b/AGENTS.md index 2553189d..7036e5b3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,7 +22,6 @@ These are product/architecture constraints — not a ban on editing existing cod - `Contact` is the normalized "person" record (name, email, phone, state/city via `src/lib/cities.ts`, CEP). Don't create a parallel "person" collection for new features (e.g. líderanças/apoiadores) — add a join collection that relates to `Contact`, the same way `Signature` and `Subscription` do. - Every action that writes to more than one collection (see `src/app/(frontend)/actions/*.ts`) wraps the writes in a Payload transaction (`payload.db.beginTransaction/commitTransaction/rollbackTransaction`) and passes `req: { transactionID }` to every `payload.create`/`payload.update` call. Follow this pattern for any new multi-collection write. - LGPD consent is tracked via a `Consent` collection (richText, versioned, optional stable `key`) referenced by relationship from `Signature`/`Subscription`/campaign `leadership`. New campaign opt-in flows resolve Consent by stable `key` (e.g. `lideranca-autopreenchimento`) and fail closed when missing — don't invent a parallel consent mechanism or hardcode document IDs for new work. -- Cache invalidation: collections/globals call `revalidateDocumentById` (`src/utilities/documents.ts`) / `revalidateGlobal` (`src/utilities/globals.ts`) in an `afterChange` hook. Add the same hook to any new collection/global that backs a public page. Collections whose listing is cached under a shared tag also call the listing helper (`revalidateCollectionListing`, e.g. `revalidatePostsListing()` → `revalidateTag('posts')`) — see "Posts & Tags" below. - Admin UI is organized via `admin.group` (e.g. `'Abaixo-assinados'`, `'Contatos'`, `'Configurações'`, `'Paginas'`, `'Campanha'`, `'Dados Eleitorais'`) — group new collections consistently instead of leaving them ungrouped. - i18n: Payload admin defaults to `pt` (not `pt-BR` — see `payload.config.ts`, `payload/i18n/pt`). - Language & naming conventions: ALL code identifiers are in English — variable, function, parameter, type/interface names, local constants, and Next.js dynamic route segment folder names used as param keys (e.g. `[type]/[category]/[slug]`, not `[tipo]/[categoria]`). Portuguese is allowed ONLY in: user-visible string literals (JSX text, button/labels), image `alt` text, SEO/metadata values (title/description/keywords), Payload admin config text (`labels`/`singular`/`plural`/`admin.description`/field `label`), and intentional URL slug/enum VALUES kept in Portuguese for SEO (e.g. the `post.type` enum values `noticia|campanha|artigo|evento`, tag/category slugs like `saude`, `eleitoral`). Never translate those data/URL values or admin labels. Renaming a route segment folder changes only the param KEY, never the public URL (segment values come from the data). @@ -33,140 +32,11 @@ These are product/architecture constraints — not a ban on editing existing cod - **`pnpm dev` honra o `PORT` do `.env.local` (OPS40):** `next dev` resolve a porta ANTES de `@next/env` carregar os env-files (commander `.env('PORT')` no `bin/next`), então o `PORT=3100+slot` do provisionador de worktree era ignorado e todo dev server subia em 3000. `pnpm dev` hoje passa por `scripts/dev.mjs`: roda o mesmo preflight do `guard-dev-db`, carrega `.env.local` → `.env` (`override:false` — env real do processo vence, como o `PORT` que o webServer do Playwright injeta) e entrega a porta ao `next dev` como **flag CLI `-p`** (`resolveDevPort`/`nextDevArgs` em `scripts/lib/cli.mjs`, unit-testados); sem `PORT` em lugar nenhum, nenhum `-p` é passado e o default 3000 (com `allowRetry`) do Next segue intacto no main repo. - Schema changes go through committed Payload migrations — `push: false` everywhere, never flip it on against a remote DB. Edit configs → `pnpm migrate:create ` → commit `src/migrations/*` (both `.ts` and `.json`, plus `index.ts`) → `pnpm migrate` locally. `pnpm build` runs `payload migrate`, so **every production deploy applies pending migrations to prod**. Prod is baselined at migration `20260715_163458_initial` — never regenerate or replace the initial migration. Full workflow (incl. hand-written data/reconciliation migrations) lives in the `payload-migrations` skill (`.agents/skills/payload-migrations`). - `Consent.text` was reconciled from `varchar` to `jsonb` via `20260715_163500_consent_text_to_jsonb` (matching the `richText` field). Any future field-type change is a migration, not a manual DB edit. -- To copy production content locally, use `pnpm db:pull` (`scripts/db-pull.mjs`): it only reads prod, only writes local, and excludes supporter PII (`contact`/`signature`/`subscription` row data). -- `pnpm db:doctor` diagnoses local database connectivity for the dev AND test targets: it names who holds the port, points at exited/crash-looping containers, and flags Postgres containers sharing one data volume (two postmasters on one PGDATA corrupt the WAL — this destroyed the local cluster's checkpoint on 2026-07-25; the canonical setup is ONE compose container on 5432 hosting `teqo` + `teqo_test`). `pnpm dev` runs the same preflight via `guard-dev-db` and refuses to start with a named remedy instead of a later ECONNREFUSED. `db:start`/`db:stop` pin the compose project with `-p teqo`, so they always target that ONE container even from a worktree directory. **`db:start` is idempotent (OPS37):** with `teqo-postgres-1` up and healthy it is a no-op — a plain `compose up` from another worktree would recreate the shared container and kill every live dev/e2e connection (the compose file's relative `./docker/postgres/init` bind mount makes the config hash differ per worktree); apply a real config/image change on purpose with `pnpm db:start --force-recreate`. -- **Per-worktree environments (`pnpm worktree next`, 2026-08-08; default-go 2026-08-10):** parallel agents each get a deterministic isolated env — no fighting over port 3000, the shared `teqo_test`, or a second Postgres container. **`next` claims BEFORE creating the worktree (OPS33, 2026-08-10):** the same queue/order and optimistic lock as `pnpm agent:claim` (shared `claimIssue` in `scripts/lib/agent-github.mjs`); a failed claim prints the reason and stops with no orphan worktree; `--issue ` claims the directed issue (`ready`) or **reopens** an already-claimed one (`in-progress`, no re-claim, worktree reuse stays idempotent); the claim brief is printed and the output warns "já claimada — não rodar `pnpm agent:claim`" (`plan`/`new`/`kill` never touch Issues; the pool's coordinated `claimIssueForPool` is untouched). `worktree next [--issue N] [--stay]` provisions: a dev-server port `3100+slot` (slot = numeric part of the issue code, capped at 999 with hash fallback, bumped on collision among live worktrees), plus dedicated databases `teqo_wt` (dev) and `teqo_wt_test` (tests) created on the shared container with the full migration chain AND the minimal seed applied (`pnpm migrate` + `pnpm db:seed:minimal` per database — OPS28 parity: CI runs the same pair before e2e, so a worktree's `pnpm test:e2e` mirrors CI instead of failing on seed-dependent specs; the seed is idempotent and local-guarded, and `--no-migrate` skips both); writes `.env.local` + `.env.test.local` (gitignored, marker `# teqo worktree env (generated by pnpm worktree next)`; manual envs are never overwritten) and copies `PAYLOAD_SECRET`/`S3_*` (all-or-nothing)/VAPID from the main repo — plus the gitignored `.opencode/secrets/*` (e.g. `penpot-token`, referenced by the worktree's `opencode.json` MCP config), without which opencode refuses to launch ("bad file reference" for the dangling `{file:…}`). **`next`/`plan`/`new` print `cd ` as the last line BY DEFAULT** — the caller applies it (shell function `worktree()` in `.agents/shell/worktree.sh`, or the `/worktree` opencode command); `--stay` suppresses the cd, `--go` explicit stays accepted as a no-op (it was the old default), and `kill` ends with `cd
` so the shell never sits in a destroyed directory. **In the interactive terminal the shell function sets `TEQO_WORKTREE_TERMINAL=1` and `next`/`plan`/`new` additionally print a `launch opencode --model deepseek/deepseek-v4-flash --auto [--prompt "/work-issue --issue "]` directive BEFORE the `cd` line, which the function executes after the cd (OPS26, 2026-08-10; OPS33: `next` sends `/work-issue --issue ` — the claimed issue — with the prompt value quoted, and the shell tokenizes the line via xargs, quote-aware, never eval; OPS31 for `plan`): `next` opens the opencode TUI in the worktree with `/work-issue --issue ` already sent (the OPS25 command runs the whole cycle; the skill reads the rest from the Issue), `plan` opens with `/plan-issue` already sent (the TUI lands straight in the planning flow), `new` opens with no prompt ("apenas conversar", no skill — the opencode CLI's `--prompt` always auto-submits, there is no prefill-without-submit; that stays an upstream-only feature request, annotated in the opencode proposition). The launch is without `exec` (exiting the TUI returns to the shell in the worktree, no auto-`kill`), `--stay` suppresses both the cd and the launch (the claim still happens), the presets are constants in `scripts/lib/worktree.mjs` (`OPENCODE_PRESET_MODEL`, `OPENCODE_SKILL_COMMAND_BY_PURPOSE`, unit-tested), and **the `/worktree` opencode command never launches a TUI** (no marker — no nested TUI). `worktree plan [bag] [--stay]` (2026-08-08) is the sibling for the `/plan-issue` skill: **each invocation creates a DIFFERENT planning worktree** so parallel `/plan-issue` sessions never share one — branch `plans/plan-issue-` when a `bag` slug is given (suffixed `-2`/`-3` if that name is taken) or the next free sequential `plans/plan-issue-` when not (`PLAN_BRANCH_PREFIX`/`planBranchName`, `scripts/lib/worktree.mjs`); the lowercase `plans/…` prefix deliberately never matches `next`'s uppercase-led `-`, so a later `next` never collides in branch or slot. `worktree new [bag] [--stay]` (OPS27, 2026-08-10) is the NEUTRAL sibling: a worktree with **no pre-defined function\*\* (explore an idea, chat, plan without registering anything) — also a DIFFERENT one per invocation, branch `work/` (suffixed `-2`/`-3` on collision) or the next free sequential `work/` (`WORK_BRANCH_PREFIX`/`workBranchName`, same `namespaceBranchName` core as `plan`); the lowercase `work/…` prefix collides with neither `next` nor `plan`, and the provisioning is identical with `purpose: 'new'` (env comment `gerado por pnpm worktree new`; the frozen env marker keeps its historical `…next` text). `kill` drops the worktree's generated databases best-effort. Tests read `.env.test.local` after `.env.test` (vitest.setup.ts / playwright.config.ts / db-doctor / gate-ci mirror the layering), and `assertTestDatabase` accepts `teqo_test` or `teqo__test` on localhost only — still fail-closed on remote. Pure derivation lives in `scripts/lib/worktree-env.mjs` (unit-tested). Without Docker (Cursor Cloud) it degrades to the shared `teqo`/`teqo_test` with a warning — and still runs migrate + seed mínimo on those shared databases (same parity; the seed re-pins campaignGoals and 5 municipalities there, overwriting manual tweaks). -- To (re)populate news content, `pnpm db:seed:posts` fetches articles live from jorgesolla.com.br into the LOCAL db (same non-local `DATABASE_URL` guard as `pnpm dev`). It writes from a CLI process outside the deployed runtime, so after seeding — or after ANY direct-DB change — you must bust the production `posts` cache via `POST /api/revalidate`. See "Posts & Tags" below. -- To (re)populate the TSE 2022 election baseline, `pnpm db:seed:tse` downloads TSE open data and imports the Bahia scope into the LOCAL db (same guard). Since the 2026-07-23 hardening, elections-tab reads are cached under the `election-tse` tag — after re-seeding a database the deployed app reads, bust it via `POST /api/revalidate?tag=election-tse`. See "Election baseline data (TSE 2022)" below. ## Histórico de entregas (movido) "Known Gaps" e os blocos "Recently resolved" saíram deste arquivo em 2026-07-30: vivem em [`docs/CHANGELOG-AGENTS.md`](docs/CHANGELOG-AGENTS.md). Novas entregas registram UMA entrada curta em `docs/changelog/-.md` e rodam `pnpm changelog:build` (agregado insert-only, OPS44) — nunca editam `docs/CHANGELOG-AGENTS.md` na mão. A referência genérica de Payload (config/collections/fields/hooks/queries/components) foi para [`docs/PAYLOAD-REFERENCE.md`](docs/PAYLOAD-REFERENCE.md) — consulta sob demanda, não always-on. Operação do paradigma de agentes paralelos (claim→PR→main→deploy gated): [`docs/AGENT-OPS.md`](docs/AGENT-OPS.md). -## Posts & Tags (news / publications) - -The public news/publications system is backed by two collections (both in the `Publicações` admin group) plus the helpers in `src/utilities/posts.ts`. - -- **`post`** (`src/collections/Post.ts`) — fields: `title`, `slug` (unique, indexed, auto-slugified from `title` when left empty), `type` (select enum `noticia|campanha|artigo|evento`), `category` (required single relationship → `tag`), `tags` (`hasMany` relationship → `tag`), `subtitle`, `coverImage` (upload → `media`), `publishedDate`, `body` (richText). Has drafts/versions (`schedulePublish`, `maxPerDoc: 5`). -- **`tag`** (`src/collections/Tag.ts`) — fields: `name`, `slug` (unique, indexed, auto-slugified from `name`), and `hidden` (checkbox, admin label "Esconder", default `false`). Tags are the shared taxonomy for both `post.category` and `post.tags`. - -**Tags are a taxonomy, not a person record.** The `Contact` convention above applies to _people_; `tag` is publication metadata (categories + a visibility control flag), so post/tag relations do not touch `Contact`. Don't fold taxonomy into `Contact` or vice-versa. - -**Electoral visibility control (`hidden` + fail-closed `isPostVisible`).** Marking a tag `hidden` hides every post that references it — as `category` or in `tags` — with a single toggle. This exists so campaign / pre-candidacy content (tagged `eleitoral`) can be pulled from the public site during the electoral period. `isPostVisible(post)` (`src/utilities/posts.ts`) returns true only when the post is `published` AND none of its related tags (`category` + `tags`) is `hidden`. It **fails closed**: an unpopulated relation (a bare numeric id) is treated as hiding, so callers must fetch with `depth >= 1`. Every public read filters through `getVisiblePosts()`, which applies this predicate to the cached published list. - -**URLs and Portuguese SEO values.** The canonical article path is `/[type]/[category]/[slug]` (e.g. `/noticia/saude/`), with `/[type]` and `/[type]/[category]` listing routes and the home "Últimas notícias" list. The `type` enum values (`noticia|campanha|artigo|evento`) and tag/category slugs (`saude`, `eleitoral`, …) are deliberately Portuguese for SEO and are **data, not identifiers** — never translate them (see the naming-conventions bullet above). The route folders are `[type]/[category]/[slug]` (English param keys); the article route redirects any stale/mismatched URL to the canonical path derived from the post's _current_ `type` + category slug. Article pages emit JSON-LD (`Article`) and Open Graph metadata. - -**Caching (mixed ISR, `posts` tag).** Public reads go through the `unstable_cache` wrappers in `src/utilities/posts.ts` (`getCachedPublishedPosts`, `getCachedPostBySlug`), all tagged `posts`. The routes set `export const dynamicParams = true` and build `generateStaticParams` from `getVisiblePosts()`: known paths are statically generated, unknown ones render on demand, and everything stays cached until the `posts` tag is busted. `revalidatePostsListing()` (`src/utilities/documents.ts`) is `revalidateTag('posts')` (the listing tag is `` `${collection}s` `` → `posts`), so one call busts the home page, every listing route, and every article route at once. - -**Self-revalidation on admin edits.** Both collections have an `afterChange` hook. `post` busts its own document tag + the `posts` listing on every publish/update (skipping only the initial draft that the admin create view generates during render). `tag` is broader: on change it re-reads every post referencing that tag (as `category` or in `tags`, passing `req` for transaction safety) and revalidates each one plus the listing — so flipping `hidden` is reflected on the site immediately. - -**Seeding news content (`pnpm db:seed:posts`).** `scripts/seed-posts.mjs` (loaded via `scripts/seed-loader.mjs`) fetches ~43 articles live from jorgesolla.com.br (WordPress REST API, with an HTML-crawl fallback), imports them as `type: 'noticia'` published posts, converts the WP HTML body to Payload Lexical, and uploads cover images through the configured media storage (Garage S3 when the `S3_*` envs are set — the adapter overwrites the deterministic `.` key natively, no pre-delete needed; local disk otherwise). The taxonomy (categories + the `eleitoral` control tag, and the per-slug classification) is hardcoded in the script; it reads/writes the `hidden` flag. It is **idempotent by slug** (existing posts are skipped; tags/media are reused by slug/filename) and reuses the same non-local `DATABASE_URL` guard as `pnpm dev` (override only with `ALLOW_REMOTE_DB=true`). `pnpm db:seed:posts --dry-run` is the plan-only pre-flight (fetches, resolves covers, reports what WOULD be created — no writes). **Since OPS60, sync with the `S3_*` envs set also requires explicit bucket-write intent: `SEED_MEDIA_CONFIRM=1`** (fail-closed, same `isTruthyEnv` pattern as `MEDIA_RECOVER_CONFIRM`; without it the sync refuses with exit 1 before any write — the `S3_*` envs alone must never arm a bucket write, since a worktree with a prod-credentials copy running sync against a local DB would write covers to the prod bucket). `--dry-run` stays flag-free. The OPS58 runbook documents the production sync (post-merge, homeserver, stack env, dry-run → sync → bust `posts` cache → verify) — copy it for future syncs (see `docs/plans/ops58-sincronizar-posts-prod-impl.md`). - -### Revalidating after a manual/direct DB change - -Admin edits made through the deployed app self-revalidate via the `afterChange` hooks above. But any write that does **not** go through the deployed Payload runtime — direct SQL, `pnpm db:seed:posts`, a DB restore / `db:pull` — will **not** bust production's frozen `posts` cache. (Even when such a write triggers the hook, its `revalidateTag('posts')` runs in that CLI/local process and cannot touch the deployed server's cache.) The pages keep serving stale content until the tag is busted. - -Bust it with the secured endpoint (`src/app/(frontend)/api/revalidate/route.ts`): - -```bash -# News (`posts` tag — default) -curl -X POST "https:///api/revalidate" \ - -H "x-revalidate-secret: $REVALIDATE_SECRET" - -# Privacy policy global after Onda 0 migration/seed (`global_privacy-policy`) -curl -X POST "https:///api/revalidate?tag=global_privacy-policy" \ - -H "x-revalidate-secret: $REVALIDATE_SECRET" -``` - -- **Auth:** send the secret via `x-revalidate-secret` or `Authorization: Bearer `; it is compared to `REVALIDATE_SECRET` with a constant-time check. -- `REVALIDATE_SECRET` must be set in the **production** env (and in your local env if you want to test the endpoint). It is documented in `.env.example`. -- **Tag:** optional `?tag=` query or JSON body `{ "tag": "..." }` (query wins). Allowlist: `posts` (default), `global_privacy-policy`, `election-tse` (bust after re-running `pnpm db:seed:tse` so the cached elections-tab reads refresh), `municipality-catalog` (bust after a migration/seed that adds or renames a município so chip indexes and `unstable_cache` loaders refresh), `social-feed` (bust after a direct-DB write to the `social-feed-settings` global — e.g. an admin-less seed of the YouTube/Instagram feed config; admin edits self-revalidate). Unknown tag → `400`. -- **Instagram sync status (S11):** the global's `instagramSyncStatus` jsonb (hidden) is written by the render path, by `afterChange` (re-sync only when IG credentials changed), and by the admin button `POST /api/social-feed/sync` (admin session via `payload.auth` + same-origin guard); the `InstagramSyncStatusPanel` ui field renders it. Runbook de credenciais: `docs/ops/instagram-feed-token-runbook.md`. -- **Responses:** `200 { revalidated: true, tag: '...' }` on success; `401` if the secret is missing/wrong; `500` if `REVALIDATE_SECRET` is not configured on the server. -- This POST is the required last step of the post-seed / direct-DB-change runbook. - -## Campaign auth (`/campanha`) - -The internal `/campanha` area is gated by its own authentication, deliberately kept **isolated from the Payload admin (`/admin`)** so a campaign session and an admin session can coexist in the same browser. - -- **`campaignUser` collection** (`src/collections/CampaignUser.ts`) — a separate Payload auth collection with `name`, optional contact `phone`, and required `role`: `coordinator` ("Coordenador Geral"), `advisor` ("Assessor"), `candidate` ("Candidato"), or `leader` ("Liderança" — default and least privilege). Staff may sign in by email; leadership accounts use the normalized 11-digit phone as `username`. It is not `users`: `admin.user` remains `users`, so campaign users cannot log into `/admin`. Its static `auth.tokenExpiration` is the 14-day ceiling because Payload's Local API does not accept a per-login TTL and `useSessions` (enabled) stores/prunes sessions using that configured expiry. -- **Isolated session cookie `campaign-token`.** The flow sets its own httpOnly cookie named `campaign-token` (constant `CAMPAIGN_TOKEN_COOKIE` in `src/utilities/campaignAuth.ts`), scoped to `path: '/campanha'`, `sameSite: 'lax'`, and `secure` only in production. It is deliberately NOT the default `payload-token` cookie — using a distinct name + path is what lets a campaign session and a Payload admin session live side by side without clobbering each other. Login defaults to **8 hours**; checking "Lembrar de mim neste dispositivo" opts into **14 days**. `setCampaignAuthCookie` owns the invariant JWT `exp` = cookie `maxAge`: it re-signs the Payload token to 8 hours with `jwtSign` or keeps the original 14-day token. Password-reset and invite login paths omit the opt-in and therefore stay at 8 hours. -- **Session verification — `getCampaignUser()`** (`src/utilities/campaignAuth.ts`). Reads the `campaign-token` cookie, calls `payload.auth({ headers })`, accepts only `user.collection === 'campaignUser'`, then reloads that document by ID. The fresh read makes role downgrades effective immediately instead of trusting a stale JWT role. -- **Login/logout server actions** (`src/app/(campaign)/campanha/actions/auth.ts`). `loginCampaign` validates input with `campaignLoginSchema` (`src/lib/schemas/campaign-login.ts`), calls `payload.login({ collection: 'campaignUser' })`, chooses the 8-hour / 14-day TTL, and — because the Local API returns a token WITHOUT setting a cookie — calls `setCampaignAuthCookie` before redirecting to `/campanha`. `logoutCampaign` authenticates the current token and delegates revocation of its `_sid` to Payload's public transactional `logoutOperation`, then clears the cookie (`maxAge: 0`) and redirects to `/campanha/login`; malformed tokens or database failures never prevent local cookie/PWA cleanup. -- **Route layout.** The route group's root layout `src/app/(campaign)/layout.tsx` renders the ``/`` with `data-theme="campaign"`. The public login lives at `src/app/(campaign)/campanha/login/` (`page.tsx` + client `LoginForm.tsx`). Everything gated sits in the `(app)` group, whose layout (`src/app/(campaign)/campanha/(app)/layout.tsx`) calls `getCampaignUser()` and `redirect('/campanha/login')` when there is no session — that layout is the barrier. -- **Biometric login (WebAuthn, B40 — 2026-07-28).** A second way into the same session, never a second session: the biometric path ends at the same `setCampaignAuthCookie` with the 14-day TTL (enrolling the device _is_ the trust opt-in), and the password path is untouched. Credentials live in `campaignWebAuthnCredential` (owner-only access in `src/utilities/access/webauthnCredentials.ts`; `update` is denied to users because the signature counter and `lastUsedAt` are written with `overrideAccess: true` inside the transaction). Four anonymous-or-authenticated JSON routes sit in `src/app/(campaign)/campanha/webauthn/` — deliberately **outside `(app)`**, since two of them run before there is a session and the cookie's `/campanha` path already covers them. **No `Consent` key, and this is not an art. 11 question:** the OS never releases the fingerprint, so what we store is a public key. - - **There is no password-less login in Payload 3.82.0.** `loginOperation` requires `password`. `issueCampaignWebAuthnSession` (`src/utilities/campaignWebAuthnSession.ts`) mints the session from public exports only: `payload.db.findOne` → `checkLoginPermission` → `addSessionToUser` (`payload/shared`) → `getFieldsToSign` + `jwtSign`. **Never load the user with `payload.findByID` here.** `addSessionToUser` read-modify-writes the _whole_ user document, so a doc that passed through `CampaignUser`'s `afterRead` `removePrivateAuthFields` would be written back without `sessions` or `email` — logging the user out of every other device — and with `avatar` expanded into an object. `user.updatedAt = null` is set for the same reason Payload's own login does it. The mint runs inside `withPayloadTransaction` under `campaign-webauthn-session:{userId}`, because rewriting the whole `sessions` array makes two concurrent logins lose one. - - **RP ID must match the host that served the page.** `getCampaignWebAuthnRelyingParty` derives `rpID`/`origin` from `getCampaignInviteBaseURL`, _and_ compares the request's host against it — returning `null` when they differ, which hides the button. Without that comparison a preview served from a different host resolves the canonical origin successfully and the browser throws `SecurityError` mid-ceremony. - - **The challenge cookie must carry the library's own challenge.** It is an HMAC-signed httpOnly cookie (5 min, single-use, path `/campanha`, precedent `supporterImportToken.ts`) — but store the exact base64url string `generateRegistrationOptions`/`generateAuthenticationOptions` returned. Generating our own alongside theirs makes every `register` answer 400. - - **Deleting a `campaignUser` needs the cascade in a hook.** Payload emits `ON DELETE SET NULL` for the required `user` relationship, which cannot apply to a `NOT NULL` column; `CampaignUser` has a `beforeDelete` that removes the user's credentials in the same transaction. E2E uses a CDP virtual authenticator (`WebAuthn.addVirtualAuthenticator`, `transport: 'internal'`), which also makes `isUserVerifyingPlatformAuthenticatorAvailable()` answer `true`. -- **Migrations.** `20260716_010420_add_campaign_user` created the auth collection; `20260728_041958_add_campaign_webauthn_credentials` added the WebAuthn credential table; the unpublished 2026-07-17 campaign chain was consolidated into `20260718_010733_consolidate_campaign_schema`, which adds role/username auth, contact phone, and the remaining final campaign schema. - -## Campaign Municípios model (2026-07-23 remodel) - -`/campanha` is organized around `municipality` ("Município") — the campaign's PREDEFINED operational territory. Deployed to production on 2026-07-23 (destructive remodel migrations applied via the Vercel build). Master plan: `docs/plans/remodelagem-municipios.md` (supersedes `docs/plans/remodelagem-pracas.md`). - -- **Município definition:** 435 seeded rows — one per Bahia municipality (416), except Salvador (19 zone municipalities, ZE 1–19); Camaçari is a single whole municipality (ZE 170/171 aggregated). Canonical catalog: `src/lib/municipalityCatalog.ts` (`tests/fixtures/municipality-catalog.snapshot.json`). Seeded by migration `20260723_200000_remodel_municipalities` (+ reconcile `20260723_202000_reconcile_municipality_remodel`). Geography is admin-only; staff edit strategy fields and the coordinator assigns `advisors`. -- **Collections (admin group `Campanha`):** `municipality`, `leadership`, `votePledge`, `organization`, `stateDeputy` (dobradinhas), `campaignDemand`, `allocationDecision`, `municipalityUpdate`, `campaignInvite`, `campaignWebAuthnCredential` (biometric login — see "Campaign auth"), `supporter`, `activity`. **Global** (same admin group): `campaignGoals` (E8 "conta da cadeira" — `stateGoal` sets the optimistic suggested-goal scenario, `margin` the pessimistic haircut; `read` = admin/staff, `update` = admin/`isCampaignUnrestricted`; no `afterChange` hook — nothing caches it). -- **Engagement level (E14):** `municipality.engagementLevel` (`n0…n4`, staff-only, no default) is the campaign's declared investment in the município — N0 monitorar … N4 investimento pleno. Only `isCampaignUnrestricted` actors move it, every move needs a rationale plus the signals that would reverse it, and the move writes an `allocationDecision` (`outcome: 'movimento'`) in the same transaction under an advisory lock. Hysteresis rules are pure (`src/lib/engagementLevel.ts`) and shared by client and server; the override is recorded with the rules it contradicted. Null means "Sem nível" — the triage queue, not a missing value to backfill. -- **Roles:** `coordinator` ("Coordenador Geral") and `candidate` ("Candidato", unrestricted visibility via `isCampaignUnrestricted`) see/manage everything staff sees; `advisor` ("Assessor") is scoped to `municipality.advisors`; `leader` ("Liderança") is **lockdown** — home is the supporter contact tool only (`LeaderContactsPanel`, `source: lideranca`), reads only supporters they created (`createdBy`), no municipalities/leaderships/pledges/demands/plans/election data. -- **Vote pledge asymmetry:** staff declare `declaredVotes` and record `estimatedVotes` (pessimistic/central/optimistic); leaders never see estimates. Aggregates use `estimated[S] ?? declared`, default `central` (`src/utilities/votePledgeData.ts`). -- **Demandas:** staff-only create/read (`canCreateCampaignDemand`); optional `leadership` provenance selected by staff. Escalated decisions: coordinator **or** candidate. -- **Dobradinhas:** `stateDeputy` entity + `municipality.stateDeputies` / `leadership.stateDeputies` hasMany; UI at `/campanha/dobradinhas`. -- **Map:** staff dashboard (`/campanha`) loads `MunicipalityMapPanel`; `/campanha/municipios` is list/overview only. **Keyed by "map key", not `ibgeCode`** (B8 F2, 2026-07-26): `mapKeyForMunicipality` returns the `municipalitySlug` for `kind === 'zona'` and the `ibgeCode` otherwise, so each of Salvador's 19 ZE is painted, hovered and opened on its own from `bahia-municipality-zones.topo.json`. Every bundle field follows that key (`municipalitiesByMapKey`, `territorialClassByMapKey`, `projectedValidVotesByMapKey`, `valuesByYear`, …) and each key maps to exactly one catalog entry, so rollups assign instead of accumulating. Salvador's **municipal** polygon is still drawn, underneath, as a non-interactive base with no data (`baseKeys` in `BahiaMap`) — two independently simplified meshes do not close on the same coastline, and deleting it opened a gap in the state outline; being out of the key index, it cannot double-count or steal a hover. Feature→key resolution is `featureMapKey` (`municipalitySlug ?? codarea ?? code`) — the three are **mutually exclusive** on the committed meshes, so it is a lookup over distinct names and not a precedence rule; the zone mesh also carries the city's `ibgeCode`, which is deliberately **not** a key property because all 19 zones share it. Since B8+ that contract is exercised on **real features of all three meshes** in `tests/int/bahiaGeometries.int.spec.ts` — over the full 417 / 27 / 19, not on hand-written literals and not on one city feature repeated per zone — and a failure of the zone chunk **degrades instead of killing the map**: `loadLayerFeatures` catches it and paints the state without the ZE (Salvador falls back to its non-interactive base polygon, not to an aggregated one — the bundle is keyed by slug), while `status === 'error'` stays reserved for the municipal mesh. **`competitiveRank` is still per city:** the TSE artifact only carries `federalRankByIbgeCode`, so all 19 zones share the city's placement — which is what the legend already claims, and an int test pins it. Scales (B13): **quantis** (default), **padrão próprio (LQ)**, **posição no município**, **% dos válidos** (B11) and **Total (votos)**. The three relative ones are **discrete classes, never a continuous ramp** — the pure math lives in `src/lib/mapScaleClasses.ts` (quantiles degrade to 3 classes below 10 municípios and the legend says so; LQ is cut on the E10 anchors in `src/lib/territorialClassAnchors.ts`). Diverging red×blue stays exclusive to the compare mode, where it means "Solla × adversário" — do not reuse it for LQ. Quantiles are computed over the **user's access scope**, so an advisor sees his portfolio classed against itself. Rank is unavailable in 2026 (TSE data) and LQ in 2026 reuses the 2022 statewide standard, the same precedent `percentValid` set. An optional proportional-symbol layer sizes bubbles by projected valid votes (area ∝ value) and colours them by the E10 class. A class label never renders alone: the readout always spells out the reason. -- **URLs:** `/campanha/municipios[/slug]`, `/campanha/dobradinhas`, `/campanha/liderancas[/id]`, `/campanha/organizacoes[/slug]`, `/campanha/demandas[/slug]`, `/campanha/atividades[/slug]`, `/campanha/atividades/giros` (compositor de giro, staff), `/campanha/apoiadores`, `/campanha/assessores` (coordinator/candidate), `/campanha/conceitos` (staff glossary), `/campanha/perfil`. - -## Campaign supporters (C2) - -Nominal supporter registry backing the campaign's base of declared supporters (roadmap item C2; engineering ready and merged to `main` on 2026-07-18, production-blocked on the legal batch). One collection in admin group `Campanha`: - -- **`supporter`** (`src/collections/Supporter.ts`) — join `Contact`↔campaign with **optional `municipality`**. Fields include `source` (`import_csv | manual | convite | evento | lideranca` for leader-created rows). -- **Consent by stable key.** `campaignConsent.ts` was generalized to `getConsentByKey` / `requireConsentByKey` (fail-closed). The two keys are `apoiador-cadastro` (declared support) and `apoiador-intencao-voto` (vote intention — highlighted, separate consent). The app fails closed if either key is missing — same pattern as `lideranca-autopreenchimento`. -- **Access.** `coordinator`/`candidate` see/manage all; `advisor` sees supporters of administered municipalities; `leader` may create supporters in linked municipalities and read only rows they created (`createdBy`); supporters without a municipality remain `coordinator`-only. Delete is admin-only. -- **Server actions** (`src/app/(campaign)/campanha/actions/supporter.ts`): `createSupporter`, `setSupporterVoteIntention`, `previewSupporterImport` / `confirmSupporterImport` (CSV, `coordinator`-only, transactional with `req: { transactionID }`, dedup by phone via `contactPhoneInvariant`), and `removeSupporterData` (deletes the `supporter`; anonymizes/clears `Contact` PII only if no other join — `leadership`/`signature`/`subscription`/other `supporter` — references it). -- **UI** `/campanha/apoiadores` — list with KPIs (total / "Certo + Tende" / "Indecisos"), filters (vote intention, territory), detail with LGPD consent block + vote-intention segmented control (disabled until consent) + minimal share kit (`wa.me` + copy text), and a 3-step CSV import wizard (Upload → Preview → Confirm). Phone is required in v1. -- **C6 scale layer (merged to `main` 2026-07-19).** CSV import up to 5000 rows now completes in one transaction: `confirmSupporterImportRecord` acquires all phone advisory locks, then `bulkInsertSupporterImport` (`src/utilities/supporterImportBulk.ts`) inserts contacts + supporters via `payload.db.drizzle` on the Payload transaction session (`getPostgresTransactionDatabase`) in 500-row chunks with `ON CONFLICT DO NOTHING` on `(contact_id, municipality_id)`. `Contact.enforceUniqueContactPhone` honors `context.skipContactPhoneInvariant` **fail-closed** (only inside an active `req.transactionID`), so the bulk path skips the per-row re-check while the single-create path is unchanged. Preview no longer round-trips the full `ok` set: `previewSupporterImportText` stages it in `supporterImportBatch` (`src/collections/SupporterImportBatch.ts`, admin-hidden, `coordinator`/admin only, migration `20260719_011015_add_supporter_import_batch`) and returns an HMAC-SHA256 single-use `importToken` (10-min TTL, actor-bound, `src/utilities/supporterImportToken.ts`); `confirmSupporterImportRecord` verifies the token and consumes the batch (delete after commit). The list KPI is a single `COUNT(*) FILTER` aggregate (`src/utilities/supporterListOverviewAggregate.ts`) mirroring `buildSupporterListWhere` + the access constraint, replacing 3× `payload.count`. Shared shells — `campaignListUrl.ts`, `CampaignListPagination`, `campaignFormFields.ts`, `mapCampaignFormActionError.ts` — replace the three per-list pagination components and the duplicated form-error ladders. Scale/DRY follow-ups from the `/simplify` pass are registered as **C8** (`docs/plans/escala-dry-pos-c6.md`). -- **Mandatory production blocker:** do not import real supporter data or capture vote intention until electoral counsel documents the LGPD art. 11 basis (vote intention is sensitive data), approves the versioned consent texts, and an admin creates `Consent.key = 'apoiador-cadastro'` and `Consent.key = 'apoiador-intencao-voto'`. The app intentionally fails closed when these keys are absent. - -## Campaign activities (C3, renamed by C13) - -Mobilization events / agenda backing the campaign's field operations (roadmap item C3; implemented and merged to `main` on 2026-07-18). **Renamed "Plano de Ação" → "Atividade" on 2026-07-25 (C13)**: the collection slug is `activity`, the route is `/campanha/atividades`, and the vocabulary guard in `tests/unit/codebaseConventions.unit.spec.ts` now fails the build on `actionPlan` / `plano de ação` / `/campanha/planos` anywhere in `src`, `tests` or `scripts` (migrations excluded — frozen history). One collection in admin group `Campanha`: - -- **`activity`** (`src/collections/Activity.ts`) — a calendarizable action/event (caminhada, comício, etc.) anchored on ONE `municipality`, with task checklist, update feed and result record. Fields: `title`, canonical immutable `slug`, `kind` / `status` enums in pt-BR, `startAt` (required beyond `rascunho`), `municipality` (required) + free-text `locality`, `organizations` (hasMany — supporting orgs), `advisors` (staff responsible; ex-`coordinators`), `deputyPresent` (checkbox "Deputado presente"), `responsible` → `Contact`, `leadership` optional, `tasks`/`updates` arrays (derived fields server-side), and the action result: `resultSummary` + `resultMedia` (upload → `media`) + derived `resultRecordedBy/At` — queryable history for future activities in the same município. No `Consent` (internal staff data). -- **Access.** `coordinator` everything; `advisor` where listed in `advisors` OR the activity's `municipality` is administered (may create, auto-included); `leader` has no access (lockdown). -- **UI** `/campanha/atividades` — list with tabs Próximos (default) / Todos / Realizados / Rascunhos, filters (kind, municipality), cards with kind/status badge + date/time + município + "Resp:" + task progress + "Deputado presente"; detail with tabs Visão geral / Tarefas / Atualizações (`/campanha/atividades/[slug]`, create at `/campanha/atividades/nova`); result form appears for staff when the activity is `realizado`. - -## Campaign map geometries (B2) - -Static Bahia map foundation for future Leaflet surfaces (roadmap B2; UI is B3). No migration, collection, Consent, or server action — same static-data pattern as `bahiaTerritories` / `bahiaTseZones`. - -- **Artifacts (committed):** `src/lib/geometries/bahia-municipalities.topo.json` (~132 KB; Topology object `municipalities`, 417 features, `properties: { codarea, name }`), `src/lib/geometries/bahia-identity-territories.topo.json` (~15 KB; object `territories`, 27 features, `properties: { code, name }`) and — since B8 F2 (2026-07-26) — `src/lib/geometries/bahia-municipality-zones.topo.json` (**~7.7 KB** since B8+ recalibrated it; object `municipalityZones`, **19** features, `properties: { municipalitySlug, name, ibgeCode }`), the Salvador ZE mesh. -- **Ground-scale policy (B8+, 2026-07-27):** how much detail a committed mesh keeps is declared **in ground units** in `scripts/lib/topology.mjs` (the first module in `scripts/lib/` — **B5 F2** lands there rather than opening a second one), and both build scripts consume it. Two knobs, both meaningless as raw numbers: `topojson-simplify` can pick its Visvalingam threshold as a **quantile of the mesh's own triangles**, and `quantize(topo, n)` lays an `n`-step grid across **the topology's own bbox** — so the `0.35` and `1e4` copied verbatim between the two scripts cut Salvador at ~0.6 m² and ~3.9 m while cutting Bahia at ~1.78 km² and ~103 m. The zone mesh shipped at **480 points/feature against the state mesh's 21.9** because of it. Now `SIMPLIFY_TOLERANCE_M2` states a tolerance per mesh in **square metres of ground** (with the density it buys measured in the comment) and quantization digits are derived per topology from `GROUND_GRID_METRES`. Two things not to re-derive: quantization alone barely helps (even on the state grid the zones stayed at 203 points/feature — the absolute weight is the lever), and **simplify before quantize**, because quantizing a dense mesh to a ~100 m grid collapses vertices into duplicates and a later `merge` produces broken rings (measured: Salvador dissolving to 24 km² instead of 307). Tolerances differ per mesh on purpose: the municipal tolerance reaches 17.9 points/feature on the zones but sheds 5% of Salvador's land area (306 → 291 km²), which is the quantity the int spec uses to prove no neighbourhood was dropped or double-counted. Guard: `MAX_POINTS_PER_FEATURE = 60` in `tests/int/bahiaGeometries.int.spec.ts`, next to the byte budget (soft, ≤ ~600 KB each) — bytes only catch a mesh nobody simplified at all. -- **Code table:** `src/lib/bahiaMunicipalityCodes.ts` — canonical municipality name → IBGE 7-digit `codarea`, plus `codeForMunicipality` / `municipalityForCode`. Fixture `tests/fixtures/bahia-municipality-codes.official.json` + int tests for bijection/coverage. -- **Runtime helpers:** `src/lib/bahiaGeometries.ts` — typed topologies, feature arrays and `getMunicipalityFeature` (the territory and zone accessors were deleted by B8+: only the int specs used them, and a `Map` built in one line is what a spec wants). TopoJSON→GeoJSON decode is LAZY (dynamic import via `loadMunicipalityGeometryModule` / `loadMunicipalityZoneGeometryModule`; B5 F1 done) — the default `/campanha` server graph never pays it. Shared feature types live in `bahiaGeometriesTypes.ts`: `BahiaFeature

` is the one spelling of `Feature`, `BahiaMeshFeature` is what the map layer receives from any of the three meshes, and geometry math (point-in-polygon, centroid, area, bounds — all built on the exported `polygonRingsOf`) takes **`PolygonalFeature`**, which declares the actual requirement instead of dragging `GeoJsonProperties` (i.e. `any`) through the signature. -- **Territory polygons:** dissolved from IBGE municipality meshes via `bahiaIdentityTerritoryRecords` (`topojson` `merge`), not the IDE Bahia shapefile (IDE remains provenance/validation reference only). -- **Rebuild (Salvador zones):** `pnpm build:municipality-zone-geometries` (`scripts/build-municipality-zone-geometries.mjs`; `--report` reconciles without writing) downloads IBGE `BA_bairros_CD2022.zip` from geoftp, parses the shapefile with **`shpjs`** (devDependency — that cut is SHP-only, SIRGAS 2000), keeps `CD_MUN === '2927408'` (170 polygons) and dissolves neighbourhood→zone against **TRE-BA RA 02/2017** (`municipalityZoneNeighborhoods.ts`). Reconciliation is **curated data in the script header**, not cleverer matching: an alias table, a table for TRE neighbourhoods with no polygon of their own (the build refuses a merge that would cross zones), and a table for the one neighbourhood the resolution splits mid-street (it goes whole to one ZE — the neighbourhood is the atom). The 5 polygons the resolution never names are assigned by **longest shared boundary**, a rule validated against the 4 it names under another label. The build fails on an orphan polygon or a TRE neighbourhood with no polygon, so 170/170 → 19/19 is an invariant, not a hope. Same cache dir and the same "**does not touch the database**" guarantee as the sibling below. -- **Rebuild:** `pnpm build:geometries` (`scripts/build-bahia-geometries.mjs`) downloads IBGE Malhas (qualidade intermediaria) + Localidades, reconciles names with `canonicalizeMunicipalityName`, simplifies/quantizes, emits the artifacts above. Cache under `data/geometries/` (gitignored; override with `GEOMETRIES_CACHE_DIR`). **Does not touch the database** — no `assertLocalDatabase` / no prod-DB risk. Not part of `pnpm build` or `pnpm dev`. Details: `docs/plans/mapa-bahia-geometrias.md`. Scale/DRY follow-ups from `/simplify`: `docs/plans/escala-dry-pos-b2.md` (B5). - -## Election baseline data (TSE 2022) - -Public TSE 2022 results back the electoral baseline (roadmap items A3 + A4). Three collections in admin group `Dados Eleitorais`: `electionTally` (per city×zone totals: eligible voters, turnout, valid/blank/null votes), `electionCandidateVote` (nominal votes per candidate×city×zone), and `electionCandidate` (candidate registry with a cross-year `identityKey` hash — no CPF or voter ID is ever persisted). Read access requires an authenticated `campaignUser` or `users` account (`canReadElectionData`); writes are Payload-admin-only, and the import runs via CLI with `overrideAccess: true`. Since the Município remodel, the consumers are `municipalityElectoralBaseline.ts` (per-municipality series/turnout), `municipalityCandidateComparison.ts` (multi-candidate table) and `municipalityMapData.ts` (map, incl. the diverging compare mode); ticket roles live in `BASELINE_TICKET_2022`. Seeds cover 2014/2018/2022 (E2 extended the original 2022-only A3 scope). Two caching layers sit on top (2026-07-23 hardening): the immutable Solla/valid-votes series per municipality ships as a committed artifact — `pnpm build:election-aggregates` → `src/lib/electionAggregates/bahia-federal-baseline.json`, loader `src/lib/bahiaElectionAggregates.ts`, snapshot-tested against `municipalityCatalog` — so the map/dashboard never query these collections for historical years; and the elections-tab loaders (`municipalityElectoralBaseline`, `municipalityCandidateComparison`, `electionCandidateOptions`) are wrapped in `unstable_cache` under the `election-tse` tag (bust via `POST /api/revalidate?tag=election-tse` after re-seeding). - -The artifact is at **v3**: v2 added E8's `campoFederalVotesByYear` / `federalTallyByYear` / `majoritarian2022`, and B13 (2026-07-26) added `federalRankByIbgeCode` — the candidate's placement among **every** federal-deputy candidate with votes > 0 in that geography, per year, keyed by IBGE code (417 codes; Salvador's 19 zone slugs sum to the whole city, which is what the map draws) and read through `getFederalCompetitiveRank`. A geography where he had no votes gets no entry, never `rank: 0`. Its input is `loadFederalVotesByCityZoneAndCandidate` in `municipalityElectoralBaseline.ts` — the sibling of `loadCampoFederalVotesByCityZone`, same statewide scan, **CLI/build-time only**. The file is 623 KB against the 700 KB budget asserted in `tests/unit/bahiaElectionAggregates.unit.spec.ts`; anything new that would blow it needs a real measurement, not a bumped constant. Rank exists only by IBGE code — add a per-slug variant when the dossier or E11 actually needs one. - -`pnpm db:seed:tse` (`scripts/seed-tse-results.mjs`) downloads the TSE open-data zips (provenance URLs + SHA-256 in the script header), parses the Bahia scope, and imports via `payload.db.drizzle` in a transaction — idempotent by replace-per-scope `(year, office, turn)`, only `voteType: 'nominal'` rows in v1. It refuses a non-local `DATABASE_URL` (same guard family as the other seeds; override with `ALLOW_REMOTE_DB=true`) and caches downloads under `data/tse/` (gitignored). No revalidate step is needed: campaign pages are dynamic with auth, not ISR-cached. - -### Local verification and deploy checklist - -1. Confirm `DATABASE_URL` is `postgresql://teqo:teqo@localhost:5432/teqo` and `.env.test` points to `teqo_test`; never use the homeserver prod DB for development, tests, E2E, or local builds. In a provisioned worktree (`pnpm worktree next`) the values come from its `.env.local` / `.env.test.local` (`teqo_wt` / `teqo_wt_test`, dev port `3100+slot`) — read them there instead of assuming the main-repo names. -2. Run `pnpm db:start`, `pnpm migrate:status`, and `DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm migrate:status`; every migration must show `Ran: Yes`. -3. Run `pnpm generate:types`, `pnpm generate:importmap` when components changed — **com as envs `S3_*` setadas (valores dummy ok) enquanto o plugin `s3Storage` for condicional: sem elas o importMap fica órfão do `S3ClientUploadHandler` e o admin abre em branco em produção (OPS69, P0 em 2026-08-19)** —, `pnpm exec tsc --noEmit`, `pnpm lint` (zero warnings — the script enforces `--max-warnings=0`), `pnpm format:check` (Prettier is the formatting authority; `pnpm format` fixes), `pnpm exec knip` (dead files/dependencies are CI-blocking; delete what your change orphaned), `pnpm check:cycles` (madge — zero circular imports), `pnpm test` (unit + int), and `pnpm build` against the local database. Payload CLI scripts (`migrate`, `generate:*`, `payload`) and the build migrate step use `--conditions=react-server` so `server-only` modules load correctly outside Next.js. **Política de e2e (OPS72):** o e2e **não roda no gate local** (`gate:push`) — é passo **explícito da skill** (`work-issue`/`agent-work-issue`): antes do push o agente roda localmente os e2e que **criou** + os da **mesma superfície afetada** — **discricionário** (o agente decide quais; ferramenta: `pnpm test:e2e:affected`, espelho local do classifier — gera `--no-deps` para runs filtrados, S6-FOLLOWUP: no dev mode a cadeia de dependencies dos projects arrasta os arquivos das dependências via closure; filtros manuais locais: `pnpm test:e2e --no-deps -- ` ou `--no-deps --project=`; limitação #72: `--no-deps` + projetos paralelos colide no `seedTestUser` → `--workers=1` ou a cadeia padrão de projetos). O **CI de PR roda apenas o blast radius** (modo `selected` via `ci-scope.mjs` — **nunca `full`**; diff high-risk classifica `full` e o PR simplesmente não roda e2e). O e2e **full** roda no `verify` do deploy manual (gateia merge e deploy — rede de segurança final antes de publicar). - - Never run `knip --fix` blind: when knip's module graph is incomplete (it still cannot load `payload.config.ts` — ledgered as P3), `--fix` deletes exports that migrations/tests still reference. Verify each removal (e.g. `git grep -w `) before deleting. - - Run gate commands bare — never piped (`pnpm test | tail` swallows the exit code, and a real failure was masked exactly this way during Pass 2). Large outputs are captured by the terminal; read them from there. -4. Scan every edited runtime source file with Aikido and resolve new findings before handoff. Do not expand hardening work into unrelated pre-existing findings without an explicit scope change. -5. Review production environment variables and migration SQL before deploy; `pnpm build` applies pending migrations to the deployed database automatically. **`NEXT_PUBLIC_SITE_URL` (ex.: `https://jorgesolla1313.com.br`) é obrigatória em Production** — sem ela, `getCampaignInviteBaseURL()` lança em runtime e o fluxo de convites/webauthn/link de import da agenda falha com mensagem genérica (C98, 2026-08-09: produção ficou sem a env e "gerar link" do feed quebrava; o preview tinha a de stage). -6. **Mandatory production blocker:** do not insert real leadership/support data or enable invites until electoral counsel documents the LGPD art. 11 basis, approves the specific versioned consent text, and an admin creates it with exactly `Consent.key = 'lideranca-autopreenchimento'`. The app intentionally fails closed when this key is absent. -7. **Remodel deploy (historical — applied to production 2026-07-23):** the destructive remodel chain (`20260721_020109_remodel_municipalities` → `20260723_200000_remodel_municipalities` + `20260723_202000_reconcile_municipality_remodel`) already ran in production via the Vercel build: campaign vertical reset, 435 municípios seeded, public-site data untouched. Treat any future destructive migration the same way — review its SQL before the first production build that includes it. - ## Core Principles 1. **TypeScript-First**: Always use TypeScript with proper types from Payload @@ -199,3 +69,7 @@ src/ ├── utilities/ # campaign*, access/* (per-domain RBAC; campaignAccess.ts re-exports), municipality*, posts, documents, globals, locks, etc. └── payload.config.ts # Main config ``` + +## Per-worktree environments + +`pnpm worktree next` provisions isolated envs per worktree: dev port `3100+slot`, databases `teqo_wt` / `teqo_wt_test` on the shared container with full migration chain + minimal seed, `.env.local` + `.env.test.local` (gitignored), copies of `PAYLOAD_SECRET`/`S3_*`/VAPID from main repo. The skill `local-database` covers the full workflow. diff --git a/package.json b/package.json index 6bd679b9..e0401485 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "test:e2e:affected": "node scripts/run-e2e-affected.mjs", "test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts", "test:unit": "cross-env NODE_OPTIONS=--no-deprecation DATABASE_URL=postgresql://invalid:invalid@127.0.0.1:1/unit_tests_must_not_connect vitest run --config ./vitest.unit.config.mts", - "ui-draft:render": "node scripts/render-ui-draft.mjs", "images:resize": "node scripts/resize-images.mjs", "images:fill": "node scripts/fill-image.mjs", "typecheck": "tsc --noEmit", diff --git a/scripts/lib/agent-forgejo.mjs b/scripts/lib/agent-forgejo.mjs index db6495e1..b9a2e340 100644 --- a/scripts/lib/agent-forgejo.mjs +++ b/scripts/lib/agent-forgejo.mjs @@ -204,8 +204,8 @@ export const claimBriefLines = (entry) => { ` id: ${issueId ?? '(none)'} priority: ${entry.priority}`, ` rename_chat: ${sessionTitle.slice(0, 200)}`, entry.meta.model - ? ` model: ${entry.meta.model} (metadata consultiva — o work-issue não verifica modelo; o pool spawna nele; ver skill model-selection)` - : ' model: ausente — registrar slug único na Issue (ver skill model-selection)', + ? ` model: ${entry.meta.model} (metadata consultiva — o work-issue não verifica modelo)` + : ' model: ausente — registrar slug único na Issue', ...(entry.satisfiedWithoutIssue.length > 0 ? [ ` deps sem issue (roadmap entregue, satisfeitas): ${entry.satisfiedWithoutIssue.join(', ')}`, diff --git a/scripts/render-ui-draft.mjs b/scripts/render-ui-draft.mjs deleted file mode 100644 index 39e5f502..00000000 --- a/scripts/render-ui-draft.mjs +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Renders a plan-issue UI draft (HTML + Tailwind) to PNG(s) for the gate. - * - * Usage: pnpm ui-draft:render -ui-draft.html> - * - * - Screenshots each `[data-shot]` scene as `-ui-draft-