C.W.K.
Lesson 05 of 06 · published

The Adapter Boundary — Narrow Polymorphism Only

~12 min · adapter, polymorphism

Level 0Curious
0 XP0/52 lessons0/16 achievements
0/100 XP to next level100 XP to go0% complete

One narrow boundary

cwkPippa has exactly one place where polymorphism is intentional: the streaming-API boundary in backend/adapters/base.py. Everything above that boundary — routes, store, services, frontend — is Claude-shaped.

Why narrow

The wire protocols genuinely differ. Claude has thinking blocks. Codex has a function-calling loop without server-side resume. Gemini has thoughtSignature preservation and dual-path auth. Ollama has its own tool schema wrapping. Below that boundary, we accept the difference. Above it, we don't.

What's above the boundary

  • Routes: chat.py assumes Claude-shape (with prefix-check escape hatch).
  • Store: conversations table has claude_session_id column. Storing Codex/Gemini/Ollama ids in it is fine — they fit Claude's shape (string id + history reconstructed elsewhere).
  • JSONL ground truth: every line is Claude-Code-compatible message format. cwkPippa-specific fields live in a nested pippa sub-object — Rule 2 expressed in the data format itself.
The principle: A 'narrow boundary' isn't a compromise. It's an admission that some differences are unavoidable (wire protocols) and others are imagined (everything else). Drawing the boundary in the right place is the architectural skill.

Progress

Progress is local-only — sign in to sync across devices.