> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# #2 Plan-and-Solve / ReWOO

> PlannerAgent emite um plano JSON estruturado; PlanRunner executa cada passo em ordem topológica resolvendo placeholders #E1 (ReWOO). Dispara automaticamente em tarefas complexas ou manualmente via /plan.

**Plan-and-Solve** sintetiza um plano estruturado **antes** do orquestrador começar a despachar. **ReWOO** (Reasoning Without Observation) estende: o plano usa placeholders `#E1`, `#E2` que são resolvidos em runtime com os outputs dos passos anteriores. Combinados, evitam o padrão caro de "despachar um agente, esperar, pensar de novo, despachar outro".

<Info>**Quando ativa:** `/plan <task>` força; `CHATCLI_QUALITY_PLAN_FIRST_MODE=always` sempre; `auto` (default) dispara quando `ComplexityScore(task) >= 6`. Para revisar o plano antes de executar, use `/plan preview <task>` (dry-run).</Info>

***

## Formato do plano

O `PlannerAgent`, quando recebe a marcação `PlannerStructuredOutputDirective` no início da task, emite JSON estrito:

```json theme={"system"}
{
  "task_summary": "Add OAuth login with Google",
  "steps": [
    {"id": "E1", "agent": "search", "task": "Find existing auth code in cli/auth"},
    {"id": "E2", "agent": "planner", "task": "Design integration plan based on #E1", "deps": ["E1"]},
    {"id": "E3", "agent": "coder",   "task": "Implement based on #E2", "deps": ["E2"]},
    {"id": "E4", "agent": "tester",  "task": "Write tests for #E3", "deps": ["E3"]}
  ],
  "parallel_groups": [["E1"], ["E2"], ["E3", "E4"]]
}
```

### Placeholders ReWOO

Qualquer passo pode injetar output de passos anteriores via `#E<n>`:

| Sintaxe        | Efeito                                  |
| -------------- | --------------------------------------- |
| `#E1`          | Substitui pelo output trimmed completo  |
| `#E1.summary`  | Primeira linha não vazia do output      |
| `#E1.head=200` | Primeiros 200 runes com `…` se truncado |
| `#E1.last=200` | Últimos 200 runes com `…` no início     |

<Tip>Use `.head=N` para tarefas grandes (ex: "dado este log #E1.head=500, diagnostique") para bound o contexto que o próximo passo vê.</Tip>

***

## Heurística de complexidade

A função `ComplexityScore(task) → int[0,10]` é calibrada para disparar Plan-First só quando paga. O score blends três sinais:

| Sinal                    | Cap | O que conta                                                                                                                                                         |
| ------------------------ | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Verbos de ação**       | 5   | `implement, add, create, fix, refactor, write, test, deploy, build, run, update, …` — bilíngue (en + pt-BR: `implementar, adicionar, criar, corrigir, escrever, …`) |
| **Artefatos de arquivo** | 3   | Matches em `\b[\w./-]+\.(go\|ts\|py\|md\|yaml\|…)\b` + `Dockerfile\|Makefile\|…`                                                                                    |
| **Sequenciadores**       | 2   | `then, after, finally, e depois, e em seguida, por fim, após, …`                                                                                                    |

### Exemplos

<Tabs>
  <Tab title="Trivial (score 1)">
    ```text theme={"system"}
    read main.go
    ```

    `auto` **não** dispara Plan-First. Orquestrador lida direto.
  </Tab>

  <Tab title="Multi-action (score 6+)">
    ```text theme={"system"}
    update auth.go and add tests/auth_test.go then run go test
    ```

    `auto` **dispara** Plan-First. 3 verbos (update, add, run) + 2 arquivos + 1 sequenciador = score 6.
  </Tab>

  <Tab title="PT-BR (score 6+)">
    ```text theme={"system"}
    criar handler em api.go e adicionar testes em api_test.go depois rodar go test
    ```

    Idêntico ao anterior — bilíngue por design.
  </Tab>
</Tabs>

***

## Fluxo de execução

<Steps>
  <Step title="Usuário dispara /agent ou /coder">
    A tarefa vai para `AgentMode.Run()`.
  </Step>

  <Step title="runPlanFirstIfApplicable">
    Checa `cli.pendingPlanFirst` (one-shot) ou `quality.ShouldPlanFirst(cfg, userQuery)`.
  </Step>

  <Step title="Planner dispatch">
    `agentDispatcher.Dispatch([{Agent: planner, Task: PlannerStructuredOutputDirective + userQuery}])`.
  </Step>

  <Step title="ParsePlan">
    Tolerante a markdown code fences e trailing prose. Valida: IDs únicos, deps apontam para passos anteriores, placeholders `#E<n>` apontam para IDs declarados.
  </Step>

  <Step title="TopologicalOrder + Execute">
    Ordem topológica estável (sort lex em ties) garante reprodutibilidade. Cada passo: resolve placeholders → dispatcher.Dispatch → armazena output.
  </Step>

  <Step title="Inject report">
    Dois messages sintéticos vão para `cli.history`:

    * **assistant**: o JSON do plano (o modelo vê o que foi tentado)
    * **user**: `FinalReport` determinístico com task/agent/status/output por passo + handoff

    <Note>O segundo message é **role=user** (não `system`) desde o fix de abril/2026. Modelos como **Claude Sonnet 4.6** recusam completion quando a conversa termina em `assistant` (*"This model does not support assistant message prefill"*). O turno de usuário sintético fecha a conversa corretamente e dá ao orquestrador um ponto-âncora explícito para finalizar.</Note>
  </Step>

  <Step title="ReAct loop continua (ou pula, se dry-run)">
    Com o report em history, o orquestrador finaliza sem re-executar os passos já concluídos. Em modo dry-run (`/plan preview`), o loop é **pulado** via `planDryRunHandled` — nenhuma chamada ao orquestrador é feita.
  </Step>
</Steps>

***

## Tolerância a falhas

Um passo que falha **não aborta** a run. O comportamento é "continue downstream with substituted error":

```go theme={"system"}
// cli/agent/quality/plan_runner.go:126
if res.Error != nil {
    hadErrors = true
    outputs[id] = fmt.Sprintf("<error: %s>", res.Error.Error())
    // continua — passos downstream verão a string "<error: …>" substituída em seus placeholders
}
```

Isso espelha como o orquestrador já reage a erros per-agent hoje (continua, sumariza, faz o modelo decidir). O flag `HadErrors` é setado para Reflexion decidir se escala.

***

## `/plan` — invocação manual

O comando `/plan` aceita seis formas. Autocomplete (Tab) oferece os subcomandos.

<CodeGroup>
  ```bash Arma o flag (sem task) theme={"system"}
  /plan
  # → "plan-first armado — seu próximo /agent ou /coder rodará um plano estruturado"
  /agent refatorar auth package para usar OAuth
  # → roda Plan-First mesmo se complexity score < threshold

  # também funciona com /coder — o flag é consumido na primeira invocação subsequente
  ```

  ```bash Inline agent (default) theme={"system"}
  /plan refatorar auth package para usar OAuth
  # → entra direto em agent mode com Plan-First armado e executa

  # Equivalente explícito:
  /plan agent refatorar auth package para usar OAuth
  ```

  ```bash Inline coder theme={"system"}
  /plan coder refatorar auth package para usar OAuth
  # → entra em coder mode (CoderSystemPrompt) com Plan-First armado e executa
  # Recomendado para tarefas que modificam arquivos / rodam builds
  ```

  ```bash Dry-run / preview (não executa) theme={"system"}
  /plan preview refatorar auth package para usar OAuth
  # → roda só o PlannerAgent, renderiza o plano estruturado, NÃO executa nenhum passo
  # Nenhuma chamada ao orquestrador é feita — ideal para revisar antes de commitar

  # Alias:
  /plan dry refatorar auth package para usar OAuth
  ```
</CodeGroup>

### Matriz de comportamento

| Forma                  | Entra em           | Executa passos?                         | Chama orquestrador? | Quando usar                                     |
| ---------------------- | ------------------ | --------------------------------------- | ------------------- | ----------------------------------------------- |
| `/plan`                | — (arma flag)      | depende do próximo `/agent` ou `/coder` | sim                 | Quer controle manual do modo consumidor         |
| `/plan <task>`         | agent              | sim                                     | sim                 | Fluxo padrão, mais rápido                       |
| `/plan agent <task>`   | agent              | sim                                     | sim                 | Equivalente explícito (simetria com `coder`)    |
| `/plan coder <task>`   | coder              | sim                                     | sim                 | Tarefas de engenharia (edições, builds, testes) |
| `/plan preview <task>` | agent (temporário) | **não**                                 | **não**             | Revisar plano antes de rodar                    |
| `/plan dry <task>`     | idem `preview`     | **não**                                 | **não**             | Alias                                           |

O flag `cli.pendingPlanFirst` é **consumido** e **cleared** na primeira invocação de `/agent` ou `/coder` subsequente. O flag `cli.pendingPlanDryRun` (exclusivo dos modos preview/dry) é limpo no mesmo ponto e faz `AgentMode.Run` retornar antes do ReAct loop via `planDryRunHandled`.

<Tip>Fluxo recomendado para mudanças grandes: **`/plan preview <task>`** primeiro → revise o JSON → se aprovado, rode **`/plan coder <mesma task>`**.</Tip>

***

## Variáveis de ambiente

| Env var                                | Default | Valores             | Efeito                            |
| -------------------------------------- | ------- | ------------------- | --------------------------------- |
| `CHATCLI_QUALITY_PLAN_FIRST_MODE`      | `auto`  | `off\|auto\|always` | Modo de disparo                   |
| `CHATCLI_QUALITY_PLAN_FIRST_THRESHOLD` | `6`     | 0..10               | Score mínimo para `auto` disparar |

### Override por persona (CHATCLI\_AGENT\_PLANNER\_\*)

O `PlannerAgent` respeita os overrides usuais de agent:

```bash theme={"system"}
# Forçar planner a usar Opus com thinking máximo
export CHATCLI_AGENT_PLANNER_MODEL="claude-opus-4-8"
export CHATCLI_AGENT_PLANNER_EFFORT="max"
```

***

## Observabilidade

Cada run emite logs estruturados:

```json theme={"system"}
{"level":"info","msg":"Plan-First triggered","forced":false,"mode":"auto","complexity":7}
{"level":"info","msg":"plan step dispatching","id":"E1","agent":"search","task":"Find existing..."}
{"level":"info","msg":"plan step dispatching","id":"E2","agent":"planner","task":"Design based on found auth code"}
{"level":"warn","msg":"plan step failed","id":"E3","agent":"coder","error":"timeout"}
```

E imprime no terminal um one-liner amigável:

```text theme={"system"}
  plan-first executed 4 step(s) before handing off to the orchestrator
```

### Spinner durante Plan-First

O spinner "planning structured steps..." aparece **somente** durante a chamada pura do `PlannerAgent` (step 1). Durante a execução do `PlanRunner` (step 2), o spinner é intencionalmente **desligado** e um print estático é emitido:

```text theme={"system"}
  executing structured plan...
```

<Warning>Isso é crítico para segurança: passos podem disparar approvals interativos (ShellAgent `exec`, CoderAgent `write`) via policy engine. Se o spinner ficasse ativo durante a execução, seu repaint `\r\033[K` sobrescreveria o prompt de aprovação e impediria a resposta. Ctrl+C continua cancelando normalmente — o ctx cancelado propaga para dispatcher e PlanRunner entre passos.</Warning>

### Modo dry-run: o que é renderizado

`/plan preview <task>` renderiza:

```text theme={"system"}
  Plano gerado (dry-run — nada será executado)

  Resumo: <task_summary do JSON>

  1. [E1] agent=search
     <task resolvida>
  2. [E2] agent=planner
     <task>
     deps: E1
  3. [E3] agent=coder
     <task>
     deps: E2

  Grupos paralelizáveis:
     [E1]
     [E2]
     [E3]

  Para executar este plano: /plan <mesma tarefa> (ou /plan coder <tarefa>)
```

Se o `ParsePlan` falhar (planner devolveu JSON malformado ou prose), o output bruto é impresso com um aviso — nunca é silencioso.

***

## Quando desligar

<Warning>Plan-First acrescenta **+1 chamada LLM** (o planner) por turn disparado. Em ambientes com budget apertado, `off` ou `threshold=8` economizam.</Warning>

```bash theme={"system"}
# off: nunca dispara, mesmo com /plan
export CHATCLI_QUALITY_PLAN_FIRST_MODE=off

# threshold alto: só dispara em tarefas muito complexas
export CHATCLI_QUALITY_PLAN_FIRST_THRESHOLD=9
```

***

## Leia também

<CardGroup cols={2}>
  <Card title="#3 Reflexion" icon="lightbulb" href="/pt/features/quality/reflexion">
    Reflexion consome `HadErrors` do plan runner para gerar lições quando passos falham.
  </Card>

  <Card title="Multi-Agent Orchestration" icon="users" href="/pt/features/multi-agent-orchestration">
    O dispatcher que Plan-Runner reutiliza é o mesmo do orquestrador padrão.
  </Card>

  <Card title="PlannerAgent (pré-PR)" icon="person-walking-luggage" href="/pt/features/customizable-agents">
    O agent existia desde antes do pipeline — esse padrão formaliza como invocá-lo de forma determinística.
  </Card>

  <Card title="Configuração completa" icon="sliders" href="/pt/features/quality/configuration">
    Todos os env vars e slashes num lugar só.
  </Card>
</CardGroup>
