Dos workers que se corrigen entre sí

Abre un worker con codex y otro con cursor-agent sobre la misma tarea, y que cada uno revise el diff del otro.

Prompt#

Abre un worker orch con codex y otro con cursor-agent en esta tarea y que se corrijan uno al otro.

Qué hace el Chair#

Verifica que no es un worker (denyWorkerFanout), resuelve el proyecto, lanza un worker por preset y le pasa a cada uno el diff del otro.

Llamadas MCP#

dispatch_worker({
  "agent":  "codex",
  "prompt": "Rewrite client/internal/gateway/rotate.go so a 429 advances the ring. Report with verify_report.",
  "title":  "rotate ring on 429 — codex pass",
  "name":   "codex-a",
  "timeout_sec": 900
})

dispatch_worker({
  "agent":  "cursor",
  "prompt": "Review codex-a's diff on orch/<session>. Say what is wrong, do not rewrite it.",
  "title":  "rotate ring on 429 — cursor review",
  "name":   "cursor-b"
})

O, cuando quieres los criterios de aceptación en el board:

task_add({ "title": "rotate ring on 429", "agent": "codex",
           "context": "gateway owns the ring; keys live in machine-home keys.env",
           "acceptance_criteria": ["go test ./internal/gateway/... -race passes",
                                   "no key material in logs"] })
task_run({ "id": "<task id>", "timeout_sec": 900 })

Relevo entre los dos, y cierre:

msg_send({ "from_session": "<chair session>", "to_worker": "cursor-b",
           "kind": "handoff", "body": "codex-a diff on orch/<session>; review, do not rewrite" })
worktree_promote({ "session": "<the session you keep>" })

Respuesta esperada#

dispatch_worker y task_run devuelven apenas el worker está corriendo: {task?, session_id, worker_id, name, worktree, log, status: "running", note}. Pasa wait: true para bloquear hasta que el worker termine; esa respuesta agrega exit y verification (la mitad del worker — tests[], symbols[], criteria[], summary, vía verify_report — más la mitad observada por orch — guardrails, files[]). msg_send devuelve {message, delivery}.

Trampas#

  • El id del preset es cursor, no cursor-agent. cursor-agent es el binario detrás; la clave del preset en orch es cursor, y corre como subproceso común — el transporte ACP solo viene para gemini y opencode.
  • codex y cursor también tienen defaults headless. agents.cmds trae de fábrica copilot, agy, claude, opencode, grok, kimi, commandcode, codex y cursor. mimo y zcode siguen existiendo solo en agents.interactive. Si despachas un preset de CLI reconocido que no tiene entrada agents.cmds.<preset>, orch falla en voz alta hacia el Chair (preset "<preset>" has no headless command: set agents.cmds.<preset>) en vez de correr el agente stub en silencio.
  • dispatch_worker regresa apenas el worker está corriendo (status: running, session_id, worker_id); los dos workers corren al mismo tiempo y el Chair recibe un mensaje handoff en el bus cuando cada uno termina. Pasa wait: true para bloquear hasta tener el código de salida y la verificación. Un worker no puede lanzar él mismo la otra mitad.
  • Los workers se hablan de lado con to_role: "sibling" o to_worker, nunca abriendo el CLI del otro.
  • Compuerta del ledger. Con clarify_before_spawn activo, el spawn se niega hasta que pase orch ledger check; force: true (o ORCH_LEDGER_FORCE=1) lo salta.