> 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-session07-honesty-regression-tests/spec.md).

# Session Specification

**Session ID**: `phase22-session07-honesty-regression-tests` **Phase**: 22 - Projection Foundation **Status**: Not Started **Created**: 2026-07-05 **Base Commit**: cfcc911bc0cd6751ed1c1b36e446e604a530fc23 **Package**: apps/web **Package Stack**: TypeScript

***

## 1. Session Overview

This session locks the Phase 22 projection honesty boundary with focused regression coverage. Sessions 01-06 created the projection contract, reducer slices, store folding, selectors, persistence cadence, replay guard, mock guard, and reset behavior; this session proves those seams cannot mint durable progress when events arrive through shared replay, reconnect snapshots, or mock traffic.

It is next because Phase 22 session state shows sessions 01-06 complete and the remaining session 08 depends on this coverage. The work is primarily test-owned in `apps/web`, using existing projection, replay, and persistence test fixtures.

The session remains non-visual. It adds no battlefield rendering, audio, UI ceremony, hosted persistence, protocol events, server routes, or second game state authority.

***

## 2. Objectives

1. Prove shared replay dispatch cannot change persisted projection progress numbers or durable local projection state.
2. Prove reconnect-style `roster_update`, `mission_state`, and `suggestion_update` snapshots reconcile or no-op without changing XP, essence, banners, kills, title progress, or War Tide numbers.
3. Prove mock/drill traffic may fold in memory only as implemented while projection persistence stays disabled.
4. Prove serialized projection snapshots remain bounded aggregate state and do not include event logs or transient presentation queues.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase22-session01-projection-contract` - Provides the projection shape, storage key, parser, persistence helpers, and baseline reducer tests.
* [x] `phase22-session02-hero-attention-reducer` - Provides replay-safe attention and Swift Command reducer behavior.
* [x] `phase22-session03-legion-enemy-reducer` - Provides replay-safe Legion reducer behavior for skirmishers, ram, gremlins, siege, and wraiths.
* [x] `phase22-session04-camp-link-boundaries` - Provides camp-link reducer behavior without fabricated progress.
* [x] `phase22-session05-store-folding-and-selectors` - Provides store hydration, selectors, and one-event projection folding.
* [x] `phase22-session06-persistence-lifecycle` - Provides guarded projection persistence, page lifecycle flush, mock/replay no-write guards, and reset storage removal.

### Required Tools Or Knowledge

* npm workspace commands from `.spec_system/CONVENTIONS.md`.
* Existing projection helpers in `apps/web/src/lib/gameProjection.ts`.
* Existing store persistence helpers in `apps/web/src/store/useGameStore.ts`.
* Existing replay dispatch helper in `apps/web/src/lib/replayLink.ts`.
* Existing focused tests in `apps/web/tests/gameProjection.test.ts`, `apps/web/tests/gameProjectionStore.test.ts`, and `apps/web/tests/replayPersist.test.ts`.

### Environment Requirements

* Node 26.2.0+ and npm 11.16.0+ per project conventions.
* Vitest with happy-dom `localStorage`, `window`, and `document` support.
* No database, migration, server, hosted service, Worker, or credential dependency applies.

***

## 4. Scope

### In Scope (MVP)

* Add or extend focused `apps/web` regression tests for the known replay/reconnect/mock anti-farming boundary.
* Test `dispatchReplayEntries()` through the public store seam with the replay flag set, proving persisted projection progress numbers do not change.
* Test replaying the same `mission_complete` or failed `tool_result` sequence twice under replay context without double-counting progress-like fields.
* Test reconnect-style `roster_update`, `mission_state`, and `suggestion_update` snapshots against seeded progress counters.
* Test `mockEnabled: true` so in-memory folding remains allowed where implemented while persisted projection writes stay disabled.
* Test that serialized projection snapshots exclude visible hero slots, strike queues, combo stages, sound cues, animation pulses, toast effects, replay entries, and raw sensitive payload fields.
* Repair `apps/web/src/lib/gameProjection.ts` or `apps/web/src/store/useGameStore.ts` only if the new tests expose an actual replay, reconnect, mock, or serialization guard defect.

### Out Of Scope (Deferred)

* Browser-local erasure inventory and `localErasure` tests - Reason: Session 08 owns `factionos-game-v1` erasure coverage and documentation closeout.
* Rendering, battlefield game presentation, camp buttons, Quest Board filtering, audio/SFX, toasts, hosted or cross-device persistence, protocol events, server routes, and new state authorities - Reason: Phase 22 only establishes and proves the projection authority.
* XP, essence, banners, kills, War Tide gain/loss behavior, title unlocks, or UI ceremony implementation - Reason: this session proves those counters are not accidentally minted before later scoped product work.

***

## 5. Technical Approach

### Architecture

Use the existing pure reducer tests in `apps/web/tests/gameProjection.test.ts` for event-level invariants, because they can seed projection counters directly and assert exact object preservation, JSON boundaries, and replay-context behavior without store side effects.

Use `apps/web/tests/gameProjectionStore.test.ts` for public store seam coverage. The store test should set `mockEnabled: false` when a real persisted write is expected, seed or flush `localStorage["factionos-game-v1"]` through existing helpers, dispatch replay entries with the replay flag, and verify the persisted projection baseline is unchanged after `__flushGameProjectionPersist()`.

Keep `apps/web/tests/replayPersist.test.ts` focused on replay-buffer parity unless the implementation needs a small assertion proving replay-buffer storage and projection storage stay separate. Source changes should be minimal and only address a failing honesty invariant.

### Design Patterns

* Fixed timestamp builders: Keep event ordering and persisted snapshots deterministic.
* Counter snapshot assertions: Capture XP, essence, banners, wraith kills, titles, and War Tide before replay/reconnect/mock paths and compare after.
* Public seam first: Exercise `dispatchReplayEntries()` and store `applyEvent()` rather than private implementation details for replay regressions.
* Privacy by serialization: Assert forbidden presentation and sensitive fields are absent from `JSON.stringify(projection)`.

***

## 6. Deliverables

### Files To Create

| File | Purpose                                                                                 | Est. Lines |
| ---- | --------------------------------------------------------------------------------------- | ---------- |
| None | This session extends existing tests and only changes source if a guard defect is found. | 0          |

### Files To Modify

| File                                         | Changes                                                                                     | Est. Lines |
| -------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------- |
| `apps/web/tests/gameProjection.test.ts`      | Add reducer-level replay, reconnect snapshot, and serialized aggregate honesty regressions. | \~160      |
| `apps/web/tests/gameProjectionStore.test.ts` | Add store-level `dispatchReplayEntries()` replay-flag and mock no-persist regressions.      | \~140      |
| `apps/web/tests/replayPersist.test.ts`       | Add narrow storage-separation coverage only if needed by the store replay test.             | \~30       |
| `apps/web/src/lib/gameProjection.ts`         | Repair reducer or serialization guard behavior only if the new tests expose a defect.       | \~40       |
| `apps/web/src/store/useGameStore.ts`         | Repair store replay/mock persistence guard behavior only if the new tests expose a defect.  | \~40       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] `dispatchReplayEntries()` with the replay flag does not change persisted projection progress numbers.
* [ ] Replayed `mission_complete` and failed `tool_result` sequences do not double XP, essence, banners, wraith kills, titles, War Tide, or other progress-like counters.
* [ ] Reconnect snapshots for `roster_update`, `mission_state`, and `suggestion_update` preserve seeded progress counters.
* [ ] `mockEnabled: true` prevents projection persistence while leaving allowed in-memory folding behavior intact.
* [ ] Serialized projections remain bounded aggregate JSON and exclude replay entries, transient presentation queues, raw prompts, broad paths, terminal output, file contents, provider payloads, tokens, and secrets.

### Testing Requirements

* [ ] `apps/web/tests/gameProjection.test.ts` covers pure reducer replay, reconnect snapshot, and serialization honesty invariants.
* [ ] `apps/web/tests/gameProjectionStore.test.ts` covers public `dispatchReplayEntries()` replay-flag behavior and mock no-persist behavior.
* [ ] Existing projection persistence and replay persistence coverage still passes.
* [ ] `npm test -- apps/web/tests/gameProjection.test.ts apps/web/tests/gameProjectionStore.test.ts apps/web/tests/replayPersist.test.ts` passes.
* [ ] `npm --workspace @factionos/web run typecheck` passes.

### Non-Functional Requirements

* [ ] Tests use fixed timestamps and small typed event builders.
* [ ] No rendering, audio, protocol, server, hosted persistence, or second projection authority is introduced.
* [ ] Production source changes, if any, remain limited to replay/mock/snapshot guard defects proven by tests.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] `npm exec -- biome check apps/web/src/lib/gameProjection.ts apps/web/src/store/useGameStore.ts apps/web/tests/gameProjection.test.ts apps/web/tests/gameProjectionStore.test.ts apps/web/tests/replayPersist.test.ts` passes for changed files.
* [ ] Primary user-facing surfaces are N/A because this session changes tests and possibly non-visual projection/store guards only.

***

## 8. Implementation Notes

### Working Assumptions

* `apps/web/tests/gameProjectionStore.test.ts` is the smallest store-level fixture for public replay and persistence behavior. Repo evidence: existing Session 06 tests already use `GAME_PROJECTION_STORAGE_KEY`, `__flushGameProjectionPersist()`, `mockEnabled`, and store `applyEvent()`. Planning can proceed because no component rendering is required.
* `suggestion_update` should be tested as the current explicit snapshot no-op for progress counters. Repo evidence: Phase 22 left camp reconciliation as an open choice and the existing reducer tests assert suggestion snapshots do not mutate links, camps, rewards, or raw prompts. Planning can proceed because the honesty invariant is stronger than a future camp-shape implementation.
* Write-expecting store tests must set `mockEnabled: false`. Repo evidence: `useSettingsStore` defaults `mockEnabled` to true and Phase 22 names it as the drill persistence guard.

### Conflict Resolutions

* The session stub permits using `gameProjectionStore.test.ts`, `replayPersist.test.ts`, or another persistence-style test. The selected interpretation is to use `gameProjectionStore.test.ts` for store replay/mock assertions and `gameProjection.test.ts` for pure reducer invariants, because those files already own the relevant helpers and avoid broad replay-buffer churn.
* Reconnect snapshots may reconcile visible non-progress state, but they must not change progress counters. The plan tests progress-counter preservation instead of forbidding all snapshot changes.

### Key Considerations

* Preserve Fun Law 1: no game resource should be generated by replay, reconnect hydration, mock traffic, or presentation-only state.
* Preserve local-first privacy boundaries: projection snapshots must not store raw prompts, broad paths, terminal output, file contents, provider payloads, tokens, secrets, or replay buffers.
* Keep Session 08 clear: browser erasure inventory and documentation closeout are intentionally deferred to the next session.

### Relevant Considerations

* \[P03] **Stable docs are the current contract**: Use README files, PRD files, and current source/tests as authority; archived PRDs and examples are traceability evidence only.
* \[P18-apps/server+apps/web] **`suggestion_update` is canonical**: Preserve hydration/store reconciliation semantics and avoid a parallel event authority.
* \[P20] **Broad privacy gates are release-critical**: Keep raw commands, terminal output, file contents, provider payloads, tokens, secrets, broad absolute paths, and replay buffers out of persisted snapshots and broad tests.
* \[P08] **Full trusted erasure remains no-claim**: Do not treat browser-local projection cleanup or reset behavior as trusted unified erasure.

### Potential Challenges

* Reused event builders can hide replay context mistakes: Keep at least one store-level replay test through `dispatchReplayEntries()` with `setReplayingFlag`.
* Existing tests may already cover part of the matrix: Extend rather than duplicate assertions, and keep new tests named around the anti-farming invariant.

***

## 9. Testing Strategy

### Unit Tests

* Pure reducer tests in `apps/web/tests/gameProjection.test.ts` for replayed mission/tool sequences, reconnect snapshots, and serialized projection exclusions.

### Integration Tests

* Store seam tests in `apps/web/tests/gameProjectionStore.test.ts` for `dispatchReplayEntries()` with replay flag and `mockEnabled` persistence blocking.

### Runtime Verification

* Run the focused Vitest command and the `@factionos/web` typecheck. No browser screenshot or app dev server is required because this session changes no UI.

### Edge Cases

* Replayed mission/tool sequence dispatched twice.
* Reconnect snapshots with seeded nonzero counters.
* Mock-enabled event that mutates memory but must leave storage unchanged.
* Serialized snapshot with forbidden presentation and sensitive field names.
* Empty or unchanged projection path to ensure persistence is not scheduled.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase22-session06-persistence-lifecycle`.
* Depended by: `phase22-session08-erasure-docs-and-validation`.

***

## 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://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase22-session07-honesty-regression-tests/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.
