marauder-actual 4594f07ebc feat(calibration): 10-question battery, config-driven voice, WCAG-safe theme
Rework calibration.py into a fixed 10-question battery:
  - 4 critical questions (language, name, persona name, gender)
  - 6 random probes drawn from the 12-item pool (all AI/tech-unrelated)

Theme inference (palette × typography × density × labels):
  - Palette: warmth × contrast × energy → default|rose|morning|evening|
    sage|paper|ink; all choices verified WCAG AA ≥4.5:1.
  - Typography: elaborate+warm → serif-warm; cool+ink → mono;
    high-contrast+cool → serif-formal; energetic+warm → mixed-modern;
    otherwise sans.
  - Density: elaborate cadence → airy; terse → dense; else normal.
  - Labels: serif-warm/mixed-modern → cursive; mono → prefix; else block.

Voice selection:
  - Removed VOICE_POOL (lang × gender heuristic).
  - Added _load_persona_voices(): reads [voices.<lang>].id from a
    cart.toml persona file at PCART_CONFIG_PATH or app/conf/persona.toml.
    Falls back to FALLBACK_VOICES when no file is present.
  - _pick_voice(lang) selects by language key only — no gender heuristic.

cart_store.Cart changes:
  - Added calibration_version: int = 1 (new carts emit 2)
  - Bumped version: 3 → 4
  - Removed unused  import

No changes to app/main.py — calibration wiring was already correct.
2026-05-29 14:00:14 +02:00

chat.saiden.dev

A quiet channel. Spike Jonze's Her (2013) as a chat UI.

chat.saiden.dev
  → Caddy reverse-proxy (TLS via Let's Encrypt)
  → FastAPI on marauder.saiden.dev:8765
      ├─ Google OAuth (authlib) + email whitelist
      └─ WebSocket → Anthropic API streaming

Status

Phase 3 — Her-aesthetic. UI plan in UI-PLAN.md. Phase 1 (ttyd + CF Tunnel) archived in _archive-ttyd/.

Local dev

cd ~/Projects/chat-saiden
uv sync
cp .env.example .env
# fill in ANTHROPIC_API_KEY, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, COOKIE_SECURE=false
uv run python -m app.main
# → http://127.0.0.1:8765

Google OAuth redirect URI for local dev (add to your Google Cloud Console OAuth client): http://127.0.0.1:8765/auth/callback

Files

Path What
app/main.py FastAPI: OAuth, session, WS streaming, Anthropic client
app/templates/chat.html Single-page UI (chat + operator prompt)
app/templates/denied.html Whitelist-rejection page, Her-styled
app/static/chat.css Design system: warm pastels, Cormorant + Caveat
app/static/chat.js WebSocket, typewriter queue, label dedup, smooth scroll
pyproject.toml uv deps
.env.example env scaffold
UI-PLAN.md Design doctrine (Her aesthetic translated to chat)
_archive-ttyd/ Phase 1 (ttyd + CF Tunnel + CF Access) — kept for reference

Deployment

Not deployed yet. Stages remaining:

  1. Caddyfile on marauder.saiden.dev (reverse proxy chat.saiden.dev → :8765)
  2. systemd unit for the FastAPI app
  3. DNS swap: chat.saiden.dev CNAME → marauder.saiden.dev (currently broken — points to deleted CF tunnel from Phase 1)
  4. Google OAuth client production redirect URI: https://chat.saiden.dev/auth/callback
  5. Smoke test live

Persona

System prompt currently hardcoded as BT-7274 (placeholder). Will swap to a dedicated Samantha cart when authored — see EEMS subject project.samantha-cart.

S
Description
Web chat interface with persona calibration, SSE streaming, and real-time TTS playback.
Readme 182 KiB
Languages
Python 65.5%
JavaScript 12.3%
CSS 12.1%
Shell 6.2%
HTML 3.9%