Channel — Videos screen #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Design drift | |
| # Audita se o código traduziu o design corretamente. As regras não vão no | |
| # prompt: o CLAUDE.md faz @design/DESIGN-SYSTEM.md, então a action carrega o | |
| # guia inteiro sozinha. O prompt só nomeia o que auditar e onde reportar. | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| paths: | |
| - "app/**" | |
| - "components/**" | |
| - "design/**" | |
| - "scripts/**" | |
| - ".github/workflows/design-drift.yml" | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: read | |
| id-token: write | |
| concurrency: | |
| group: design-drift-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| env: | |
| PEN_FILE: design/pendev/youtube-channel.pen | |
| APP_URL: http://localhost:3000/@FullCycle/videos | |
| jobs: | |
| audit: | |
| if: github.event.pull_request.draft == false | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| - name: Instalar pen.dev CLI | |
| run: npm install -g @pen.dev/cli && pen version | |
| # Três evidências, todas textuais. Nenhum PNG: render do design sem render | |
| # da app é comparação de um lado só. E a tool `browser` do pen, que | |
| # fecharia o loop carregando a app, exige o app desktop e não roda aqui. | |
| # | |
| # components.html geometria/tipografia RESOLVIDA em px (só tema claro) | |
| # components.json qual token o design usa (nome do token) | |
| # tokens.json o que cada token vale em light e dark | |
| # screens.json composição das telas: quais componentes, em que ordem | |
| # | |
| # As telas não são `reusable`, então ficariam fora das três primeiras — | |
| # sem screens.json o audit cobre componente e não cobre página. | |
| # | |
| # O HTML existe para o agente não ter que resolver $radius-sm -> 8px | |
| # sozinho — errar essa resolução é literalmente a regra 3 do audit. | |
| - name: Extrair design | |
| env: | |
| PEN_CLI_KEY: ${{ secrets.PEN_CLI_KEY }} | |
| run: | | |
| mkdir -p /tmp/design | |
| jq -S '{themes, variables}' "$PEN_FILE" > /tmp/design/tokens.json | |
| jq -S '[.. | objects | select(.reusable == true)] | sort_by(.name) | |
| | map(walk(if type == "object" then del(.id, .x, .y) else . end))' \ | |
| "$PEN_FILE" > /tmp/design/components.json | |
| NODES=$(jq -r '[.. | objects | select(.reusable == true) | .name] | join(";")' "$PEN_FILE") | |
| PEN_NODES="$NODES" ./scripts/pen-export.sh \ | |
| "$PEN_FILE" /tmp/design/components.html 1 html-tailwind | |
| ./scripts/pen-outline.py "$PEN_FILE" > /tmp/design/screens.json | |
| ls -la /tmp/design | |
| # A comparação numérica: sobe a app, lê getComputedStyle de cada | |
| # [data-component] e confronta com o design renderizado. `rounded-lg` no | |
| # código e `rounded-[8px]` no design são strings diferentes e o mesmo | |
| # valor — o navegador normaliza os dois dialetos, então isto vira | |
| # aritmética e não julgamento. Não roda se ainda não houver rota. | |
| - name: Comparação numérica com a app | |
| id: numeric | |
| continue-on-error: true | |
| run: | | |
| if [ ! -d app ] || [ -z "$(find app -name 'page.tsx' -not -path 'app/page.tsx' 2>/dev/null)" ]; then | |
| echo "sem rota de tela ainda — comparação numérica pulada" > /tmp/design/numeric.md | |
| exit 0 | |
| fi | |
| npm ci --silent | |
| npx playwright install chromium --only-shell >/dev/null 2>&1 || npx playwright install chromium | |
| npm run build | |
| npm start & | |
| for _ in $(seq 1 40); do | |
| curl -sf -o /dev/null "$APP_URL" && break || sleep 2 | |
| done | |
| node scripts/compare-styles.mjs /tmp/design/components.html "$APP_URL" \ | |
| > /tmp/design/numeric.md 2>&1 || true | |
| cat /tmp/design/numeric.md | |
| # Seis das nove regras são regex sobre o diff. Rodá-las aqui é | |
| # determinístico e grátis; o agente entra só para verificar e julgar. | |
| - name: Pré-análise mecânica | |
| env: | |
| PEN_FILE: design/pendev/youtube-channel.pen | |
| run: ./scripts/drift-scan.sh "origin/${{ github.base_ref }}" | tee /tmp/design/scan.txt | |
| - uses: anthropics/claude-code-action@v1 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| prompt: | | |
| Audite drift entre o design e o código neste PR. | |
| As regras estão em design/DESIGN-SYSTEM.md, já carregado via CLAUDE.md. | |
| SIGA ESTA ORDEM. Ela existe para você não gastar turnos: | |
| 1. Leia /tmp/design/scan.txt PRIMEIRO. A varredura mecânica já rodou | |
| sobre o diff e listou as ocorrências das regras 1, 2, 4, 5, 6, 8, | |
| os radius da 3, e os data-component sem frame no .pen (metade da | |
| 7). Se uma seção não aparece lá, essa regra passou: NÃO a | |
| reinvestigue, e não abra arquivo para reconferir o que ela cobre. | |
| 2. Para cada ocorrência listada, abra só aquele arquivo e confirme | |
| se é violação de verdade ou uso correto. | |
| 3. Leia /tmp/design/numeric.md. As divergências ali são medidas, | |
| não inferidas — vire cada uma em achado da regra 10. | |
| 4. Só então cheque as regras 7 e 9, que exigem comparar com o design. | |
| NUNCA use Read em /tmp/design/components.html: são 107KB e vai | |
| estourar seu contexto. Use grep com data-pencil-name="<nome>". | |
| Evidência disponível, cada uma autoridade sobre uma coisa: | |
| - /tmp/design/components.html — cada componente com geometria e | |
| tipografia JÁ RESOLVIDAS em px, marcado com data-pencil-name. | |
| Grepe por data-pencil-name="Chip" para achar um componente. | |
| Use para conferir NÚMEROS: 32px de altura, 8px de radius, 14/20 de | |
| texto. Só tem tema claro. NUNCA copie código daqui: a saída é | |
| achatada (hex cru, px absoluto) e viola as regras 1, 2 e 9. | |
| - /tmp/design/components.json — qual TOKEN o design usa em cada | |
| propriedade ($radius-sm, $surface-chip). Use quando a pergunta for | |
| "qual token deveria estar aqui". | |
| - /tmp/design/tokens.json — o que cada token vale em light E dark. | |
| Autoridade sobre cor e tema; o CSS do repo é transcrição e pode | |
| estar errado. | |
| - /tmp/design/numeric.md — a comparação numérica JÁ FEITA entre o | |
| design renderizado e a app rodando, por [data-component]. Se ela | |
| listar divergências, elas são fato, não hipótese: reporte cada uma | |
| como regra 10, apontando o arquivo do componente. Se disser | |
| "nenhuma divergência numérica", não reinvestigue geometria de | |
| componente — foi medida. | |
| - /tmp/design/screens.json — a COMPOSIÇÃO de cada tela: quais | |
| componentes, em que ordem, dentro de que container, com que gap e | |
| padding. É contra isto que os arquivos em app/ devem bater. | |
| Conteúdo instanciado (títulos, thumbnails) foi podado de | |
| propósito: aquilo é fixture, não design. | |
| Escopo — decida pelo que mudou: | |
| git diff --name-only origin/${{ github.base_ref }}...HEAD | |
| - Mudou código (app/, components/): audite os arquivos alterados. | |
| - Mudou SÓ o design (design/pendev/): o código não mudou, mas pode | |
| ter ficado defasado. Compare o que mudou no .pen contra os | |
| componentes React correspondentes, mesmo que eles não estejam no | |
| diff. Este é o caso que mais escapa em review. | |
| - Mudaram os dois: faça as duas coisas. | |
| Procure exatamente estas dez falhas — todas compilam e parecem | |
| certas, por isso passam em review: | |
| 1. Cor crua em className (`#`, `rgb(`, `hsl(`) — quebra o tema escuro | |
| 2. Qualquer variante `dark:` — significa token semântico faltando | |
| 3. Radius traduzido pelo nome em vez do valor. Os nomes do .pen estão | |
| deslocados um degrau: $radius-sm é 8px e vira rounded-lg, não | |
| rounded-sm. Confira contra a tabela do §6. | |
| 4. `p-14` onde o design pede $space-14 (58px, não os 56px de p-14) | |
| 5. `text-lg`/`text-sm` usados achando que batem com o .pen | |
| (font-size-lg é 16px; text-lg do Tailwind é 18px) | |
| 6. Altura fixa em thumbnail (`h-[201px]`) em vez de aspect-video | |
| 7. Token ou componente que não existe em tokens.json nem no .pen. | |
| Exceção única: estados de interação e foco (§9). | |
| 8. Prop `className` exposta em componente (§7) | |
| 9. Página que não bate com screens.json: componente faltando, ordem | |
| trocada, container com gap ou padding diferente. Atenção ao | |
| Header Region, que usa $space-14 — 58px, não os 56px de p-14. | |
| 10. Componente cujos valores DIVERGEM do design. Esta é a definição | |
| de drift e a mais importante da lista: o componente existe, o | |
| nome está certo, e uma propriedade não bate — padding, gap, | |
| altura, cor, tipografia. Confira contra components.html (px já | |
| resolvido) e components.json (o token). Vale mesmo quando o | |
| .tsx não está no diff: se o scan disser que o design mudou, o | |
| código correspondente está defasado até prova em contrário. | |
| Para cada achado, poste comentário inline na linha exata, com a regra | |
| violada e a correção, citando a seção do DESIGN-SYSTEM.md. | |
| Comentário inline só cola em linha que está no diff: se o arquivo | |
| defasado não mudou neste PR, comente na linha do .pen que causou a | |
| divergência, nomeando o arquivo e a linha do código. | |
| Se não houver achado, não poste nada. | |
| Não reporte estilo, nomes ou arquitetura fora dessas dez. | |
| claude_args: | | |
| --max-turns 60 | |
| --allowedTools "mcp__github_inline_comment__create_inline_comment,Read,Grep,Glob,Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(jq:*),Bash(diff:*),Bash(comm:*),Bash(sed:*),Bash(head:*),Bash(tail:*),Bash(wc:*),Bash(ls:*)" |