# Refinement - Orquestrador Autônomo de Demandas SDD

## Rastreabilidade
- Orquestração: Orquestrador Autônomo de Demandas SDD
- Slug: orquestrador-autônomo-de-demandas-sdd
- Stage: refinement
- Estado atual: in_review
- Origem: Tasks (`04-tasks.md`) + Tech Spec v2 (`03-techspec.md`) + PRD (`02-prd.md`) + risco high (`00-risk-classification.md`).
- Próximo artefato: Execução em `06-execution.md`.
- Obrigatório por risco (fator `external_dependency`); este é o checkpoint antes da execução.

## Resumo
Fase 1 do orquestrador: motor durável dirigido por demanda que faz o **planejamento autônomo** (ingestão → Idea → PRD → Tech Spec → Tasks → Refinamento) e **pausa nos gates** (aprovação CLI/Slack), sem tocar produção e sem ativar execução de código. Construímos a *cola* (motor + estado durável + reuso do runner já existente) e os **seams de adapter** com local/Markdown como default operante. 15 tasks em 6 pacotes de trabalho; o caminho crítico é o motor (`tick`/gate/approval); os refactors habilitantes vêm primeiro para evitar duplicação e regressão.

## Solução proposta
- **Camadas** (sem top-level novo): `domain/orchestrator/` (puro: demand, queue, state, engine, gate, approval) + `runtime/stage_runner.rs` (geração **extraída** de `tui::runner`) + `runtime/adapters/` (local default + Slack assinado + stubs).
- **Reuso, não reescrita**: `stage::can_navigate`, `orchestration::parse_index`, `persist::write_atomic`, `domain::providers`, `runtime::redaction`. A geração headless já existe — só é extraída para um módulo neutro compartilhado por TUI e engine.
- **Durabilidade**: `.sdd/state/<slug>.json` (primário, atômico, lock, `schema_version`) é a verdade do motor; o `traceability-map` é cache de display e só recebe estados que `StageStatus::from_yaml` entende (Opção A).
- **Segurança como barreira primária**: motor não executa nada do provider; motor não tem caminho que aprove gate; escrita confinada a `docs/<slug>/` e `.sdd/`; demanda tratada como dado não confiável; redação ampliada em todos os writers.

### Pacotes de trabalho (sugestão de PRs)
| PR | Tasks | Foco | Tamanho |
|---|---|---|---|
| WP1 | 001, 002 | Refactors habilitantes (helpers in-process + extração do runner) | L |
| WP2 | 003, 004 | Fundação de dados (fila + estado durável) | M |
| WP3 | 005, 006, 007, 008 | Motor de planejamento (tick + gate + aprovação) | L |
| WP4 | 009, 010, 011 | Geração real + segurança (redação + anti-injeção + path) | L |
| WP5 | 012, 013 | CLI `demand` + `auto` + auditoria | M |
| WP6 | 014, 015 | Adapters (local/Slack) + TUI esteira + fechamento | M |

## Pontos de observação
- **Regressão na extração do runner (002)**: rodar testes de equivalência da saída de geração da TUI **antes** de plugar o engine; é o maior risco brownfield.
- **Mapeamento de estado (Opção A)**: nunca gravar `awaiting_approval`/`ready_for_exec` no campo por-artefato do map — quebra `can_navigate`/`current_stage` da TUI.
- **Sem auto-aprovação**: garantir, por teste, que `tick` jamais cria um registro `approve`; aprovação só por humano (CLI) ou callback Slack verificado.
- **Default-deny de aprovadores**: allowlist vazia ⇒ gate não aprovável (nunca "qualquer um").
- **Redação é defesa-em-profundidade**: cobrir formatos (Slack/GitHub/GitLab/JWT/AWS/PEM/URL-cred/e-mail) e aplicar em todos os writers; a barreira primária é não compor segredo.
- **Guardrail headless**: o `bash-guard` pode não interceptar comandos de provider headless; por isso, na Fase 1 o motor só captura Markdown (não executa).
- **Assinatura Slack é da Fase 1** (HMAC + timestamp ≤5min + anti-replay) porque a aprovação por Slack altera o estado do motor.
- **Heterogeneidade de provider**: começar por 1 provider (o default) no runner real; `RunnerError::NotHeadless` → estado `manual:<etapa>`.
- **`schema_version`**: versão divergente em queue/state ⇒ erro claro, sem leitura silenciosa.

## Checklist
- [ ] WP1: `update_stage_state` serde + `required_sections` exposto + `validate_state(in_progress)` + timeouts/retries em `ProviderSelection` + extração `runtime::stage_runner` com testes de equivalência.
- [ ] WP2: `Demand` + slug validado + fila com dedup; `.sdd/state` atômico + lock + `schema_version` + reconstrução.
- [ ] WP3: `tick` ingestão + avanço idempotente até gate; pausa em PRD/TechSpec/Refinamento; aprovação segura + retomada.
- [ ] WP4: geração real + validação de seções + nome canônico; redação ampliada (teste por formato); anti-injeção + deny-check + path-allowlisting.
- [ ] WP5: CLI `demand enqueue/list/status/approve/reject` (+json); `auto tick/run` (watch/intervalo/concorrência); `.sdd/orchestrator.jsonl` redigido.
- [ ] WP6: adapters traits + LocalAdapter default + SlackAdapter assinado + Jira/Confluence stubs; TUI esteira; suíte completa + matriz de evidências.

## Subtasks
Estimativas relativas (S≈≤meio dia, M≈1 dia, L≈2+ dias). Detalhe e prompts em `04-tasks.md`.

| ID | Subtask | Est. | Depende |
|---|---|---|---|
| SDD-OAD-001 | Helpers reusáveis in-process | M | — |
| SDD-OAD-002 | Extrair `runtime::stage_runner` | L | — |
| SDD-OAD-003 | `Demand` + fila `.sdd/queue/` | M | — |
| SDD-OAD-004 | Estado `.sdd/state/<slug>.json` | M | 003 |
| SDD-OAD-005 | `tick` ingestão (FakeRunner) | M | 001,003,004 |
| SDD-OAD-006 | `tick` avanço até gate | M | 002,005 |
| SDD-OAD-007 | `gate` pausa + notify escapado | S | 006 |
| SDD-OAD-008 | `approval` seguro + retomada | M | 004,007 |
| SDD-OAD-009 | Plugar geração real + nome canônico | M | 001,002,006 |
| SDD-OAD-010 | Redação ampliada (todos writers) | M | 004,009 |
| SDD-OAD-011 | Entrada não confiável + path-allowlisting | M | 009 |
| SDD-OAD-012 | CLI `sdd demand ...` | M | 003,008 |
| SDD-OAD-013 | `sdd auto tick/run` + auditoria | M | 006,012 |
| SDD-OAD-014 | Adapters (local + Slack assinado + stubs) | L | 007,008 |
| SDD-OAD-015 | TUI esteira + fechamento/evidências | M | 005–014 |

## Definition of Done
- Todas as 15 subtasks com DoD individual cumprido (ver `04-tasks.md`).
- `cargo test`, `cargo clippy -- -D warnings`, `cargo check` verdes; sem regressão na TUI/CLI/`stage`/`orchestration`.
- Matriz de evidências preenchida: retomada pós-restart; não vazamento **por formato** em todos os writers; `tick` não auto-aprova; anti-spoof Slack; path traversal barrado; fluxo manual intacto.
- Modo autônomo **desligado por default**; ativação documentada.
- ADR criado após a execução para as decisões "orquestrador durável" e "extração do runner" (`sdd adr`).
- Memória atualizada para os próximos agentes.

## Flags e configurações
- **Feature flag (kill-switch)**: `autonomous.enabled: false` por default em `sdd.config.yaml`. Desligado ⇒ nenhuma ingestão/avanço autônomo; fluxo manual inalterado.
- **`approvers`** (novo bloco): `{ cli: [git-email/usuário], slack: [Uxxxx] }`. **Default vazio ⇒ default-deny** (gate não aprovável autonomamente).
- **`adapters`** (seleção): `{ work_tracker: local|jira, docs: local|confluence, chat: local|slack, repo: local|github|bitbucket }`. Default tudo `local`.
- **`auto`**: `{ watch: true|false, interval_s: <n>, max_concurrency: 2 }`.
- **`schema_version: 1`** para `.sdd/queue/*.json` e `.sdd/state/*.json` (rejeitar divergente).
- **Env de credencial (NÃO lidas na Fase 1; só quando o adapter for habilitado)**: `SLACK_SIGNING_SECRET`, `SLACK_BOT_TOKEN` (escopo `chat:write`), `JIRA_*`, `CONFLUENCE_*`. Repo provider sem permissão de push no caminho autônomo.
- **Reaproveita** `memory.redact_secrets: true` e os hooks (`bash-guard`, `notify`, `trace-log`, `subagent-audit`).
