agents-lab

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

View on GitHub

Pipeline canônico de posteridade (.project-first)

Objetivo: preservar contexto de forma durável e retomável com baixo custo.

Skill distribuída: práticas recorrentes deste guia são resumidas em packages/lab-skills/skills/control-plane-ops/SKILL.md para que o contrato board-first/long-run viaje com a stack, não apenas com a documentação local.

Regra principal

  1. Canônico primeiro: atualizar .project/*.
  2. Derivados depois: HANDOFF.md (delta curto) e ROADMAP.md (macro).

Diretriz de arquitetura (primitivas + adapters)

Matriz operacional mínima de equivalência

Camada de hard intent (independente de storage)

Onboarding dual-mode (sem migração forçada)

Use este framing com usuários novos:

  1. Modo A — .project-first (canônico local)
    • melhor quando o usuário quer governança integrada no workspace;
    • estado oficial em .project/*.
  2. Modo B — adapter-first (sistema do usuário)
    • melhor quando o usuário já opera em outro sistema (Markdown/Obsidian, DB/API, automação/web);
    • o agente trabalha junto do sistema existente, sem impor migração total.
  3. Modo C — canônico + espelho do operador (opcional)
    • o estado oficial continua em .project/*;
    • um adapter projeta esse estado para Markdown renderizável (ex.: Obsidian/vault);
    • referência inicial de template: https://github.com/aretw0/vault-seed.

Invariantes em ambos os modos:

Estratégia de longo prazo para .project

.project é o adapter local-first atual, não o destino final obrigatório. O papel correto dele é preservar semântica operacional enquanto outros adapters amadurecem. A regra de longo prazo é: semântica canônica primeiro, storage substituível depois.

Papéis do .project

Hard intent vs soft evidence

Trate .project como hard intent local quando a ação for fechamento de task, handoff de continuidade, verificação de gate, foco de uma fatia local ou replay de sessão dentro do workspace atual. Nesses casos, use superfícies bounded (board_task_create, board_update, board_task_complete, context_watch_checkpoint) e evite scripts ad hoc.

Trate .project como soft evidence quando houver outro sistema explicitamente escolhido pelo usuário, quando o dado veio de espelho externo, quando o foco estiver stale, quando houver múltiplos escritores ou quando a sessão estiver em modo remoto/CI/colony sem ownership claro. Soft evidence pode orientar seleção e diagnóstico, mas não deve fechar task, disparar executor nem decidir conflito sozinho.

Modos de trabalho e ownership

Modo Leitura Escrita permitida Regra de conflito
Agente único local .project é adapter canônico local board/handoff/verification bounded git diff esperado + checkpoint fresco
Múltiplos agentes locais .project é shared evidence um owner por task/fatia; outros só append evidence conflito vira checkpoint/ask, não overwrite
Worktree/colony espelho por worktree ou merge controlado artifacts locais + promoção seletiva reconciliar por task/evidence, nunca por merge cego
Remote/offload .project é contrato de entrada/saída report/artifact primeiro; apply só com canal autorizado delivery gate decide promoção
GitHub Actions/CI .project é snapshot/gate evidence preferir comments/artifacts; escrita direta só por política PR/MR revisável antes de canônico
Issue tracker externo .project é adapter/cache sync por mapeamento task/event/evidence tracker pode ser fonte hard se escolhido explicitamente
Markdown/Obsidian inbox/espelho do operador captura/projeção, não fechamento estratégico promover para task só via decision gate

Regras para não virar ruído

  1. Um agente não deve tratar stale focus como autoridade; completed/stale precisa cair para diagnóstico.
  2. Board/handoff são hot path; blocos amplos são contexto, não motivo para varredura recorrente.
  3. Escrita em .project deve ser pequena, auditable e ligada a uma fatia; se exigir migração/sync, vira tarefa própria.
  4. Em paralelismo, prefira append evidence ou task ownership explícito; evite reordenar/reescrever o board inteiro.
  5. .project não deve bloquear agente que opera em adapter externo escolhido; nesses casos ele registra espelho/handoff mínimo.
  6. Antes de executor, repetition ou scheduler dependerem de .project como autoridade, o modo de ownership e stale evidence precisa estar explícito para aquela lane.

Compatibilidade futura

A saída de .project não é “remover”, é tornar substituível. Todo adapter futuro deve preservar task/event/intent/evidence, decisionGate, verificação antes de conclusão e replay idempotente. Quando um backend externo virar fonte hard intent, .project passa a cache local ou espelho de recuperação, com sync auditável e conflito fail-closed.

Modo de entrega multi-ambiente (native/container/CI)

Para calibrar execução contínua entre máquina local, container e CI:

GitHub Actions (modo fábrica guardado)

Budget de reinflação do orchestrator (guardrails-core.ts)

Para manter a stack pronta para usos simples e avançados sem acoplamento opinativo:

Hatch progressivo (simple-first)

Para primeiro contato de sessão/projeto, o hatch deve começar em trilha simples:

Checklist de release/dogfooding (portabilidade da fábrica)

Antes de promover hardening interno como capability da pi-stack:

  1. Separar canônico vs local: confirmar que a melhoria está em primitivas/adapters (não em convenção exclusiva do laboratório).
  2. Native-first por padrão: quando existir primitiva first-party (ex.: steer/follow-up), ela deve ser default; convenções extras ficam opt-in.
  3. Governança preservada: manter no-auto-close, verification gate e budget discipline em qualquer interface/runner.
  4. Evidência de portabilidade: registrar no board ao menos 1 verificação (inspect/command/test) provando que o ganho é reutilizável fora do agents-lab.
  5. Rollback explícito: documentar fallback seguro caso a promoção aumente ruído, custo ou acoplamento.

Loop operacional (5-10 min)

  1. Capturar mudanças no board canônico:
    • decisions, requirements, tasks, verification, handoff.
  2. Rodar higiene:
    • pnpm run project:verification:check
    • /safe-boot artifacts (ou pnpm run pi:artifact:audit:strict no gate)
    • project-validate
    • project-status
  3. Atualizar derivados:
    • HANDOFF.md com apenas delta operacional.
    • ROADMAP.md com direção macro (sem estado diário).
  4. Fechar sessão com WIP=1:
    • manter uma frente ativa em in-progress por sessão.

Template rápido (copiar/colar)

1) Decisão (decisions)

2) Requisito (requirements)

3) Task (tasks)

4) Verificação (verification)

Soft intent vs Hard gate de qualidade

Monitores por modo de execução

Long-runs precisam de monitores como trilho de confiança, não como fricção de permissão repetida. Política resumida:

Lease válido de long-run = loop running + task/intenção elegível + budget/provider/machine seguros + escopo autorizado. Enquanto o lease valer, monitores não devem pedir confirmação redundante; devem auditar ou agregar sinal. Runbook completo: docs/guides/monitor-overrides.md#política-por-modo-de-execução.

Adapters de mensageria fora da TUI/Web

Canais como Telegram podem operar o control plane como UI degradada, não como nova fonte de verdade. Capability map mínimo:

Capacidade TUI/Web Telegram/message adapter
Status curto, gates, quota e máquina suportado suportado com resumo bounded
Acionar loop/checkpoint/task selecionada suportado suportado via intent canônico auditado
Revisão rica de diffs/logs longos suportado degradado; enviar link/resumo e cair para TUI/Web quando necessário
Editar board diretamente não recomendado não suportado; usar board_query/board_update/intents
Fechar task estratégica/no-auto-close suportado com verification degradado; exigir decision packet + confirmação explícita

Todo adapter remoto deve preservar budget/delivery gates, registrar evidência em tasks/verification/handoff, e tratar truncamento/atraso de mensagem como motivo para fallback local em vez de decisão silenciosa.

Soft/hard intent de internacionalização

Política no-obvious-questions no loop canônico

Para manter velocidade de cruzeiro em long-run:

Perfil opt-in de economia de contexto

O baseline permanece agnóstico e simples: board canônico, handoff curto, gates locais e monitores calibrados. Otimizações inspiradas em squeez devem entrar como perfil opt-in de economia de contexto, com os seguintes limites:

Sinais de oportunidade de economia devem ser passivos e pouco ruidosos: status/telemetria curta que indique repetição de tool-output, handoff grande demais, evidência re-lida após compactação ou lista de next-actions truncada. O sinal deve sugerir “economizar no próximo slice” sem forçar compactação nem esconder evidência canônica. Influências como squeez entram assim no dia a dia: output shaping, dedupe e checkpoints sintéticos como prática incremental, sempre medidos contra retomada correta.

O context_watch_status expõe autoCompact.contextEconomy / contextEconomySummary como sinal passivo. Exemplos de oportunidades: next-actions-truncated, large-handoff, many-next-actions e resume-prompt-truncated. Esses estados são info/telemetria: não mudam o gatilho de compactação, não bloqueiam o loop e servem para melhorar o próximo checkpoint/status.

Cadência de tools diagnósticas

No hot path do executor, evitar chamar pacotes de status por hábito. context_watch_status, machine_maintenance_status, quota/provider/monitor/session analytics e similares devem ser usados quando há fronteira ou sinal: pós-/reload, seleção de task, pré-long-run, checkpoint/near-compact, erro/pressão, ou pedido explícito. A primitiva resolveToolCadenceDecision formaliza a regra: board surfaces bounded continuam no caminho canônico; diagnostic packs ficam reservados para troubleshooting. Depois que um sinal estiver calibrado, confiar no steering passivo e reabrir diagnóstico só quando o sinal pedir.

A adoção eventual de mdt fica separada: é trilha de doc-drift/single-source docs (check primeiro, update depois), não pipeline de ideias/backlog.

Mapa de influências (Squeez + MDT + Impeccable)

Regra prática: influência externa só entra quando vira primitive/checklist pequena, mensurável e reversível. Referência de síntese bounded: docs/research/impeccable-style-influence-2026-04.md.

Governança de updates de dependências pi/extensões

Atualizações de pi, extensões e skills devem seguir trilha determinística antes de entrar no baseline local-first:

  1. Detectar: registrar versão atual, versão candidata, changelog/fonte e escopo afetado (runtime, tool, monitor, docs, package).
  2. Canário controlado: aplicar em escopo isolado ou janela curta, rodar gate focal (test:monitor:smoke ou smoke específico) e comparar sinais de memória/storage/throughput quando a mudança impactar long-run.
  3. Decidir: promover, manter em hold/deny, ou reverter. A decisão precisa citar evidência mínima: comando/teste, impacto operacional e plano de rollback.
  4. Assimilar first-party quando fizer sentido: se a dependência externa aumentar risco/custo/complexidade ou bloquear continuidade, abrir proposta de assimilação parcial/total com migração reversível, API mínima e teste de compatibilidade.

Durante overnight/unattended, updates ficam em hold por default; o loop pode continuar com a versão corrente, registrando a oportunidade no board em vez de quebrar uma execução ativa.

Storage pressure antes de long-run

Long-runs maiores só são confiáveis quando o ambiente ainda tem folga de armazenamento. Antes de lote grande, ou quando o host estiver perto do limite, usar o gate dry-first:

pnpm run ops:disk:check
# equivalente: node scripts/host-disk-guard.mjs

Contrato atual:

Evitar diagnósticos ad-hoc amplos (du/grep/find sobre C:, home, node_modules, AppData) durante long-run: preferir host-disk-guard e comandos focais com limite de saída.

Discoverability operacional da lane-queue

Política operacional atual: native-first.

Durante long-run:

Retry resiliente para overload/rate-limit de provider

Para preservar continuidade em long-run diante de erros transitórios (server_is_overload, 429, 5xx):

Configuração (.pi/settings.json):

{
  "piStack": {
    "guardrailsCore": {
      "longRunIntentQueue": {
        "dispatchFailureBlockAfter": 3,
        "rapidRedispatchWindowMs": 300000,
        "dedupeWindowMs": 120000,
        "identicalFailurePauseAfter": 3,
        "orphanFailurePauseAfter": 1,
        "identicalFailureWindowMs": 120000,
        "orphanFailureWindowMs": 120000,
        "providerTransientRetry": {
          "enabled": true,
          "maxAttempts": 10,
          "baseDelayMs": 2000,
          "maxDelayMs": 60000,
          "backoffMultiplier": 2
        }
      }
    }
  }
}

Notas operacionais:

Configuração operacional sem editar JSON manualmente

Para ajustes frequentes de runtime (long-run queue + autonomia pragmática), preferir comando dedicado:

Exemplos:

Contrato:

Roteamento determinístico de shell por host (evitar tentativa-e-erro)

Para reduzir falhas de execução por mismatch de shell/PATH, o guardrails-core aplica perfil de host em runtime.

Contrato inicial (hard-pathway):

Objetivo: transformar um soft-intent operacional em comportamento previsível e reproduzível, sem depender de acerto manual do agente.

Macro-APIs determinísticas (roadmap de refactor)

Para reduzir edição “na unha” em fluxos repetitivos, priorizar superfície macro com contrato estável:

Contrato mínimo:

Implementação incremental atual:

Referência de contrato inicial: docs/research/task-bud-144-macro-api-contract-2026-04-24.md.

Mutação segura para arquivo grande e query estruturada (roadmap)

Para operações de maior risco (arquivo extenso / SQL), usar pathway dedicado com preflight explícito.

Contrato mínimo:

Implementação incremental atual:

Referência de contrato inicial: docs/research/task-bud-145-safe-mutation-structured-query-contract-2026-04-24.md. Evolução planejada para I/O estruturado centralizado (loam-inspired): docs/research/task-bud-149-structured-io-loam-bridge-2026-04-25.md.

Steering signal-first (tool-surface diet)

No loop canônico, steering diário deve priorizar sinais passivos de stream/status (ex.: warn/checkpoint/compact, operatorSignal) em vez de depender de tool-call manual.

Regras operacionais:

Implementação atual (slice 2/4):

Referência de contrato inicial: docs/research/task-bud-146-context-steering-signal-invariant-2026-04-24.md.

Nota operacional (atalhos): o pacote pi-workflows registra Ctrl+H para solicitar pause de workflow. Em alguns terminais, Ctrl+Backspace envia Ctrl+H; isso pode disparar pause acidental com a mensagem “Pause requested — workflow will pause after current step completes.”.

Bloat-smell advisory (calibrado, baixo ruído)

Objetivo: preservar throughput de fábrica sem inflar resposta/código em silêncio.

Regras operacionais:

Pipeline de galvanização (repetitivo -> hard pathway)

Objetivo: reduzir consumo recorrente de LLM sem perder governança.

Fluxo canônico:

  1. Descobrir padrões repetitivos com evidência de consumo (tokens/cost/requests) via analytics (session_analytics_query tipo galvanization).
  2. Classificar e ranquear oportunidade por frequência + gasto observado (determinístico, advisory).
  3. Propor pathway hard por candidato com gates explícitos:
    • equivalência funcional em fixture representativo;
    • rollout em dry-run com rollback imediato;
    • verification passed antes de promover default.
  4. Roadmap de mitigação registra baseline vs pós-automação projetado (tokens/cost/requests) para priorização, sem implementar hardening prematuro fora da lane ativa.

Governança de sinais (ownership + noise-budget)

Objetivo: manter discoverability útil sem sobrecarregar o operador com sinais concorrentes.

Ownership mínimo por classe:

Regras de noise-budget (advisory):

Meta-sinal de ruído excessivo (advisory):

Governança de board em worktrees/sessões paralelas

Política padrão: single writer canônico para .project/tasks.json e .project/verification.json. Worktrees/subagentes podem propor mudanças, mas a sessão control-plane principal aplica via board_query/board_update ou etapa gerada/revisada.

Quando houver mais de um writer potencial:

Fluxo pós-worktree recomendado:

  1. worker entrega diff/patch ou resumo gerado, sem assumir posse do board canônico;
  2. control-plane compara mtime/branch e aplica update canônico com lock+atomic;
  3. valida board_query/verificação focal;
  4. commit inclui board apenas se a promoção foi intencional.

Mirror externo (GitHub/Gitea) sem perder board canônico

Entidades externas são mirrors, não autoridade principal, salvo política explícita por projeto.

Contrato de sync:

Contrato de conflito:

Contrato de promoção seletiva (worktree -> main)

Quando o delivery mode estiver em apply-to-branch, a evidência de conclusão deve explicitar seleção de escopo:

Regras operacionais:

Guardrail de scan-bounds no loop longo

Em sessões com context_watch em warn/checkpoint/compact:

  1. Warn: somente investigação bounded-by-default (sem busca ampla em logs/sessions).
  2. Checkpoint: handoff canônico obrigatório antes de novo diagnóstico.
  3. Compact: parar investigação, compactar e retomar do handoff.

Checklist operacional rápido:

Proxy/index incremental para superfícies grandes (simple-first)

Para sustentar long-runs com baixo custo de contexto, usar query surfaces antes de leitura crua.

Ordem operacional recomendada:

  1. Board canônico (.project/*)
    • preferir operações estruturadas (append/update/query) em vez de abrir blocos inteiros;
    • para loops de tarefa/verificação, usar superfície dedicada (board_query, board_update) com resposta curta e cache incremental;
    • fallback para leitura completa apenas quando a query não cobrir o caso.
  2. Sessões/logs (.pi/agent/sessions/*.jsonl)
    • usar session_analytics_query como superfície padrão;
    • leitura deve ser bounded-by-default (janela de cauda + limite por linha/records) para evitar explosão de contexto.
  3. Fallback explícito
    • quando leitura crua for inevitável, registrar no handoff o motivo, escopo e limite usado (offset/limit ou arquivo único).

Invariantes de segurança operacional:

Política structured-first para artefatos críticos

Quando o alvo for .project/*.json, a política padrão é não usar edit/write textual direto se houver superfície tipada equivalente. O guardrail structured-first bloqueia mutações textuais nesses arquivos e registra auditoria guardrails-core.structured-first-block com o caminho recomendado.

Caminhos canônicos:

Fallback textual só é aceitável quando não existir superfície tipada suficiente; nesse caso, registrar no board/handoff o motivo, o escopo exato e a validação pós-mutação.

Migração curta: project_proxy_* -> board_*

A superfície canônica de board usa apenas board_query e board_update.

Contratos úteis (rationale-aware):

Substituição direta:

Contrato de rollout:

Remediação de artefatos pi já commitados (sem perder progresso)

Quando descobrir que um artefato efêmero entrou no git por engano:

Cenário A — remediação leve (recomendado por padrão)

Use quando não há dado sensível e o objetivo é apenas parar de versionar.

  1. confirmar trabalho local antes de qualquer ação:
    • git status --short
  2. conferir violações da policy:
    • /safe-boot artifacts
  3. remover do índice sem apagar cópia local:
    • git rm --cached -- <path>
  4. garantir ignore para recorrência (.gitignore/baseline)
  5. validar novamente:
    • pnpm run pi:artifact:audit:strict

Cenário B — remediação pesada (histórico)

Use somente com confirmação explícita quando houver exposição sensível real.

  1. rotacionar credenciais primeiro;
  2. planejar rewrite de histórico (janela coordenada com time);
  3. executar purge seletivo e comunicar force-push;
  4. revalidar baseline com pi:artifact:audit:strict.

Regra de pragmatismo: prefira Cenário A sempre que possível; Cenário B só quando o risco justificar custo operacional.

Higiene de scripts ad-hoc (.sandbox/tmp)

Para reduzir gordura operacional sem perder rastreabilidade:

  1. Classificar por intenção
    • keep: utilitário recorrente (nome estável + uso repetido em sessões);
    • archive: útil só como evidência de investigação pontual;
    • remove: script descartável sem valor de reprodução.
  2. Critério de permanência (keep)
    • deve ter propósito claro, entrada/saída previsível e não depender de caminho hardcoded de sessão única;
    • idealmente substituir por superfície canônica (board_query, session_analytics_query, tools first-party) quando existir.
  3. Política de runtime artifacts
    • arquivos efêmeros de runtime (.pi/*.json de sessão/loop) permanecem fora de versionamento;
    • podem ser mantidos localmente para operação, mas não entram em commit.
  4. Evidência mínima no board
    • registrar no notes da task de higiene o inventário resumido (keep/archive/remove) e o rational em 1–3 linhas.

Higiene de superfície distribuída (lab x usuários)

A higiene operacional não é só sandbox; inclui o que está sendo distribuído para usuários.

Regras:

Slimming/deprecation-by-default:

Política de retomada pós-compactação

Retomar apenas com:

  1. .project/handoff.json
  2. .project/tasks.json
  3. checkpoint curto em docs/research/... (se houver)

Se esses três estiverem íntegros, não é necessário reconstruir contexto narrativo longo.

Cadência adaptativa pós-resume (anti-timidez residual)

Após auto-compact/auto-resume, a cadência não deve herdar micro-slice por inércia.

Contrato operacional:

Objetivo: preservar segurança do contexto sem exigir confirmação do operador para continuar quando o estado já está saudável.

Milestone mode (control-plane long-run)

Para rodar um milestone quase unattended no control plane, operar com um contrato explícito:

Rehearsal local-first de unattended

Antes de promover para agent-as-tools, subagentes ou GitHub Actions, o rehearsal local precisa provar o ciclo mínimo:

  1. escolher foco explícito (task ou milestone local-first) e gravar no handoff;
  2. executar slice bounded sem chamar pacote diagnóstico por hábito;
  3. validar gate focal;
  4. commitar apenas arquivos intencionais;
  5. atualizar tasks/verification/handoff;
  6. se o foco terminar, continuar com a próxima fatia local-safe óbvia; se a próxima opção for ambígua ou protegida, registrar focus-complete e pedir decisão em vez de driftar para pesquisa, CI/remote ou backlog lateral.

Critério de maturidade: três ou mais slices locais seguidos com foco preservado, smoke verde, commits pequenos, handoff fresco e nenhuma seleção automática de escopo protegido. Só depois disso remote/offload entra como canário controlado e opt-in.

A primitiva evaluateUnattendedRehearsalGate formaliza esse scorecard: continue-local enquanto faltarem critérios, blocked quando houver drift/protected-scope ou blockers, e ready-for-canary apenas quando todos os critérios locais estiverem verdes. A tool unattended_rehearsal_gate também retorna summary; use esse resumo compacto em handoff/auto-resume quando a decisão operacional basta, preservando o payload detalhado para auditoria ou debug.

A decisão operacional após foco completo deve seguir a doutrina operacional do control-plane unattended: continuar sozinho em mudanças locais pequenas e reversíveis; parar apenas em risco, ambiguidade real ou escopo protegido.

Durante o rehearsal, cada slice deve registrar uma evidência curta em formato estável: slice=<n> focus=<task|milestone> gate=<comando|inspeção> commit=<sha> drift=<yes|no> next=<ação>. O registro pode ficar em nota do board/handoff, evitando uma nova superfície grande de tracking.

Quando houver dúvida sobre a linha antes de gravar evidência, use validateUnattendedRehearsalSliceEvidence como checagem leve: ela deve retornar valid=yes missing=none invalid=none. Falhas indicam corrigir a linha curta, não expandir para payload verboso.

Para marker checks operacionais, prefira safe_marker_check: a tool é shell-agnostic, normaliza acentos/case quando solicitado e trata marcadores command-sensitive como política explícita. Use checks artesanais via shell apenas em testes/código quando o helper puro evaluateTextMarkerCheck for mais adequado.

Se ainda usar comandos inline como cmd.exe /c node -e, evite crases/backticks dentro das strings procuradas: shells podem interpretar o conteúdo antes do Node e produzir falso negativo. Prefira marcadores sem crase, ou normalize acentos e pontuação antes de comparar.

Resultado esperado: maior autonomia operacional sem perder previsibilidade, auditabilidade e controle de risco.

Pre-compact calm-close (anti-paralisia)

Quando context_watch_status.level=compact, o fechamento deve ser calmo (sem pânico e sem travar):