# ADR - Orquestrador Autônomo de Demandas SDD

## Rastreabilidade
- Orquestração: Orquestrador Autônomo de Demandas SDD
- Slug: orquestrador-autônomo-de-demandas-sdd
- Stage: adr
- Estado atual: draft
- Origem principal: `06-execution.md`
- Artefatos relacionados: `03-techspec.md` (v2), `04-tasks.md`, `05-refinement.md`, revisão do Agent Team.

## Status
- Estado: Aceito
- Data da decisão: 2026-06-08
- Dono técnico: mantenedor do `sdd-layer`
- Escopo: módulo `domain/orchestrator`, `runtime` (redação, slack), superfície CLI `sdd demand`/`sdd auto`.

## Contexto
A Fase 1 transformou o `sdd` de harness disparado por humano em **orquestrador durável dirigido por demanda**. O codebase já tinha: máquina de etapas pura (`tui::stage`), leitura de estado (`tui::orchestration`), e um **motor de geração headless completo** em `tui::runner` (Codex/Claude/Opencode/Cursor/Antigravity + harness determinístico). A revisão do Agent Team (architecture/security/data-contract) marcou a reescrita desse runner como o **maior risco de regressão** e apontou que `can_navigate` é baseado em aprovação, não em produção.

## Problema
Como adicionar ingestão de fila + avanço autônomo + gates humanos + geração real **sem** reescrever o código mais sensível (o runner), sem quebrar a TUI/fluxo manual, e mantendo segurança (sem auto-aprovação, sem vazamento de segredo, entrada externa não confiável)?

## Decisão
1. **Reuso, não reescrita do runner**: o runner real é um `HeadlessRunner` (composition root, `main.rs`) que envolve `tui::runner::spawn_stage` de forma síncrona e lê o artefato gerado — a mesma geração testada da TUI. Selecionável por `--real` (default `FakeRunner`, stub determinístico para testes).
2. **Camadas**: motor puro/determinístico em `src/domain/orchestrator/` (`demand`, `queue`, `state`, `engine`, `approval`); efeitos em `src/runtime/` (`redaction`, `slack`); `main.rs` é o composition root que injeta o runner via trait `StageRunner`. Sem top-level novo.
3. **Estado durável — Opção A**: `.sdd/state/<slug>.json` é a fonte primária (cursor, status rico, lock, approvals, `schema_version`). O `traceability-map` só recebe estados que `StageStatus::from_yaml` entende (`recorded|in_progress|approved|skipped`) — estados ricos (`awaiting_approval`/`ready_for_exec`/`manual:*`) **nunca** vão para o campo por-artefato, preservando a TUI.
4. **Avanço por `cursor` + detecção de gate**, não `can_navigate`: o motor produz etapas como `recorded` e avança pelas não-gate, pausando em PRD/TechSpec/Refinamento. `can_navigate` (baseado em aprovação) segue válido só para o fluxo humano da TUI.
5. **Segurança**: o motor **não tem caminho que escreva `approve`** (RN-02); `approvers` com **default-deny**; redação separada `redact_text` (segredos, segura p/ auditoria) vs `redact_pii` (segredos + e-mail, p/ conteúdo não confiável); verificação de assinatura Slack (HMAC-SHA256 + anti-replay) como barreira do canal Slack; limites de tamanho de entrada + escrita confinada via slug validado.

## Alternativas consideradas
| Alternativa | Benefícios | Custos/Riscos | Decisão |
|---|---|---|---|
| Reimplementar o runner headless no motor | Camadas "puras" | Duplica montagem de comando/redação; 2º ponto de regressão de segurança; reescreve 3.4k linhas | **Rejeitada** (arch-C1) |
| Extrair o núcleo do `tui::runner` para `runtime` agora | Camadas ideais | Refactor grande e arriscado no código mais sensível, sem provider para validar | Adiada (quando houver 2º consumidor real) |
| Adicionar estados ricos ao `StageStatus` do map | Um só modelo de estado | Quebra `can_navigate`/`current_stage` da TUI (vira `Unknown`) | **Rejeitada** → Opção A |
| Usar `can_navigate` no avanço autônomo | Reuso aparente | Bloqueia tudo (etapas são `recorded`, não `approved`) | **Rejeitada** → cursor+gate |

## Consequências
- Positivas: zero regressão na TUI/fluxo manual; geração real disponível via o mesmo caminho testado; segurança por construção (sem auto-aprovação, default-deny, redação); domínio testável sem rede.
- Negativas/Trade-offs: `HeadlessRunner` no composition root acopla `main.rs` a `tui::runner` (aceitável — é o wiring); dupla escrita do artefato (runner + engine) idempotente; geração real plena depende de provider configurado.
- Dívida técnica assumida: abstração de adapters (Jira/Confluence/Slack) e extração do runner para `runtime` ficam para quando houver consumidor real; `#[allow(dead_code)]` pontual em itens de contrato futuro.

## Impactos e riscos
- Código e arquitetura: novo módulo `domain/orchestrator` + `runtime/slack`; `main.rs` ganha comandos `demand`/`auto`.
- Dados/contratos: `.sdd/queue/<id>.json` e `.sdd/state/<slug>.json` com `schema_version`; extensão futura do map (bloco `demand`) ainda pendente.
- Segurança/privacidade: redação ampliada; assinatura Slack; default-deny; entrada não confiável redigida (PII) e limitada.
- Performance: `tick` = um passo por demanda; `auto run` em loop até idle; sem busy-poll. Runner real é subprocesso/thread por etapa.
- Observabilidade: `.sdd/orchestrator.jsonl` (tick, gate_request, redigido) + `sdd demand list`/`auto status`.

## Plano de adoção
- Default seguro: modo autônomo via CLI explícita (`sdd auto`), `FakeRunner` por default, `approvers` vazio nega.
- Para geração real: configurar provider (codex/claude/...) e usar `--real`; configurar `approvers` em `sdd.config.yaml`.
- Próximos: webhook Slack (consome `runtime::slack::verify_slack_signature` + `apply_decision` canal Slack); abstração de adapters Jira/Confluence; esteira na TUI; extração do runner.

## Plano de reversão
- Reverter é localizado: remover os comandos `demand`/`auto` e o módulo `domain/orchestrator` não afeta o fluxo manual nem a TUI (são aditivos). `--real` desligado volta ao stub. Sinais de reversão: instabilidade do `spawn_stage` síncrono ou divergência de estado state↔map.

## Evidências
- Execução: `06-execution.md`
- Testes: `cargo test` → 328 passed; `cargo clippy --all-targets -- -D warnings` → limpo. Inclui RFC 4231 (HMAC), loop de planejamento completo, default-deny, não-auto-aprovação, retomada idempotente, runner real (scaffold).
- Smoke: `sdd auto run` (multi-demanda até gates) e `sdd auto tick --real` (artefato real gerado).

## Histórico de revisão
| Data | Autor | Alteração | Motivo |
|---|---|---|---|
| 2026-06-08 | mantenedor | Criação da ADR | Pós-execução da Fase 1 |
