> 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/phase22-session05-store-folding-and-selectors/implementation-notes.md).

# Implementation Notes

**Session ID**: `phase22-session05-store-folding-and-selectors` **Package**: apps/web **Started**: 2026-07-05 11:20 **Last Updated**: 2026-07-05 11:20

***

## Session Progress

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

***

## Task Log

### 2026-07-05 - Session Start

**Environment verified**:

* [x] Prerequisites confirmed
* [x] Tools available
* [x] Directory structure ready

***

### Task T001 - Verify Session 04 Artifacts And Current Store Seams

**Started**: 2026-07-05 11:16 **Completed**: 2026-07-05 11:20 **Duration**: 4 minutes

**Notes**:

* Confirmed Session 04 validation passed and established `apps/web/src/lib/gameProjection.ts` as the projection reducer authority.
* Located current `GameStore` interface, replay persistence helpers, `applyEvent`, `resetToSeed`, existing selector placement, and projection helper exports.

**Files Changed**:

* `.spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md` - started session progress and task evidence log.
* `.spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md` - marked T001 complete.

**Verification**:

* Command/check: `if [ -d ".spec_system/scripts" ]; then bash .spec_system/scripts/analyze-project.sh --json; else bash /home/aiwithapex/.codex/plugins/cache/apexdev/apex-spec/2.2.18-codex/skills/apex-spec/scripts/analyze-project.sh --json; fi`
  * Result: PASS - current session resolved to `phase22-session05-store-folding-and-selectors`, monorepo true, package `apps/web`.
  * Evidence: analyzer reported the session directory exists with `spec.md` and `tasks.md`.
* Command/check: `if [ -d ".spec_system/scripts" ]; then bash .spec_system/scripts/check-prereqs.sh --json --env --package apps/web; else bash /home/aiwithapex/.codex/plugins/cache/apexdev/apex-spec/2.2.18-codex/skills/apex-spec/scripts/check-prereqs.sh --json --env --package apps/web; fi`
  * Result: PASS - spec system, jq, git, npm workspace manager, and `apps/web` manifest checks passed.
  * Evidence: checker returned `"overall": "pass"` with no issues.
* Command/check: `sed -n '1,260p' .spec_system/specs/phase22-session04-camp-link-boundaries/validation.md`; `rg -n "interface GameStore|resetToSeed|applyEvent|selectQuestBoard|replay|create\\(|export const select" apps/web/src/store/useGameStore.ts`; `rg -n "export function|export const|reduceGameProjection|loadPersistedGameProjection|createInitialGameProjection|parsePersistedGameProjection" apps/web/src/lib/gameProjection.ts`
  * Result: PASS - Session 04 validation result was PASS; store and projection seams needed by this session are present.
  * Evidence: `applyEvent`, replay helpers, `resetToSeed`, Quest Board selector pattern, and projection exports were all located.
* UI product-surface check: N/A - setup inspection only, no rendered UI changed.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T002 - Create Focused Store Test File And Fixtures

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added a dedicated store integration suite with dynamic fresh imports, fixed-clock setup, storage error fixture, and typed event builders.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - created focused store tests and shared fixtures.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - 1 file passed.
  * Evidence: 9 tests passed under the web Vitest project.
* Command/check: `npm exec -- biome check apps/web/src/store/useGameStore.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - no fixes applied.
  * Evidence: Biome checked both changed files successfully.
* UI product-surface check: N/A - test-only task.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T003 - Add Projection Store Imports

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Imported `createInitialGameProjection`, `loadPersistedGameProjection`, `reduceGameProjection`, and `GameProjection` into the web store.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - added projection value and type imports.

**Verification**:

* Command/check: `npm exec -- biome check apps/web/src/store/useGameStore.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - import ordering and lint checks passed.
  * Evidence: Biome checked both changed files with no fixes.
* UI product-surface check: N/A - store import only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T004 - Add GameProjection Store Field And Selector Slice Type

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added `gameProjection: GameProjection` to `GameStore` and exported `GameProjectionStoreSlice` as a narrow `Pick<GameStore, "gameProjection">`.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - extended store state contract and selector slice type.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - selector and store integration tests passed.
  * Evidence: 9 tests passed, including the narrow-slice selector test.
* UI product-surface check: N/A - state contract only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T005 - Initialize Projection From Persisted Storage

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Initialized `gameProjection` with `loadPersistedGameProjection()` during Zustand store creation.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - added store creation hydration.
* `apps/web/tests/gameProjectionStore.test.ts` - covered valid, empty, malformed, throwing, and unavailable storage.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - hydration tests passed.
  * Evidence: valid persisted projection loaded; fallback cases returned fresh projections.
* UI product-surface check: N/A - no rendered UI changed.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* Failure path completeness: covered malformed, throwing, and unavailable browser storage at the store seam (`apps/web/tests/gameProjectionStore.test.ts`).

***

### Task T006 - Export Projection Selectors

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Exported `selectGameProjection`, `selectGameAlertFocus`, and `selectGameLegion` from `useGameStore.ts`.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - added projection selector helpers beside existing Quest Board selectors.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - selector test passed.
  * Evidence: selectors read from a `{ gameProjection }` slice rather than a full store object.
* UI product-surface check: N/A - pure selector helpers only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T007 - Add Selector Tests

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added a selector test for projection, alert focus, and Legion reads from a narrow store slice.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added selector coverage.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - selector coverage passed.
  * Evidence: 9 tests passed; first test verifies all three selector outputs.
* UI product-surface check: N/A - test-only task.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T008 - Add Store-Local Projection Fold Helper

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added `foldGameProjection` beside replay helpers; it derives `now`, `isReplaying`, and `mockEnabled` from store/settings state.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - added store-local folding helper.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - replay and mock-context tests passed.
  * Evidence: reducer spy observed `isReplaying` and `mockEnabled` values from store/settings state.
* UI product-surface check: N/A - store logic only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* Contract alignment: reducer context is built with the existing `GameProjectionReduceContext` fields (`apps/web/src/store/useGameStore.ts`).

***

### Task T009 - Wire Projection Folding Into applyEvent

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Called `foldGameProjection(e, state)` after replay capture and before the existing event switch; store updates only when the reducer returns a new reference.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - inserted guarded projection fold in `applyEvent`.
* `apps/web/tests/gameProjectionStore.test.ts` - covered one-event folding and reducer-call count through a spy.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - event folding and reducer spy tests passed.
  * Evidence: default-path `awaiting_input` changed projection state; spy saw exactly one reducer call per applied event in the mock-context test.
* UI product-surface check: N/A - no rendered UI changed.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* Duplicate action prevention: reference-change guard avoids redundant `gameProjection` writes when reducer returns the same projection (`apps/web/src/store/useGameStore.ts`).

***

### Task T010 - Preserve Existing applyEvent Branch Behavior

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Left existing switch branches intact and added projection folding before them as an independent state update.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - preserved existing switch cases while adding projection folding before the switch.

**Verification**:

* Command/check: `git diff -- apps/web/src/store/useGameStore.ts`
  * Result: PASS - diff shows no edits inside roster, hero, mission, Quest Board, command-center, toast, or default switch bodies.
  * Evidence: store diff is limited to projection imports, state field, selectors, fold helper, pre-switch fold call, hydration, and reset memory.
* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - store integration tests passed.
  * Evidence: `server_toast` still reaches the existing switch while projection folding runs first.
* UI product-surface check: N/A - no rendered UI changed.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T011 - Reset Projection Memory In resetToSeed

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added `gameProjection: createInitialGameProjection()` to `resetToSeed()` without removing the projection storage key.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - reset now refreshes in-memory projection.
* `apps/web/tests/gameProjectionStore.test.ts` - covered storage preservation on reset.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - reset memory test passed.
  * Evidence: in-memory projection reset to a fresh shape while `localStorage["factionos-game-v1"]` remained unchanged.
* UI product-surface check: N/A - no rendered UI changed.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* State freshness on re-entry: reset now clears projection memory together with other seed-backed store branches (`apps/web/src/store/useGameStore.ts`).

***

### Task T012 - Add Projection Hydration Tests

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added dynamic-import hydration tests for valid persisted projection, empty string, malformed JSON, projection-key read failure, and unavailable `localStorage`.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added hydration coverage.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - hydration cases passed.
  * Evidence: valid storage hydrated exactly; invalid and unavailable storage returned fresh projections.
* UI product-surface check: N/A - test-only task.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* Failure path completeness: invalid browser storage paths recover without throwing (`apps/web/tests/gameProjectionStore.test.ts`).

***

### Task T013 - Add One-Event Folding Tests

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added an `applyEvent(awaiting_input)` test that changes projection attention and leaves the legacy `heroes` branch untouched.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added one-event projection folding coverage.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - one-event folding test passed.
  * Evidence: projection gained flare focus for `hero-store-only`; `state.heroes["hero-store-only"]` remained undefined.
* UI product-surface check: N/A - test-only task.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* Contract alignment: event folding uses the public store `applyEvent` seam and the reducer-owned projection shape.

***

### Task T014 - Add Replay And Mock Context Tests

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added replay-context test for `replayingSinceMs` and mock-context spy test for `useSettingsStore.getState().mockEnabled`.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added replay and mock context coverage.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - replay and mock-context tests passed.
  * Evidence: replayed input cleared flare without Swift Command gain or replay capture; reducer spy saw mock true then false.
* UI product-surface check: N/A - test-only task.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* Duplicate action prevention: replay path avoids recapturing replay events into `eventLog` (`apps/web/tests/gameProjectionStore.test.ts`).

***

### Task T015 - Add Reset Memory Tests

**Started**: 2026-07-05 11:20 **Completed**: 2026-07-05 11:24 **Duration**: 4 minutes

**Notes**:

* Added reset test proving fresh in-memory projection and storage-key preservation.

**Files Changed**:

* `apps/web/tests/gameProjectionStore.test.ts` - added reset memory coverage.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - reset test passed.
  * Evidence: projection became `createInitialGameProjection(LATER_NOW)` and persisted raw storage stayed unchanged.
* UI product-surface check: N/A - test-only task.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* State freshness on re-entry: reset test confirms projection memory cannot retain stale folded state after `resetToSeed()`.

***

## Checkpoints

### Checkpoint 1 - 2026-07-05 11:24

* Checks run: `npm test -- apps/web/tests/gameProjectionStore.test.ts`; `npm exec -- biome check apps/web/src/store/useGameStore.ts apps/web/tests/gameProjectionStore.test.ts`.
* Scope reread: `spec.md` requires non-visual store folding, hydration, selectors, replay/mock context, and reset memory only; no UI, protocol, server, or persistence writes were added.
* Next task: T016 focused projection store and reducer tests.

***

### Task T016 - Run Focused Projection Store And Reducer Tests

**Started**: 2026-07-05 11:26 **Completed**: 2026-07-05 11:26 **Duration**: 1 minute

**Notes**:

* Ran the session-required focused store integration and pure reducer suites together.

**Files Changed**:

* `.spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md` - recorded focused test evidence.
* `.spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md` - marked T016 complete.

**Verification**:

* Command/check: `npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/gameProjection.test.ts`
  * Result: PASS - 2 files passed.
  * Evidence: 33 tests passed: 9 store integration tests and 24 reducer tests.
* UI product-surface check: N/A - test gate only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T017 - Run Typecheck And Changed-File Biome

**Started**: 2026-07-05 11:26 **Completed**: 2026-07-05 11:27 **Duration**: 1 minute

**Notes**:

* Ran the web package typecheck and the specified changed-file Biome check.

**Files Changed**:

* `.spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md` - recorded typecheck and Biome evidence.
* `.spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md` - marked T017 complete.

**Verification**:

* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - `tsc -b --noEmit` exited 0.
  * Evidence: web package typecheck completed without errors.
* Command/check: `npm exec -- biome check apps/web/src/store/useGameStore.ts apps/web/src/lib/gameProjection.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - 3 files checked.
  * Evidence: Biome reported no fixes applied.
* UI product-surface check: N/A - quality gate only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Task T018 - Validate ASCII And LF Requirements

**Started**: 2026-07-05 11:27 **Completed**: 2026-07-05 11:27 **Duration**: 1 minute

**Notes**:

* Checked session artifacts and changed app files for ASCII encoding and CRLF absence.

**Files Changed**:

* `.spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md` - recorded ASCII/LF evidence.
* `.spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md` - marked T018 and completion checklist complete.

**Verification**:

* Command/check: `file .spec_system/specs/phase22-session05-store-folding-and-selectors/spec.md .spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md .spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md apps/web/src/store/useGameStore.ts apps/web/src/lib/gameProjection.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - checked files reported as ASCII text/source.
  * Evidence: all session artifacts and changed app files are ASCII.
* Command/check: `LC_ALL=C grep -n '[^[:print:][:space:]]' .spec_system/specs/phase22-session05-store-folding-and-selectors/spec.md .spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md .spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md apps/web/src/store/useGameStore.ts apps/web/src/lib/gameProjection.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - no non-ASCII bytes found.
  * Evidence: command exited with no matches.
* Command/check: `grep -l $'\r' .spec_system/specs/phase22-session05-store-folding-and-selectors/spec.md .spec_system/specs/phase22-session05-store-folding-and-selectors/tasks.md .spec_system/specs/phase22-session05-store-folding-and-selectors/implementation-notes.md apps/web/src/store/useGameStore.ts apps/web/src/lib/gameProjection.ts apps/web/tests/gameProjectionStore.test.ts`
  * Result: PASS - no CRLF line endings found.
  * Evidence: command exited with no matches.
* UI product-surface check: N/A - quality gate only.
* UI craft check: N/A - no UI surface changed.

**BQC Fixes**:

* None.

***

### Checkpoint 2 - 2026-07-05 11:27

* Checks run: `npm test -- apps/web/tests/gameProjectionStore.test.ts apps/web/tests/gameProjection.test.ts`; `npm --workspace @factionos/web run typecheck`; `npm exec -- biome check apps/web/src/store/useGameStore.ts apps/web/src/lib/gameProjection.ts apps/web/tests/gameProjectionStore.test.ts`; ASCII/LF shell checks.
* Scope reread: all success criteria are covered; store folding remains non-visual and adds no protocol, server, hosted persistence, audio, toasts, or second projection authority.
* Next task: none inside implement; handoff to `creview`.


---

# 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/phase22-session05-store-folding-and-selectors/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.
