Verificar o site portfólio
Status: lançamento, diagnóstico, limpeza e um primeiro conjunto de fluxos estão comprovados em produção (2026-10-02, testado 82ec737, chrome-devtools-axi, WebGL2 real em Apple M3 Pro). A cobertura é parcial: cada arquivo features/*.md tem uma linha Last live proof: que diz exatamente o que foi executado e o que não foi; uma funcionalidade cuja linha diz none nunca foi testada. Nada aqui está "verificado" porque este arquivo o descreve.
Apenas acionamento manual (regra do usuário, 2026-10-02): esta skill e o PStack são executados apenas quando o usuário solicita verificação explicitamente. Um commit, push, PR ou ativação de um modo não a inicia, e nada aqui pode ser conectado a um hook git, script de ciclo de vida de pacote, job de CI ou agendamento. O frontmatter define disable-model-invocation: true, então o agente nunca a pega por conta própria. Inicie manualmente: Claude Code /verify; Codex $verify quando o Codex descobrir .agents/skills/verify; qualquer outro agente: leia este arquivo e execute as etapas abaixo explicitamente. Auditoria de acionamentos automáticos em 2026-10-02, nenhum executa um navegador: .husky/pre-commit (lint-staged, config .lintstagedrc: eslint e prettier em arquivos staged), .husky/commit-msg (commitlint), package.json prepare (husky), .github/workflows/ci.yml (type-check, lint, fmt:check, vitest, build, budget). test:e2e e visual-baseline são apenas scripts manuais. O core.hooksPath deste checkout aponta para um diretório de hooks do firstmate fora do repositório, não para .husky.
O uso do navegador é autorizado apenas para uma execução explícita de verificação (a execução de 2026-10-02 foi autorizada pelo capitão, substituindo a retenção anterior do navegador). As receitas do Drive são escritas como ações do usuário e resultados observáveis para que sejam executadas com chrome-devtools-axi ou qualquer outra skill de navegador.
Todo problema em aberto, hipótese e lacuna de prova ao vivo reside em um único ledger: docs/verification/verification-issues.md. Os arquivos de funcionalidade linkam para ele e não o repetem. Leia features/README.md para o mapa antes de direcionar qualquer coisa.
Qual é a superfície
Um aplicativo Next.js 16 (App Router, proxy.ts, pré-renderização estática, React Compiler). Onze edições ao vivo compartilham um modelo de conteúdo e um conjunto de rotas; a edição do visitante decide a aparência. O proxy reescreve /<path> para /f/<edition>/<path>; / mostra o seletor (/flavors) até que o cookie hr_flavor contenha um ID de edição ativa. NEXT_PUBLIC_FLAVOR=<id> fixa uma compilação em uma edição. A lista de edições é flavors/registry.ts. A lista de rotas por edição é content/site.ts pages mais /owner, /projects/<slug>, /lab/<slug>, /ask/<slug>, /ask/page/<n>, /md/* espelhos, /llms.txt, /sitemap.xml, /robots.txt.
Este é um Next.js com alterações de última hora. Antes de tocar no código do aplicativo, leia o guia correspondente em node_modules/next/dist/docs/ (o AGENTS.md do repositório assim o diz).
Harness existente (reutilizar, não duplicar)
playwright.config.ts e e2e/*.spec.ts já cobrem a maior parte do comportamento da casca. Uma execução de verificação direciona o site ao vivo para o que eles não provam e os cita para o que provam. Nunca copie uma asserção e2e em um arquivo de funcionalidade como um segundo conjunto de testes.
| Cobertura existente | Onde | O que prova |
|---|---|---|
| A saída da compilação é pré-renderizada | e2e/static-routes.spec.ts (projeto build) | nenhuma rota pública é renderizada por solicitação, nenhuma revalidação baseada em tempo |
| Suíte específica mínima | home, navigation, ask, lab, motion, preferences, print, disclosure, command-menu, link-preview, markdown specs, projetos desktop e mobile | Mínima apenas (cookie hr_flavor=minimal) |
| Suíte específica Drawing Set | e2e/drawing-set.spec.ts, projetos desktop-drawing-set, mobile-drawing-set | índice de folhas, menu de comando, persistência Customize, log /now, sem estouro em 768 |
| Casca compartilhada para as outras nove | editions.spec.ts, a11y.spec.ts, command-dialog.spec.ts, projetos desktop-<id> e mobile-<id> | toda rota 200 com um h1, edição 404, menu de comando, tema Customize, alternância de tema do cabeçalho, axe em claro e escuro com movimento reduzido, diálogo de comando e contratos de teclado |
Essas suítes são executadas com bun run test:e2e e iniciam seu próprio bun run build && bun run start -p 3020 (reuseExistingServer: true fora do CI, então qualquer processo já em 3020 é reutilizado silenciosamente). Elas são automação de navegador: execute-as apenas sob solicitação, um worker, com 3020 confirmado livre. Elas não foram executadas em 2026-10-02. Sua aprovação ou reprovação não é uma prova de nada que este mapa marque como uma lacuna (veja o ledger).
Portões não-navegador que existem: bun run lint, bun run type-check, bun run test (vitest), bun run fmt:check, bun run check:identity, bun run budget (após uma compilação). Executá-los é permitido e não diz nada sobre o comportamento da UI.
Lançamento
Um servidor por tarefa, em uma porta específica da tarefa, iniciado a partir de uma compilação de produção porque é o que a configuração e2e e static-routes.spec.ts assumem (next dev não faz parte deste plano).
.agents/skills/verify/scripts/doctor.sh # higiene de env e árvore, nenhum servidor necessário
.agents/skills/verify/scripts/serve.sh start 3071 # compilar, iniciar, aguardar prontidão, escrever arquivo PID
.agents/skills/verify/scripts/doctor.sh 3071 # agora também sonda a instância em execução
serve.sh start faz exatamente isto: recusa se a porta estiver ocupada, executa bun run build e bun run start -p <port> com todas as variáveis Sanity, ask e flavor não definidas (para que o site renderize o conteúdo de fallback empacotado e não faça chamadas ao CMS), registra o PID do servidor em $RUN_DIR/server.pid, e aguarda até que GET /flavors responda 200. As portas 3000 e 3020 são recusadas (3020 pertence à configuração do Playwright). Uma compilação sobrescreve .next; não inicie duas execuções em um mesmo checkout.
Pronto significa tudo isto: serve.sh imprimiu ready, GET /flavors é 200, e GET / com o cookie hr_flavor=minimal é 200 e contém um <h1>. Não direcione nada que não tenha atendido a todos os três.
Desmontagem: .agents/skills/verify/scripts/serve.sh stop 3071 (veja Limpeza).
Diagnóstico
.agents/skills/verify/scripts/doctor.sh [port] é somente leitura. Ele responde "esta instância vale a pena ser direcionada e é segura". Ele falha (código de saída 1) quando qualquer uma destas condições se aplica:
- Um arquivo
.env,.env.local,.env.development*,.env.production*existe na raiz do repositório (Next carregaria segredos Sanity ou ask e a direção poderia escrever em um conjunto de dados real). - Qualquer uma de
NEXT_PUBLIC_SANITY_PROJECT_ID,SANITY_API_READ_TOKEN,SANITY_API_WRITE_TOKEN,SANITY_REVALIDATE_SECRET,ASK_COOKIE_SECRET,ASK_OWNER_PASSPHRASE,NEXT_PUBLIC_FLAVORestá definida no shell de chamada. HEADnão é o commit que a execução alega, ou a árvore está suja (ele imprime ambos).- Com uma porta: a porta não é propriedade do PID em
$RUN_DIR/server.pid,/flavorsnão é 200,/api/visitsnão é 503 (deve ser 503: é assim que a compilação de fallback prova que o contador de visitantes não pode escrever em um CMS), ou/comhr_flavor=minimalnão tem<h1>.
Execute-o primeiro sempre que algo parecer estranho.
Pré-requisitos que uma execução deve declarar
- Conteúdo: fallback empacotado (
content/fallback/), o padrão. Uma execução contra um projeto Sanity configurado é uma execução diferente com aprovação do proprietário, um conjunto de dados descartável e um token somente leitura; veja features/cms-prerequisites.md. Nenhuma execução pode escrever em um CMS, alterar o conteúdo do proprietário, implantar ou tocar em credenciais. - Viewports: desktop 1440x900 e telefone (perfil "Pixel 7" do Playwright: toque, ponteiro grosseiro, sem hover), os dois que a configuração e2e usa. Claro e escuro. Movimento ativado e
prefers-reduced-motion: reduce. - Armazenamento: comece cada execução de flavor a partir de um perfil vazio com apenas o cookie
hr_flavor=<id>(o que ostorageStatedo e2e faz). Nunca use uma sessão de navegador autenticada compartilhada. - Nível de cena: o nível de cena segue WebGL2,
Save-Data,prefers-reduced-data,deviceMemorye ponteiro (lib/scene/tier.ts). Registre os sinais de nível do navegador com cada prova de cena. Um navegador headless sem GPU prova T0 e o poster, não o 3D.
Direção
Navegador: chrome-devtools-axi com sua própria sessão, porta e perfil isolado; nunca se conecte automaticamente ao Chrome do usuário. Configuração comprovada (2026-10-02):
export CHROME_DEVTOOLS_AXI_SESSION=<unique-task-name> CHROME_DEVTOOLS_AXI_PORT=<free port> CHROME_DEVTOOLS_AXI_AUTO_CONNECT=0
export CHROME_DEVTOOLS_AXI_MCP_PATH="$(npm prefix -g)/lib/node_modules/chrome-devtools-mcp/build/src/bin/chrome-devtools-mcp.js" # evita o bootstrap do npx
export CHROME_DEVTOOLS_AXI_HEADED=1 CHROME_DEVTOOLS_AXI_CHROME_ARGS="--enable-gpu --ignore-gpu-blocklist" # WebGL2 real; headless prova apenas o poster
chrome-devtools-axi emulate --viewport "1440x900x2" # desktop; "412x915x2.625,mobile,touch" para o perfil Pixel 7
chrome-devtools-axi emulate --color-scheme dark|light
# movimento reduzido: reinicie a ponte (`chrome-devtools-axi stop`) com --force-prefers-reduced-motion anexado a CHROME_ARGS
chrome-devtools-axi run <<'EOF' ... EOF # varreduras com script; pare a ponte no final
Notas de ferramentas da execução: em scripts run, page.wait(ms) lança "fn is not a function", então durma com await new Promise(r=>setTimeout(r,ms)); process.env não está disponível lá, substitua valores no texto do script; hr_flavor não pode ser limpo de document.cookie, então escolha uma edição abrindo /?flavor=<id>; emulate não tem uma flag de movimento reduzido; um clique de ponteiro no Paper visualmente oculto do Press expirou (teclado ArrowRight funcionou, WEB-H8); o hook zshz deste shell retorna não zero em cd, então use caminhos absolutos. Cada arquivo de funcionalidade em features/ lista as ações, handles estáveis e estado final observável. Handles em ordem de preferência: papel ARIA e nome acessível, caminho da rota, html[data-theme], html[data-motion], html[data-scene], [data-scene-poster], a chave localStorage hr.*.prefs por edição (e2e/support/site.ts prefsKeyFor). Sem coordenadas.
Padrões de prova:
- Exercite a rota e o controle reais, não um setter de store. Prefira o controle visível a edições de
localStorage; use o armazenamento apenas para configurar um estado inicial que o arquivo de funcionalidade nomeia. - Capture a ação e o estado após ela: um snapshot ARIA e uma captura de tela para a UI, o status da resposta e os cabeçalhos para verificações HTTP, o console e o log de solicitações com falha para cada direção.
- Um teste unitário ou spec e2e aprovado não é prova de um fluxo não exercitado. Marque a funcionalidade
Last live proof:apenas após o fluxo real ter sido executado, com data, commit e caminho da evidência. - Reporte um caminho inalcançável com a etapa tentada e a pré-condição não atendida. Não reporte um ponto de entrada ignorado como verificado através de outro.
Evidência
Diretório: $EVIDENCE_DIR, padrão $HOME/.verify-evidence/website/<run-id>/ onde <run-id> é <UTC timestamp>-<short HEAD>. Layout: doctor.txt, server.log (copiado de $RUN_DIR), depois <feature-id>/<step>.aria.txt, <step>.png, console.txt, network.txt. Após uma direção, adicione uma linha ao Last live proof: do arquivo de funcionalidade (data, commit, caminho da evidência) e uma linha ao ledger. Copie $RUN_DIR/server.log para o diretório de evidência antes de stop, porque stop remove $RUN_DIR. A evidência sobrevive à limpeza e nunca é excluída por esta skill.
Limpeza
.agents/skills/verify/scripts/serve.sh stop <port> mata apenas o PID em $RUN_DIR/server.pid (e os filhos que ele iniciou), então remove $RUN_DIR. Ele nunca mata pelo nome do processo e nunca toca em um processo que não iniciou. Ele deixa .next (um artefato de compilação que o checkout já ignora) e $EVIDENCE_DIR em paz. Se o arquivo PID estiver faltando, ele relata isso e não mata nada. Após uma execução com falha, execute-o antes de tentar novamente para que nenhuma porta permaneça ocupada.
$RUN_DIR é ${TMPDIR:-/tmp}/website-verify-<port>; ele contém apenas o arquivo PID e o log do servidor.
Ajudantes
scripts/doctor.sh [port]: a verificação somente leitura acima. Saída 0 saudável, 1 não vale a pena direcionar.scripts/serve.sh start <port>escripts/serve.sh stop <port>: lançamento e desmontagem acima.
Ambos são executáveis e usam apenas bash, curl, lsof, git e bun.