Harness & agentes · Mecanismo de orquestração · FER-1039

Auditoria Fable 05/09: síntese

Três executores Grok 4.6 (Cursor, via herdr) auditaram duas horas do orquestrador Fable no chat Bancal (worktree sl-bancada-all-in-one, épico FER-827). Esta página condensa os três relatórios, agrupa os problemas em clusters e lista os acionáveis por camada do stack de orquestração do Mac.

Janela: 2026-09-05 11:47:42Z–13:47:42Z (08:47–10:47 BRT). Veredito dos três lanes: ISSUES Fontes: timing.md, tools.md, policy.md, candidates.jsonl, verified.md, clusters.md.

1. O que foi feito

O coordenador recortou 2524 registros com carimbo de tempo de cinco arquivos jsonl do projeto (prepare.cjs, manifest.json) e despachou três workers com lanes disjuntas e 10 min de orçamento cada. Nenhum worker conseguiu autenticar o Linear MCP; a auditoria ficou só em arquivos locais até este card.

WorkerLaneSaídaVeredito
1Cronologia, throughput, loops de espera, trabalho duplicado, caminho críticotiming.mdISSUES
2Escolha de ferramenta: comandos falhos, saída grande, GUI vs API, polling, dispatchtools.mdISSUES
3Arquitetura de instruções: conflitos de mandato, cerimônia, perda de memória entre handoffspolicy.mdISSUES

A cadeia auditada

Não são duas horas de um contexto só. São cinco sessões do mesmo chat, encadeadas por auto-clear e handoff, com menos de 4 s entre uma e outra. A vida de cada contexto encolhe: ~50 min, depois ~14, ~15 e a âncora ainda rodava quando a janela fechou.

2. Os números

4
auto-clears na janela
35
Skill calls (8 skills × 4 clears + 3 abortadas)
36 / 35
herdr wait / read (fer-81 sozinho: ~23–30 passos)
116
chamadas Linear MCP inline (49 save_issue, 32 save_comment)
297
Bash (74 em background) vs 13 Write+Edit
9 + 5
recusas de isolamento + bloqueios do classifier
21 / 0
gh / gh-axi
~57 min
silêncio do orquestrador >60 s, só nas 2 primeiras sessões (worker 1 disse 48; recomputado 57,5)

Contagens sobre o log do orquestrador. Os panes dos executores não estão no corpus: nada aqui mede o trabalho do Grok dentro dos fer-*. Nenhum total de tokens foi calculado. Verificação independente das contagens: seção 6.

3. O stack de orquestração (as camadas que os acionáveis tocam)

Linearmemória persistente: épico, cards, takeover, FER-996
Skillsorchestrate-with-linear, herdr-executors, orchestrator-contract, stay-available, handoff
HooksSessionStart (mandatos), UserPromptSubmit (lembrete), PostToolUse (deps de skill), PreToolUse herdr
Herdrpanes fer-*, open-swarm-tab.sh, watch-blocked.sh, executor-hard-cut.sh
Auto-clear + handoffauto-clear-watch.sh, arquivos w5N_p1-*.md, kickoff

4. Problemas em clusters

Seis clusters. Cada acionável aponta a camada do stack e o estado hoje, no arquivo em disco (checado pelo executor B em 05/09): aplicado parcial pendente. Os hooks citados nos relatórios em ~/.claude/hooks/ não existem lá; as cópias vivas estão em ~/agents-config/shared/hooks/.

C1 A cerimônia de skills depois do /clear enche a próxima janela de 200k

Achados: timing#1, policy#1, policy#3. O maior alavancador e o mais barato.

Causa raiz. Três camadas exigem "primeira resposta": os cats do SessionStart, orchestrate-with-linear tratando /clear como tópico novo, e o checklist do handoff (Ordem 1 com oito skills). grill-with-docs ainda força mais duas via PostToolUse. O sidecar que poderia pular a recarga é chaveado por session_id, e o clear gera outro. Resultado: 8 skills × 4 clears, primeira escrita no Linear só 27–39 s depois da primeira Skill, e a vida do contexto cai de 50 min para 14–16.

AcionávelCamada / arquivoEstadoEvidência
Depois do /clear, carregar no máximo 1 skill; sem burst de 8. "Continuação não é tópico novo": mesmo label, pula o loading step, só takeover + list_issuesSkills: orchestrator-mandate.md, orchestrate-with-linearpendentemandate L5 ainda manda Skills-only; skill L39 "continuation is a new topic"
Persistir skills-loaded por pane id, não por session idHooks: post-tool-use-skill.sh + lib.sh sidecar_dirpendentelib.sh L21–23: sidecar em $HOOK_SESSION_ID
SessionStart exclusivo por papel: sem poteto-mode quando há orchestrator-mandateHooks: settings.json SessionStartpendenteL187–200 faz cat dos dois mandatos
Lembrete do UserPromptSubmit só no primeiro prompt da sessão (foram 96 iguais)Hooks: settings.json UserPromptSubmitpendenteL246–252: echo em todo submit
Tirar grill/gap-waves do checklist de continuação; hook de deps só quando o Next steps grilaSkills: grill-with-docs frontmatter + PostToolUsependenterequires: [grilling, domain-modeling] ainda dispara
Kickoff não pode codificar procedimento de 8 skillsAuto-clear: auto-clear-watch.sh default_kickoff, /handoffparcialkickoff padrão = ler handoff (L428); /handoff ainda pede "Suggested skills" (L501)
Watcher não reenvia o mesmo kickoffAuto-clear: step_kickoffaplicadoL552–556, FER-1033
Handoff é snapshot, não procedimentoSkills: handoff/SKILL.mdaplicado (texto)L37; contradito pelos handoffs vivos com Ordem 1

Métrica de aceite. No próximo SessionStart:clear deste chat: Skill calls até o primeiro herdr agent ou list_issues = 0 ou 1; tempo até o primeiro herdr ≤ 15 s; intervalo entre auto-clears não cai abaixo de 30 min só por cerimônia.

C2 O wait não espera; a leitura do terminal vira o sinal de status

Achados: timing#2, tools#1, mais as propostas contraintuitivas dos workers 1 e 2.

Causa raiz. O Bash manda herdr agent wait para background em menos de 5 s (34 de 36). O orquestrador nunca bloqueia no fim do executor. Nas duas primeiras sessões ele sai (away_summary, silêncio de 4–7 min); nas três seguintes ele polla: read + wait + read a 45 registros/min, o que consome a janela em 14 min. --until idle não é predicado de conclusão. O fer-81 sozinho rendeu 23–30 passos de status.

AcionávelCamada / arquivoEstadoEvidência
Um wait --until done que bloqueia, ou notify-on-done; nunca em backgroundHerdr + Skills: herdr-executorspendenteL15 manda start, prompt e wait "detached"
No timeout: herdr agent get e decidir por agent_status; read só em done/blockedSkills: tabela de falhas de herdr-executorspendenteL61: read de 40 linhas a cada wait
Tirar --until idle das receitasSkills: receitas N=1 e N≥2pendenteL60 e L80
Teto de ciclos wait+read por agente; ler todos os vivos num único comando (for n in fer-… já existe)Skills + scriptspendentesem cap; receita é por nome
120 s de rearme + corte de 10/12 minSkills + executor-hard-cut.shaplicadoCUT_S=600, KILL_S=720; correção do dono nesta janela
Prova de produto: MCP/HTTP/CLI primeiro; browser só para print por URLSkills: seção "Prova de produto"aplicadoL92–93
Worker não carrega browser-control sem o card dizer que a API não bastaHooks: SessionStart + prompt do executorparcialprompt proíbe skills de orquestração; SessionStart ainda faz cat de browser-control-mandate.md

Métrica de aceite. Por executor vivo: wait+read ≤ 3 a cada 10 min até done; read/start ≤ 2; nenhum wait que volta "running in background" seguido de read em 15 s. Agentes paralelos lidos num só turno.

Tensão a resolver. Os workers 1 e 2 querem wait quieto e bloqueante. A regra atual de herdr-executors (L61, correção do dono) manda ler o pane a cada 120 s. As duas não podem ser a regra ao mesmo tempo. Sugestão: manter o rearme de 120 s, trocar a leitura de pane por agent get, e ler o pane só quando o status é blocked, unknown ou done sem VERDICT.

C3 O caminho quente do orquestrador é cerimônia serial e I/O gordo

Achados: timing#3, tools#3.

Causa raiz. O único escritor do jsonl do orquestrador é obrigado a recarregar skills, escriturar o Linear e esperar agente por agente. Dispatch usa três CLIs (open-tab, start, prompt). ToolSearch do Linear repetiu 4 vezes; curl na porta :3100 do Linear 6 vezes; get_issue FER-964 com includeRelations devolveu 17–22 kB mais de uma vez; dois dumps de Bash acima de 30 kB; gh 21 vezes e gh-axi zero, embora o SessionStart o injete.

AcionávelCamada / arquivoEstadoEvidência
Escrever no Linear só na conclusão do executor, não a cada pollLinear + Skills: "When executor reports arrive"pendenteL163–169 ok; loading step e self-improvement ainda escrevem no meio
Pular ToolSearch do Linear depois da primeira escrita MCP que deu certoSkills: Tool referencependenteL199 manda ToolSearch em todo load
Heartbeat com get_issue sem includeRelations; nunca curl :3100Skillspendentesem proibição escrita
gh-axi para GitHub; um comando simples por chamada, sem $( )Hooks: SessionStart gh-axiparcialL157–163 roda o binário; nenhuma skill proíbe gh + jq
Arquivos do repo via Read/Grep; dumps de Bash limitados antes de voltarnão codificadopendente
open-swarm-tab uma vez, depois start com prompt no mesmo argv (se a CLI aceitar)Herdr: receita N=1pendenteL43–60; capacidade da CLI não verificada
Latch por sessão para check-compat.sh e helpers relidos (16 cats de open-swarm-tab, 10 do watcher)Herdr scriptspendenteL19–22 sem latch
Não fechar tab que herdr agent list não devolveHerdr: N=1 L65parcialfecha só a tab da receita; sem guarda para ids velhos
Não ler handoffs de ontem quando o w5N_p1 de hoje existeAuto-clear / handoffpendentenão codificado

Métrica de aceite. Bash por executor, do start ao done, ≤ 8. Linear MCP por vida de contexto ≤ 10 sem pedido do dono. gh-axigh. Curl em :3100 = 0. ToolSearch do Linear ≤ 1 por sessão. Nenhum resultado de Bash acima de 8 kB.

C4 Recusa de isolamento vira loop de reescrita

Achado: tools#2.

Causa raiz. Bash é o padrão para git, HTTP, MCP e GitHub. Depois de um "Refusing to run" (9) ou de um bloqueio do classifier (5), a ação seguinte é um Bash mais ofuscado ($VAR como nome de comando, python3 -c, git -C, curl JSON-RPC em /api/mcp) em vez de Read, MCP ou caminho literal. Cadeia de 15–25 chamadas por intenção travada (sonda MCP 13:12–13:18Z; edição do watcher 13:28–13:31Z). O guarda está certo; a repetição, não.

AcionávelCamada / arquivoEstadoEvidência
Depois de uma recusa: caminhos literais, sem $VAR em nome de comando, sem git -C fora do cwd; script salvo e rodado por caminhoHooks: PreToolUse de isolamento + regra de condutapendentedeny existe; nenhuma skill diz "pare após 1 recusa"
Arquivo fora do worktree (auto-clear-watch.sh): parar e relatarHooks: classifier + isolamentoaplicado (guarda) / pendente (obedecer)Edit bloqueado em 8aecd549:393
MCP do produto pelas tools do ToolSearch, não por curl/python; nunca extrair token de ~/.claude.json por Bashnão codificadopendenteToolSearch achou as tools em 78d3b533:229 antes do loop de curl

Métrica de aceite. Recusas de isolamento ≤ 1 por janela; zero curl/python JSON-RPC em /api/mcp depois de um ToolSearch bem-sucedido para o mesmo servidor.

C5 Loop de auto-melhoria e unidades atômicas roubam a meta do dono

Achado: policy#2.

Causa raiz. O Linear é a memória, mas a sucessora age pelo Meta comprimido do handoff, que tinha perdido o card da prova ao vivo. O dono repetiu a meta duas vezes (12:26Z) e pediu às 13:08Z para não perder o pedido entre handoffs. O loop de auto-melhoria transforma cada erro em um novo pai de Harness despachado no mesmo segmento, no mesmo orçamento de 10 min da prova. Um único ISSUES virou três pais. Título duplicado (MCP-host) criado duas vezes em 2,3 min: idempotência é frase, não hook. "Escrita de issue via herdr" é um MUST que o orquestrador precisa violar para manter o board verdadeiro (49 save_issue inline).

AcionávelCamada / arquivoEstadoEvidência
Bloco "meta do dono" congelado na descrição do épico; a primeira leitura da sucessora é get_issue nesse épico, antes de qualquer spawn de HarnessLinear + Skills: orchestrate-with-linear L157–158, handoff Metaparcialentendimento gravado no pai; loading step ainda é Skill → list_issues
Auto-melhoria: linha no FER-996 no segmento; pai de Harness entra como Todo; despacha só sem prova ao vivo In Progress (cap 1)Skills: seção Self-improvement looppendenteL191–195: "in the same segment" e "dispatch that parent"
ISSUES de executor de prova viram sub-issues do pai da prova, salvo tema novoSkills: Board visibility L65 + Dogfood L189pendente (conflito)"todo tópico é pai" briga com sub-issue do pai da prova
Hook nega save_issue com create sem list_issues prévio do mesmo títuloHooks: post-tool-use-linear.sh → novo PreToolUsependenteL10–15 só grava o sidecar linear-written
"Escrita via herdr" vira should, ou existe um executor escriturário de verdadeSkills: Board integrity L183pendenteainda MUST

Métrica de aceite. Depois do próximo /clear, a primeira resposta ao dono nomeia o pai da prova ao vivo sem o dono repetir a meta. Nenhum pai de Harness despachado enquanto um filho da prova está In Progress. Zero títulos iguais em 10 min.

C6 A pilha de mandatos é "ou" no papel e "e" no SessionStart

Achado: policy#3 (parte que C1 não cobre).

Causa raiz. O SessionStart injeta poteto-mode, orchestrator, browser-control e gh-axi juntos, a cada clear (16 anexos). Regras demais de "primeira resposta": ler handoff, Skills-only, comentário no Linear, poteto-mode, decompor e despachar, ficar disponível. O modelo cumpre o checklist mais recente e pula o resto: 8 skills carregadas, e o comentário de obrigações que elas exigem apareceu 1 vez em 32. Fila: 85 enqueue / 27 dequeue / 56 remove, prompts do dono empilhando sobre um orquestrador em cerimônia.

AcionávelCamada / arquivoEstadoEvidência
Parágrafos de isenção de worker ficam como estãoHooks: os três mandatosaplicadopoteto L5; orchestrator L7; browser-control L3
pre-tool-use-herdr.sh exige FER-n e sidecar linear-written no start/promptHooks: agents-configaplicadoL66–72
Fundir stay-available com o wait do herdrSkillsnão fazerstay-available é do Task/PSTACK do Cursor; herdr é CLI. Fundir mistura dois harnesses

Métrica de aceite. No próximo SessionStart:clear de pane de orquestrador, a primeira mensagem tem zero ou uma Skill (orchestrate-with-linear) e contém takeover no épico ou rearme do herdr.

Ordem sugerida de execução (benefício estimado ÷ custo)

  1. C1 SessionStart exclusivo por papel + "continuação não é tópico novo". Uma edição em settings.json e uma em orchestrate-with-linear. Estimativa: segmentos pós-clear voltam para ~50 min.
  2. C1 skills-loaded por pane id em lib.sh.
  3. C1 UserPromptSubmit só no primeiro prompt.
  4. C2 tirar --until idle; wait --until done + agent get; read só em blocked/unknown.
  5. C5 auto-melhoria vira fila (Todo) enquanto há prova ao vivo In Progress.
  6. C3 proibir curl :3100; ToolSearch do Linear uma vez; sem includeRelations em heartbeat.
  7. C3/C4 gh-axi e "pare após 1 recusa de isolamento".
  8. C2 wait bloqueante ou notify-on-done no herdr. Maior ganho de parede, maior custo.
  9. C5 hook de idempotência para save_issue.
  10. C3 start + prompt num argv só se a CLI aceitar.

Todos são propostas nascidas de lacuna, não de ordem direta. Pela regra do board, cada um entra como pai em Harness & agentes e vai para Aprovação Pendente com o antes/depois exato. Exceção: itens que o dono já ordenou (120 s, corte de 10 min, kickoff sem reenvio) já estão aplicados.

5. O que preservar e as propostas contraintuitivas

Preservar

  • Panes sobrevivem ao clear. fer-81, fer-83, fer-87… foram lidos pela sessão seguinte sem novo start. É o único motivo de o corte de 4 s não ser uma parada total. Manter nomes e pane ids no handoff.
  • Takeover no épico. Um comentário em FER-827 por sessão nomeando o handoff lido e a tabela de executores vivos. Foi assim que os cinco arquivos puderam ser encadeados.
  • Linear MCP para escritas. save_issue/save_comment, nunca GraphQL por curl.
  • Leituras de pane com teto de bytes (tail -c 1800–4000) quando uma leitura é mesmo necessária.
  • Guardas que recusam git -C fora do worktree e edição em ~/.local/share/auto-clear/. A recusa é o guarda funcionando.
  • 120 s de wait + corte de 10 min como estão hoje em herdr-executors. Foram correções do dono durante a janela.

Contraintuitivo

  • Worker 1: os buracos de 3–7 min parecem desperdício e as sessões a 45 registros/min parecem progresso. É o contrário: o frenesi é o que queima 200k em 14 min. Prefira um wait que bloqueia e um orquestrador quieto.
  • Worker 2: pare de ler o terminal do filho para decidir se espera. Um wait --until done mais herdr agent get parece menos informado e termina com menos tokens do pai. Se o worker travou em GUI, o erro é dele.
  • Worker 3: pare de carregar skills depois de /clear. A política não é cara por não ser lida; é cara por ser relida num contexto que encolhe até a releitura causar o próximo handoff. Persista um bit "política já aplicada" por pane.

6. Verificação independente das contagens

O executor A (FER-1040) recomputou as contagens contra candidates.jsonl com verify_counts.py. O censo central bate. Quatro números divergem; nenhum inverte um achado.

ContagemRelatórioReportadoRecomputadoStatus
Registros total e por sessão (268 / 625 / 645 / 701 / 285)timing, manifest25242524confirmado
Bash / Skill / Write / Edit / Read / ToolSearchtiming, tools297 / 35 / 10 / 3 / 3 / 5iguaisconfirmado
Linear MCP (save_issue / save_comment / list_comments / get_issue / list_issues)timing, tools116 = 49/32/19/12/4iguaisconfirmado
herdr wait / start / prompttiming, tools36 / 15 / 21iguaisconfirmado
herdr readtiming 35; tools 29 (classificado)35 / 2935confirmado vs timing; divergente vs tools
herdr gettools12divergente (piora a razão, não inverte)
Skills: 8 nomes, poteto-mode 0, por sessão 0+8+11+8+8policy, timing3535confirmado
"Refusing to run" / classifiertools9 / 59 / 5confirmado
gh / gh-axitools21 / 021 / 0confirmado
curl em :3100tools56divergente (extra em 65dd9aeb:611)
save_issue com título (creates)policy1615divergente
Título duplicado (MCP-host)policy2× (8aecd549:245, :365)confirmado
away_summarytiming55confirmado
Silêncio >60 s: 65dd / 1ddd / 3 últimas / somatiming25,3 / 22,9 / 0 / 48,2 min25,31 / 32,21 / 0 / 57,52 mindivergente em 1ddd e na soma
Bash em backgroundtiming7474confirmado

Leitura das divergências: o silêncio do orquestrador nas duas primeiras sessões é ~9 min maior do que o worker 1 disse (57,5 min, não 48,2); as três sessões seguintes continuam sem nenhum buraco. O número de creates é 15, não 16. A razão wait+read contra get fica pior para o achado do worker 2, não melhor. Nenhuma das quatro muda a direção de um top-3.

7. Lacunas declaradas

8. Board

CardO quêExecutor
FER-1039Pai: síntese em HTML da auditoria (este documento)Fable (orquestrador, ordem do dono)
FER-1040A: recomputar as contagens contra candidates.jsonlverified.mdherdr fer-1, cursor-grok-4.6-high
FER-1041B: clusterizar e checar cada acionável contra os arquivos atuais do stack → clusters.mdherdr fer-2, cursor-grok-4.6-high

Os três workers da auditoria original não criaram card (board.md). FER-1039 é o registro que faltava.