# Execution - Orquestrador Autônomo de Demandas SDD

## Rastreabilidade
- Orquestração: Orquestrador Autônomo de Demandas SDD
- Slug: orquestrador-autônomo-de-demandas-sdd
- Stage: execution
- Estado atual: in_progress
- Origem: Tasks (`04-tasks.md`) + Tech Spec v2 (`03-techspec.md`) + Refinamento (`05-refinement.md`).
- Branch: `feat/orquestrador-autonomo-demandas`.
- Progresso: **11/15 tasks** (+parciais 011/014/015) + ADR. Núcleo + observabilidade + segurança + **runner real (opt-in)** concluídos. **O orquestrador roda autonomamente** (`sdd auto run [--real]`), gera artefatos reais via provider headless, pausa nos gates dizendo o que decidir, com segredos redigidos. Restam apenas itens de **dependência externa ou polish**: esteira na TUI (015), wiring real de webhook Slack/Jira/Confluence (014), e o anti-injeção pleno no prompt compartilhado (011, dentro de `tui::runner`).

## Tarefa
- **SDD-OAD-003 — `Demand` + slug validado + fila `.sdd/queue/`** (data). Concluída.
- **SDD-OAD-004 — Estado durável `.sdd/state/<slug>.json`** (data). Concluída.
- **SDD-OAD-005 — `engine::tick` ingestão** (demanda → orquestração → Idea). Concluída.
- **SDD-OAD-006 — `engine::tick` avanço até gate** (uma etapa por tick; pausa em PRD/TechSpec/Refinamento). Concluída.
- **SDD-OAD-008 — Aprovação humana + retomada** (allowlist default-deny, sem auto-aprovação, aprovar avança / reprovar reabre). Concluída.
- **SDD-OAD-012 — CLI `sdd demand enqueue/list/status/approve/reject` + `sdd auto tick/status`** (+`--json`). Concluída.
- **SDD-OAD-013 — `sdd auto run` (loop até idle/gate) + auditoria `.sdd/orchestrator.jsonl`** (`engine::run_until_idle`). Concluída.
- **SDD-OAD-010 — Redação ampliada** (Slack `xox*`, GitHub `gh*_`/`github_pat_`, GitLab `glpat-`, JWT, AWS `AKIA`, PEM, URL com credencial); `redact_pii` separado para e-mail; `redact_text` aplicado à auditoria. **E-mail NÃO é redigido na auditoria** (o autor da aprovação precisa dele). Concluída.
- **SDD-OAD-011 (parcial) — Entrada não confiável**: limites de tamanho de `title`/`description`; escrita confinada a `docs/<slug>`/`.sdd` via slug validado (anti-traversal). Restante (demanda-como-dado delimitado no prompt + system prompt restritivo + deny-check) acoplado ao runner real (009).
- **SDD-OAD-007 — Notify de gate (canal local)**: ao pausar num gate, registra `gate_request` na auditoria e imprime o artefato a revisar + o comando de aprovação. Canal Slack fica no 014. Concluída.
- **SDD-OAD-014 (parcial) — Verificação de assinatura Slack** (`runtime::slack`): HMAC-SHA256 sobre `sha2` (sem nova dep), janela anti-replay, comparação de tempo constante; vetor RFC 4231 validado. Barreira primária do canal Slack (RF-07). Resta o endpoint de webhook + abstração de adapters (Jira/Confluence) — dependência externa.
- **SDD-OAD-015 (parcial) — Fechamento/hygiene**: removido o `#![allow(dead_code)]` de módulo; allows pontuais e documentados só nos itens de contrato de tarefas futuras. Resta a esteira na TUI.
- **SDD-OAD-009 — Runner real (opt-in `--real`)**: `HeadlessRunner` (composition root) envolve `tui::runner::spawn_stage` de forma síncrona e lê o artefato gerado; provider/modelo/effort resolvidos por etapa; descrição da demanda entra como input com PII redigida (parte da 011). Default segue `FakeRunner` (zero regressão). Validado pelo caminho determinístico. Concluída.
- **ADR** (`06-adr.md`): decisões "reuso do runner / camadas / Opção A / cursor vs can_navigate / segurança" registradas e validadas.
- Inclui a reconciliação do plano com o estado real do código.

## Resumo da implementação
Módulo de domínio isolado e testável `src/domain/orchestrator/`:
- `demand.rs` / `queue.rs` (003): modelo + fila durável `.sdd/queue/`, dedup, `schema_version`, slug validado.
- `state.rs` (004): `EngineState` durável `.sdd/state/<slug>.json`, lock exclusivo/re-entrante, `save`/`load` atômicos, Opção A (`artifact_state_for_status`).
- `engine.rs` (005+006): `StageRunner` trait + `FakeRunner`; `tick()` produz **uma etapa por demanda por chamada** — cria a orquestração (reuso in-process de `artifact_dir`/`ensure_index`/`stage_file`/`update_stage_state`), gera a etapa do `cursor`, marca `recorded`, avança pelas não-gate e **pausa** ao concluir um gate (PRD/TechSpec/Refinamento). `RunnerError::NotHeadless` → estado `manual:<stage>`.
- `approval.rs` (008): `Approvers` (default-deny por canal), `authorize`, `apply_decision` — aprovar marca o gate `approved` no map e avança o `cursor` (ou `ReadyForExec` ao aprovar Refinamento); reprovar reabre a etapa. **O motor nunca aprova** (autoria separada — RN-02), com teste `engine_never_self_approves`.
- `mod.rs`: helper compartilhado `write_atomic`.
- `#![allow(dead_code)]` temporário (removido ao ligar à CLI/TUI em 012/013/015).

### Reconciliação do plano (deltas)
- **`can_navigate` não serve ao avanço autônomo**: é baseado em aprovação (`approved`), mas o motor produz etapas como `recorded`; o avanço usa `cursor` + detecção de gate. `can_navigate` segue válido para o fluxo humano da TUI.
- SDD-OAD-001 simplificado (privados do crate root acessíveis via `crate::`); `update_stage_state` serde, `ProviderSelection.timeouts/retries`, `validate_state(in_progress)` adiados para quando consumidos.
- `infer_artifact` filename-first já implementado — risco de hint mitigado.
- **007 (notify do gate)**: a pausa já existe (006); a emissão do pedido via `notify`/`ChatAdapter` fica para a fase de adapters (014).
- Sem mudança estrutural: arquitetura/contratos da Tech Spec v2 válidos.

## Arquivos alterados
- `src/domain/orchestrator/mod.rs` (novo; `write_atomic`; registra approval/demand/engine/queue/state)
- `src/domain/orchestrator/demand.rs` (novo, +7 testes)
- `src/domain/orchestrator/queue.rs` (novo, +7 testes)
- `src/domain/orchestrator/state.rs` (novo, +8 testes)
- `src/domain/orchestrator/engine.rs` (novo, +5 testes)
- `src/domain/orchestrator/approval.rs` (novo, +7 testes)
- `src/domain/mod.rs` (registra `pub mod orchestrator;`)
- `src/main.rs` (SDD-OAD-012/013/007/009: comandos `Demand`/`Auto` + handlers; `audit_tick`+`emit_gate_requests`; `HeadlessRunner`+`select_runner` (`--real`); fix-in-passing do lint `:1099` — pré-existente da v0.6.1)
- `src/runtime/redaction.rs` (SDD-OAD-010: formatos ampliados + `redact_pii`, +3 testes)
- `src/runtime/slack.rs` (SDD-OAD-014: verificação de assinatura HMAC-SHA256, novo, +6 testes; registrado em `runtime/mod.rs`)
- `src/domain/orchestrator/demand.rs` (SDD-OAD-011: limites de tamanho, +1 teste)
- `src/domain/orchestrator/{mod,engine,state}.rs` (SDD-OAD-015: dead_code allow de módulo → allows pontuais)
- `tests/cli.rs` (+3 testes de integração: `demand_enqueue_tick_and_human_approval_flow`, `auto_run_drives_to_gate_with_audit`, `auto_tick_real_uses_headless_runner`)

## Testes e evidências
- `cargo test` (suíte completa) → **328 passed** (baseline 280 + 45 unit + 3 integração), 0 falhas.
- Smoke `sdd auto run` (2 demandas): 3 iterações → 4 etapas → ambas `awaiting_approval` no PRD; auditoria em `.sdd/orchestrator.jsonl`.
- `cargo clippy --all-targets -- -D warnings` → **No issues found**.
- Destaque unit: `full_planning_loop_reaches_ready_for_exec`, `engine_never_self_approves`, `authorize_is_default_deny`, `unauthorized_author_is_rejected`, retomada idempotente, lock exclusivo, Opção A.
- Destaque integração + smoke (binário real): `sdd demand enqueue` → `sdd auto tick` (idea) → `sdd auto tick` (prd→gate, `paused`) → `status` (`awaiting_approval`) → `approve --by mallory` **negado** (default-deny) → `approve --by alan` **avança**; artefatos `01-idea.md`/`02-prd.md` gravados; `--root` é flag do grupo (antes do subcomando).

## Riscos e pendências
- **Runner real (009)**: ✅ ligado opt-in (`--real`). Para geração via LLM, configurar um provider (codex/claude/...) + auth; o caminho determinístico (sem provider) gera scaffold real.
- **Segurança**: 010 ✅; 014 (assinatura Slack) ✅; 011 ✅ no que é local (limites, confinamento, input redigido) — resta o anti-injeção pleno (dado delimitado + system prompt restritivo + deny-check) dentro de `tui::runner::build_provider_prompt` (código compartilhado, requer extração cuidadosa — SDD-OAD-002).
- **Dependência externa** (fora do que dá para validar localmente): endpoint de webhook Slack + adapters Jira/Confluence (014); extração de `runtime::stage_runner` (002).
- **Polish**: esteira na TUI (015) — observabilidade já existe via `sdd demand list`/`auto status`.
- Itens adiados (quando consumidos): `ProviderSelection.timeouts/retries`, `validate_state(in_progress)`, `update_stage_state` serde, bloco `demand:` no map.
- **Working tree**: contém trabalho não commitado da v0.6.1 — commit seletivo dos arquivos da feature (`src/domain/*`, `src/runtime/{redaction,slack}.rs`, comandos da CLI em `src/main.rs`, `tests/cli.rs`), separado do `sdd update`/`:1099`.
