# Arandu v0.7.0 — Speaker-Aware Extraction

> Para: Time Arandu Spector
> De: Pedro
> Data: 2026-03-25

## O que mudou

A v0.7.0 resolve um bug crítico de identidade na extração. Antes, quando alguém dizia "Meu nome é Pedro, moro em Botafogo, trabalho na Stone", o sistema criava entidades duplicadas (`user` + `Pedro`) e gerava ~15 fatos ao invés de ~5, porque confundia **quem fala** com **quem lembra**.

O problema era conceitual: o `user_id` é o **agente** (o cérebro que armazena), não a pessoa falando. Faltava dizer pro sistema quem é o speaker.

### A correção

Adicionamos `speaker_name` como parâmetro **obrigatório** no `write()`:

```python
# Antes (v0.6.x)
await memory.write(
    user_id="meu-agente",
    message="Meu nome é Pedro, moro em Botafogo.",
)
# Problema: criava entidade "user" + entidade "Pedro" + fatos duplicados

# Agora (v0.7.0)
await memory.write(
    user_id="meu-agente",
    message="Meu nome é Pedro, moro em Botafogo.",
    speaker_name="Pedro",
)
# Resultado: só entidade "Pedro", fatos corretos, zero duplicação
```

### O que muda na prática

1. **`speaker_name` é obrigatório** — toda chamada a `write()` precisa dele. Sem ele, dá `TypeError`. Se passar vazio, dá `ValueError`.

2. **Pronomes resolvem pro speaker** — "I", "me", "eu", "myself" agora resolvem pra `person:pedro` (se `speaker_name="Pedro"`), não mais pra um genérico `user:self`.

3. **Entidade "user" não existe mais** — o sistema nunca cria entidade "user". Sempre usa o nome do speaker.

4. **Sem mirror facts** — "Pedro trabalha na Stone" é 1 fato. O sistema NÃO cria "Stone emprega Pedro" como segundo fato. Antes criava.

5. **`run_write_pipeline()` também mudou** — se alguém usa a API avançada direto, agora recebe `speaker_name` como parâmetro.

## Breaking change

Sim, é breaking change. **Não tem problema** — ninguém está usando em produção além de nós testando. Não precisa de migration, não tem dado pra migrar.

Todo código que chama `write()` precisa adicionar `speaker_name`. É só isso.

## O que foi alterado

### Código (4 arquivos)

| Arquivo | O que mudou |
|---------|-------------|
| `src/arandu/client.py` | `speaker_name: str` obrigatório no `write()`, validação |
| `src/arandu/write/extract.py` | 3 prompts viraram templates com `{speaker_name}`, proíbem "user" e mirror facts |
| `src/arandu/write/entity_resolution.py` | Pronomes resolvem pro speaker (`person:{slug}`), não mais `user:self` |
| `src/arandu/write/pipeline.py` | Propaga `speaker_name` pro extraction e entity resolution |

### O que NÃO mudou

- Read pipeline (retrieve) — zero alteração
- Banco de dados / migrations — zero alteração
- Background jobs — zero alteração
- Reconciliation / upsert — zero alteração

### Testes

374 testes passando. Todos os testes existentes foram atualizados + 5 novos testes específicos pra speaker-aware extraction.

## O que pedimos de vocês

### 1. Rodar os cenários de teste

Tem uma bateria de 14 cenários em `.vibeflow/test-plans/speaker-aware-extraction-test-plan.md`. Cobrem:

- Caso base (apresentação pessoal)
- Pronomes em inglês e português
- Múltiplas entidades sem duplicação
- Edge cases (speaker_name diferente do nome na mensagem, apelidos, code-switching)
- Mensagens sobre terceiros
- Validações de erro (speaker_name vazio)
- Update cross-message (reconciliation com speaker)
- E2E write → retrieve

Cada cenário tem critério PASS objetivo. Rodem com LLM real (GPT-4o ou Claude) e reportem o output.

### 2. Avaliar a documentação

Atualizamos toda a documentação (EN + PT-BR) pra refletir o `speaker_name`. Peço que revisem com olho crítico:

- **Getting Started** (`docs/en/getting-started.md` e `docs/pt-BR/getting-started.md`) — o fluxo de onboarding faz sentido? A explicação de `user_id` vs `speaker_name` tá clara?
- **Write Pipeline** (`docs/en/concepts/write-pipeline.md` e `docs/pt-BR/concepts/write-pipeline.md`) — a seção de entity resolution sobre pronomes do speaker tá compreensível?
- **Cookbook** (`docs/en/cookbook.md` e `docs/pt-BR/cookbook.md`) — os exemplos estão corretos e completos?
- **Write API** (`docs/en/advanced/write-api.md` e `docs/pt-BR/advanced/write-api.md`) — a assinatura de `run_write_pipeline` tá atualizada?
- **API Reference** (`docs/en/reference/index.md` e `docs/pt-BR/reference/index.md`) — tá consistente?

Pergunta-chave pra avaliação: **se um dev que nunca viu o Arandu ler só os docs, ele vai entender que precisa passar `speaker_name` e por quê?** Se a resposta for não, me falem onde ficou confuso.

### 3. Verificar no banco

Após rodar os cenários, façam uma query direto no banco:

```sql
SELECT * FROM memory_entities WHERE entity_key = 'user:self';
```

Esperado: **zero linhas**. Se aparecer alguma coisa, tem bug.

## Resumo rápido

| Item | Status |
|------|--------|
| Código | Completo, 4 arquivos alterados |
| Testes unitários | 374/374 passando |
| CI (ruff + mypy + pytest) | Verde |
| Docs EN | Atualizados |
| Docs PT-BR | Atualizados |
| CHANGELOG | Atualizado |
| Versão | 0.7.0 |
| Cenários de teste | 14 cenários prontos |

A release precisa ser disparada manualmente no GitHub Actions quando estiverem satisfeitos com os testes.
