teqo-backup/docs/GUARDRAILS.md
Cursor Agent 1ad8863994
OPS12 — CI bloqueia Closes/Fixes em PR só docs/plans
- Lógica pura em plansOnlyClosesGuard.mjs + CLI check-plans-only-pr-closes
- Job plans-only-closes em ci-pr.yml (rollup checks)
- Unit tests com fixture do incidente #115
- plan-issue, agent-pr-workflow, PR template e GUARDRAILS atualizados

Closes #116

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 11:26:19 +00:00

10 KiB

Guardrails

Ledger dos guardrails determinísticos colhidos de kind:agent-miss (fluxo pnpm agent:file-miss → harvest no engineering-audit → guarda programática) e dos endurecimentos de guarda existentes. Uma linha por guarda: origem, classe na escada de determinismo, mecanismo, status.

Classes (escada do Pass 3 D6 / skill engineering-audit passo 4b): 1 tipo (estado ruim irrepresentável) · 2 ESLint · 3 spec de convenção · 4 análise estática em CI (knip/madge) · 5 pin comportamental · 6 doc/convenção (judgment-only declarado — não fingir que doc é guarda).

Ativos

Guarda Origem Classe Mecanismo Status
agent:ship exige stamp de /simplify casado com HEAD; PR Ready + auto-merge + watch até MERGED #83 3 (script + hooks) scripts/agent-ship.mjs, .cursor/hooks/guard-pr-create.mjs (bloqueia gh pr create manual), .cursor/hooks/pr-merge-watchdog.mjs (re-engata com PR aberto) vivo desde 2026-07-31 (PR #89); miss fechada no Pass 4
Alocador de municípios em specs — sem slug fixo + mutação; sem municipio=<slug> em e2e; regex de nome de catálogo ancorada #73 3 tests/unit/testMunicipalityAllocatorConventions.unit.spec.ts (3 regras; mutações = assign/touch/create*/payload.update municipality) PR #93 (Pass 4)
Sheet compartilhada por lista — chip cells exigem CampaignListSheetProvider; invariante dev no overlay #52 3 + 5 tests/unit/sharedSheetHostConventions.unit.spec.ts; console.error development-only em CampaignCellEditOverlay PR #94 (Pass 4)
Navegação e2e assentada — goto→goto sem settle falha o build #54 3 tests/unit/e2eNavigationConventions.unit.spec.ts (settle = await expect/waitForURL/click/reload/login/catch) PR #95 (Pass 4)
Readiness de autenticador virtual antes da cerimônia WebAuthn #53 3 mesma spec (spec com WebAuthn.addVirtualAuthenticator deve chamar expectCampaignBiometricsReady() PR #95 (Pass 4)
Convenção de navegação e2e (goto = cold load/contrato; in-shell = continuidade) #54 6 (judgment-only) parágrafo em docs/TESTING.md PR #95 (Pass 4)
Update de globals públicos nunca "qualquer autenticado" P0 do Pass 4 (sem issue) 3 tests/unit/globalAccessConventions.unit.spec.ts ban Boolean(user) em src/globals PR #91 (Pass 4)
Loaders de notificação tipados pelo ator (recipientID arbitrário irrepresentável) P0 adjacente do Pass 4 1 assinatura (payload, user: CampaignUser) + overrideAccess: false sob canReadOwnNotifications PR #91 (Pass 4)
Die-helpers da CLI importados onde usados; DAY_MS single-source P1 do Pass 4 (sem issue) 3 tests/unit/scriptCliConventions.unit.spec.ts PR #92 (Pass 4)
src/lib não type-importa @/utilities/** (direção única também para tipos) dodge do Pass 3 (suggestionCatalog) 2 ESLint no-restricted-imports allowTypeImports: false na zona src/lib PR #92 (Pass 4)
Local API com user sempre declara overrideAccess; import dinâmico de módulos server banido em utilities guarda ausente (medida baseline 59/0) 3 tests/unit/localApiOverrideAccessConventions.unit.spec.ts PR #92 (Pass 4)

Precedentes vivos (anteriores ao primeiro harvest)

Guarda Origem Classe Mecanismo
Vocabulário banido (Praça/Núcleo/Plano de Ação, accent-tolerant) C13 / W4f / P3-K 3 codebaseConventions.unit.spec.ts
server-only em utilities acopladas (sweep payload/next/*) Pass 2 W2 / P3-K 3 codebaseConventions.unit.spec.ts
Escadas de formActions nos wrappers (runCampaignFormAction/Redirect) W4d / C8 F4b 3 codebaseConventions.unit.spec.ts (filename *FormActions.ts — dodge actions/*.ts ledgerado)
Ratchet de bypass admin não documentado P3-E 3 codebaseConventions.unit.spec.ts (por arquivo, só diminui)
Mensagens de recusa como constantes + correspondência throw↔safelist P3-A 3 codebaseConventions.unit.spec.ts:216-263
as never banido Pass 1 2 ESLint no-restricted-syntax
src/lib não importa utilities/ (valores) Pass 2 W2 2 ESLint no-restricted-imports
0 ciclos de import Pass 2 4 madge (pnpm check:cycles)
Dead code (arquivos/deps/exports em erro) Pass 2 W4b 4 knip em CI
migration-lock (≤1 PR aberto tocando schema) agentes paralelos 4 job em ci-pr.yml
PR só docs/plans/ sem Closes/Fixes/Resolves #116 OPS12 4 scripts/lib/plansOnlyClosesGuard.mjs + scripts/check-plans-only-pr-closes.mjs + job plans-only-closes em ci-pr.yml
Seed mínimo obrigatório com migration (contrato manifest) OPS fluxo PR 3 + 5 tests/unit/seedMinimalManifest.unit.spec.ts + job CI migrate→seed→int
Regex de template ancorada em e2e P3-C 3 codebaseConventions.unit.spec.ts (ampliada para literais no Pass 4)
Consent fail-closed por chave estável D3/Onda 0 5 pins int submitWhatsapp/liderança/apoiador

Misses colhidas aguardando guarda (fila do harvest)

(nenhuma — todas as 5 abertas em 2026-07-31 foram classificadas: 4 com guarda shippada + 1 com guarda já viva. Novas kind:agent-miss entram aqui até o próximo audit.)