Gates
Ciclo de vida de todo gate de conformância na Koder Stack: como um check vira gate, o budget de falso-positivo obrigatório, o escape hatch auditado e a demoção automática. Operacionaliza stack-RFC-014 R3–R5. Um gate só recebe `block` depois de soak advisory→warn; todo `block` carrega `fp_budget`; estourar o budget demove pra `warn` e abre ticket de recalibração no componente dono. Sem esta policy, gates viram cultura de bypass.
Document format reference: meta/docs/stack/policies/document-format.kmd
Esta policy fecha a fase 4 da
stack-RFC-014. Ela não define a linguagem de regras (Kanon, RFC-015) nem constrói o wiring no/k-commit(ticket keystone) — ela define como um gate se comporta para que o wiring possa ser conformante. Sem ela, ligar umblockno choke point seria, ironicamente, não-conforme à própria RFC que o pede.
1. O problema que esta policy resolve
A Stack tem o motor (koder-spec-audit avalia Kanon; bindings --exec roda o verify_by de uma cláusula) e specs que declaram seus gates (kanon_bindings). O que faltava: a disciplina de ciclo de vida de um gate. Um gate ligado em block sem budget de falso-positivo, sem override auditado e sem demoção automática ensina cultura de bypass — a primeira vez que reprova um caso legítimo, a sessão aprende a contornar (--no-verify), e o gate inteiro perde confiança. Gate bom protege; gate ruim treina evasão.
2. O reticulado de dureza
advisory (1) < warn (2) < block (3) — a escala de GateLevel do Kanon. Um gate só aperta ao longo de uma aresta refines (filho nunca afrouxa o do pai — provado por koder-spec-audit refines, finding kanon-gate-loosen).
- advisory — registra o finding; não interrompe nada. Estado de nascimento.
- warn — visível e ruidoso; não interrompe. Estado de soak.
- block — interrompe a ação (commit/CI). Só depois de soak limpo.
3. Ciclo de vida de um gate
nasce advisory → soak (coleta findings reais, calibra FP) → warn → soak limpo → block
↑ │
recalibração ←──┴── estourou fp_budget ─┘ (demoção R5)Promover é decisão de evidência, não de vontade: um gate vira block quando o soak em warn mostra findings reais e zero falso-positivo confirmado dentro do budget. Estourar o budget reverte o caminho.
4. Requisitos normativos (Kanon)
Requirement: Block carrega budget
Todo binding com gate: block SHALL declarar fp_budget (default: 2/30d — dois falso-positivos confirmados por 30 dias). FP confirmado = override registrado cuja justificativa a triagem aceita. *(Já enforçado estruturalmente pelo motor: koder-spec-audit bindings → kanon-block-without-budget.)*
Requirement: Escape hatch auditado
Todo gate block SHALL ter override de um comando que registra ator + motivo + diff em log versionado. Override silencioso (--no-verify cru) em path coberto por um gate é, ele próprio, drift detectável — não um escape legítimo.
Requirement: Demoção automática
Gate que estoura seu fp_budget SHALL ser demovido automaticamente a warn e abrir ticket de recalibração no componente dono. Demoção preserva a confiança no conjunto: um gate ruim não fica reprovando, ele volta pra soak.
Requirement: Promoção com soak, nunca block-direto
Gate novo SHALL nascer advisory, passar por warn, e só então promover a block. Ligar block direto (sem soak que calibre o FP) é o anti-padrão que gera o primeiro bypass.
5. O ledger de gates
Os budgets, overrides registrados e contagem de FP por gate vivem num ledger versionado (registries/gates.md — criado pela fatia de wiring do /k-commit, RFC-014 fase 1). O ledger é o que a demoção automática (R5) consulta. Enquanto o ledger não existe, gates ficam em advisory/warn (sem block), porque block sem ledger não tem como honrar a demoção.
6. Não-objetivos
- Definir a linguagem de regras — é a
stack-RFC-015(Kanon); esta policyconsome os bindings, não os define.
- Construir o gate no
/k-commit— é o ticket keystone (RFC-014 fase 1); estapolicy é o contrato que aquele wiring obedece.
- Substituir o gate de regressão (
koder-test-gate) ou o de ícones(
kicon --check) — esses já são gates conformes; esta policy os generaliza sob um ciclo de vida único.