Adventure memory lifecycle
The production test account reached the 16-notebook creation limit. Deleting a native Adventure does not currently retire its notebook, so the limit is a lifetime limit instead of a simultaneous-story limit. Existing stories remain readable.
Implement confirmed native deletion as a queued campaign retirement in the account-bound save. Commit save revision CAS and notebook retirement in one transaction. Preserve active profiles, the legacy shared notebook, other accounts, other editions and unrecognized old notebooks. Keep a payload-free revision -1 marker for explicitly deleted campaigns so delayed replies cannot recreate their memory; exclude markers from the active-story quota. Normal revisions remain nonnegative. No schema migration is required.
The browser removes a pending retirement only after an explicit server acknowledgement. Failed saves, account switches, stale tabs and old hosts retain it. No automatic age-based pruning is authorized.
Checks: real local PostgreSQL-compatible storage for capacity, late writes and atomic rollback; browser save fixtures for confirmed deletion and acknowledgements; existing NPC/save tests, hosted build/typecheck/OSS verification. Production mutation requires the usual reviewed release flow. This file will record actual outcomes; the plan itself is not evidence of a fix.
Verified implementation
Confirmed menu deletion now captures the original campaign ID before the native engine selects the surviving profile. The browser uploads the queued retirement with the account save. The host validates the explicit queue, rejects active references, preserves other editions' references and commits retirement only after successful save CAS, in the same transaction. Revision -1 records contain only {}; stale writes cannot match or recreate them. Account, legacy and unrecognized conversations are preserved. Errors distinguish a full quota from a deleted campaign without calling a provider.
All 509 NPC/save checks and 715 web checks pass. The hosted build and typecheck pass. The new late-reply test proves deletion during generation prevents both memory restoration and a player debit. A first version appended that case after eight requests and correctly hit the existing rate limit; it now uses its own disposable account rather than weakening admission. The initial broad web command omitted the existing canvas runtime; its corrected invocation retains every assertion.
Compiled English desktop and Chinese 844×390 touch-emulated menu journeys use the real save service with local PGlite: fill 16 slots, create another native Adventure, confirm deletion of the old one while offline, reconnect, observe its atomic retirement, allocate the new memory and reload the surviving native profile. Both pass without page errors. They make no production writes or provider calls. Physical phones remain unverified. Browser evidence is under the game worktree's output/campaign-memory/; the immutable native engine remains 5f5e85c3fc.
OSS export verification initially hit a Windows race: shared:test and shared:build both cleaned shared/dist. Windows export tests now run serially; all exported build/typecheck/tests pass. Linux CI keeps its existing concurrency.
This is forward cleanup for explicitly deleted Adventures, not automatic reclamation of pre-existing orphan notebooks. Those records remain untouched; continuing an existing Adventure remains possible at capacity. Old hosts do not acknowledge retirement, so the browser retains the queue and retries at a bounded interval. Rolling the browser back preserves additive metadata; keep the new host lifecycle handling when rolling back presentation. No schema migration, bulk deletion or gameplay/pacing change is included.
