memory: /snapshot — worldtree-sdk cutover slice-1+2 complete + pushed (aba1730)
Slice-2 (sessions/turn) done end-to-end through the House Code Discipline; both heid gates triaged+fixed. Captures the KEY ADAPTER FACTS foot-guns for slices 3-7 (open-world dicts, body-derived turn_id, ConnectFailed(0) transport normalization, consumer_key bound-only, nested-detail error_code parsing) + the two-lens gate value proof. Slice-3 (persona/authored-history) next.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
`[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`.
|
||||
+38
-34
@@ -1,6 +1,6 @@
|
||||
# Persistent memory — ratatoskr
|
||||
|
||||
_Last updated: 2026-07-18_
|
||||
_Last updated: 2026-07-19_
|
||||
|
||||
> **Always check for `/tmp/ratatoskr-dev-handoff.md`** — if it exists and its
|
||||
> `Written:` stamp is under an hour old, read it (it carries the in-flight
|
||||
@@ -44,34 +44,38 @@ upstream API key stays server-side (INV-003).
|
||||
|
||||
## Current state / in-flight
|
||||
|
||||
_As of 2026-07-18 (evening):_
|
||||
_As of 2026-07-19:_
|
||||
|
||||
**🔨 ACTIVE MIGRATION — worldtree-sdk cutover (issue #20), starting slice-1.** Operator ruled ADOPT
|
||||
(2026-07-18): ratatoskr cuts its CONSUMER client layer over to consume **worldtree-sdk (Python) 1.0.0** —
|
||||
retire the hand-rolled httpx wrappers (`sessions`/`sse_client`/`tier3`) behind a thin `ratatoskr.wt`
|
||||
adapter over the SDK. Both TS + Python SDK 1.0.0 are GA (**Python live + pip-installable on the gitea
|
||||
PyPI** — DEC-5 gate cleared). Ratatoskr's own **parity pass shaped the Python spine** (open-world reads,
|
||||
caller-injected transport, per-wire role/model). Design locked (6 DECs, vor-cross'd with worldtree-codex,
|
||||
heid-panel-reviewed → error-map table added); contract `docs/contracts/worldtree_sdk_cutover.contract.md`
|
||||
(committed `e45640c`). **SLICE-1 IN PROGRESS:** ✅ dep integrated + DEC-5 verified + committed (`29c4fda`) — `worldtree-sdk==1.0.0`
|
||||
installs from the gitea registry (reuses bifrost's index auth, NO new token; core dep + `[tool.uv.sources]`),
|
||||
`WorldtreeClient` constructs with an injected transport (`_owns_client=False`, INV-CUT-1 confirmed live),
|
||||
suite 534 green. **NEXT = the adapter** `src/ratatoskr/wt.py` (TDD): `build_client(base_url, *, api_key,
|
||||
admin_key, transport)` → `WorldtreeClient(auth=, admin_auth=, transport=)` (DESIGN CARE: SDK does per-request
|
||||
auth via the providers; our injected `httpx.AsyncClient` carries base_url/UA/timeout, NOT the Authorization
|
||||
header — read the SDK `client.py` @ `~/development/worldtree-sdk` for the split, INV-CUT-1) + `translate_error`
|
||||
DEFAULT (SDK `ApiError`→`SessionApiFailed`, discriminated `WorldtreeError` subclasses passthrough; route-specific
|
||||
rows come in later slices). Unit-test; NO surface wiring (slice-2). Then slices 2-7 (route-family + deletions,
|
||||
live-smoke per slice). Scope: consumer layer ONLY;
|
||||
Bifrost provider planes untouched. Multi-session grind. Full design → auto-memory
|
||||
`project_worldtree_sdk_cutover`. This SUPERSEDES the #371 "repin rides the later Python milestone" framing
|
||||
below (that milestone shipped; we're adopting, not just repinning).
|
||||
**🔨 ACTIVE MIGRATION — worldtree-sdk cutover (issue #20): SLICE-1 + SLICE-2 COMPLETE + PUSHED, slice-3 next.**
|
||||
Operator ruled ADOPT (2026-07-18): ratatoskr cuts its CONSUMER client layer over to **worldtree-sdk (Python)
|
||||
1.0.0**, retiring the hand-rolled httpx wrappers behind a thin `ratatoskr.wt` adapter. Design locked (6 DECs,
|
||||
vor-cross'd, heid-panel-reviewed); contract `docs/contracts/worldtree_sdk_cutover.contract.md`. **SLICE-1
|
||||
(adapter foundation) ✅ + SLICE-2 (sessions/turn) ✅ DONE + PUSHED** — origin at `aba1730` (12-commit arc
|
||||
`b1fbadd`→`aba1730`, tags v0.21.3–.10, pushed 2026-07-19): adapter (`b907a7b`, all 6 route families
|
||||
create/list/messages/tools/stream/cancel + the § Error-map mapping) → CLI rewire (`e3a10ad`) → web rewire
|
||||
(`5c595b8`) → orphan deletion (`59602fe`, sse_client 714→224 + sessions 677→608; DEC-4 LIVE-SMOKE PASSED on
|
||||
:8081 create+stream+cancel FIRST) → heid-code-review fixup (`74d41eb`) → heid-bug-hunt fixup (`aba1730`).
|
||||
Suite **497 green**. **KEY ADAPTER FACTS (foot-guns for slices 3-7):** the SDK returns **open-world dicts**
|
||||
(not typed objects) for session reads → presenters read mappings, `info["session_id"]`; SDK events
|
||||
(`TurnEvent`) carry `sse_id: str` + a **body-derived `turn_id` that's ABSENT on text/thinking frames** → parse
|
||||
the cancel target's turn from the composite `sse_id`, NOT `event.turn_id`; the SDK **normalizes transport
|
||||
failures to `ConnectFailed(status=0)`** (not raw httpx) → presenters catch it; the adapter re-wraps SDK stream
|
||||
errors → ratatoskr caller-semantic exceptions (DEC-2, keep ratatoskr's typed exceptions); `consumer_key` is
|
||||
BOUND-create-only (adapter nulls it when unbound, else the SDK auths as the consumer); the SDK's error-envelope
|
||||
parser **prefers the nested `detail`** so a top-level `error_code` doesn't surface (why create's bound-502 is
|
||||
NOT gated on error_code, unlike list's 422). **NEXT = slice-3** (persona `set_persona_state` + authored-history
|
||||
`write_history` + first_message presets — retires the still-hand-rolled `create_session`/`get_session_messages`
|
||||
that the `--seed-first-message` probe uses); then slice-4 (agents/tier3, FOLDS the `model`→`role` cutover),
|
||||
slice-5 (characters/me/caps), slice-6 (admin — `stream_admin_events`+`get_session_bifrost` still hand-rolled),
|
||||
slice-7 (teardown: retire contracts #2/#15, drop `httpx-sse`, minor bump per DEC-6 w/ operator approval).
|
||||
Scope: consumer layer ONLY; Bifrost provider planes untouched. Full design → auto-memory
|
||||
`project_worldtree_sdk_cutover`.
|
||||
|
||||
**⏸️ DEFERRED — tier3 agents `model`→`role` (scope B), on worldtree-dev's deploy flag.** WT renames the
|
||||
agents-RESPONSE selector `model`→`role` (spec 1.2, commit `387c67b`, NOT yet deployed). `_parse_tier3_agent_info`
|
||||
reads `body["model"]` → KeyErrors post-deploy. Operator chose scope B (full tier3 `model`→`role` incl.
|
||||
contract #15 + CLI `--model`→`--role`). Implement ON the deploy flag, not before (breaks the current demo);
|
||||
folds into cutover slice-4. Auto-memory `project_tier3_agents_model_to_role_pending`.
|
||||
**⏸️ DEFERRED — tier3 agents `model`→`role` (scope B), folds into cutover slice-4.** WT renamed the
|
||||
agents-RESPONSE selector `model`→`role` (spec 1.2). **DEPLOY NOW LIVE** on :8080/:8081 (v1.0.0b128,
|
||||
worldtree-dev confirmed 2026-07-19 — was the deploy-flag gate; acked). Operator chose scope B (full tier3
|
||||
`model`→`role` incl. contract #15 + CLI `--model`→`--role`); lands in cutover slice-4 where tier3.py routes
|
||||
through the SDK (doing it standalone now = throwaway). Auto-memory `project_tier3_agents_model_to_role_pending`.
|
||||
|
||||
**✅ RESOLVED — the "app product" workstreams leave Rata entirely (operator 2026-07-18).**
|
||||
**No arbo fork, no SillyTavern-on-Rata** — a NEW repo (template-dev standing up) takes over BOTH
|
||||
@@ -115,13 +119,12 @@ Full record → `persistent-memory.d/2026-07-18-368-silo-test-passed.md`. Siblin
|
||||
(2) R39 Phase-2 **matched-quartets rebuild** (confirmatory, "whenever"); (3) bifrost **snapshot-cursor
|
||||
adoption** (ruled normative, not blocking → `persistent-memory.d/2026-07-16-bifrost-cursor-conformance.md`).
|
||||
|
||||
**Substrate / environment:** branch `main` at **v0.21.2**. **origin at `b1fbadd`** (pushed 2026-07-18:
|
||||
canonical syncs `5d06a27`/`80c8d58`, ephemeral-Echo `c7016f2` #19, coverage-map→SDK-surface `b1fbadd`).
|
||||
**UNPUSHED local commits** (cutover work — operator hasn't pushed): cutover contract `e45640c` #20, the
|
||||
`memory:` snapshot, dep-integration `29c4fda` (worldtree-sdk==1.0.0), + this snapshot — **push is the
|
||||
operator's call**. origin `git@gitea.phasefinal.com:vh/ratatoskr.git`. **NEW core dep: `worldtree-sdk==1.0.0`**
|
||||
(gitea PyPI, `[tool.uv.sources]`). bifrost **`==1.1.4`** / wire v0.7; WT openapi vendored 2.3.0,
|
||||
**conversation-api-spec re-synced to v1.1** (`b4a278c`); **suite 534 green**. Personal WT on **b127**
|
||||
**Substrate / environment:** branch `main` at **v0.21.10**, **fully PUSHED to origin at `aba1730`** (slice-2
|
||||
cutover arc `b1fbadd`→`aba1730` + tags v0.21.3–.10 pushed 2026-07-19). origin
|
||||
`git@gitea.phasefinal.com:vh/ratatoskr.git`. **NEW core dep: `worldtree-sdk==1.0.0`** (gitea PyPI,
|
||||
`[tool.uv.sources]`; `httpx-sse` retires at slice-7). bifrost **`==1.1.4`** / wire v0.7; WT openapi vendored
|
||||
2.3.0, **conversation-api-spec re-synced to v1.1** (`b4a278c`); **suite 497 green** (was 534 pre-cutover; net
|
||||
delta = adapter/rewire tests added, ~80 deleted hand-rolled turn-stream tests). Personal WT on **b128**
|
||||
(`http://10.250.50.152:8081`; #368 silo + #364 promotion-hygiene live both instances). The combined
|
||||
**:8392** provider (memory+affect) + **:8765** web are THE surfaces, dev-box BACKGROUND SHELLS —
|
||||
restart via `scratchpad/relaunch_by_pid.py <pid>` (pid via `ss -ltnp | grep <port>`). `env.sh` sets
|
||||
@@ -271,6 +274,7 @@ decision. Captures rationale that won't be obvious from code alone.
|
||||
- `[2026-07-18]` **ephemeral-template (Echo) create SHIPPED (`v0.21.2`, `c7016f2`, #19)** — `config` passthrough + `--system-prompt` + `SessionInfo.kind/config` + `--whoami` roles fix. Diagnosed from the ignored `session_api_failed` startup line; role/model drift resolved w/ worldtree-dev (spec re-synced v1.1). TDD + heid contract-review + bug-hunt.
|
||||
- `[2026-07-18]` **Rata = THE reference consumer of the worldtree-sdk Python spine** — parity pass (12 grounded findings) shaped its contract BEFORE build (open-world reads, caller-injected transport, per-wire role/model — adopted); coverage-map re-anchored to the SDK's 41-op ratified surface (`b1fbadd`); 4 ergonomics items parked post-v1 with wtsdk-dev.
|
||||
- `[2026-07-18]` **worldtree-sdk cutover DECIDED — adopt the Python SDK for the consumer client layer** (operator, overriding "stay hand-rolled"). Issue #20; contract `docs/contracts/worldtree_sdk_cutover.contract.md` (`e45640c`, vor-cross'd + heid-reviewed); auto-memory `project_worldtree_sdk_cutover`. Consumer layer only, Bifrost provider untouched; slice-1 foundation next. See in-flight.
|
||||
- `[2026-07-19]` **worldtree-sdk cutover SLICE-1 + SLICE-2 COMPLETE + PUSHED (origin `aba1730`, v0.21.10, 497 green).** The biggest, riskiest cutover slice done end-to-end through the full House Code Discipline (adapter→cli→web→delete→live-smoke→both heid gates); the bug-hunt caught 4 real confirmed bugs the conformance lens couldn't, and a convergent code-review finding was correctly REJECTED as category-5 (SDK envelope-parser behavior). Slice-3 next. → `persistent-memory.d/2026-07-19-worldtree-sdk-cutover-slice-1-2-complete.md`
|
||||
|
||||
_65 older entries (2026-05-* debug-TUI/web era + the 2026-06-14 → 06-18 Bifrost-provider build / #17+#18 / #295-296 era) archived to archival-memory.md._
|
||||
|
||||
|
||||
Reference in New Issue
Block a user