agents-lab

Local-first lab for reusable AI-agent primitives and the curated pi-stack.

View on GitHub

Monitor Overrides — Classifiers sem lock-in de provider

Para curadoria operacional de perfis/ruído/custo e rollout default-on, ver docs/guides/monitor-curation-master-plan.md.

Este guia cobre como manter os classifiers dos monitors funcionando ao alternar entre providers (ex.: GitHub Copilot ↔ OpenAI Codex) sem atrito.

Problema original

O @davidorex/pi-behavior-monitors publica classifiers com modelo bare:

model: claude-sonnet-4-6

Sem prefixo de provider, o runtime pode resolver para backend errado e os monitors podem ficar inativos sem erro visível.

No setup openai-codex, havia ainda uma falha adicional: classifiers sem prompt.system geravam payload com instructions vazio no backend Responses, resultando em:

No tool call in response (...) error: {"detail":"Instructions are required"}

Investigação base: 202604-pi-hedge-monitor-investigation. Issue upstream: davidorex/pi-project-workflows#1


Solução no @aretw0/pi-stack

A extensão monitor-provider-patch agora:

  1. mantém hedge.monitor.json com conversation_history desabilitado por padrão (opt-in);
  2. calibra fragility.monitor.json para contexto lean e trigger padrão has_file_writes (overrideável);
  3. resolve modelo de classifier por provider (defaultProvider + mapa configurável);
  4. garante overrides em .pi/agents/ para os 5 classifiers;
  5. auto-repara overrides legados sem prompt.system (compat com OpenAI Codex Responses);
  6. avisa quando overrides existentes divergem do provider/modelo atual;
  7. fornece comando /monitor-provider para diagnosticar e sincronizar.
  8. promove defaults distribuíveis de qualidade (nudge language-agnostic de verificação em commit-hygiene e work-quality) para *.instructions.json no session_start, sem depender de edição manual local.

Além disso, o pi-stack agora inclui a primitiva first-party monitor-sovereign (modo audit/shadow) para começar a convergência de semântica entre guardrails e monitores sem depender de runtime third-party para observabilidade básica.

Fonte distribuível vs override local

Higiene de versionamento (curated-default)

Para a baseline oficial, artefatos efêmeros de runtime devem ficar fora do git por padrão.

Checklist rápido:

  1. /safe-boot artifacts para inspecionar drift dentro do Pi;
  2. pnpm run pi:artifact:audit:strict no gate;
  3. se houver arquivo indevido rastreado, usar git rm --cached -- <path> (sem apagar cópia local);
  4. só versionar extras de monitor/runtime por decisão explícita de opt-in do projeto.

Perfil opt-in de economia de contexto

Monitores continuam baseline leves e provider-aware. Qualquer prática inspirada em squeez deve ser opt-in e mensurável:

mdt não participa da decisão de monitor: quando adotado, deve apenas checar drift de documentação/snippets de policy que descrevem os monitores.

Taxonomia rápida: warning de sessão vs issue de monitor

Quando o operador disser “o warning está atrapalhando a conversa”, assumir primeiro que ele está falando de warning runtime da sessão (notify/status), não de issue persistido.

Essa distinção evita falso positivo de diagnóstico e reduz ciclos de correção no lugar errado.

Comando principal

Convenção do laboratório: não criar “doctor” paralelo por domínio.
Use /doctor para saúde global do runtime e /monitor-provider para calibragem dos classifiers.

/monitor-provider status
/monitor-provider apply
/monitor-provider template

Defaults provider-aware

Defaults embutidos no patch:

Você pode sobrescrever via settings.

Configuração recomendada

Em .pi/settings.json (ou ~/.pi/agent/settings.json):

{
  "piStack": {
    "monitorProviderPatch": {
      "classifierThinking": "off",
      "classifierModelByProvider": {
        "github-copilot": "github-copilot/claude-haiku-4.5",
        "openai-codex": "openai-codex/gpt-5.4-mini"
      },
      "hedgeConversationHistory": false,
      "fragilityWhen": "has_file_writes"
    }
  }
}

Mapeamento prático (Claude → Codex)

Para manter classifiers no mesmo “tier” operacional:

Perfil anterior (Copilot/Claude) Perfil sugerido (Codex) Intenção
github-copilot/claude-haiku-4.5 openai-codex/gpt-5.4-mini sensor leve e barato
github-copilot/claude-sonnet-4.6 openai-codex/gpt-5.2-codex (ou gpt-5.4) sensor mais estrito

Regra simples: classifiers de monitor tendem a performar melhor com modelo “mini/leve” + thinking: off.


Guard vs Monitor (semântica única)

No laboratório, ambos devem compartilhar a mesma primitiva de trigger (when, tool(...), every(n)) e o mesmo modelo de fatos; muda apenas o modo de execução (enforce vs observe).

Política por modo de execução

Monitores devem proteger long-runs autorizadas sem virar uma segunda fonte de permissão redundante. A matriz abaixo é o default pragmático; perfis mais estritos são opt-in.

Modo L1 observe L2 advisory L3 enforce Monitores que podem ficar off Intenção
interactive-dev sim sim sim nenhum por default feedback rico durante desenvolvimento assistido
control-plane sim, com cooldown sim, sem interromper warn só risco real/autorização/custo/dados sensores ruidosos sem evidência nova manter o loop andando com status/audit claros
overnight/unattended sumarizado apenas em checkpoint/erro repetido budget, destructive/security, machine pressure, protected scopes nudges de estilo/qualidade não críticos rodar por muito tempo e parar só em risco/blocker real
subagent mínimo raro, agregado no retorno hard gates herdados do control-plane monitores conversacionais redundantes evitar que worker perca throughput por perguntas locais
swarm/colony agregado por run pós-run ou promotion gate budget/delivery/selective-promotion monitores por-turno que duplicam reviewer/soldier preservar governança sem multiplicar ruído por agente

Lease de autorização long-run

Uma long-run autorizada é válida enquanto os quatro sinais permanecem verdadeiros:

  1. loop/lane runtime está running e sem stop-condition bloqueante;
  2. board task/intenção canônica continua elegível e dentro do escopo permitido;
  3. budget/provider/machine gates seguem ok ou warn não bloqueante;
  4. não houve nova ação destrutiva, protected-scope, publish/CI/settings, ou dado sensível fora do contrato autorizado.

Enquanto esse lease estiver válido, monitores L1/L2 não devem reverter para confirmação do operador só por falta de contexto local. Eles podem registrar observe/advisory, mas interrupção fica reservada a L3/hard gates ou a checkpoint/compact lanes.

Perfil no-interrupt para loops longos

Em control-plane, overnight/unattended, subagent e swarm/colony:

Runbook de desligar/religar monitores

Config da primitiva first-party (.pi/settings.json):

{
  "piStack": {
    "monitorSovereign": {
      "enabled": false,
      "mode": "audit",
      "reportMaxEntries": 40,
      "startupNotify": false
    }
  }
}

Comandos:

/monitor-sovereign status
/monitor-sovereign on
/monitor-sovereign off
/monitor-sovereign enable <monitor-name>
/monitor-sovereign disable <monitor-name>
/monitor-sovereign refresh
/monitor-sovereign reset

Tools equivalentes (automação):

monitor_sovereign_control { action: "status|refresh|reset|on|off|enable|disable", monitor?: "hedge" }
monitor_sovereign_status { verbose?: true }
monitor_sovereign_delta {}

Evidência offline/repetível (sem sessão interativa):

pnpm run monitor:stability:evidence
pnpm run monitor:stability:evidence:write
pnpm run monitor:stability:gate
pnpm run monitor:stability:gate:strict
pnpm run subagent:readiness
pnpm run subagent:readiness:strict

Em sessão isolada sem @davidorex/pi-project-workflows, o comando /monitors não existe. Nesse caso, use /monitor-sovereign on|off para controle básico dos specs locais.

Classify failures e prontidão unattended

Classify failures de monitor devem ser tratados como sinal de prontidão, não como falha fatal imediata. Uma ocorrência isolada como No tool call in response é warning/advisory; repetição no mesmo monitor degrada prontidão de unattended; volume acima do limiar bloqueia strong unattended até correção.

A direção de pesquisa é reduzir dependência de LLM para steering: preferir classificadores sovereign/determinísticos, heurísticas locais e evidência estruturada; usar classifier LLM como fallback calibrado quando realmente agrega qualidade.

Superfície de apoio: monitor_classify_failure_readiness resume impacto sem mutação, sem dispatch e sem autorizar operação.

O instalador @aretw0/pi-stack também consegue sugerir um patch idempotente nos agents/templates de monitores existentes para alinhar o contrato: se o template fala em JSON, esse JSON deve ser tratado como argumentos de classify_verdict; não deve haver resposta em plain text/raw JSON fora da tool call. Por leniência com o usuário, isso não é aplicado automaticamente: o instalador apenas avisa quando há novo estilo disponível, e a aplicação exige opt-in explícito com --monitor-prompt-patch. Assim a correção é distribuível para usuários, mas mudanças em monitores locais permanecem autorizadas pelo operador.

Gate operacional de release (monitors)

Antes de qualquer publish RC/final:

  1. monitors-control on
  2. rodar smoke curto com provider alvo (mínimo 3 turns com eventos que acionem monitor)
  3. verificar monitors_compact_status e monitors-status
  4. bloquear publish se aparecer novo classify failed (especialmente Instructions are required)
  5. em caso de falha: /monitor-provider apply, /reload, repetir smoke

Critério de saída: runtime de monitor estável no provider alvo, sem novos classify failures durante o smoke.

Nota prática: pnpm run verify agora tenta auto-repair do contrato crítico de classify (systemPrompt: compiled.systemPrompt) em cópias divergentes de @davidorex/pi-behavior-monitors/dist/index.js antes de falhar. Além disso, no session_start, monitor-provider-patch aplica o mesmo reparo de runtime (best-effort) para reduzir drift após reinstalações.

Diagnóstico rápido de drift

Se você trocou provider e os monitors “sumiram”:

  1. Rode:

    /monitor-provider status
    
  2. Se houver divergência entre modelo resolvido e overrides atuais, rode:

    /monitor-provider apply
    /reload
    
  3. Confirme estado dos monitores:

    /monitors status
    

Projeto novo

Ao iniciar projeto novo com @aretw0/pi-stack:

  1. instalar stack (npx @aretw0/pi-stack --local);
  2. definir defaultProvider;
  3. configurar piStack.monitorProviderPatch.classifierModelByProvider;
  4. rodar /monitor-provider apply;
  5. /reload.

Assim você evita copiar .pi/agents entre repositórios e reduz lock-in de provider.