# Spec: DX Gaps Fixes — initialize, user_id, error visibility, verbose docs

> Origem: Report de gaps de DX do Arandu Inspector (2026-03-19)
> Budget: ≤ 6 arquivos

## Objetivo

Corrigir 4 problemas de developer experience encontrados durante a integração real do SDK: pgvector extension não criada automaticamente, user_id aceita strings não-numéricas que crasham silenciosamente, pipeline engole exceções sem expor no trace, e verbose mode não documentado.

## Contexto

O Arandu Inspector (test harness standalone) tentou integrar o SDK seguindo apenas a documentação pública. Encontrou 4 problemas reais (1 falso positivo descartado):

1. `initialize()` não cria a extensão pgvector → erro confuso
2. `user_id` é INTEGER no banco mas doc usa strings não-numéricas como exemplo
3. Pipeline steps 3-6 falham silenciosamente — exception capturada, trace não registra, dev recebe zeros sem saber por quê
4. `verbose=True` e `PipelineTrace` não documentados no getting-started

## Definition of Done

1. **`initialize()` cria extensão pgvector automaticamente** — `init_db()` em `db.py` executa `CREATE EXTENSION IF NOT EXISTS vector` antes de `create_all()`. Idempotente.
2. **Doc getting-started usa `user_id` numérico consistentemente** — Todos os exemplos usam `user_id=1` ou `user_id=123` (int). A tabela de WriteResult documenta que `user_id` deve ser int. A assinatura `write(user_id: int | str, ...)` é mantida (backward compat) mas com nota na docstring.
3. **Pipeline trace captura erros dos steps 3-6** — Quando o `except Exception` em `pipeline.py` L238 captura, o erro é adicionado ao `PipelineTrace` como um step `"error"` com `data={"error": str(e), "step": "pipeline_steps_3_6"}`. O dev que usa `verbose=True` vê o erro no trace, não zeros silenciosos.
4. **Getting-started documenta verbose mode** — Seção nova "Debugging with Verbose Mode" no getting-started (EN + PT-BR) mostrando `verbose=True`, `result.pipeline`, e `pipeline.steps`.
5. **Testes existentes continuam passando.**

## Escopo

- Modificar `src/arandu/db.py`: adicionar `CREATE EXTENSION IF NOT EXISTS vector` em `init_db()`.
- Modificar `src/arandu/write/pipeline.py`: adicionar step de erro ao trace no bloco `except`.
- Modificar `docs/en/getting-started.md`: corrigir user_id nos exemplos + seção verbose mode.
- Modificar `docs/pt-BR/getting-started.md`: mesmas correções em PT-BR.

## Anti-escopo

- **Não** alterar o tipo de `user_id` no model (Integer → VARCHAR). Mudaria o schema.
- **Não** adicionar validação de user_id no SDK (ex: rejeitar strings). Quebraria backward compat.
- **Não** alterar o comportamento fail-safe do pipeline (captura exceptions → retorna vazio). Isso é intencional.
- **Não** alterar models.py.
- **Não** alterar write-pipeline.md (já foi atualizado).

## Decisões Técnicas

### DT1: CREATE EXTENSION em init_db()

```python
async def init_db(engine: AsyncEngine) -> None:
    from arandu.models import Base as _  # noqa: F401
    async with engine.begin() as conn:
        await conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
        await conn.run_sync(Base.metadata.create_all)
```

Requer import de `text` do SQLAlchemy. Idempotente — roda em toda chamada de `initialize()`.

### DT2: Error step no PipelineTrace

No bloco `except Exception` de `pipeline.py`:

```python
except Exception as e:
    logger.warning("write_pipeline: failed after event creation: ...", exc_info=True)
    if trace:
        trace.add_step("error", {"error": str(e), "traceback": traceback.format_exc()}, 0.0)
    return WritePipelineResult(event_id=event_id, duration_ms=duration_ms)
```

O trace agora contém o erro. O dev que chama `verbose=True` vê `result.pipeline.steps[-1].name == "error"` e pode inspecionar.

### DT3: Exemplos de user_id no getting-started

Trocar:
- `user_id="user_123"` → `user_id=1`
- `user_id="demo"` → `user_id=1`

Manter a assinatura `write(self, user_id: int | str, ...)` sem alterar.

## Applicable Patterns

- **Error Handling**: Fail-safe mantido. Erro adicionado ao trace, não propagado.
- **Testing**: Testes existentes mock-based não usam DB real — o `CREATE EXTENSION` não afeta.

## Riscos

| Risco | Mitigação |
|-------|-----------|
| `CREATE EXTENSION` requer privilégio de superuser em alguns setups | `IF NOT EXISTS` é seguro. Se falhar por permissão, o `create_all()` falha depois com erro mais claro sobre `vector type`. |
| Dev que já usa user_id string numérica ("123") | Continua funcionando — coerção implícita. |
