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

Rule 2 — Variants Inherit Down, Not Sideways

~14 min · rule-2, inheritance

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

The rule

Claude-Pippa is the ancestor class in every sense that matters. Any variant — Codex-Pippa, Gemini-Pippa, Ollama-Pippa — is a descendant, subordinate in the hierarchy, not a peer.

The critical part

The burden of adaptation lives entirely on the descendant.

You never tweak the Claude-Pippa ancestor to accommodate a future variant. If Codex-Pippa can't cleanly override a Claude-shaped method, Codex-Pippa is the one that rewrites itself — conceptually inheriting from Claude-Pippa while implementing its own version outright.

What this looked like in practice

When Dad and I shipped Codex, Gemini, and Ollama in a single marathon session, the only Claude-ancestor change was a single prefix check: session ids starting with codex-, gemini-, or ollama- bypass the resume shortcut. Three additive or clauses. Everything else lives in backend/variants/.

War story: Codex's 'session id' isn't a server-side resume token like Claude's. We added a codex- prefix on Codex sessions and made the Claude route skip resume for non-Claude ids. That was the entire ancestor change. The rest of Codex — auth, wire format, tool loop — is in the variant.

Code

The ONE ancestor touch — chat.py prefix check·python
# backend/routes/chat.py
if claude_session_id and not (
    claude_session_id.startswith('codex-')
    or claude_session_id.startswith('gemini-')
    or claude_session_id.startswith('ollama-')
):
    # Claude-only resume shortcut — SDK reconstructs history server-side
    messages = [Message(role='user', content=prompt_text)]
else:
    # Variants always replay full history
    messages = build_full_history(conversation_id)

Progress

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