From 45dbbfaf6dc76bdb7190d97662c6352a9092c3e7 Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Tue, 15 Sep 2026 23:09:17 -0300 Subject: [PATCH] =?UTF-8?q?docs(plans):=20OPS113=E2=80=93OPS116=20?= =?UTF-8?q?=E2=80=94=20designer=20agent=20+=20design=20hi-fi=20no=20gate?= =?UTF-8?q?=20(Related=20#1056,=20Related=20#1057,=20Related=20#1058,=20Re?= =?UTF-8?q?lated=20#1059)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...13-agentes-designer-e-designer-degraded.md | 120 ++++++++++++++++++ .../ops114-plan-issue-design-hifi-no-gate.md | 106 ++++++++++++++++ ...5-work-issue-designer-em-qualquer-toque.md | 113 +++++++++++++++++ .../ops116-painel-ui-design-retrocompat.md | 111 ++++++++++++++++ 4 files changed, 450 insertions(+) create mode 100644 docs/plans/ops113-agentes-designer-e-designer-degraded.md create mode 100644 docs/plans/ops114-plan-issue-design-hifi-no-gate.md create mode 100644 docs/plans/ops115-work-issue-designer-em-qualquer-toque.md create mode 100644 docs/plans/ops116-painel-ui-design-retrocompat.md diff --git a/docs/plans/ops113-agentes-designer-e-designer-degraded.md b/docs/plans/ops113-agentes-designer-e-designer-degraded.md new file mode 100644 index 00000000..1bd31f3f --- /dev/null +++ b/docs/plans/ops113-agentes-designer-e-designer-degraded.md @@ -0,0 +1,120 @@ +# OPS113 — Agentes `designer` e `designer-degraded`: design hi-fi como fonte de verdade + +Status: rascunho +Atualizado em: 2026-09-15 +Issue: #1056 +Priority: P2 +Impeccable: A — N/A sem UI de produto +Rascunho UI: N/A — sem UI +Appetite: ~0,5–1 dia eng; um outcome verificável +Responsável: — + +## Intenção + +O gate do plan-issue produz hoje um _rascunho_ visual que, por doutrina, é proibido de ter brand, tokens e polish — e é descartável. A decisão visual em alta fidelidade não existe em lugar nenhum: ela é reinventada na implementação, sem referência para o humano aprovar antes e sem alvo estável para portar e criticar depois. O fim é previsível: a tela construída diverge do que foi aprovado e a crítica vira opinião. + +Este item cria o papel de **designer** — especialista de julgamento visual que **cria** o design hi-fi de referência e **critica** a implementação contra o design aprovado — e eleva o artefato `docs/plans/-ui-design.html` a **fonte de verdade do port**: o implementador porta classe-a-classe para React/Next. Em paralelo, um **designer degradado** cobre quota/indisponibilidade do modelo frontier sem pular design em silêncio — mas **nunca certifica**. + +Não é o retorno do `design-vision` (removido na OPS105): não é um describer de imagem, é design de criação/crítica com visão nativa. E não é entrega de UI de produto: nenhuma tela muda aqui. + +## Persona e fluxo + +- **Persona / contexto:** fsolla no gate, abrindo o `.html` no browser para aprovar o design antes de qualquer código; agente implementador (`work-issue`/`agent-work-issue`) portando para React/Next. +- **Job principal:** ver e aprovar o design final hi-fi antes da implementação e, depois, portar e verificar paridade sem perder fidelidade. +- **Fluxo desejado:** + 1. Item com UI entra no plan-issue; o designer cria o artefato hi-fi (tokens reais, brand, copy pt-BR real). + 2. Humano abre o `.html`, itera com o designer e aprova; o artefato entra no PR do plano. + 3. Na implementação, o executor porta classe-a-classe do artefato. + 4. O designer critica a implementação contra o design aprovado; mudança material volta ao humano no PR. + 5. Se o frontier falhar, o ladder desce explicitamente e registra o tier; tier degradado marca `DEGRADED` e não certifica. +- **Anti-goals de produto:** não muda UI de produto; não é implementação disfarçada; não é um segundo Figma/Penpot nem substitui o MCP `penpot`; não ressuscita o describer de imagem da OPS105; o designer nunca escreve em `src/`; tier degradado nunca certifica; sem OpenRouter/Grok/Qwen no caminho de design. + +## Objetivo e aceite + +- `designer` existe e é invocável (`mode: all`, `temperature: 0.7`, `model: openai/gpt-5.6-sol`) com os dois modos de tarefa — **Criar** hi-fi e **Criticar** implementação — e sem permissão de escrita em `src/`. +- `designer-degraded` existe e é invocável (`mode: subagent`, `model: opencode-go/deepseek-v4.1-flash`): cria/estende/critica, marca todo output `DEGRADED` e exige sign-off humano. +- A doutrina viva é `ui-design-html.md` (renomeada de `ui-draft-html.md`) e trata o artefato como fonte de verdade do port; tokens/brand/shadcn passam a ser esperados; o teto protetivo permanece. +- O ladder `gpt-5.6-sol → gpt-6-astra → deepseek-v4.1-flash (DEGRADED) → deepseek-flash (DEGRADED, inline)` está documentado e auditável: quota/indisponível desce explicitamente e registra o tier no PR — nunca pula design em silêncio. +- Pré-requisito operacional verificado **antes** de pinar: provider `openai` religado, auth feito, ids confirmados em `opencode models | grep '^openai/'` e visão funcionando no caminho OAuth. +- Artefato imutável como registro histórico no git; mutável durante o work-issue pelo designer, com mudança material voltando ao humano no PR. + +## Dados (intenção) + +- **Vou apresentar dados?** Não — autoria de agente e doutrina de design; sem métrica ou superfície de dados. +- **Decisões desbloqueadas:** N/A. +- **Forma:** N/A. + +## Dados da decisão (literais) + +- **N/A — sem dados de produto.** Os literais fixados nesta entrega são de configuração de agente/doutrina e estão verbatim em "Escopo e entregáveis" (modelos, modos, temperatura, caminhos e nomes) — não são decisão de dados. + +## Escopo e entregáveis (literais) + +- **Doutrina — rename + reescrita:** `.agents/skills/plan-issue/ui-draft-html.md` → `.agents/skills/plan-issue/ui-design-html.md`. Eleva: tokens reais/brand/shadcn OK e esperados; o HTML é fonte de verdade do port (não mais descartável). Mantém: zero JS de comportamento; estados como cenas estáticas; 390/1280; copy pt-BR real; sem imports de `src/`; sem decisão de engenharia; claims só os aprovados no plano; `NEEDS ASSET`; LGPD/TSE; um CTA primário. +- **Artefato:** `docs/plans/-ui-design.html` (autossuficiente, Tailwind v4 browser CDN) + `docs/plans/-ui-design-assets/*.svg` quando ícones/ilustrações próprios forem necessários. +- **SVG:** lucide/shadcn primeiro; custom só quando não houver equivalente; grid 24px, `currentColor`, stroke no padrão lucide; salvar em `-ui-design-assets/`. +- **`designer`:** `.opencode/agent/designer.md` — `mode: all`, `temperature: 0.7`, `model: openai/gpt-5.6-sol`; visão nativa, com parada fail-closed se o modelo não enxergar (nunca descrever o que não viu). +- **`designer-degraded`:** `.opencode/agent/designer-degraded.md` — `mode: subagent`, `model: opencode-go/deepseek-v4.1-flash`; nunca certifica. +- **Ladder:** `openai/gpt-5.6-sol` → `openai/gpt-6-astra` (mesmo pool Plus; crítica contestada/pixel-critical) → `opencode-go/deepseek-v4.1-flash` (flat; `DEGRADED`) → `deepseek/deepseek-flash` (direto; `DEGRADED`; o orquestrador faz inline). +- **Pré-requisito operacional (fora do repo):** remover `openai` de `disabled_providers` no config global, `opencode auth login openai`, confirmar os ids expostos **antes** de pinar e confirmar imagem/visão no caminho OAuth. **Verificado em 2026-09-15:** provider religado + OAuth conectado; `openai/gpt-5.6-sol` e `openai/gpt-6-astra` expostos (15 ids no total); smoke de visão OK (PNG sólido lido corretamente pelo Sol). +- **Doc operacional (opcional, 1 parágrafo):** `docs/AGENT-OPS.md` — autoria/pin/fallback de agente, apontando para a doutrina. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `.agents/skills/plan-issue/` (doutrina), `.opencode/agent/` (novos agentes), `docs/plans/` (artefatos), `docs/AGENT-OPS.md` (opcional). +- **Precedente a olhar:** `.opencode/agent/designer-campanha-solla.md` (frontmatter `mode`/`temperature` e bloco de visão nativa/fail-closed, L63–65); OPS105 (o que não ressuscitar); OPS101 (proibição de `model:` vale para `.opencode/commands/`, não para agentes). +- **Risco de acoplamento:** OPS114 consome o nome novo da doutrina e OPS115 os triggers no work-issue; nenhum teste/guard lê `.opencode/agent/*.md` hoje — o pin é contrato de prompt, não de teste. + +## Dependências + +- Nenhuma dura. **OPS114** (atualiza consumidores do nome antigo) vem depois deste rename; **OPS115** (triggers no work-issue) consome o contrato daqui — ambos fora de escopo. + +## Fora de escopo + +- Atualizar consumidores de `ui-draft-html.md` (template, `SKILL.md`, outras skills) → OPS114. +- Triggers/não-triggers de quando o designer entra no work-issue → OPS115. +- Arquivo de escalada `designer-astra` → pergunta aberta. +- Qualquer mudança em UI de produto ou `src/`, mudança no MCP `penpot`, e guard/teste novo lendo `.opencode/agent/*.md`. + +## Rabbit holes de produto + +- **"Já que existe designer, redesenha o produto inteiro."** Se alguém "só completar": novo shell, paleta global, telas fora do item. **Corte neste item:** um artefato por item de UI, do escopo do item. +- **"Deixa o designer editar `src/` e já entregar a tela."** Se alguém "só completar": o artefato vira implementação e o gate perde a função. **Corte neste item:** output só em `docs/plans/-ui-design.*`. +- **"Cria `designer-astra.md` por simetria."** Se alguém "só completar": prompt gêmeo, drift garantido. **Corte neste item:** pergunta aberta abaixo, com recomendação de não criar arquivo extra. + +## Questões em aberto (produto) + +- **`designer-astra` (`openai/gpt-6-astra`): arquivo extra ou só troca via `/models`?** **Opções:** A) arquivo `.opencode/agent/designer-astra.md` gêmeo | B) um só `designer.md`, com troca de modelo via `/models` quando a crítica for contestada/pixel-critical | C) partial compartilhado + dois arquivos. **Recomendação:** B — evita twin/drift (`AGENTS.md`: "Edit the owner, don't twin") e o tier fica registrado no PR; reavaliar com evidência só se precisar de frontmatter distinto. _(assumido — validar no gate)_ +- **Documentar autoria/pin/fallback de agente em `docs/AGENT-OPS.md`?** **Opções:** A) sim, 1 parágrafo curto linkando a doutrina | B) deixar só na doutrina | C) item futuro. **Recomendação:** A — o doc é o ponto de entrada da operação de agentes; sem isso o ladder fica enterrado na skill. _(assumido)_ + +## Fases (ordem de entrega) + +1. **F1 — Doutrina:** rename + reescrita de `ui-design-html.md` (contrato elevado, teto mantido, regras de SVG e o ladder). Consumidores do nome antigo ficam para OPS114. +2. **F2 — Agentes:** criar `designer` e `designer-degraded` com frontmatter pinado, modos Criar/Criticar, proibição de escrita em `src/`, rótulo `DEGRADED` e sign-off humano. +3. **F3 — Operacional e verificação:** pré-requisito (provider/auth/ids/visão), smoke dos dois agentes, formatação e o parágrafo opcional em `docs/AGENT-OPS.md`. + +## Verificação + +- `opencode models | grep '^openai/'` lista `openai/gpt-5.6-sol` (e o id de escalada, se exposto) antes do pin; `opencode-go/deepseek-v4.1-flash` já é o modelo em uso. Se o id fixado não existir: **parar e escalar o humano** — não pinar adivinhação nem trocar de modelo em silêncio. +- Os dois agentes carregam na sessão; o `designer` cria um artefato de exemplo e o diff só toca `docs/plans/` (nada em `src/`). +- O `designer-degraded` rotula `DEGRADED` no output e recusa certificar sem sign-off. +- Busca pelo nome antigo (`ui-draft-html`) não encontra referências nos arquivos desta entrega; consumidores restantes são dívida declarada do OPS114. +- `pnpm exec prettier --check` nos arquivos tocados (`.opencode/` não está no `.prettierignore`); o artefato de exemplo abre no browser via Tailwind CDN. + +## Riscos + +- **Pinar id não exposto pelo OAuth.** O `openai` está hoje em `disabled_providers`; pinar antes da verificação quebra o agente em silêncio. **Mitigação:** pré-requisito primeiro; fail-closed e escalada se o id não existir. +- **Certificação degradada por atalho.** PR que trata `DEGRADED` como design aprovado. **Mitigação:** rótulo obrigatório + sign-off humano + tier registrado no PR. +- **Teto protetivo relaxado demais.** Com brand/tokens permitidos, o artefato tenta virar implementação (JS, estado, decisões). **Mitigação:** a doutrina mantém o teto explícito e a proibição de `src/`. +- **Drift entre os dois prompts.** `designer` e `designer-degraded` duplicam regras e divergem. **Mitigação:** doutrina como fonte única; prompts apontam para ela, não a copiam. +- **Referências quebradas ao nome antigo entre F1 e OPS114.** Dívida declarada; este item não edita consumidores (template, `SKILL.md`, etc.). + +## Referências + +- GitHub Issue #OPS113 (a registrar; placeholder) +- `.agents/skills/plan-issue/ui-draft-html.md` — doutrina atual, a renomear; `intention-template.md`/`SKILL.md` — consumidores (OPS114) +- `.opencode/agent/designer-campanha-solla.md` — precedente de frontmatter e visão nativa/fail-closed (L63–65) +- `docs/changelog/2026-09-14-ops105.md` — `design-vision` removido; não ressuscitar +- `tests/unit/opencodeCommands.unit.spec.ts` (41–44) — proibição de `model:` em comandos não cobre agentes +- `~/.config/opencode/opencode.jsonc` — config global (fora do repo); hoje `openai` em `disabled_providers` +- `docs/AGENT-OPS.md`; `AGENTS.md` ("Edit the owner, don't twin") diff --git a/docs/plans/ops114-plan-issue-design-hifi-no-gate.md b/docs/plans/ops114-plan-issue-design-hifi-no-gate.md new file mode 100644 index 00000000..c914f9a6 --- /dev/null +++ b/docs/plans/ops114-plan-issue-design-hifi-no-gate.md @@ -0,0 +1,106 @@ +# OPS114 — plan-issue: design hi-fi obrigatório no gate (substitui o rascunho low-fi) + +Status: rascunho +Atualizado em: 2026-09-15 +Issue: #1057 +Priority: P2 +Impeccable: A — N/A (muda doutrina de ferramenta de agentes, não UI de produto) +Rascunho UI: N/A — sem UI +Appetite: ~0,5 dia eng; uma varredura de referências + reescrita cirúrgica da skill +Responsável: — + +## Intenção + +O gate do `plan-issue` nasceu vendendo um **rascunho UI low-fi** (HTML descartável, sem assets) para validar item que muda UI. Com o sub-agente `designer` (OPS113), o gate pode entregar **design hi-fi** — HTML+Tailwind com assets SVG — que é **fonte de verdade do port** (classe-a-classe), não rascunho descartável. Enquanto os dois caminhos coexistem, a skill aponta para o artefato velho, o escritor do plano carrega doutrina de UI que não é mais dele e o gate pede um PNG que já não existe (o renderizador `scripts/render-ui-draft.mjs` foi removido em 2026-08-21). Este item aposenta o low-fi e faz a skill apontar para o design hi-fi — sem tocar UI de produto. + +## Persona e fluxo + +- **Persona / contexto:** quem invoca `/plan-issue` (agente principal, mesa, iterando um lote) e o humano que valida o lote no gate, abrindo o design no browser. +- **Job principal:** transformar uma ideia que muda UI em design hi-fi revisável + Issue rastreável, sem virar implementação. +- **Fluxo desejado:** ideia classificada B/C/D → explorador traz findings → escritor escreve o plano (sem gerar UI) → `designer` produz o design por ideia UI (paralelo) → orquestrador grava os arquivos no disco → plano aponta `Design UI:`/seção com link e cenas (390/1280/estados) → gate abre o HTML, itera, confirma. +- **Anti-goals de produto:** não migrar planos antigos; não transformar o design em protótipo funcional; não criar um segundo pipeline de design paralelo ao `designer`; não mexer no painel. + +## Objetivo e aceite + +- **Outcome:** para item que muda UI (B/C/D), o gate exige `docs/plans/-ui-design.html` + `docs/plans/-ui-design-assets/*.svg` produzidos pelo sub-agente `designer`; o escritor do plano não gera mais UI. +- O frontmatter do plano usa `Design UI:` (antes `Rascunho UI:`) e o corpo usa a seção `### Design UI (B/C/D)` com link do HTML + cenas (390/1280/estados); PNG embutido deixa de ser exigência. +- Nenhuma referência a `ui-draft-html.md`, `-ui-draft.html` ou "Rascunho UI" sobra fora de `docs/plans/**` e `docs/changelog/**`. +- Planos antigos e seus `-ui-draft.html`/PNGs ficam intactos (não renomear, não migrar). +- Guardrails: o design não carrega comportamento JS nem nomeia componente final (não vira implementação); doutrina do gate continua fora de `docs/plans/`. + +## Dados (intenção) + +- **Vou apresentar dados?** Não — mudança de doutrina de ferramenta de agentes. +- **Decisões desbloqueadas:** o executor de um item UI decide o port olhando o HTML hi-fi (classe-a-classe) em vez de reconstruir de rascunho descartável. +- **Forma:** _adiada ao plano de implementação_. + +## Dados da decisão (literais) + +- **Artefato obrigatório (B/C/D):** `docs/plans/-ui-design.html` + `docs/plans/-ui-design-assets/*.svg`, produzido pelo sub-agente `designer` (OPS113); o orquestrador grava no disco. +- **Rename de doutrina:** `.agents/skills/plan-issue/ui-draft-html.md` → `.agents/skills/plan-issue/ui-design-html.md` (conteúdo hi-fi entregue no OPS113; se ainda existir com o nome velho, `git mv` aqui, sem tocar no conteúdo elevado). +- **Rename de campo/seção:** `Rascunho UI:` → `Design UI:`; `### Rascunho UI (B/C/D)` → `### Design UI (B/C/D)`. +- **Edits em `.agents/skills/plan-issue/SKILL.md`:** `:26` (regra dura 4), `:42` (input do escritor — remove a doutrina de UI), `:60` (checklist do gate), `:100` (Passo 3c — remove `ui-draft-html.md`), `:112` (Passo 3d — dispatch do `designer` em paralelo por ideia UI + gravação dos arquivos), `:119` (gate — link do `-ui-design.html` + cenas 390/1280/estados). +- **Edits em `.agents/skills/plan-issue/intention-template.md`:** `:15` (campo), `:32–33` (comentário do esboço, aponta para `ui-design-html.md`), `:39–45` (seção + path), `:98` (remove "PNGs embutidos" órfão), `:106–107` (notas A vs B/C/D). +- **Edits em `.agents/skills/plan-issue/shaping.md:56` e `skills-map.md:42`:** link da doutrina + vocabulário "design hi-fi de gate". +- **Fora do sweep (imutável/outro dono):** `docs/plans/**` e `docs/changelog/**` (inclui `docs/CHANGELOG-AGENTS-HISTORY.md`); `scripts/lib/issues-panel.mjs:100` e `scripts/issues-tui.mjs` (retrocompat do painel = OPS116). +- **Sem mudança:** `.opencode/commands/plan-issue.md` (delega à skill) — confirmar por grep no fim. +- **Prettier:** `docs/plans/` **não** está no `.prettierignore` — o HTML/SVG novos do `designer` precisam passar `pnpm format:check`. +- **Precedente sem doc:** `docs/design-refs/latest/*.html|.png` (11 pares) — ver pergunta aberta. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `.agents/skills/plan-issue/` (SKILL.md, intention-template.md, shaping.md, skills-map.md, `ui-design-html.md`); leitura de `docs/plans/` e `docs/design-refs/`. +- **Precedente a olhar:** OPS108 (flag `--auto` na skill) e OPS109/OPS110 (skill + painel) — mudança de comportamento de skill é doc-only, sem código de app. +- **Risco de acoplamento:** o painel resolve o irmão `-ui-draft.html` por convenção; não tocar — só deixar o nome novo documentado para o OPS116 implementar a retrocompat. + +## Dependências + +- **OPS113 (dura):** cria o sub-agente `designer` e eleva a doutrina hi-fi; sem ele não há produtor do artefato. +- **OPS116 (suave, mesmo lote):** retrocompat do painel para `-ui-design.html`; não bloqueia este item, mas sem ele o painel não abre o design novo. + +## Fora de escopo + +- Migrar/renomear planos antigos (`-ui-draft.html` e PNGs). +- Painel/CLI e seus testes (`scripts/lib/issues-panel.mjs`, `scripts/issues-tui.mjs`) — OPS116. +- Gates de implementação (`work-issue`/`agent-work-issue`) — continuam lendo o plano como está. +- Mover/limpar `docs/design-refs/` (vira pergunta aberta, não ação). +- UI de produto e `/impeccable`. + +## Rabbit holes de produto + +- **"Já que estamos mexendo, migra os planos antigos."** Acervo imutável vira PR gigante. **Corte neste item:** retrocompat fica no OPS116; aqui só o nome novo. +- **"O designer pode escrever o componente direto."** Vira implementação antes do gate. **Corte neste item:** output só em `docs/plans/-ui-design.*`. +- **"Embutir PNG no plano de novo."** O renderizador não existe mais (HTML-only desde 2026-08-21). **Corte neste item:** o humano abre o HTML; crítica usa screenshots do app renderizado (OPS115). + +## Questões em aberto (produto) + +- **`docs/design-refs/latest/` vira a casa de designs compartilhados?** **Opções:** A) `design-refs` guarda design compartilhado/reusado por mais de um item (par `.html`+`.png`) e o design de item mora com o plano (`-ui-design.html`); B) unificar tudo em `design-refs`, desligando o irmão do plano; C) manter o precedente informal e não documentar. **Recomendação:** A — preserva o contrato "o design viaja com o plano/Issue", reconhece os 11 pares existentes como precedente de design compartilhado e documenta a convenção na doutrina. Hoje `docs/design-refs/latest/` não tem doc de convenção, e a paleta dos UX Pilot é referência **não** aplicável (`.agents/rules/projects/nucleos-eleitorais.mdc:183`). _(assumido — validar no gate)_ + +## Fases (ordem de entrega) + +1. **F1 — Skill (owner):** reescrever `.agents/skills/plan-issue/SKILL.md` (regra dura 4, input do escritor, checklist, Passo 3c, Passo 3d com dispatch do `designer`, Passo 4/gate) e confirmar/renomear a doutrina para `ui-design-html.md`. +2. **F2 — Template e vizinhos:** `intention-template.md` (campo, seção, notas), `shaping.md:56`, `skills-map.md:42`. +3. **F3 — Sweep + prova:** varredura de referências fora de `docs/plans`/`docs/changelog` (zero), `format:check`, confirmação de que `.opencode/commands/plan-issue.md` não muda e walkthrough de um item UI fictício pelo fluxo novo. + +## Verificação + +- Varredura dupla (`ui-draft`, `Rascunho UI`) restrita a `!docs/plans/**` e `!docs/changelog*/**` → vazio; resultado colado no PR. +- `git diff --name-only ...HEAD` → nada sob `docs/plans/` nem `docs/changelog/`. +- `pnpm format:check` verde (markdown, HTML e SVG). +- Leitura do `SKILL.md` final: escritor não recebe doutrina de UI; 3d dispatcha `designer`; gate mostra `-ui-design.html` + cenas. + +## Riscos + +- **Doutrina ainda no nome antigo (OPS113 incompleto).** Fail-closed: não linkar arquivo inexistente; se o OPS113 não entregou `ui-design-html.md`, este item fica bloqueado pelo `depends` em vez de adivinhar o path. +- **Referência oculta ao low-fi.** Mitigação: varredura dupla por nome e por vocabulário, com exclusões explícitas. +- **Sweep vazar para arquivos imutáveis.** Mitigação: checar `git diff --name-only` contra `docs/plans/` e `docs/changelog/`. +- **Prettier vermelho em HTML/SVG novo.** Mitigação: `pnpm format` antes do commit; `format:check` na verificação. + +## Referências + +- GitHub Issue #OPS114 (a registrar; placeholder) +- Design UI (gate): N/A +- `.agents/skills/plan-issue/SKILL.md` · `intention-template.md` · `shaping.md` · `skills-map.md` — arquivos a editar primeiro +- `.agents/skills/plan-issue/ui-draft-html.md` (atual) → `ui-design-html.md` (novo, OPS113) +- `docs/design-refs/latest/` — 11 pares `.html`+`.png`; `.agents/rules/projects/nucleos-eleitorais.mdc:183` +- `AGENTS.md` — convenção "edit the owner, don't twin" e operação das skills diff --git a/docs/plans/ops115-work-issue-designer-em-qualquer-toque.md b/docs/plans/ops115-work-issue-designer-em-qualquer-toque.md new file mode 100644 index 00000000..0ec9d1f9 --- /dev/null +++ b/docs/plans/ops115-work-issue-designer-em-qualquer-toque.md @@ -0,0 +1,113 @@ +# OPS115 — work-issue/agent-work-issue: designer em qualquer toque de design + crítica visual fail-closed + +Status: rascunho +Atualizado em: 2026-09-15 +Issue: #1058 +Priority: P2 +Impeccable: A — N/A (skills/regras de agente; sem UI de produto) +Rascunho UI: N/A — sem UI +Appetite: ~0,5–1 dia eng; um outcome verificável +Responsável: — + +## Intenção + +O designer vira agente próprio (OPS113/OPS114), mas enquanto ninguém o chamar ele não muda nada: hoje as duas skills de execução tratam UI como um item de checklist ("shape → craft → critique → polish", `work-issue/SKILL.md:143-144`) e o implementador improvisa estrutura visual quando o caminho aperta. A intenção é fechar esse vão: **qualquer toque de design nos dois fluxos passa pelo designer**, e **qualquer diff que muda UI só é certificado com crítica visual contra o app renderizado** — quando o designer não está disponível, o item desce de tier explicitamente e não se auto-certifica; sign-off humano. + +"Qualquer toque de design" tem fronteira: decidir estrutura visual é do designer; portar isso para o markup, fiar dados, rotas, queries e copy é do implementador. O que não pode continuar é o silêncio — um diff visual sem veredito do designer. + +## Persona e fluxo + +- **Persona / contexto:** quem roda as skills (fsolla na sessão humana; workers do pool quando reativados) e o agente implementador, que hoje decide layout no meio do código sem um dono visual. +- **Job principal:** garantir que todo toque visual nasça do designer e seja conferido contra o app renderizado antes de fechar — sem transformar trabalho não-visual em cerimônia. +- **Fluxo desejado:** item UI entra no work-issue com o design do plano → trigger dispara → designer estende o artefato **antes** de implementar (ou adapta o design aprovado quando ele não puder ser seguido como está) → implementador porta → no fim, diff que muda UI passa por crítica do designer com screenshots (390/1280 + estados) → veredito registrado; sem veredito válido, `DEGRADED` + sign-off humano. +- **Anti-goals de produto:** virar passo obrigatório para item sem UI; dar ao designer a caneta de wiring/estado; duplicar a `/impeccable`; pular design em silêncio; pinar `model:` em commands; ressuscitar o pool. + +## Objetivo e aceite + +- As duas skills exigem o designer nos 4 triggers: (a) superfície/estado visual novo que o design do plano não cobre (designer estende o artefato antes de implementar); (b) design aprovado não pode ser seguido como está (designer propõe a adaptação; implementador nunca improvisa estrutura visual); (c) ao final, qualquer diff que muda UI — crítica contra o app renderizado (screenshots 390/1280 + estados); (d) ícones/ilustrações saem do designer. +- Non-triggers seguem com o implementador: fiação de dados/lógica no markup aprovado, hooks/rotas/queries, copy, port mecânico de seção aprovada, bug que restaura o design aprovado, reuso de tokens/componentes já especificados. +- **Fail-closed:** diff que muda UI sem crítica válida do designer não é certificado — desce de tier explícito, marca `DEGRADED` no artefato e no PR, e para em sign-off humano; nunca "segue sem". +- Fallback ladder documentada na skill e aplicada no dispatch do designer (valores literais abaixo), com o tier usado registrado no PR. +- Artefato vivo: o designer pode estendê-lo durante o work-issue; mudança material vs o aprovado no gate volta ao humano no PR. +- Ownership repo-wide: uma linha em `engineering-standards.mdc` (vizinha de "Edit the owner, don't twin") declara que decisão de estrutura visual pertence ao designer; o implementador só porta. +- Guardrails: commands seguem proibidos de `model:` (OPS101); `/impeccable` é referenciada, nunca duplicada; o pool continua dormente. + +## Dados (intenção) + +- **Vou apresentar dados?** Não — `Dados: N/A`: processo de agente, sem superfície de dados de campanha. +- **Decisões desbloqueadas:** N/A. +- **Forma:** N/A. + +## Dados da decisão (literais) + +- Ladder (descer, nunca pular): `openai/gpt-5.6-sol` → `openai/gpt-6-astra` (mesmo pool Plus) → `opencode-go/deepseek-v4.1-flash` (flat; tier `designer-degraded`) → `deepseek/deepseek-flash` (direto, inline pelo orquestrador). +- Tier degradado marca `DEGRADED` no artefato e no PR e **não** certifica: veredito certificado só sai dos tiers primários; no degradado, sign-off humano. +- Crítica com screenshots 390 e 1280 + estados críticos, via Playwright. Sem browser/Cloud (`agent-work-issue`), não há certificação → `DEGRADED`, jamais "pulei por falta de browser". +- Rota canônica de crítica: `/impeccable` (`shape`/`critique`/`polish`) — referenciar, não duplicar. +- `model:` pinado é proibido nos commands (OPS101); `--model` do `agent:register` (`scripts/agent-register.mjs:20,46`) é metadata de pool dormente e não entra aqui; no `work-issue` a sessão humana não verifica modelo (`:96-98`). +- O design do plano é o artefato do OPS114 (`docs/plans/-ui-design.html` + `-ui-design-assets/*.svg`). + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `.agents/skills/work-issue/SKILL.md` (decomposição `:13-61`, checklist `:65-76`, Passo 4 `:136-155`), `.agents/skills/agent-work-issue/SKILL.md` (`:24-31`, `:33-43`, `:75-79`), `.agents/skills/work-issue/execution-pipeline.md` (ordem `:15`, deltas por ator `:89-92` — dono da mecânica compartilhada), `.agents/rules/engineering-standards.mdc` (`:46-51`, linha nova vizinha do `:50`). Possível encaixe em `.agents/skills/work-issue/engineering-brief.md` (tabela "skills sob demanda") e citação em `docs/AGENT-OPS.md`. +- **Precedente a olhar:** a própria decomposição em sub-agentes das duas skills; `agent-work-issue` (deltas do pool); `.agents/skills/impeccable/SKILL.md:41-48` como catálogo de comandos. +- **Risco de acoplamento:** editar os donos (duas skills + pipeline), nunca twinar; agente designer e formato do artefato são de OPS113/OPS114; o mecanismo do fail-closed (gate da skill? postcondição? hook?) fica no impl plan; o safety net `agent-pr-ready-automerge.yml` arma auto-merge em qualquer PR ready — a tensão com o sign-off humano precisa de decisão lá. + +## Dependências + +- **OPS113 (dura)** — o agente `designer`; sem ele não há a quem despachar. +- **OPS114 (dura)** — o aparato de design do lote; este item só conecta os fluxos e torna o designer obrigatório. + +## Fora de escopo + +- Criar ou ajustar o agente designer e o formato do artefato (OPS113/OPS114). +- Reescrever a `/impeccable` ou criar uma segunda skill de crítica visual. +- Pinar `model:` nos commands ou reativar o pool supervisor (OPS65). +- Redesenhar UI de produto, tokens ou shells — este item não toca produto. +- Exigir designer em item sem UI (classe A). + +## Rabbit holes de produto + +- **"Já que tem designer, todo commit passa por ele."** Vira imposto sobre trabalho não-visual. **Corte neste item:** non-triggers explícitos; default é não despachar. +- **"O designer decide a solução."** Inverte ownership e atropela engenharia. **Corte neste item:** designer decide estrutura visual; wiring/estado/rotas são do implementador. +- **"Sem designer agora, segue e revisa depois."** É exatamente o silêncio que o item existe para matar. **Corte neste item:** fail-closed com `DEGRADED` + humano. +- **"Reescreve a impeccable dentro da skill."** Twin de um dono que já existe. **Corte neste item:** referência à skill canônica. +- **"Aproveita e religa o pool."** Orquestração de agentes não é o pedido. **Corte neste item:** pool dormente, nada de supervisor. + +## Questões em aberto (produto) + +- **Como o fluxo autônomo entrega o sign-off humano no tier degradado sem violar o contrato "nunca Draft; PR ready + auto-merge"?** **Opções:** A) o PR degradado se declara `DEGRADED` e o impl plan escolhe o mecanismo que o mantém fora do auto-merge (veto à la `audit/*` ou não-ready); B) degradado interrompe antes de abrir PR e comenta na Issue; C) degradado só existe no `work-issue` (no autônomo, ausência de tier primário = `blocked`). **Recomendação:** A — preserva a entrega rastreável (PR) e torna o sign-off um estado visível; o caminho concreto fica no impl plan. _(assumido — validar no gate)_ +- **Onde o trigger (a) é detectado — no impl plan ou durante a execução?** **Opções:** A) no impl plan, que já lista as superfícies; B) durante a execução, quando a superfície nova aparece no código. **Recomendação:** os dois — o plan antecipa; a execução não pode encontrar superfície nova e improvisar sem despachar o designer. _(assumido)_ +- **`engineering-brief.md` ganha linha de design na tabela "skills sob demanda"?** **Opções:** A) sim, apontando o agente designer; B) não, o gatilho vive nas skills. **Recomendação:** A se o impl plan achar que ajuda explorador/escritor; acessório, não aceite. _(assumido)_ + +## Fases (ordem de entrega) + +1. **Ownership:** a linha da rule em `engineering-standards.mdc`, vizinha do "Edit the owner, don't twin". +2. **Triggers + ladder:** triggers/non-triggers e a ladder nas duas skills, com a mecânica compartilhada no `execution-pipeline.md` (deltas por ator). +3. **Fail-closed:** crítica final obrigatória + `DEGRADED`/sign-off humano costurados no fechamento de cada fluxo. + +## Verificação + +- `pnpm gate:fast` verde; diff só de docs/skills/regras (sem migration, schema, access ou UI). +- Asserções no PR: triggers (a)–(d) e non-triggers presentes nas duas skills; ladder com os 4 slugs; `DEGRADED`; linha de ownership na rule; `/impeccable` citada sem conteúdo duplicado. +- Walkthrough no PR: item UI hipotético mostrando onde cada fluxo exige o designer antes de implementar e no fechamento; degradação simulada mostra o caminho `DEGRADED` + humano. +- Sem UI de produto → Impeccable A, sem rascunho UI. + +## Riscos + +- **Pulo silencioso do design** (o pior caso): ladder explícita + `DEGRADED` + tier registrado no PR; nunca inferir "não precisava". +- **`DEGRADED` fechar por auto-merge:** o safety net arma qualquer PR ready — o sign-off humano precisa sobreviver a ele; mecanismo é decisão explícita do impl plan. +- **Cerimônia em item não-visual:** non-triggers listados; default é não despachar; o trigger (a) tem que nomear a superfície nova. +- **Bloat das skills:** texto curto; mecânica no pipeline; impeccable por referência. +- **Drift entre os dois fluxos:** a mecânica compartilhada vive no `execution-pipeline.md`; cada skill declara só o delta. + +## Referências + +- GitHub Issue #OPS115 (a registrar; plano nasce `blocked`) +- `.agents/skills/work-issue/SKILL.md` (`:13-61`, `:65-76`, `:96-98`, `:136-155`) e `.agents/skills/agent-work-issue/SKILL.md` (`:24-31`, `:33-43`, `:75-79`) — os dois donos +- `.agents/skills/work-issue/execution-pipeline.md` (`:15`, `:89-92`) — dono da mecânica compartilhada +- `.agents/rules/engineering-standards.mdc` (`:46-51`) — onde entra a linha de ownership +- `.agents/skills/impeccable/SKILL.md` (`:1-3`, `:41-48`) — crítica visual canônica +- `scripts/agent-register.mjs` (`:20`, `:46`) e `.opencode/commands/work-issue.md` — pin de modelo proibido nos commands (OPS101); pool dormente +- `.github/workflows/agent-pr-ready-automerge.yml` + `scripts/github-pr-automerge.mjs` — safety net que arma auto-merge em PR ready (tensão do `DEGRADED`) +- `AGENTS.md` — convenções de skills/regras e changelog da entrega diff --git a/docs/plans/ops116-painel-ui-design-retrocompat.md b/docs/plans/ops116-painel-ui-design-retrocompat.md new file mode 100644 index 00000000..5165e4a7 --- /dev/null +++ b/docs/plans/ops116-painel-ui-design-retrocompat.md @@ -0,0 +1,111 @@ +# OPS116 — Painel/TUI: aceitar `-ui-design.html` com retrocompat `-ui-draft.html` + +Status: rascunho +Atualizado em: 2026-09-15 +Issue: #1059 +Priority: P2 +Impeccable: A — N/A (tooling de terminal; não toca UI de produto) +Rascunho UI: N/A — sem UI +Appetite: ~0,5 dia eng; um outcome verificável +Responsável: — + +## Intenção + +O OPS114 renomeou o artefato de validação visual do planejamento de "rascunho UI" para "design UI", com arquivo `docs/plans/-ui-design.html`. O painel de issues (`pnpm issues:tui`, OPS109) ficou para trás: continua procurando só `-ui-draft.html` e chamando a ação de "rascunho UI". Depois do OPS114, uma Issue nova com design no gate aparece no painel como se não tivesse o arquivo — a tecla `w` diz "não tem" mesmo tendo — e o operador perde o atalho de abrir o design no browser antes de decidir sobre a Issue. Quero que o painel reconheça os dois nomes — preferindo o novo — e fale "design UI", sem tocar nos planos antigos. + +## Persona e fluxo + +- **Persona / contexto:** o mantenedor (fsolla) operando issues pelo terminal, na mesa ou via SSH, olhando uma Issue antes de aprovar o plano ou entrar no run. +- **Job principal:** ver que a Issue tem design UI e abri-lo no browser com uma tecla, sem caçar o caminho no GitHub ou no disco. +- **Fluxo desejado:** lista → seleciona a Issue → no detalhe vê `w design UI · ` (ou "não tem (classe A)") → aperta `w` e o `.html` abre no browser padrão (ou imprime o caminho, quando não há display). +- **Anti-goals de produto:** não vira renderizador de imagem nem preview embutido; não migra o acervo legado de planos; não muda a UI de produto do `/campanha` nem o site; não adiciona ações novas ao painel. + +## Objetivo e aceite (outcome) + +- Issue cujo plano tem só `-ui-design.html` aparece com o design disponível no detalhe e a tecla `w` abre/entrega o caminho certo. +- Issue legada, com só `-ui-draft.html`, continua funcionando igual a hoje (retrocompat; planos antigos são imutáveis). +- Quando os dois arquivos existem, o painel usa o `-ui-design.html`. +- O painel (detalhe, ajuda e mensagens) fala "design UI"; "rascunho UI" some das superfícies do painel. +- O contrato `--json` segue legível pelo consumidor atual sem quebra silenciosa: a linha da Issue carrega o **caminho real** do arquivo encontrado e a informação de existência. +- Nada de PNG: só HTML (a decisão "HTML-only, no PNG rendering" continua). + +## Dados (intenção) + +- **Vou apresentar dados?** Não — é ferramenta de operação; a "superfície" é a própria TUI, sem métrica de produto. +- **Decisões desbloqueadas:** N/A — não há decisão de negócio; é continuidade de leitura do acervo de planos. +- **Forma:** N/A. + +## Dados da decisão (literais) + +- **Decisão de dados de produto:** N/A — nada de eleitoral/contato/consentimento neste item. +- Nomes literais: preferir `docs/plans/-ui-design.html`; cair para `docs/plans/-ui-draft.html` quando o primeiro não existir, na mesma base do plano de intenção já usada para `-impl.md`. +- Nomenclatura recomendada (menor churn): manter a chave `uiDraft` no view model e no `toJsonPayload` (`version: 1`), porém com `path` = arquivo **realmente encontrado**; quem quiser saber o nome concreto lê o sufixo do caminho. Campo novo (`variant`) ou rename fica fora. +- Strings exatas (substituindo as atuais em `scripts/issues-tui.mjs:19,339,340,359,637`): `w design UI` · `w abrir design UI no browser` · `w design UI: não tem (classe A)`. +- Sem mudança de schema → sem migration (`pnpm migrate:create` não é usado neste item). + +## Escopo + +- `scripts/lib/issues-panel.mjs`: derivar os **dois** nomes irmãos (`-ui-design.html` preferido, `-ui-draft.html` fallback) e devolver no view model/JSON o caminho real do que existe — mantendo a chave atual `uiDraft`. +- `scripts/issues-tui.mjs`: sondar existência na ordem design → draft; strings "rascunho UI" → "design UI" (ajuda `:19`, linha de ação `:339-340`, rodapé `:359` e mensagem do handler `w` `:637`). +- Testes unit dos dois specs do painel: atualizar expectativas de nome e cobrir design-only, draft-only, ambos (design vence) e nenhum. +- Entrada de changelog da entrega (`docs/changelog/2026-09-15-ops116.md`), conforme convenção do repo. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `scripts/lib/issues-panel.mjs` (derivação pura: `siblingPlanPaths`, `buildIssueRow`, `buildPanelViewModel`, `toJsonPayload`) e `scripts/issues-tui.mjs` (I/O: `readPlans`, render do detalhe, handler `w`). +- **Precedente a olhar:** OPS109 (`docs/plans/ops109-painel-issues-no-terminal.md` + impl), que estabeleceu o painel, a chave `uiDraft` e os 28 `-ui-draft.html` legados; OPS114 para o contrato do nome novo. +- **Risco de acoplamento:** a existência do arquivo é checada no CLI (o lib é puro e não toca disco) — manter essa divisão. `--json` é consumido por teste/script: tratar a chave como superfície pública (mudança silenciosa é regressão). + +## Dependências + +- **OPS114 (dura, declarada no registro)** — dono do rename `-ui-design.html`/"design UI" nos planos e na skill. No código, este item é seguro mesmo antes: sem arquivo novo, o fallback legado mantém tudo como está. + +## Fora de escopo + +- Migrar/renomear os `*-ui-draft.html` e PNGs existentes em `docs/plans/` (~28 HTMLs e ~45 PNGs) — acervo legado é imutável. +- Recriar renderizador de PNG/`scripts/render-ui-draft.mjs` (removido em 2026-08-21; HTML-only segue). +- Renomear a chave `uiDraft` do view model/JSON ou subir a versão do payload (churn sem consumidor novo). +- Tocar na skill `plan-issue`/template (dono do rename é o OPS114) ou em UI de produto. +- Qualquer mudança em claim/registro/sessões, guards de CI, ou no fluxo `--json` além do necessário. + +## Rabbit holes de produto + +- **"Já que achou o caminho, deixar o painel renderizar o HTML/imagem."** Vira viewer embutido, segundo dono de preview. **Corte:** só abrir no browser/imprimir caminho, como hoje. +- **"Aproveitar e renomear tudo para `-ui-design`."** Puxa migração de acervo imutável e PR de planos antigos. **Corte:** retrocompat de leitura. +- **"Limpar o vocabulário no repo inteiro."** Renomeia docs/changelog/skill (dono é OPS114) e explode o diff. **Corte:** só as superfícies do painel. + +## Questões em aberto (produto) + +- **A mensagem de ausência mantém "(classe A)"?** **Opções:** A) uniforme (`design UI: não tem (classe A)`) | B) sem "design UI". **Recomendação:** A — uma palavra por superfície; o "(classe A)" já explica. _(assumido — validar no gate)_ +- **Caminho exibido quando nenhum arquivo existe:** **Opções:** A) candidato novo (`-ui-design.html`) com `exists: false` | B) manter o antigo. **Recomendação:** A — ensina o nome novo; o fallback real continua valendo quando o legado existir. _(assumido)_ +- **Dependência do OPS114 é dura?** **Opções:** A) dura (bloqueia claim até o rename estar em main) | B) suave (o item só lê nomes). **Recomendação:** A no registro, como pedido pelo gate; a entrega é segura de qualquer forma. _(assumido)_ + +## Fases (ordem sugerida) + +1. **Camada pura** — dois candidatos de design no `siblingPlanPaths` + caminho real no view model; escrever primeiro os unit tests (design-only, draft-only, ambos, nenhum) e fazer passar. +2. **CLI** — `readPlans` sonda design → draft; render/ajuda/mensagens para "design UI"; smoke manual `pnpm issues:tui --json` (com token) conferindo o caminho real numa issue com draft legado. +3. **Fechamento** — specs existentes atualizados, changelog da entrega e verificação abaixo. + +## Verificação + +- Unit focado nos dois specs do painel (rápido, sem DB): + `pnpm test:unit -- tests/unit/issuesPanel.unit.spec.ts tests/unit/issuesPanelRegression.unit.spec.ts` +- Gate local (lint + typecheck + unit completo): `pnpm gate:fast` +- Guarda de localização de testes (nenhum spec novo fora de `tests/unit`): `node scripts/check-test-locations.mjs` +- Smoke manual (não-gate, exige `GITHUB_TOKEN`): `pnpm issues:tui --json` e conferir que uma Issue com `-ui-draft.html` traz o caminho real e `exists: true`; abrir `pnpm issues:tui` e conferir "design UI" no detalhe. + +## Riscos + +- **Regressão silenciosa do `--json`:** manter `version: 1` e o shape `{ path, exists }`; campo a mais seria contrato novo sem pedido. +- **Confusão de nomes no código:** a chave `uiDraft` passa a significar "design UI (novo ou legado)" — comentar no owner em vez de duplicar campos. +- **Teste que fixa o nome antigo:** os dois specs citados têm expectativas literais de `-ui-draft.html`; atualizar junto (senão o gate fica vermelho). +- **Acervo legado:** não tocar nos arquivos existentes; a retrocompat é de leitura, não de migração. + +## Referências + +- GitHub Issue #OPS116 (a registrar; placeholder) +- Design UI (gate): N/A — classe A (sem UI de produto) +- Plano pai (imutável): `docs/plans/ops109-painel-issues-no-terminal.md` e `docs/plans/ops109-painel-issues-no-terminal-impl.md` +- Arquivos owner: `scripts/lib/issues-panel.mjs:5,89-101,180-254,359-391`; `scripts/issues-tui.mjs:19,104-120,335-341,354-363,633-639` +- Testes: `tests/unit/issuesPanel.unit.spec.ts:91-105,153-156,265,290`; `tests/unit/issuesPanelRegression.unit.spec.ts:152` +- Guards/CI citados: `scripts/check-test-locations.mjs`, `scripts/check-plans-only-pr-closes.mjs`; gate local `pnpm gate:fast` (`lint && typecheck && test:unit`)