# Next Session: Cross-Channel Calling v2 — Contact Management + E2E Hardening

## What was built (Session 421)
Cross-channel call initiation: Telegram → `make_phone_call` tool → Panda phone API (port 8770) → file-based IPC → phone daemon → ADB dial → Annie converses → post-call Telegram notification.

**7 commits**: `e4810fe` → `d1dc532`. **2689 tests pass.** Full pipeline E2E verified on Reethi's number.

## What works
- "Call Reethi, her number: 7899488319" → Annie queues call → Pixel dials ✅
- OFFHOOK polling (no greeting into voicemail) ✅
- Auto-answer loop yields to outgoing call requests ✅
- Speaker identity for third-party calls (transcript labels callee, not Rajesh) ✅
- Contact lookup from notes when no number provided ✅
- `start.sh` passes all env vars inline (no manual .env edits needed) ✅

## What needs work

### 1. Contact Book (Rajesh has ideas)
**Current**: Phone numbers stored as free-text notes via `save_note(category="people")`. Lookup uses regex to find numbers in text mentioning the name. Fragile.

**Problem**: When Rajesh said "Call Roshni" (no number), Annie searched notes, found nothing, and returned "I don't have Roshni's number." But the LLM paraphrased it as "requires a private channel for security" — confusing.

**Open questions for Rajesh**:
- Should contacts be a structured store (JSON file with name→number mapping)?
- Or should Annie use the existing `people` notes category with a standard format?
- Should Annie auto-save numbers when given? ("Call Reethi, her number: 7899488319" → also saves it)
- Should contacts come from the Pixel's actual contact book via ADB (`adb shell content query --uri content://contacts`)?

### 2. LLM Response Quality
Annie's handler returns clean messages like "I don't have Roshni's number. What's Roshni's number?" but the LLM (Nemotron Super on Beast) paraphrases them into something different/worse. Consider:
- Returning the message as a `[DIRECT_RESPONSE]` that bypasses LLM rewriting
- Or making the handler message so clear the LLM preserves intent

### 3. Reethi Call Didn't Complete
Four calls were queued to Reethi. The first was consumed but the daemon was stuck in auto-answer (fixed in `24c9b51`). The second was attempted — ADB dialed but OFFHOOK poll saw IDLE immediately (fixed 3s delay in `d1dc532`). Calls 3 & 4 were queued while Rajesh was on a live phone call with Annie — they may have been consumed while the daemon was busy.

**Need to verify**: Restart daemon fresh → send one "Call Reethi" → confirm full call lifecycle (dial → ring → Reethi answers → Annie greets → conversation → hangup → Telegram notification).

### 4. Post-Call Telegram Notification
`TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` are now passed to the daemon via `start.sh`. But untested — the one live call that dialed immediately returned "no answer." Need E2E test of the notification path.

## Key files
- `scripts/phone_api.py` — Panda HTTP API (aiohttp, port 8770)
- `scripts/phone_call.py` — Phone daemon (request file check at loop top + inside auto-answer poll)
- `services/annie-voice/phone_loop.py` — `run_conversation()` with context/callee_name, OFFHOOK polling, post-call notify
- `services/annie-voice/text_llm.py` — `_dispatch_make_phone_call` handler + `_lookup_contact_number`
- `services/annie-voice/tool_schemas.py` — `MakePhoneCallInput`
- `services/annie-voice/tests/test_make_phone_call.py` — 40 tests
- `start.sh` — inline env vars for Annie + phone daemon + phone API
- Plan: `~/.claude/plans/swirling-tinkering-flute.md` (v2, 25 adversarial findings)

## Env var cheat sheet (all handled by start.sh now)
| Var | Where | Value |
|-----|-------|-------|
| `PHONE_CALL_ENABLED` | Titan (Annie) | `true` (inline in start.sh) |
| `PANDA_PHONE_URL` | Titan (Annie) | `http://192.168.68.57:8770` (inline) |
| `PHONE_CALL_TOKEN` | Titan + Panda | Read from `~/.her-os-phone-token` |
| `TELEGRAM_BOT_TOKEN` | Panda (daemon) | Read from telegram-bot/.env (inline) |
| `TELEGRAM_CHAT_ID` | Panda (daemon) | Read from telegram-bot/.env (inline) |

## Start command
```bash
# Everything is wired into start.sh — just:
./start.sh panda    # starts phone daemon + phone API
./start.sh annie    # starts Annie voice with make_phone_call enabled
```
