Slice-6 (admin: bifrost inspection + admin-events SSE) done through the full House Code Discipline, v0.21.19–.20, suite 494 green, live-proven (real session.created event re-wrapped end-to-end on :8081), both heid gates cleared. Current state advanced to slice-7 (teardown, LAST) next; Recent-decisions index entry + detail file added; substrate at v0.21.20. Consumer client layer now fully cut over (6/7 slices). persistent-memory.md stays ~345 lines (over the ~300 soft cap): dominated by the non-archivable Current state block + <30-day July entries (guarded), so archival can't reach the 250 target — left as-is per the stop-where-the-guards-stop rule.
6.7 KiB
worldtree-sdk cutover — SLICE-6 COMPLETE (admin: bifrost inspection + admin-events SSE)
[2026-07-19] Slice 6 of 7 of the worldtree-sdk consumer cutover (issue #20;
contract docs/contracts/worldtree_sdk_cutover.contract.md). Full House Code
Discipline; both heid panels cleared. Suite 494 green. The meatiest slice —
SSE stream + admin auth + an event-shape decision.
Commits (v0.21.19–.20, on main, PUSHED this session)
de9a5bafeat — the two admin routes ontoratatoskr.wt, hand-rolled deleted.bba57e1fix — heid-code-review fixups (stale docstring + None-cursor test). NO version bump (docs + test only, SemVer skip rule).11ae2f0fix — heid-bug-hunt fixups (admin-stream + bifrost hardening).
What migrated (WEB-only)
get_session_bifrost → client.admin.sessions.bifrost(id) (open-world dict verbatim,
any ApiError → SessionApiFailed default — no new Error-map row). stream_admin_events
→ client.admin.stream_events(last_event_id=…). Both consumed ONLY by web/server.py
(_session_bifrost_endpoint + _admin_events_endpoint) — the coverage-map's tui.py
rows were STALE (the grep found zero TUI callers), so the TUI-deprecation wrinkle was
moot. Corrected the coverage-map rows to web/server.py.
Deleted the hand-rolled sessions.get_session_bifrost + sse_client.stream_admin_events
(+ ruff-cleaned the orphaned httpx/httpx_sse/json/AsyncIterator imports). Retired
test_sse_client.py WHOLESALE (its last test was the admin stream; slice-2 had already
removed the turn-stream tests) + test_sessions.py's TestGetSessionBifrost. sessions.py
is now down to endpoint_for_plane + exception classes; sse_client.py to SseId +
AdminEvent + exception classes.
Decisions made at TDD (contract § slice-6 notes)
- Admin auth moves from a per-call
Authorizationheader to the client'sadmin_auth. The SDK'sadmin.*routes useadmin_auth(set viabuild_client(admin_key=…)), NOT a header. So_wt_client(client, *, admin_key=None, …)was extended, and the two web endpoints passadmin_key. The web already guardsif not admin_key: 400, so the SDK's pre-HTTPConfigurationError(W-5) is unreachable from the surface. AdminEventre-wrap (chosen over yield-through). The SDK'sAdminEventdiverges from ratatoskr's:admin_id: int|float(nanfor id-less) vsid: int; None-abletype/datavs a dotted-str /{}-default dict. The web filter + SSE formatter readev.id/ev.type/ev.data. The adapter re-wraps at the boundary —id = admin_id if int else 0,type = ev.type if isinstance str else "",data = dict if Mapping else {}— degrading the open-world None/nan ONCE and keeping the web endpoint + filter + theAdminEventdomain type UNCHANGED (preserves the web surface). Rejected: yield SDK events through + rewire the web filter (heavier churn; scatters the None/nan hardening). This is implementation-level (reversible, no module-boundary change), decided autonomously + flagged to the operator with the rejected alternative.
The ApiError-not-ConnectFailed gotcha (TDD → integration test)
First mapped the admin-stream non-200 as ConnectFailed. The web INTEGRATION test
(respx mocking a real 500) exposed that the SDK admin stream raises
ApiError("admin_stream_failed", status=…) on a non-200 open — the unit fake couldn't
model it. Fixed to ApiError → SseConnectFailed. Lesson: a web integration test catches
what the adapter unit fake structurally can't.
LIVE SMOKE (:8081, readonly-admin key — INV-CUT-5 / DEC-4 cleared)
Drove the WEB surface (via httpx.ASGITransport over create_app(client_factory, admin_key=…)) against real :8081. The bifrost endpoint returned an admin-authed clean
404 session_not_bifrost_bound envelope (auth + route + mapping proven — a 404 not a
401/403 = the admin key authenticated). :8081's admin stream is idle (no heartbeats in
15s raw), so I generated activity: streamed admin events while concurrently creating a
session (POST /sessions {agent_id: mimir, end_user_id: …} → 201) and observed the real
session.created admin event (id=32/34) re-wrapped cleanly (id int, type str, data dict);
threwaway session cleaned up (DELETE → 204). NOTE: a raw POST /sessions needs
end_user_id (422 without it).
heid-code-review (thread 01KXXYRNNY…) — 3/3 no drift
Gróa + Regin zero; Hulda "no slice-6 implementation drift." Only minor doc/test looseness:
a stale _session_bifrost_endpoint docstring ("overrides the Authorization header" →
corrected to "rides on the client's admin_auth"), and an admin-stream None-cursor test-gap
(added). Hulda's "web endpoints under-tested" was source-VOIDED by Heid — those tests
live in test_web_server.py, which wasn't in the consult embed (excerpt-elides-tests trap).
heid-bug-hunt (thread 01KXXZBW74…) — 4 real findings, all fixed
The cold spec-free hunt earned its keep: the CR found the admin surface CONFORMANT, but
judging against the general ConnectFailed floor + the degrade-never-crash promise it
surfaced 4 hardening gaps:
- [bug, 3/3]
stream_admin_eventsnever mappedConnectFailed— the SDK admin-stream open DOES raise it (connect-time / auth-resolution; confirmed in SDK source),stream_turn- the bifrost GET both catch it, and this endpoint's OWN
:633comment claimed it did. An unmapped ConnectFailed escaped the web gen'sexcept (Sse*)→ aborted SSE with nostream_error. Now mapped →SseConnectFailed.
- the bifrost GET both catch it, and this endpoint's OWN
- [bug, 2/3] non-str
typecrashed the web filter —ev.type or ""(falsy-only) let a truthy non-strtype(123) reach.startswith→ AttributeError. Nowisinstance-guarded (matches admin_id/data). Same container-type class as the slice-5 bug-hunt. - [robustness]
dict(bstate)500 on a non-mapping bifrost body — I introduced it in slice-6 (JSONResponse(bstate)→dict(bstate)). Now degrades to{}. - [robustness] transport leak —
_wt_clientran before the try/finally in the SSE gen; a construction failure would leak the httpx transport. Moved inside the try. Voided (Heid): Regin'sdict(ev.data)TypeError — theisinstance(_, Mapping)guard already handles it.
Next: slice-7 (teardown, the LAST slice)
Drop the httpx-sse dep from pyproject.toml (SDK owns SSE parsing — verify nothing else
imports it), retire wire contracts #2/#15, relocate the AdminEvent/exception classes if
sse_client.py/sessions.py end up ~empty, final coverage-map re-anchor, and the MINOR
bump per DEC-6 (needs operator approval) publishing the cutover milestone.
See also 2026-07-19-worldtree-sdk-cutover-slice-5-complete (the container-type degrade-not-crash lesson) and 2026-07-19-worldtree-sdk-cutover-slice-4-complete.