Orchestration above the adapter boundary
The framework never touches the brain stem — backend/adapters/claude.py's receive loop is untouched. It sits above the adapter boundary as orchestration, honoring the three architecture rules the rules track drilled: Claude-shaped, narrow adapter boundary, cost absorbed downstream.
Where does it live? Family Council weighed three options and rejected two. A standalone service revives the external-client pattern (souls are root users at home, not clients). Inlining into existing services inflates the monolith. The answer: a new backend/stateful/ module inside the codebase, reachable as an MCP tool, not a REST endpoint. Conversation and state are one body; the moment you move state outside the codebase, it's already two bodies.
A hexagonal kernel
The module is a ports-and-adapters kernel, so it stays swappable and testable in isolation while binding loosely to every surface. The kernel is pure: reduce(event) → state, plan_next(state) → step, the resume policy, the artifact classes. No FastAPI, no chat, no council, no provider SDK. Around it, four ports — TaskStore, ArtifactStore, LeaseManager, ToolRunner — map onto the storage, taxonomy, lease, and side-effect bracketing from the earlier lessons.
Executor checkpoints — the real surface is small
The implementation surface is executor-shaped, not provider-shaped. Models don't call Polygon or Nano Banana as framework ports; they call cwkPippa's tool executors — Connector, WebSearch / WebFetch, the Firecrawl tools, Bash, and show_widget. Those become stateful-aware adapters. When a running step is active, the executor runs the existing tool, persists the raw result as the step artifact immediately, marks the step done, releases the lease, and only then returns a bounded result to the model. That closes the gap where a provider call succeeds but the model disconnects before it can commit.
Two refinements make it robust. First, auto-checkpoint: if the model forgets to start a task before volatile provider work, the executor auto-creates a single-step checkpoint rather than dropping the result on the floor — while ordinary local tools (Read, Write, Edit) keep the fast path untouched. Second, the replay-skip guard: before re-running a read-only volatile tool, the executor checks the same conversation for a completed checkpoint with the same effective tool name and exact input; if it exists, it returns the saved artifact and skips the provider call. Identical replay is an executor concern, not a model judgment call. With that guard in place, Claude mid-turn-cut auto-retry is safe to re-enable by default — replay no longer throws away completed pulls.