`[2026-07-19]` **worldtree-sdk cutover — SLICE-1 + SLICE-2 COMPLETE + PUSHED (origin `aba1730`, v0.21.10).** The consumer client layer's biggest, riskiest slice (sessions/turn) is fully migrated onto `worldtree-sdk (Python) 1.0.0` behind the `ratatoskr.wt` adapter, run end-to-end through the House Code Discipline. Pushed 2026-07-19 (12-commit arc `b1fbadd`→`aba1730`, tags v0.21.3–.10). Suite **497 green**. ## The arc (all on origin/main) | Part | Commit | What | |---|---|---| | Slice-1 foundation | `12cd864` (v0.21.3) | `build_client` + `translate_error` DEFAULT (ApiError→SessionApiFailed) + passthrough; INV-CUT-1 (injected transport, `_owns_client=False`) test-proven | | Slice-2 adapter (read/create) | `bb158ae` (v0.21.4) | create/list/messages/tools over `client.sessions.*`, per-route error mapping | | Slice-2 adapter (stream/cancel) | `b907a7b` (v0.21.5) | resilient `stream_turn` + `cancel_turn`; SDK stream errors re-wrapped → ratatoskr caller-semantic exceptions (DEC-2) | | Slice-2 CLI rewire | `e3a10ad` (v0.21.6) | `_amain`/`_run_turn`/render onto SDK `TurnEvent`s + open dicts | | Slice-2 web rewire | `5c595b8` (v0.21.7) | Starlette endpoints + SSE→JSON serialization; browser contract preserved | | Slice-2 deletion | `59602fe` (v0.21.8) | sse_client 714→224, sessions 677→608; orphaned turn-stream family + Event model removed; **DEC-4 live-smoke PASSED first** | | heid-code-review fixup | `74d41eb` (v0.21.9) | INV-CUT-2 completeness (cancel/stream ApiError default) + contract error-map amendments | | heid-bug-hunt fixup | `aba1730` (v0.21.10) | 4 confirmed bugs + open-world render hardening | ## KEY ADAPTER FACTS (foot-guns for slices 3-7) - **The SDK returns open-world dicts** (`Mapping`, NOT typed objects) for session reads → presenters read mappings (`info["session_id"]`), never attributes. Ratatoskr's typed `SessionInfo`/`SessionPage` retired. - **SDK `TurnEvent` shape:** `sse_id: str` (the composite `"{turn}:{seq}"`) + a **body-derived `turn_id` that is ABSENT (None) on text/thinking frames.** The mid-stream cancel target must parse the turn from `sse_id`, NOT read `event.turn_id`. (This was a live bug — sigint-cancel saw "no event".) - **The SDK normalizes transport failures to `ConnectFailed(status=0)`** (not raw httpx errors) → presenters catch `wtsdk.ConnectFailed` for network paths; a stream `ConnectFailed` maps → `SseConnectFailed`. - **The adapter re-wraps SDK stream errors → ratatoskr's caller-semantic exceptions** (DEC-2 keeps ratatoskr's typed exceptions; SessionRetired→SessionApiFailed, ConnectionDropped→SseConnectionDropped, Malformed*/ TurnIdFlip→same-named, ConnectFailed/terminal ResumeError→SseConnectFailed). - **`consumer_key` is BOUND-create-only** — the adapter nulls it when `bifrost is None`, else the SDK's credential precedence auths as the consumer instead of the default bearer. - **The SDK's error-envelope parser PREFERS the nested `detail`** dict when present, so a top-level `error_code` doesn't surface. That's why create's bound-502 is NOT gated on error_code (unlike list's 422+cursor_invalid, whose flat body surfaces the code) — INV-002 also makes the handshake the sole bound-502 cause. This is a genuine cross-frontier triage win: 2/3 heid arms flagged the missing gate; it was correctly REJECTED as category-5 wrong-grounding (the SDK parser wasn't in the arms' file set). ## The two heid gates (the value proof) - **heid-code-review** (Gróa+Hulda substantive, Regin zero=weak): adopted the cancel/stream ApiError-default completeness + error-map table amendments; correctly rejected the bound-502-gate finding (above). - **heid-bug-hunt** (Gróa 8 / Hulda 6 / Regin 6; Heid source-checked, refuted 2 Regin FPs): caught **4 real confirmed bugs the conformance lens structurally could not see** — SessionRetired(410) uncaught by both presenters (crash/dropped-stream), cli consumer_key forwarded on unbound create (auth divergence), sse_id None-crash, cancel never-raise gap — plus open-world render hardening. Rejected 4 as verified FPs (incl. Hulda's "deleted funcs break callers" — grep-verified zero callers pre-deletion). Both surfaces re-smoked live after fixup: create+stream+cancel round-trip clean on :8081 (b128). ## What's still hand-rolled (later slices) `create_session`/`get_session_messages` (the `--seed-first-message` probe uses them — retire in slice-3); `set_persona_state`/`write_authored_history`/`first_message` (slice-3); agents/tier3 incl. `model`→`role` (slice-4, deploy live b128); characters/me/capabilities/models (slice-5); `stream_admin_events`/ `get_session_bifrost` (slice-6). Slice-7 teardown: retire contracts #2/#15, drop `httpx-sse`, minor bump (DEC-6, operator approval). Full design → auto-memory `project_worldtree_sdk_cutover`.