Component Bug Discovery — dogfooding incident → ticket → conditional fix → signal-back
Quando uma sessão (qualquer IA da Stack) está USANDO uma instância instalada/em-execução de um componente Koder (ex.: um `kflow`, `kdb`, `kvs` instalado; um binário/CLI/daemon Koder) enquanto faz trabalho não-relacionado, e identifica um DEFEITO nesse componente (crash, saída errada, commit perdido, arquivo corrompido, regressão, perf cliff), ela é o sensor com o **contexto forense mais rico do instante**. Esta policy torna a resposta um reflexo único: SEMPRE registrar um ticket forense; e então, segundo houver ou não **lock duro** ativo, ou corrigir agora (se cabível) ou abrir o ticket + alerta de dependência + esperar o sinal-back do fixer. Costura peças que já existiam (lock-carve-out, blocked-work-monitor, broadcast-alerts, regression-tests, backlog `blocked-by`) num fluxo só.
As IAs da Stack dogfoodam os componentes Koder o tempo todo: editam repos através de um kflow instalado, consultam um kdb rodando, commitam via kvs. Quando uma delas tropeça num defeito do próprio componente, ela está no ponto de maior contexto possível — sabe o que estava fazendo, o que quebrou, e o blast-radius imediato. Largar só um "deu erro" desperdiça isso; e ficar em silêncio deixa a próxima sessão repetir o tropeço. Esta policy converte cada IA num sensor ativo de regressão: a descoberta vira um ticket forense e, quando ela depende do fix, uma dependência rastreável com sinal-back — sem serializar à toa o que o KVS#202 já tornou seguro fazer em paralelo.
R1 — Quando dispara
Sempre que, usando uma instância instalada ou em-execução de um componente Koder (não editando o código-fonte dele — consumindo o componente), a sessão observar um comportamento que é um defeito do componente, não da própria tarefa:
- crash / panic / exit não-zero inesperado;
- saída errada, corrupção de dado, commit perdido, *rquivo do repo
corrompido* índice inconsistente (típico da janela de soak do
kvs); - regressão vs. comportamento anterior, perf cliff, deadlock, vazamento;
- violação de invariante documentada do componente.
Não dispara para: erro de uso da própria sessão (config errada minha), bug no código que estou editando (isso é a tarefa normal), ou indisponibilidade de infra (rede/host — isso é incidente de ops, não bug de componente).
R2 — SEMPRE registrar: dois tiers de captura
Todo defeito observado é registrado — mas o peso do registro depende do tier. Exigir o ensaio forense completo (as 6 seções abaixo) para todo evento é um erro de design: a maioria dos defeitos de soak de um forge/store concorrente (kvs) são races recuperadas de alta frequência (CAS-retry, lost-update suspect que o #208 já re-mergeou, orphan reconciliado). Pedir um ensaio à mão por CAS-retry é caro demais → a sessão dropa todos em silêncio, inclusive os que importam. O conserto é separar os tiers:
R2.a — Tier 1: evento mecânico/recuperado de alta frequência → captura por telemetria
Race recuperada, lost-update suspect já re-mergeado, orphan reconciliado, retry de CAS — eventos onde o componente já se recuperou e o valor forense de cada ocorrência individual é baixo, mas o padrão agregado é o que o gate de soak precisa. Para estes, a captura é determinística pela telemetria do próprio componente (ex.: kvs wc stats linha 3a — orphaned kvs commits, #209), agregada num registro rolante — não um ticket forense à mão por ocorrência. A sessão não para para escrever ensaio; o bridge telemetria→registro (tool- agnóstico, dentro do componente — não um hook de um harness específico) faz a captura para toda IA e para o CI. Porém: se a telemetria do componente ainda não captura essa classe de evento, isso é um gap de instrumentação → a sessão registra como Tier 2 (o ticket nomeia "instrumentar X em <stats>").
R2.b — Tier 2: defeito novo / não-recuperado → ticket forense completo
Defeito novo, não-recuperado, perda real de dado, corrupção, regressão, crash, deadlock, violação de invariante — qualquer evento cujo contexto a telemetria mecânica não carrega (D11 debuggability). Aqui o ticket forense completo continua obrigatório e imediato, pela sessão descobridora, em <component>/backlog/pending/NNN-...md. Inserir ticket novo é operação collision-free — permitida mesmo sob lock duro de outra sessão (lock-carve-out.kmd R2), então nunca há razão para não registrar.
Regra de não-rebaixamento: a ausência de um stream Tier-1 automatizado não rebaixa um evento Tier-2 ao silêncio. Na dúvida sobre o tier, trate como Tier 2 (registre o ticket). "A telemetria devia ter pego" nunca é desculpa para não registrar um defeito que ela não pegou.
O ticket Tier-2 captura o contexto forense enquanto ele ainda existe (seções obrigatórias):
- Sintoma — o que foi observado, verbatim (mensagem, hash sumido, path
corrompido).
- Contexto de uso — o que a sessão fazia no instante (comando, tarefa,
componente consumido, versão/instância:
kflow version, container, host). - Repro — passos mínimos, se já dá pra isolar; senão, o estado bruto.
- Causa-raiz provável — a melhor hipótese da descobridora, com a evidência
que ela vê agora (não adivinhação vazia).
- Consequências / blast-radius — o que mais foi (ou pode ter sido) afetado:
outras sessões, outros commits, dados a jusante.
- Caso de regressão — o teste que falha sem o fix (
regression-tests.kmdobriga teste por bug; capturar o caso falho agora, quando é mais barato).
Use o prefixo do componente (registries/ticket-prefixes.md) ao referir-se ao ticket cross-stack.
R3 — Decisão corrigir-ou-esperar — chaveada por LOCK DURO (não por "tem outra IA ali")
Premissa KVS#202 (lock advisory por default,
kvs wc commitpath-scoped com merge AST): edição concorrente no mesmo componente é segura. O gatilho da bifurcação NÃO é "outra sessão está mexendo no componente" (quase sempre está, e tudo bem) — é se há um lockexclusivity: hardativo (migraçãorebrandrelease), perlock-carve-out.kmdR1.
R3.a — SEM lock duro ativo (caso comum) → corrija se cabível
Edição é segura. Decida pelo custo de context-switch, não pela presença de outras sessões:
- Bug pequeno / dentro do contexto da tarefa atual → corrija agora: fix +
teste de regressão +
kvs wc commit -- <paths>(path-scoped) + push + mova o ticket paradone/. Depois retome sua tarefa. Este é o caminho default do dogfooding (a descobridora é quem melhor entende o bug agora). - Bug grande / fora de escopo (corrigir desviaria muito da tarefa atual) →
deixe o ticket forense (R2) detalhado em
pending/e siga sua tarefa. Não pague o context-switch caro. Outra sessão (ou um/k-gono componente) pega o ticket depois.- Exceção — você depende do fix para continuar: se a tarefa atual *não
avança* sem o fix, "seguir" não é opção. Como não há lock duro, o caminho mais barato ainda é você mesma corrigir (está livre para editar). Só caia no R4 (esperar) se houver razão concreta para não corrigir (ex.: o fix exige expertise/recurso que você não tem agora).
- Exceção — você depende do fix para continuar: se a tarefa atual *não
R3.b — COM lock duro ativo → NÃO edite; vá para R4
Sob lock exclusivity: hard, editar o código-fonte do componente é proibido mesmo com autorização (lock-carve-out.kmd: buildtestdeploy/edição de src,lib,pkg,cmd,internal nunca entram em carve-out). O ticket forense (R2) já está registrado. Se você depende do fix, siga o R4. Se não depende (notou o bug mas sua tarefa avança sem ele), basta o ticket — a sessão dona do lock duro, ou a próxima, resolve.
R4 — Caminho esperar-e-sinalizar (dependo do fix e não posso/não devo corrigir)
Quando a tarefa atual depende do fix e corrigir você mesma não é o caminho (lock duro ativo, ou bug fora do seu alcance agora):
- Ticket forense (R2) já está em
pending/. - Marque sua própria tarefa/ticket com
blocked-by: <COMPONENT>-NNNapontando para o ticket do bug (Rule 10 do
/k-go;backlog.kmd). É dependência de ticket, nãogated_by:(não é condição externa fora do backlog — é outro ticket que alguém vai implementar). - Emita um alerta de broadcast
kind: bug-depemmeta/context/notices/active/<slug>.md(broadcast-alerts.kmd) declarando: o componente, o ticket do bug, e que você depende dele para prosseguir.priorityalta (7–8),audience: all,component: <component>. Isso faz toda sessão que tocar o componente ver que há um fix pendente bloqueando trabalho real — e dá ao fixer o handle para o sinal-back (R5). - Arme o blocked-work-monitor (
blocked-work-monitor.kmd: watcherlaptop-side com TTL + ping durável koder-notify), ancorado no sinal de pronto: o ticket do bug movido para
<component>/backlog/done/OU o alertabug-depvirandostatus: done.
R5 — Sinal-back do fixer
Quem pegar o ticket do bug (numa sessão de /k-go no componente, ou a própria dona do lock duro ao terminar a wave dela), ao concluir a correção — fix + teste de regressão verde + push + ticket movido para done/ — deve sinalizar de volta:
- Flipar o alerta
bug-deporiginal parastatus: done(1 linha nofrontmatter). É o sinal explícito que re-aciona a descobridora.
- Se o fixer não vê nenhum alerta
bug-dep(a descobridora não emitiu, ou jáarquivou), mover o ticket para
done/basta — o monitor da descobridora também ancora nisso. Os dois sinais são redundantes de propósito.
O fixer não precisa atualizar a instância instalada da descobridora — isso é responsabilidade dela (R6). O sinal-back diz "o código está corrigido em origin/master", não "sua instância foi atualizada".
R6 — Retomada da descobridora
Quando o monitor re-invoca a sessão (sinal de pronto disparou):
- Atualize a instância instalada do componente para a versão com o fix
(rebuildreinstallupgrade — ex.:
/k-reinstall <slug>, ou redeploy se for um serviço; trabalho pesado fora do laptop perheavy-work-isolation.kmd). - Re-valide que o bug sumiu de fato (rode o caso de R2). Só então retome a
tarefa original.
- Se o bug persistir após o upgrade → reabra o ticket (de
done/parain-progress/) com a nova evidência e re-arme o ciclo (R4). Não retome em cima de um fix que não pegou. - Higiene: arquive o alerta
bug-dep(mvparanotices/archive/) — umalerta
status: donenão é exibido, mas arquivar fecha a trilha.
Worked example — commit perdido na janela de soak do kvs
Sessão A, editando engines/kodec, commita via kvs wc commit. Dois turnos depois nota que aquele commit sumiu do origin/master (regressão do soak
201).
- R2 → abre
products/dev/kvs/backlog/pending/NNN-soak-commit-loss-...md:sintoma (hash X ausente, era ancestral de Y), contexto (
kvs wc commit -- <paths>às HH:MM, versãokvs vN), repro/estado, causa-raiz provável (race no temp-index / CAS no ref?), consequências (o trabalho de A nesse path; possíveis outros commits da janela), caso de regressão. - R3 →
kvsestá com lock duro? Em geral não (advisory). Se A consegueisolar a causa e é pequeno → corrige (R3.a) e fecha. Se é grande e A depende da correção do
kvspara confiar nos próprios commits → como não há lock duro, A ainda é quem melhor entende; corrige se conseguir. - R4 (só se houver lock duro de release no
kvs, ou se A não tem comodiagnosticar o race agora) →
blocked-byna tarefa do kodec + alertabug-dep(priority 8) + monitor. - R5/R6 → o fixer do
kvsfecha o ticket + flipa o alerta; A re-instala okvs, re-commita o trabalho perdido do kodec, retoma.
Por que (testes)
- T1 — Ao perceber um defeito numa instância de componente em uso, a sessão
abre um ticket forense antes de prosseguir ou de pedir input. Verificável: o turno contém a criação do
<component>/backlog/pending/NNN-...mdcom as seções de R2. - T2 — O ticket forense carrega contexto-de-uso + causa-raiz-provável +
consequências (não só "deu erro"). Verificável: as seções existem e são específicas.
- T3 — A decisão corrigir-vs-esperar é chaveada por lock duro, não por
"tem outra sessão no componente". Verificável: sem lock duro, a sessão corrige (ou segue) em vez de esperar; só espera sob lock duro ou impossibilidade real.
- T4 — Quando a sessão depende do fix e espera, ela usa
blocked-by:(ticket-dep), não um
gated_by:novo, e emite alertakind: bug-dep+ arma o monitor. Verificável: os três artefatos aparecem. - T5 — O fixer, ao fechar o ticket, sinaliza de volta (flip do alerta
para
status: doneeou ticket → `done`). Verificável: o sinal existe. - T6 — A descobridora atualiza a instância e re-valida o sumiço do bug
antes de retomar — nunca retoma em cima de um fix não-verificado. Verificável: o passo de upgrade + re-validação aparece na retomada.
- T7 — A captura é tier-aware (R2.aR2.b): evento mecânicorecuperado de
alta frequência é captado pela telemetria do componente (não exige ticket à mão por ocorrência), enquanto defeito novonão-recuperadoperda-de-dado exige o ticket forense Tier-2. Verificável: um soak com N races recuperadas não gera N tickets à mão (gera rollup de telemetria), mas a 1ª perda real gera o ticket Tier-2. A ausência do stream Tier-1 nunca silencia um Tier-2 (regra de não-rebaixamento).