> For the complete documentation index, see [llms.txt](https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/.spec_system/archive/sessions/phase30-session05-persistence-and-save-contracts/spec.md).

# Session Specification

**Session ID**: `phase30-session05-persistence-and-save-contracts` **Phase**: 30 - AI Rogue Game Extension **Status**: Not Started **Created**: 2026-06-22

***

## 1. Session Overview

This session formalizes AI Rogue browser-local persistence after the Session 04 Ledger proved deterministic economy claims with a narrow localStorage guard. It adds versioned Zod contracts for preferences, wallet, ledger entries, run history, save slots, reset behavior, and migration boundaries so later dungeon simulation and upgrade sessions can attach to stable state instead of ad hoc browser writes.

It is next because Sessions 01-04 have locked the product direction, mounted the disabled-first extension, proven the lazy PixiJS runtime boundary, and implemented the `Insight Shards` economy and claim idempotency. Session 07 depends on durable save/load and wallet contracts, and Session 06 needs a clear boundary for future run snapshots without coupling simulation code to browser APIs.

The scope stays intentionally coarse. This session stores preferences and reset intent in tiny localStorage records, stores wallet, ledger, run history, and save slots in IndexedDB, and wires React surfaces to loading, empty, malformed, error, and reset states. It does not add combat, dungeon simulation, spendable upgrades, relic effects, or generated runtime data writes.

***

## 2. Objectives

1. Define versioned AI Rogue save contracts with Zod defaults and migration tests for preferences, wallet, ledger, run history, save metadata, and future runtime snapshots.
2. Add browser-local persistence helpers that use localStorage for tiny preferences and IndexedDB for larger wallet, ledger, run history, and save records.
3. Bridge the existing Session 04 claim-store behavior into the new ledger and wallet persistence path without breaking refresh idempotency.
4. Wire Settings, Ledger, Loadout, and Play surfaces to save/load/reset states with explicit loading, empty, malformed, error, offline, and unavailable handling.
5. Prove that malformed, missing, stale, and partial records are safely handled and that reset clears only AI Rogue browser-local state.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase30-session01-direction-and-asset-readiness` - Locked AI Rogue naming, local-first posture, currency language, asset boundaries, and privacy non-goals.
* [x] `phase30-session02-extension-shell-and-routes` - Registered Play, Ledger, Loadout, and Settings views plus initial browser-local capability declarations.
* [x] `phase30-session03-pixijs-runtime-boundary` - Proved route-scoped runtime lifecycle, reset controls, and no shared PixiJS chunk leakage.
* [x] `phase30-session04-economy-and-ledger` - Added deterministic economy snapshots, stable redemption keys, localStorage claim idempotency, and privacy-safe Ledger UI.

### Required Tools Or Knowledge

* Existing AI Rogue economy contracts in `src/extensions/ai-rogue/economy.ts` and `src/extensions/ai-rogue/economy-schema.ts`.
* Existing claim compatibility helper in `src/extensions/ai-rogue/claim-store.ts`.
* Existing AI Rogue views under `src/extensions/ai-rogue/views/`.
* Extension capability declarations in `src/extensions/types.ts` and `src/extensions/ai-rogue/capabilities.ts`.
* Vitest happy-dom patterns, React Testing Library, and Playwright route interception patterns already used by AI Rogue tests.

### Environment Requirements

* Bun 1.3.14 project tooling.
* React 19, TanStack Router/Start, Vite 8, Tailwind CSS 4, Zod, Vitest, happy-dom, Playwright, and Chromium.
* Browser localStorage and IndexedDB availability with denial or failure handled as normal degraded states.

***

## 4. Scope

### In Scope (MVP)

* AI Rogue maintainer can parse persisted local data safely - implemented with versioned Zod schemas, defaults, migration helpers, and stale-record tests.
* AI OS operator can keep preferences across refresh - implemented through a tiny localStorage preferences store with malformed-record recovery.
* AI OS operator can keep wallet, ledger, run history, and save slot metadata across refresh - implemented through IndexedDB records with typed read/write helpers and explicit error mapping.
* AI OS operator can claim shards without losing Session 04 idempotency - implemented by bridging existing localStorage claim records into the wallet and ledger persistence path.
* AI OS operator can reset AI Rogue local state only - implemented through Settings reset actions that clear AI Rogue storage keys and IndexedDB stores while preserving LiveData, extension enablement, and unrelated app storage.
* Later runtime sessions can save and load coarse run snapshots - implemented as schema and bridge contracts without adding simulation or combat logic.

### Out Of Scope (Deferred)

* Dungeon simulation, combat, world generation, turn rules, and FOV - Reason: Session 06 owns deterministic simulation.
* Rendering real saved dungeon state, spendable upgrades, and wallet-backed loadout purchases - Reason: Session 07 owns first playable integration.
* Skill-linked classes, relic progression, achievements, and expanded run history semantics - Reason: Session 08 owns progression depth.
* Remote storage, hosted database, sync service, new collectors, admin bridge, network calls, auth flows, raw generated data writes, or script writes - Reason: Phase 30 persistence stays browser-local and disabled-first.

***

## 5. Technical Approach

### Architecture

Add `save-schema.ts` under `src/extensions/ai-rogue/` for version constants, Zod schemas, TypeScript types, default builders, and migration helpers. The schema should cover preferences, wallet balances, ledger entries, run history summaries, save slot metadata, and a coarse runtime snapshot envelope that can hold future Session 06 simulation state without knowing its internals yet.

Add `persistence.ts` as the browser storage boundary. It should expose small localStorage helpers for preferences and a Promise-based IndexedDB wrapper for wallet, ledger, run history, and save slot records. The wrapper should accept injectable storage/open helpers for unit tests, map denied or unavailable browser APIs into explicit result objects, and keep transaction boundaries small enough that failed writes leave the previous durable record intact.

Update `claim-store.ts` as a compatibility facade instead of deleting the Session 04 localStorage key. Reads should continue recognizing `ai-os.ai-rogue.claims.v1`, while new claim completion should also write the versioned wallet and ledger records through the persistence layer. This keeps existing refresh idempotency and gives Session 07 a stable wallet contract.

React wiring should remain route-scoped. `LedgerView` reads wallet and ledger state alongside the existing economy snapshot. `SettingsView` owns preferences and reset controls. `LoadoutView` may display persistent wallet/preference readiness but must not add upgrade purchase behavior. `PlayView` and `runtime-canvas.tsx` should expose only coarse save/load/restart state and events until the simulation exists.

### Design Patterns

* Versioned schema boundary: all persisted records parse through Zod with defaults, migration results, and dropped-record warnings.
* Browser-storage adapter: persistence code isolates localStorage and IndexedDB APIs from React components and pure economy modules.
* Compatibility facade: the existing claim-store key remains readable so current users and tests do not lose idempotency.
* Idempotent writes: claim, wallet, ledger, reset, save, and load actions use stable keys, in-flight guards, transaction boundaries, and failure rollback.
* Privacy-safe persistence: only aggregate counts, balances, dates, safe labels, settings, and coarse run metadata are stored; raw prompts, commands, logs, paths, credentials, provider payloads, and generated private data stay out.

***

## 6. Deliverables

### Files To Create

| File                                                        | Purpose                                                                                                                                                  | Est. Lines |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `src/extensions/ai-rogue/save-schema.ts`                    | Versioned Zod schemas, defaults, migration helpers, and types for preferences, wallet, ledger, run history, save metadata, and coarse runtime snapshots. | \~260      |
| `src/extensions/ai-rogue/persistence.ts`                    | localStorage and IndexedDB persistence helpers with explicit result types, transactions, reset helpers, and test injection points.                       | \~360      |
| `src/extensions/ai-rogue/use-save-state.ts`                 | React hook for loading, saving, resetting, and refreshing AI Rogue browser-local state with explicit UI states.                                          | \~220      |
| `src/extensions/ai-rogue/__tests__/save-schema.test.ts`     | Schema default, valid, missing, stale, malformed, and migration coverage.                                                                                | \~220      |
| `src/extensions/ai-rogue/__tests__/persistence.test.ts`     | Storage adapter, IndexedDB failure, transaction, reset, claim migration, and privacy tests.                                                              | \~280      |
| `src/extensions/ai-rogue/__tests__/use-save-state.test.tsx` | Hook coverage for loading, empty, denied-storage, reset, and duplicate-trigger states.                                                                   | \~180      |
| `tests/e2e/ai-rogue-persistence.spec.ts`                    | Browser proof for preferences surviving refresh, claim/wallet idempotency, save/load states, and reset scoping.                                          | \~180      |

### Files To Modify

| File                                                | Changes                                                                                                              | Est. Lines |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------- |
| `src/extensions/types.ts`                           | Add an IndexedDB capability declaration kind if needed for accurate extension capability reporting.                  | \~5        |
| `src/extensions/ai-rogue/capabilities.ts`           | Declare browser-local IndexedDB persistence alongside existing generated-data and localStorage capability reasons.   | \~15       |
| `src/extensions/ai-rogue/claim-store.ts`            | Preserve legacy claim reads while bridging claims into versioned wallet and ledger persistence.                      | \~120      |
| `src/extensions/ai-rogue/views/ledger-view.tsx`     | Read durable wallet and ledger state, show migration/reset warnings, and write claim completion through persistence. | \~140      |
| `src/extensions/ai-rogue/views/settings-view.tsx`   | Replace locked preview controls with persistent preference controls and AI Rogue-only reset actions.                 | \~220      |
| `src/extensions/ai-rogue/views/loadout-view.tsx`    | Display persistent wallet, preference, and save readiness without adding upgrade purchases.                          | \~90       |
| `src/extensions/ai-rogue/views/play-view.tsx`       | Surface coarse save/load/run-history state around the runtime boundary.                                              | \~90       |
| `src/extensions/ai-rogue/views/runtime-canvas.tsx`  | Emit coarse restart/save/load events and guard reset while persistence work is in flight.                            | \~120      |
| `src/extensions/ai-rogue/__tests__/client.test.tsx` | Add view, capability, Ledger, Loadout, Settings, and Play persistence-state coverage.                                | \~160      |
| `src/routes/__tests__/extensions-routes.test.tsx`   | Update AI Rogue route expectations for storage capability labels and persistence states.                             | \~80       |
| `tests/e2e/ai-rogue-ledger.spec.ts`                 | Extend claim refresh coverage to durable wallet and ledger idempotency.                                              | \~80       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Preferences survive refresh and malformed preference records fall back to safe defaults with a visible warning.
* [ ] Wallet, ledger, run history, and save slot metadata persist through IndexedDB and recover safely from missing, stale, partial, or malformed records.
* [ ] Existing Session 04 claim idempotency continues to work after refresh and is mirrored into the durable wallet and ledger records.
* [ ] Reset clears only AI Rogue localStorage keys and AI Rogue IndexedDB stores while preserving generated LiveData, extension enablement, and unrelated app storage.
* [ ] Play and runtime surfaces expose save/load/restart readiness without adding simulation, combat, or upgrade behavior.

### Testing Requirements

* [ ] Schema tests cover current records, older versions, missing fields, malformed payloads, dropped invalid entries, and future snapshot envelopes.
* [ ] Persistence tests cover localStorage unavailable, IndexedDB unavailable, transaction failure, duplicate claim writes, reset scoping, and privacy.
* [ ] Hook and component tests cover loading, empty, error, offline, denied storage, reset confirmation, and in-flight duplicate prevention.
* [ ] Playwright coverage verifies preference refresh persistence, claim/wallet idempotency, save/load readiness, reset scoping, and no private text leakage.

### Non-Functional Requirements

* [ ] No prompts, transcripts, command bodies, command outputs, private paths, credentials, bearer tokens, raw logs, raw provider payloads, or generated private data are stored or rendered.
* [ ] No new network, hosted database, remote sync, service worker, worker simulation, collector, admin bridge, auth flow, or server endpoint is introduced.
* [ ] IndexedDB records remain AI Rogue namespaced and versioned.
* [ ] Extension capability declarations accurately reflect browser-local storage APIs used by the extension.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Focused Vitest suite passes.
* [ ] Focused Playwright persistence suite passes.
* [ ] `bun run typecheck` passes or any pre-existing unrelated failure is documented with evidence.

***

## 8. Implementation Notes

### Working Assumptions

* Native IndexedDB is the right first storage dependency: `package.json` has no `idb` helper dependency, the Phase 30 PRD names IndexedDB directly, and a narrow wrapper avoids adding a package for one browser-local store.
* The Session 04 claim localStorage key remains a compatibility source: `claim-store.ts` already persists `ai-os.ai-rogue.claims.v1`, the Session 04 Playwright test proves refresh idempotency through that key, and preserving it lets planning proceed without breaking shipped claim behavior.
* Coarse runtime snapshots should be envelope-only in this session: Session 06 has not yet created deterministic simulation state, so save/load can define the metadata and bridge contract now while leaving full dungeon state empty until later sessions.

### Conflict Resolutions

* The Session 05 stub says larger state belongs in IndexedDB, while Session 04 stored claim records in localStorage. The chosen interpretation is to keep localStorage for legacy claim idempotency and preferences, then mirror claim completion into IndexedDB wallet and ledger records. This satisfies the new persistence contract without invalidating existing refresh behavior.
* Settings needs reset controls, but generated runtime data and extension enablement are outside AI Rogue browser-local persistence. Reset therefore clears only AI Rogue storage keys and IndexedDB stores; it must not delete `src/data/live-data.json`, extension enablement config, or unrelated browser storage.

### Key Considerations

* Persistence errors are expected runtime states, not crashes. Browser storage can be denied, unavailable, quota-limited, stale, or malformed.
* `IndexedDB` is a browser-local data store, not a hosted database. No SQL, server migration, remote sync, or generated type artifact is required.
* Keep all storage keys under an `ai-os.ai-rogue` prefix and record schema versions near the stored payloads.

### Potential Challenges

* IndexedDB testing in happy-dom may be incomplete: make the persistence layer accept injected open/storage adapters so failure paths and transactions can be tested deterministically.
* Reset UX can accidentally over-clear: define an allowlist of AI Rogue keys and stores and test that unrelated localStorage keys survive.
* Ledger migration can double-credit if key handling drifts: use the existing redemption key as the idempotency boundary for both localStorage and IndexedDB records.

### Relevant Considerations

* \[P02] **Static extension registry requires code changes**: Capability updates belong in the compile-time extension type and AI Rogue declaration, not in a dynamic plugin surface.
* \[P02] **Extension payloads and labels stay bounded**: Persist only bounded labels, balances, dates, states, and metadata; do not store raw generated payloads.
* \[P02] **Zod schemas with `.default()` for safe parsing**: Additive defaults and migration helpers are the main safety mechanism for stale local records.
* \[P00] **Stack conventions**: Bun, Vite 8, TanStack Start, React 19, and Cloudflare Worker compatibility remain baseline constraints even though this session is browser-local.
* \[P27] **Repo-wide formatting drift remains**: Run scoped formatting checks on session files and avoid broad repo formatting churn.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Storage trust boundaries: malformed, stale, unavailable, or denied browser storage must not crash views or corrupt previous records.
* Mutation safety: claim, reset, save, load, and preference writes need duplicate-trigger prevention while in flight.
* Reset scoping: AI Rogue reset must not delete generated LiveData, extension enablement, unrelated localStorage keys, or non-AI Rogue IndexedDB stores.

***

## 9. Testing Strategy

### Unit Tests

* Test `save-schema.ts` defaults, migrations, stale versions, malformed input, dropped invalid ledger entries, and future snapshot envelope parsing.
* Test `persistence.ts` localStorage reads/writes, IndexedDB read/write transactions, unavailable storage, quota/write failures, reset allowlist, and legacy claim migration.

### Integration Tests

* Test `use-save-state.ts`, Ledger, Settings, Loadout, and Play components with loading, empty, error, offline, denied-storage, reset, and claimed states.
* Test extension routes for updated capability declarations and persistence state rendering.

### Runtime Verification

* Run Playwright on `/extensions/ai-rogue/settings`, `/extensions/ai-rogue/ledger`, `/extensions/ai-rogue/loadout`, and `/extensions/ai-rogue/play` with mocked LiveData and browser storage.
* Verify preferences survive reload, claim state remains idempotent after reload, save/load readiness is visible, reset clears only AI Rogue state, and private path or prompt-like strings do not render.

### Edge Cases

* Missing localStorage.
* IndexedDB open denied or unavailable.
* IndexedDB write failure after read success.
* Legacy localStorage claims present without IndexedDB records.
* Stale schema version with missing wallet or ledger fields.
* Reset during another persistence operation.
* Example LiveData and offline browser state.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase30-session01-direction-and-asset-readiness`, `phase30-session02-extension-shell-and-routes`, `phase30-session03-pixijs-runtime-boundary`, `phase30-session04-economy-and-ledger`
* Depended by: `phase30-session07-play-runtime-integration`, `phase30-session08-progression-depth`, `phase30-session09-content-polish-and-mobile`, `phase30-session10-quality-gates-and-enablement`

***

## Next Steps

Run the `implement` workflow step to begin implementation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/.spec_system/archive/sessions/phase30-session05-persistence-and-save-contracts/spec.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
