> 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/specs/phase24-session07-honesty-and-persistence-boundaries/spec.md).

# Session Specification

**Session ID**: `phase24-session07-honesty-and-persistence-boundaries` **Phase**: 24 - Legion II - Live Tier And Combat Playback **Status**: Not Started **Created**: 2026-07-08 **Base Commit**: 2c9645b1360bda08ef6cc6c67677f506274e6278 **Package**: apps/web **Package Stack**: TypeScript

***

## 1. Session Overview

This session proves that Phase 24 live-tier combat remains honest across replay, reconnect, mock mode, persistence, and browser-local erasure boundaries. The work focuses on the existing `apps/web` projection reducer, store persistence seam, replay dispatch path, Quest Board pending-link path, and local erasure helper.

The session is next because Sessions 02 and 04 shipped the camp-to-mission link and combat playback surfaces that can now create visible links, strikes, wraith pressure, and verification-only kill moments. Before generated asset handoff and final phase validation, the code needs regression proof that those moments cannot be replay-farmed, mock-farmed, or leaked into durable storage with raw prompts or other sensitive values.

The implementation should preserve the existing single projection authority and single browser storage key. Pending-link prompt matching may remain an in-memory runtime mechanism, but persisted `factionos-game-v1` snapshots must stay aggregate-only and browser-local erasure must clear the full Phase 24 surface without adding a new inventory key.

***

## 2. Objectives

1. Prove replayed linked missions, verifications, live-enemy events, and link-creating sequences do not create persisted kills, links, wraith stacks, counters, or durable progress.
2. Prove reconnect and snapshot-style events reconcile without accumulating kills, wraith stacks, or camp-link records.
3. Keep mock-mode live-tier drills in memory only, with no persisted projection changes from links, enemies, or combat events.
4. Tighten projection persistence, storage inventory, privacy tests, and browser-local erasure coverage so `factionos-game-v1` remains aggregate-only.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase24-session02-camp-mission-linkage` - Provides pending link recording, `mission_start` binding, and Quest Board accept/assign link paths.
* [x] `phase24-session04-combat-playback-effects-layer` - Provides linked combat playback and verification-only kill presentation surfaces.

### Required Tools Or Knowledge

* `apps/web/src/lib/gameProjection.ts` owns projection types, reducer slices, persistence helpers, pending links, live enemy folding, and storage key constants.
* `apps/web/src/store/useGameStore.ts` owns `replayingSinceMs`, mock-enabled persistence context, projection flush scheduling, and `resetToSeed`.
* `apps/web/src/lib/replayLink.ts` owns `dispatchReplayEntries` and the replaying flag callback.
* `apps/web/src/lib/localErasure.ts` owns browser-local erasure inventory and execution.
* Focused tests run through Vitest from the repo root.

### Environment Requirements

* Node 26.2.0+ and npm 11.16.0 per `.spec_system/CONVENTIONS.md`.
* Browser storage tests run under the existing happy-dom Vitest environment.

***

## 4. Scope

### In Scope (MVP)

* A web operator can trust that replay dispatch cannot mint durable live-tier progress - Add reducer and store regressions for linked mission, verification, live enemy, and link-creating replay streams.
* A web operator can trust reconnect snapshots are reconciliation only - Add snapshot regressions for roster, mission, suggestion, and clean-scan events without kill, link, stack, or counter accumulation.
* A web operator can run mock drills without durable game progress - Add mock-mode regressions for pending links, failed tool wraiths, live enemies, and scanner camp snapshots.
* A web operator's browser storage remains aggregate-only - Scrub prompt-bearing pending links from persisted projection snapshots while keeping runtime pending-link matching intact.
* A web operator can erase Phase 24 browser-local projection data through existing browser erasure - Extend erasure tests for live-tier aggregate payloads and reject new camp, Legion, scanner, combat, or live-tier storage keys.
* Privacy sentinels remain out of persisted state, UI-facing labels, and fixtures - Assert no raw prompts, command output, file contents, absolute paths, provider payloads, environment values, or secrets appear in serialized projection data.

### Out Of Scope (Deferred)

* Generated visual asset implementation - Reason: Session 08 owns generated Phase 3 asset references and handoff.
* Phase exit documentation and section 13A acceptance report - Reason: Session 09 owns full phase validation and docs.
* Trusted unified erasure claims - Reason: This session only proves browser-local erasure for existing web storage boundaries.
* Hosted persistence, hosted identity, analytics, public replay hosting, push, remote execution, or new protocol/server routes - Reason: Phase 24 explicitly excludes them.

***

## 5. Technical Approach

### Architecture

Keep `gameProjection.ts` as the single source of game truth. Add a persistence scrub path inside the projection persistence helpers so in-memory `pendingLinks` can still hold prompt text long enough for `mission_start` matching, while `persistGameProjection` writes only aggregate-safe projection data. The persisted form should keep safe live-enemy records, bounded ids, counters, timestamps, `campLinks`, and alert focus, but it should not retain raw pending-link prompts or other prompt-bearing transient data. Loading older persisted snapshots should normalize unsafe pending-link payloads away rather than reviving raw prompt data.

Use reducer tests to cover pure replay, reconnect, serialization, and privacy behavior. Use store tests to prove the real `applyEvent`, `replayingSinceMs`, `dispatchReplayEntries`, mock setting, debounce flush, and storage inventory behave together. Use Quest Board tests to update the current pending-link expectation: normal accept and assign paths may record a runtime link, but the persisted projection snapshot must not contain the dispatched prompt. Use local erasure tests to prove the existing `browser_settings` boundary clears Phase 24 aggregate payloads and that no new browser storage key is introduced.

The implementation should not create a second projection authority, new storage key, protocol event, server route, diagnostic UI, or documentation-only proof.

### Design Patterns

* Runtime-only sensitive matching: Keep prompt matching local to active memory and strip prompt-bearing transient link state before persistence.
* Pure reducer proof first: Add deterministic reducer tests before store integration tests so behavior is easy to isolate.
* Existing store guard reuse: Use `shouldPersistGameProjection`, `replayingSinceMs`, and `mockEnabled` instead of adding a parallel persistence switch.
* Inventory tests as gates: Enumerate storage keys and fail on new camp, Legion, scanner, combat, battlefield, or live-tier keys.

***

## 6. Deliverables

### Files To Create

| File | Purpose                                                                                                                     | Est. Lines |
| ---- | --------------------------------------------------------------------------------------------------------------------------- | ---------- |
| None | No new source or test file is required; this session extends existing projection, store, Quest Board, and erasure coverage. | 0          |

### Files To Modify

| File                                         | Changes                                                                                                                              | Est. Lines |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| `apps/web/src/lib/gameProjection.ts`         | Add projection persistence scrubbing and legacy persisted pending-link normalization while preserving runtime pending-link matching. | \~90       |
| `apps/web/tests/gameProjection.test.ts`      | Add reducer replay, reconnect, serialization, live-tier aggregate, verification-only kill, and privacy regressions.                  | \~240      |
| `apps/web/tests/gameProjectionStore.test.ts` | Add store-level replay dispatch, mock-mode, storage unchanged, and inventory regressions for live-tier events.                       | \~190      |
| `apps/web/tests/questBoardStore.test.ts`     | Update pending-link persistence expectations so prompts remain runtime-only and do not appear in `factionos-game-v1`.                | \~80       |
| `apps/web/tests/localErasure.test.ts`        | Extend browser-local erasure coverage for Phase 24 aggregate live-tier payloads and key inventory.                                   | \~100      |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Replayed linked missions, verifications, live-enemy events, and pending-link sequences do not create persisted kills, links, counters, wraith stacks, or camp progress.
* [ ] Reconnect and snapshot-style events reconcile without accumulating kills, wraith stacks, camp links, or durable counters.
* [ ] Mock-mode live-tier drills can fold in memory but cannot write new `factionos-game-v1` state.
* [ ] Runtime pending-link matching still works for Quest Board accept and assign paths.
* [ ] Persisted projection snapshots do not contain raw pending-link prompts.

### Testing Requirements

* [ ] Reducer regressions written and passing for replay, reconnect, live enemies, verification-only kills, serialization, and privacy.
* [ ] Store regressions written and passing for `dispatchReplayEntries`, `replayingSinceMs`, mock mode, and storage inventory.
* [ ] Quest Board pending-link persistence expectations updated and passing.
* [ ] Browser-local erasure tests cover Phase 24 aggregate payloads through the existing key.

### Non-Functional Requirements

* [ ] `factionos-game-v1` remains the only game projection storage key.
* [ ] No new protocol event, server route, hosted dependency, public replay behavior, diagnostic UI, reward system, or trusted-erasure claim is added.
* [ ] Serialized projection data excludes raw prompts, output, file contents, absolute paths, provider payloads, environment values, and secrets.

### Quality Gates

* [ ] All files ASCII-encoded
* [ ] Unix LF line endings
* [ ] Code follows project conventions
* [ ] `npm --workspace apps/web run typecheck` passes
* [ ] Focused projection, store, Quest Board, and erasure tests pass

***

## 8. Implementation Notes

### Working Assumptions

* Session package is `apps/web`: The analyzer candidate, Phase 24 PRD, session stub, and all required code anchors point to `apps/web`, and no protocol or server changes are needed.
* Pending-link prompts should become runtime-only for persistence: Session 02 uses prompt matching to bind a mission to a camp, but Session 07's objective and storage scope require persisted projection data to stay aggregate-only. Planning can proceed because the runtime link can still exist before serialization.
* Browser-local erasure needs no new boundary: `localErasure.ts` already includes `GAME_PROJECTION_STORAGE_KEY` under `browser_settings`, so the session should extend proof rather than add an inventory key.

### Conflict Resolutions

* `apps/web/tests/questBoardStore.test.ts` currently proves a normal accept path persists the raw dispatched prompt, while the Session 07 stub requires no raw prompts in persisted projection state. The Session 07 privacy boundary is the later and more specific requirement, so this plan updates the test and implementation to keep prompts out of `factionos-game-v1`.
* `SECURITY-COMPLIANCE.md` still describes optional short pending camp-link prompts in derived projection storage, while Session 07 requires aggregate-only persistence. The code and focused tests should move to the stricter boundary now; Session 09 owns final documentation and inventory wording.

### Key Considerations

* Do not remove in-memory camp-to-mission linkage behavior while fixing persistence.
* Do not add a new game storage key to avoid storing pending-link prompts.
* Keep mock and replay guards centralized through the existing store context.
* Treat storage contents and test fixtures as privacy surfaces, not only UI labels.

### Potential Challenges

* Dropping pending links from persisted snapshots can affect reload-before-mission-start behavior: Preserve live in-memory behavior and document this as the privacy-preserving boundary inside tests.
* Existing tests are large and share helper patterns: Extend the closest existing files instead of creating a broad new harness.
* Legacy persisted snapshots may contain raw pending links: Normalize them away on load so old storage does not revive prompt text.

### Relevant Considerations

* \[P22-apps/web] **Single projection authority**: Keep reducer logic, parsing, persistence guards, and constants in `gameProjection.ts`.
* \[P22-apps/web] **Honesty regression matrix**: Cover reducer, store, replay, reconnect, mock, serialization, persistence, reset, and erasure seams.
* \[P23-apps/web] **Storage inventory regressions**: Enumerate browser keys and reject new camp, Legion, scanner, battlefield, combat, or live-tier keys.
* \[P23-apps/web] **Scanner camp projection stays aggregate-only**: Keep raw issue text, prompts, paths, file contents, provider payloads, scan roots, and secrets out of projection storage.
* \[P08] **Full trusted erasure remains no-claim**: Keep this session limited to browser-local projection cleanup.
* \[P07] **Redaction is boundary-specific**: Treat persistence, tests, erasure summaries, and UI labels as separate privacy boundaries.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* A replay or mock event path can mutate memory and accidentally flush durable progress.
* Prompt-bearing pending links can leak through JSON persistence even if UI labels are safe.
* Browser-local erasure can clear the old projection payload but miss new live-tier aggregate shapes.

***

## 9. Testing Strategy

### Unit Tests

* `apps/web/tests/gameProjection.test.ts`: Reducer replay matrix, reconnect snapshots, verification-only kill constraints, live enemy privacy, persistence scrub serialization, legacy raw pending-link load normalization, and aggregate-only root-key assertions.

### Integration Tests

* `apps/web/tests/gameProjectionStore.test.ts`: `dispatchReplayEntries` with linked mission and live enemy events, mock-mode live-tier folding, unchanged persisted snapshot assertions, storage inventory checks, and reset persistence flush behavior.
* `apps/web/tests/questBoardStore.test.ts`: Accept and assign paths keep runtime pending links but do not persist raw prompts.
* `apps/web/tests/localErasure.test.ts`: Browser erasure preview and confirm remove Phase 24 aggregate payloads through existing boundaries and do not expose raw values.

### Runtime Verification

* Run `npm test -- --run apps/web/tests/gameProjection.test.ts apps/web/tests/gameProjectionStore.test.ts apps/web/tests/questBoardStore.test.ts apps/web/tests/localErasure.test.ts`.
* Run `npm --workspace apps/web run typecheck`.
* Run ASCII and LF checks over modified files.

### Edge Cases

* Replayed `mission_start`, `mission_update`, `task_verification`, `tool_result`, `test_failure`, `build_error`, `ts_errors`, `lint_error`, and stall events cannot change persisted progress.
* Reconnect snapshots cannot duplicate wraith stacks, camp links, kills, or counters.
* Mock enabled state can animate or fold in memory but cannot create a durable projection write.
* Legacy raw pending-link storage loads without reviving prompt text.
* Duplicate erasure requests return cached summaries without raw values and without claiming trusted unified erasure.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase24-session02-camp-mission-linkage`, `phase24-session04-combat-playback-effects-layer`
* Depended by: `phase24-session09-validation-and-documentation`

***

## 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/specs/phase24-session07-honesty-and-persistence-boundaries/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.
