Keep the local Claude test rig, and record what it found

`backend/tools/claude_shim.py` serves an OpenAI-compatible endpoint backed by
the local `claude` command line tool, so a demo can be played against a real
model with no API key. Each request spawns one `claude --print` process, which
suits the turn engine: the app assembles the whole prompt every turn and
expects a stateless endpoint.

Playing the Pokemon demo through it made all five of the world-state changes in
`plan/16` work, and the refusal loop ran end to end for the first time: turn 3
clamped to nothing, turn 4's assembled prompt carried the correction verbatim,
and the model's next delta was right. Two failures previously blamed on the
code were the demo model. One is a schema fault and is still open: Milo's three
Pokemon share one `active_hp` stat, so a switch leaves the newcomer at 0 HP.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PacdRuPXSkQQy4ZYdH32hF
This commit is contained in:
parththakkar106
2026-08-28 18:42:24 +05:30
co-authored by Claude Opus 5
parent 6cbf6d996f
commit ef4da7fda2
5 changed files with 470 additions and 5 deletions
+8
View File
@@ -954,6 +954,14 @@ guest survives with no re-parenting and no migration step. Three kinds of row sh
users table: local (email NULL, not guest), guest (email NULL, guest), registered (email
set).
**Guests start with a story already in progress.** `starter.py` copies a shipped export
bundle into each new guest account at the same point the row is created. An empty account
gives a visitor nothing to read, and the daily demo turns are limited, so learning what
the app does used to cost one of them. The copy is the guest's own from the first moment:
they can edit, branch, delete, or export it, and nothing links it back to the file. The
guest row is committed before the copy is attempted, so a failure there still leaves them
with an account, and the copy itself runs inside a savepoint.
**Guests expire; accounts don't.** One row per curious visitor adds up, so `cleanup.py`
deletes guests idle for `AIDND_GUEST_RETENTION_DAYS` (default 5), measured as
`COALESCE(last_seen_at, created_at)`, because `_touch` only writes `last_seen_at` hourly