> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase23-session04-store-persistence-boundaries/implementation-notes.md).

# Implementation Notes

**Session ID**: `phase23-session04-store-persistence-boundaries` **Package**: apps/web **Started**: 2026-07-05 18:42 **Last Updated**: 2026-07-05 18:42

***

## Session Progress

| Metric              | Value     |
| ------------------- | --------- |
| Tasks Completed     | 16 / 16   |
| Estimated Remaining | 0 minutes |
| Blockers            | 0         |

***

## Task Log

### 2026-07-05 - Session Start

**Environment verified**:

* [x] Prerequisites confirmed with `check-prereqs.sh --json --env --package apps/web`
* [x] Package context resolved to `apps/web`
* [x] Required npm version available: `npm -v` -> 11.16.0
* [x] Required Node version available through `npx -y node@26.2.0 -v` -> v26.2.0
* [x] Directory structure ready

***

## Checkpoints

### Checkpoint 1 - After T007

**At**: 2026-07-05 18:47 **Tests/Checks**:

* `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 25 tests passed.

**Spec Drift Review**:

* Re-read session objectives and scope in `spec.md`.
* Confirmed changes remain limited to focused store and browser-local erasure regressions.
* Confirmed no protocol event, UI surface, hosted state, trusted-erasure claim, or new storage authority was added.

**Next Task**: T008 - add normal `applyEvent` scanner camp persistence coverage.

***

### Task T001 - Verify Projection Persistence Store Paths

**Started**: 2026-07-05 18:42 **Completed**: 2026-07-05 18:43 **Duration**: 1 minute

**Notes**:

* Verified `applyEvent` folds all server events through `foldGameProjection` and schedules projection persistence only when `shouldPersistGameProjection` allows it.
* Verified projection writes use the existing debounce, max-latency, lifecycle flush, and test-only flush hook.
* Verified `resetToSeed()` clears pending projection writes and removes `GAME_PROJECTION_STORAGE_KEY`.

**Files Changed**:

* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "applyEvent|resetToSeed|__flushGameProjectionPersist|GAME_PROJECTION_STORAGE_KEY|persist|replay|mock" apps/web/src/store/useGameStore.ts`
  * Result: PASS - found store folding, replay guard, flush hook, reset cleanup, and persistence scheduling call sites.
  * Evidence: `applyEvent` folds via `foldGameProjection`; `resetToSeed()` calls `clearPendingGameProjectionPersist()` and `removePersistedGameProjection()`.
* Command/check: `rg -n "GAME_PROJECTION_STORAGE_KEY|__flushGameProjectionPersist|persist|localStorage|replay|mock|reset|hydrate" apps/web/src/lib/gameProjection.ts`
  * Result: PASS - confirmed `factionos-game-v1`, storage parse/load/persist helpers, and replay/mock persistence guard.
  * Evidence: `persistGameProjection()` writes only `GAME_PROJECTION_STORAGE_KEY`; `shouldPersistGameProjection()` returns false for replay or mock.
* UI product-surface check: N/A - task was code-path inspection only.
* UI craft check: N/A - no UI changed.

***

### Task T002 - Verify Browser-Local Erasure Projection Inventory

**Started**: 2026-07-05 18:43 **Completed**: 2026-07-05 18:43 **Duration**: 1 minute

**Notes**:

* Verified `localErasure.ts` imports `GAME_PROJECTION_STORAGE_KEY` and includes it in `BROWSER_GAME_PROJECTION_STORAGE_KEYS`.
* Verified the browser settings boundary clears projection storage and current tests assert raw projection values are not surfaced.

**Files Changed**:

* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "GAME_PROJECTION_STORAGE_KEY|factionos-game|camp|localStorage|executeBrowserErasure|browser-local" apps/web/src/lib/localErasure.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - found projection-key import, browser storage inventory, erasure execution, and existing projection-key assertions.
  * Evidence: `BROWSER_GAME_PROJECTION_STORAGE_KEYS = [GAME_PROJECTION_STORAGE_KEY]`; tests clear and inspect the same key.
* Command/check: `sed -n '1,260p' apps/web/src/lib/localErasure.ts`
  * Result: PASS - erasure plans iterate known storage keys and verify absence by boundary.
  * Evidence: `BROWSER_BOUNDARY_PLANS` puts projection storage under `browser_settings`.
* UI product-surface check: N/A - task was erasure helper inspection only.
* UI craft check: N/A - no UI changed.

***

### Task T003 - Verify Scanner Snapshot Test Reuse Points

**Started**: 2026-07-05 18:43 **Completed**: 2026-07-05 18:43 **Duration**: 1 minute

**Notes**:

* Verified reducer-level scanner snapshot factories in `gameProjection.test.ts` cover codebase issues, scanner snapshots, camp sector lookup, replay-inert snapshots, and mock memory folding.
* Verified `gameProjectionStore.test.ts` already owns fresh module imports, fake timers, `dispatchReplayEntries`, `__flushGameProjectionPersist`, persistence scheduling, replay guard, mock guard, hydration, and reset tests.

**Files Changed**:

* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "makeSuggestionUpdate|codebase|camp|legion|scanner|__flushGameProjectionPersist|dispatchReplayEntries|mockEnabled|hydrate|resetToSeed|GAME_PROJECTION_STORAGE_KEY" apps/web/tests/gameProjection.test.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - found reusable scanner fixture patterns and store-level persistence helpers.
  * Evidence: reducer tests include `makeScannerIssue`, `makeScannerSnapshot`, and aggregate camp assertions; store tests include `readPersistedProjection`, `flushProjectionWrites`, and replay/mock persistence cases.
* Command/check: `sed -n '1450,1690p' apps/web/tests/gameProjection.test.ts`
  * Result: PASS - confirmed Session 03 expectations for camp folding, entrenchment, removal, replay inertness, and mock folding.
  * Evidence: tests assert aggregate camp counts, safe sector labels, and `shouldPersistGameProjection` boundaries.
* UI product-surface check: N/A - task was test-pattern inspection only.
* UI craft check: N/A - no UI changed.

***

### Task T004 - Add Store Scanner Issue Fixtures

**Started**: 2026-07-05 18:43 **Completed**: 2026-07-05 18:45 **Duration**: 2 minutes

**Notes**:

* Added store-test `CodebaseIssue`, scanner issue, scanner snapshot, multi-sector camp snapshot, and clean snapshot helpers.
* The multi-sector fixture includes `apps/web` and `docs` sectors plus intentionally raw scanner title/message/prompt/path values for later aggregate-only assertions.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added scanner snapshot fixtures.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "makeCodebaseIssue|makeScannerIssue|makeScannerSnapshot|makeStoreCampSnapshot|makeCleanScannerSnapshot" apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - all fixture helpers are present in the store-level test file.
  * Evidence: helpers create codebase scanner issues with bounded ids, safe sector inputs, and clean empty snapshots.
* UI product-surface check: N/A - test fixture task only.
* UI craft check: N/A - no UI changed.

***

### Task T005 - Add Persisted Projection And Storage Inventory Helpers

**Started**: 2026-07-05 18:45 **Completed**: 2026-07-05 18:45 **Duration**: 1 minute

**Notes**:

* Added `expectPersistedProjection`, browser storage-key enumeration, projection-key presence assertions, and no camp-specific storage-key assertions.
* Helpers allow existing replay storage to coexist while rejecting any new camp, Legion, or scanner-specific browser key outside `GAME_PROJECTION_STORAGE_KEY`.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added persisted projection and storage inventory helpers.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "expectPersistedProjection|browserStorageKeys|expectNoCampSpecificStorageKeys|expectProjectionStorageInventory" apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - storage helpers are present and scoped to `GAME_PROJECTION_STORAGE_KEY`.
  * Evidence: helper filters reject `camp`, `legion`, or `scanner` storage keys except the existing projection key.
* UI product-surface check: N/A - test helper task only.
* UI craft check: N/A - no UI changed.

***

### Task T006 - Add Aggregate-Only Serialization Assertions

**Started**: 2026-07-05 18:45 **Completed**: 2026-07-05 18:45 **Duration**: 1 minute

**Notes**:

* Added a shared assertion that serialized projections keep aggregate issue ids and safe sector labels while omitting raw scanner title, message, prompt, terminal/provider/file wording, absolute paths, environment wording, and secret-like tokens.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added raw scanner omission constants and projection serialization assertion.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "RAW_SCANNER_FORBIDDEN_VALUES|expectSerializedProjectionOmitsRawScannerValues" apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - aggregate-only privacy assertion and forbidden raw values are present.
  * Evidence: assertion checks persisted JSON for issue ids and safe sector label while excluding raw scanner details.
* UI product-surface check: N/A - test helper task only.
* UI craft check: N/A - no UI changed.

***

### Task T007 - Add Local-Erasure Camp Storage Inventory Assertion

**Started**: 2026-07-05 18:45 **Completed**: 2026-07-05 18:46 **Duration**: 1 minute

**Notes**:

* Added a browser storage-key helper in `localErasure.test.ts` and asserted seeded browser state has no camp, Legion, or scanner-specific key outside `GAME_PROJECTION_STORAGE_KEY`.

**Files Changed**:

* `apps/web/tests/localErasure.test.ts` - added local-erasure storage inventory helper and preview assertion.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `rg -n "CAMP_SPECIFIC_STORAGE_KEY_PATTERN|browserStorageKeys|expectNoCampSpecificBrowserStorageKeys" apps/web/tests/localErasure.test.ts`
  * Result: PASS - local-erasure key inventory helper and assertion are present.
  * Evidence: helper rejects camp/Legion/scanner-specific keys except `GAME_PROJECTION_STORAGE_KEY`.
* UI product-surface check: N/A - test helper task only.
* UI craft check: N/A - no UI changed.

***

### Task T008 - Add Normal Scanner Camp Persistence Store Test

**Started**: 2026-07-05 18:46 **Completed**: 2026-07-05 18:49 **Duration**: 3 minutes

**Notes**:

* Added a store-level `applyEvent` test that folds a real scanner `suggestion_update` into two aggregate camps, waits for explicit projection flush, and verifies persistence under `GAME_PROJECTION_STORAGE_KEY`.
* Asserted safe aggregate fields, sector labels, no camp-specific storage keys, and no raw scanner title/message/prompt/path/secret values in serialized projection JSON.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added normal scanner camp persistence regression.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 29 tests passed.
  * Evidence: new store persistence test passed with aggregate camps persisted only under `factionos-game-v1`.
* UI product-surface check: N/A - test-only store regression.
* UI craft check: N/A - no UI changed.

***

### Task T009 - Add Replayed Scanner Snapshot Persistence Guard

**Started**: 2026-07-05 18:48 **Completed**: 2026-07-05 18:49 **Duration**: 1 minute

**Notes**:

* Added a store-level test that replays scanner snapshots through `dispatchReplayEntries` and through an explicit `replayingSinceMs` state.
* Verified replayed scanner snapshots leave in-memory camps empty and leave persisted projection bytes unchanged.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added replayed scanner snapshot guard regression.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 29 tests passed.
  * Evidence: replayed scanner snapshot test passed and asserted `localStorage["factionos-game-v1"]` stayed byte-for-byte unchanged.
* UI product-surface check: N/A - test-only store regression.
* UI craft check: N/A - no UI changed.

***

### Task T010 - Add Mock Scanner Memory-Only Persistence Guard

**Started**: 2026-07-05 18:48 **Completed**: 2026-07-05 18:49 **Duration**: 1 minute

**Notes**:

* Added a mock-enabled scanner snapshot test that folds drill camps into in-memory projection state.
* Verified persisted projection storage remains equal to the pre-existing raw value and no camp-specific storage key appears.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added mock scanner memory-only persistence guard.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 29 tests passed.
  * Evidence: mock scanner test passed and asserted persisted projection stayed byte-for-byte unchanged.
* UI product-surface check: N/A - test-only store regression.
* UI craft check: N/A - no UI changed.

***

### Task T011 - Add Hydration And Clean Snapshot Camp Reconciliation

**Started**: 2026-07-05 18:49 **Completed**: 2026-07-05 18:49 **Duration**: 1 minute

**Notes**:

* Added a post-boot store test that hydrates from the existing projection key, then folds a real scanner snapshot through non-replay `applyEvent`.
* Verified replayed clean snapshots do not remove camps, while a real clean snapshot clears camps and sectors in memory and persisted projection storage.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added hydration and clean snapshot reconciliation regression.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 29 tests passed.
  * Evidence: hydration/clean snapshot test passed and proved only real non-replay snapshots remove camps.
* UI product-surface check: N/A - test-only store regression.
* UI craft check: N/A - no UI changed.

***

### Task T012 - Production Repair Assessment

**Started**: 2026-07-05 18:49 **Completed**: 2026-07-05 18:50 **Duration**: 1 minute

**Notes**:

* Focused regression tests passed against existing production store, projection, and erasure code.
* No production repair was required; no new storage key, protocol event, hosted state, or trusted-erasure claim was introduced.

**Files Changed**:

* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded no-op repair assessment.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 29 tests passed with no production changes.
  * Evidence: production files `apps/web/src/store/useGameStore.ts`, `apps/web/src/lib/gameProjection.ts`, and `apps/web/src/lib/localErasure.ts` were not modified.
* UI product-surface check: N/A - no UI changed.
* UI craft check: N/A - no UI changed.

***

### Task T013 - Add Scanner Camp Reset Regression

**Started**: 2026-07-05 18:50 **Completed**: 2026-07-05 18:51 **Duration**: 1 minute

**Notes**:

* Added reset coverage for a pending scanner camp write.
* Verified `resetToSeed()` clears in-memory camps, cancels pending projection writes, and keeps `GAME_PROJECTION_STORAGE_KEY` absent after explicit flush and timer advancement.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added scanner camp reset regression.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 31 tests passed.
  * Evidence: reset regression passed and asserted projection storage remained absent.
* UI product-surface check: N/A - test-only store regression.
* UI craft check: N/A - no UI changed.

***

### Task T014 - Add Browser-Local Camp Erasure Regression

**Started**: 2026-07-05 18:50 **Completed**: 2026-07-05 18:51 **Duration**: 1 minute

**Notes**:

* Added erasure coverage proving aggregate camp projection storage under `GAME_PROJECTION_STORAGE_KEY` is removed.
* Verified duplicate idempotency summaries remain value-free and do not leak raw projection payloads or secret-like values.

**Files Changed**:

* `apps/web/tests/localErasure.test.ts` - added camp aggregate erasure and duplicate idempotency regression.
* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded task evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 31 tests passed.
  * Evidence: erasure regression passed and asserted summaries omit raw camp aggregate and `secret-token` values.
* UI product-surface check: N/A - test-only erasure regression.
* UI craft check: N/A - no UI changed.

***

### Task T015 - Run Focused Store And Erasure Vitest

**Started**: 2026-07-05 18:52 **Completed**: 2026-07-05 18:52 **Duration**: 1 minute

**Notes**:

* Ran focused Vitest for the store persistence and browser-local erasure regression files under Node 26.2.0 and npm 11.16.0.
* Used the root `npm test -- <files>` invocation because `@factionos/web` does not define a package-local `test` script; the root Vitest project selects the web test project for these files.

**Files Changed**:

* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded validation evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - 2 files passed, 31 tests passed.
  * Evidence: `localErasure.test.ts` ran 5 tests and `gameProjectionStore.test.ts` ran 26 tests.
* UI product-surface check: N/A - test validation only.
* UI craft check: N/A - no UI changed.

***

### Task T016 - Run Typecheck And ASCII/LF Validation

**Started**: 2026-07-05 18:52 **Completed**: 2026-07-05 18:53 **Duration**: 1 minute

**Notes**:

* Ran Biome formatting on the changed test files; no fixes were applied.
* Ran web package typecheck under Node 26.2.0 and npm 11.16.0.
* Verified changed implementation-session files are ASCII-only and LF-only, then ran `git diff --check`.

**Files Changed**:

* `.spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md` - recorded final validation evidence.

**Verification**:

* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm exec -- biome format --write apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts`
  * Result: PASS - formatted 2 files; no fixes applied.
  * Evidence: Biome reported `Formatted 2 files in 8ms. No fixes applied.`
* Command/check: `npx -y -p node@26.2.0 -p npm@11.16.0 npm --workspace @factionos/web run typecheck`
  * Result: PASS - TypeScript build check completed.
  * Evidence: `tsc -b --noEmit` exited 0.
* Command/check: `perl -ne 'print "$ARGV:$.: non-ascii\n" if /[^\x00-\x7F]/; print "$ARGV:$.: CRLF\n" if /\r/; close ARGV if eof' apps/web/tests/gameProjectionStore.test.ts apps/web/tests/localErasure.test.ts .spec_system/specs/phase23-session04-store-persistence-boundaries/tasks.md .spec_system/specs/phase23-session04-store-persistence-boundaries/implementation-notes.md`
  * Result: PASS - no output.
  * Evidence: no non-ASCII or CRLF findings.
* Command/check: `git diff --check`
  * Result: PASS - no whitespace errors.
  * Evidence: command exited 0 with no output.
* UI product-surface check: N/A - validation task only.
* UI craft check: N/A - no UI changed.

***


---

# 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://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase23-session04-store-persistence-boundaries/implementation-notes.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.
