> 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-session07-scanner-and-golden-age-states/spec.md).

# Session Specification

**Session ID**: `phase23-session07-scanner-and-golden-age-states` **Phase**: 23 - Legion I - Scanner Camps **Status**: Not Started **Created**: 2026-07-05 **Base Commit**: 92c5c6435e458469026be3a3d0fe0ce844a38e20 **Package**: apps/web **Package Stack**: TypeScript

***

## 1. Session Overview

This session makes scanner lifecycle states legible on the `apps/web` battlefield. The board should distinguish Dispatch Scouts, scan-not-run, scan-failed, Legion-present, mock drill, zero-hero, and Golden Age states without inventing enemy progress or moving scanner configuration into the battlefield.

It is next because Phase 23 Sessions 01-06 are complete: scanner issue snapshots already reconcile into `GameProjection`, ranked camps already render on the battlefield, and Quest Board focus plus dry Banish already use real issue ids. Session 07 adds the remaining state presentation around that camp layer.

The implementation must stay presentation- and guardrail-focused. It may derive UI state from the existing Quest Board scan status, current camp aggregate, visible heroes, and mock setting, but it must not add protocol events, storage keys, hosted state, camp rewards, camp damage, new required audio assets, scan configuration ownership, or trusted-erasure claims.

***

## 2. Objectives

1. Add a typed battlefield scanner-state view model for Golden Age, scan-not-run, running scouts, failed scans, mock drills, and Legion-present states.
2. Render scanner lifecycle and clean-state treatments on the battlefield with product-facing copy, stable `data-testid` hooks, and reduced-motion static equivalents.
3. Preserve camp honesty by ensuring failed scan snapshots cannot clear existing camps unless a real successful clean snapshot removes the issues.
4. Extend focused tests for Golden Age, scan-not-run, running scouts, failed-scan camp preservation, reduced motion, zero-hero neutrality, and mock drill labeling.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase23-session04-store-persistence-boundaries` - proves real camp aggregates persist only through `localStorage["factionos-game-v1"]`, while replay and mock-mode writes remain durable-progress inert.
* [x] `phase23-session05-quest-board-camp-focus` - provides camp inspection and dry Banish through existing Quest Board issue actions.
* [x] `phase23-session06-battlefield-camp-layer` - renders ranked camps on the battlefield and leaves scan lifecycle, clean-state, failed-scan, and mock drill presentation to this session.
* [x] `phase22-session05-store-folding-and-selectors` - provides the web store projection selector pattern and single projection authority.

### Required Tools Or Knowledge

* React 19, TypeScript, Tailwind utility conventions, and CSS in `apps/web/src/index.css`.
* Existing scanner normalization in `apps/web/src/lib/questBoardModel.ts` and Quest Board state in `apps/web/src/store/useGameStore.ts`.
* Existing projection reducer and camp reconciliation in `apps/web/src/lib/gameProjection.ts` and `apps/web/src/lib/legionCamps.ts`.
* Existing battlefield layering in `apps/web/src/components/battlefield/Battlefield.tsx`.
* Vitest and React Testing Library patterns in `apps/web/tests/Battlefield.test.tsx`, `apps/web/tests/gameProjection.test.ts`, and `apps/web/tests/gameProjectionStore.test.ts`.

### Environment Requirements

* Node 26.2.0 or newer and npm 11.16.0.
* Root workspace dependencies installed.
* Commands run from the repository root.

***

## 4. Scope

### In Scope (MVP)

* A battlefield scanner-state helper derives state from `QuestBoardState`, ranked camps, visible hero count, and `useSettingsStore.mockEnabled`.
* Dispatch Scouts presentation appears for running codebase, analysis, or project scans when current scan status identifies the run.
* A short-lived scouts-dispatched state is visible when a qualifying manual scan transitions into running, with cleanup on component unmount.
* Running scan status renders scout activity on or near the battlefield, with a static reduced-motion badge replacing motion-only trails or riders.
* Golden Age renders only after a canonical scanner snapshot has completed and the latest codebase issue count is zero.
* Scan-not-run renders when no completed scanner snapshot exists, and it does not masquerade as Golden Age.
* Failed scan state is legible, but it does not become enemy progress and does not clear existing camps unless a successful real scanner snapshot removes those issues.
* Existing camp rendering remains the source for Legion-present state.
* Mock-enabled visible camps are bannered as drill/non-progress state.
* Zero-hero battlefield state can show scout status, Golden Age, or a small camp census, but visible copy must not imply that an army is present.
* Add `data-testid` hooks for Golden Age, scan-not-run, failed-scan, scout-state, reduced-motion scout-state, mock drill, and zero-hero behavior.
* Add focused battlefield and reducer tests where the behavior lands.

### Out Of Scope (Deferred)

* Scan configuration ownership, scan roots, ignore-pattern editing, disabled run gating, and diagnostics - Reason: these remain in existing Quest Board and Settings utility UI.
* Public-demo synthetic fronts - Reason: Phase 23 explicitly excludes public demo synthetic camp work.
* Required new audio assets - Reason: this session may reuse a safe existing cue only if available, but audio is not required for the phase.
* Camp damage, camp clearing animation, target flags, XP, loot, banners, achievements, kill credit, Dawn Report changes, bosses, seasons, dynamic audio, or live combat playback - Reason: later phases own these mechanics.
* New protocol events, server routes, storage keys, hosted state, or trusted-erasure claims - Reason: existing `suggestion_update`, Quest Board state, and browser-local projection boundaries are sufficient.
* Documentation closeout and final phase audit - Reason: Session 08 owns final validation and documentation after behavior is proven.

***

## 5. Technical Approach

### Architecture

Add `apps/web/src/lib/battlefieldScannerState.ts` as a pure helper that accepts the normalized Quest Board state, visible ranked camp count, visible hero count, and mock setting. It should return a compact discriminated union for states such as `scan_not_run`, `scouts_running`, `scan_failed`, `golden_age`, `legion_present`, and `drill`. The helper must use exhaustive handling for known scan statuses and avoid copying raw issue details.

Add `apps/web/src/components/battlefield/ScannerStateLayer.tsx` as a presentation-only component. It renders product-facing board badges, calm Golden Age treatment, failed-scan copy, scout activity, static reduced-motion equivalents, and mock drill labels. It should receive a derived view model and `reduceMotion`; it should not reconcile camps, call APIs, own scanner configuration, or mutate projection state.

In `Battlefield.tsx`, read `questBoard`, `gameProjection`, `rankedCamps`, `visibleHeroes`, `reduceMotion`, and `mockEnabled`. Derive scanner state, track a short-lived scouts-dispatched transition when a scan moves into running, clear that local timer on unmount, and render `ScannerStateLayer` without disturbing the existing `CampLayer`, hero tokens, empty terrain button, or remote participant overlay.

In `gameProjection.ts`, add or verify a failed-scan guard so failed scanner snapshots do not reconcile empty `codebaseIssues` into camp deletion. Real successful clean snapshots must still clear camps and produce the Golden Age presentation. This keeps failed scan state visible while preserving the projection as the single camp authority.

### Design Patterns

* Pure view-model helper: keep scan-state classification easy to test without rendering.
* Presentation-only layer: mirror `CampLayer.tsx` and `achievementCelebration.ts` by keeping battlefield effects beside the board component.
* Selector-led rendering: keep camp and clean-state decisions grounded in `GameProjection` and normalized Quest Board state.
* Reduced-motion parity: every moving scout treatment has a static badge with equivalent information.
* Product-surface copy only: scanner diagnostics, roots, ignored patterns, and disabled gating stay in utility surfaces.

***

## 6. Deliverables

### Files To Create

| File                                                        | Purpose                                                                                                                          | Est. Lines |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `apps/web/src/lib/battlefieldScannerState.ts`               | Pure classifier for battlefield scanner lifecycle, clean-state, failed-scan, and drill states.                                   | \~160      |
| `apps/web/src/components/battlefield/ScannerStateLayer.tsx` | Battlefield presentation layer for Dispatch Scouts, Golden Age, scan-not-run, failed-scan, zero-hero, and mock drill treatments. | \~210      |
| `apps/web/tests/battlefieldScannerState.test.ts`            | Focused pure-helper coverage for scanner state classification.                                                                   | \~160      |

### Files To Modify

| File                                                  | Changes                                                                                                                                | Est. Lines |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `apps/web/src/components/battlefield/Battlefield.tsx` | Derive scanner state, track short-lived scouts-dispatched UI state, wire `ScannerStateLayer`, and preserve current camp/hero layering. | \~90       |
| `apps/web/src/lib/gameProjection.ts`                  | Preserve existing camps when `suggestion_update.scanStatus.status` is failed; allow successful clean snapshots to clear camps.         | \~30       |
| `apps/web/src/index.css`                              | Add scanner-state, Golden Age, failed-scan, scout, drill, and reduced-motion styles.                                                   | \~110      |
| `apps/web/tests/Battlefield.test.tsx`                 | Add focused component tests for Golden Age, scan-not-run, scouts, failure, reduced motion, zero-hero, and drill presentation.          | \~220      |
| `apps/web/tests/gameProjection.test.ts`               | Add reducer regression proving failed scans do not clear camps and successful clean snapshots still do.                                | \~80       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Running scanner status renders Dispatch Scouts presentation on the battlefield.
* [ ] Reduced-motion mode renders a static scout-status badge instead of motion-only scout treatment.
* [ ] Golden Age renders only for a completed canonical scanner snapshot with zero current codebase issues.
* [ ] Scan-not-run renders when the scanner has not produced a snapshot and never appears as Golden Age.
* [ ] Failed scan state is visible without clearing existing camps or creating enemy progress.
* [ ] Successful clean scanner snapshots can still clear camps and drive the Golden Age state.
* [ ] Mock-enabled visible camps are visibly labeled as drill/non-progress state.
* [ ] Zero-hero state does not imply an army is present.
* [ ] Existing scanner configuration, roots, ignore patterns, disabled gating, and diagnostics remain outside the battlefield surface.
* [ ] No new protocol event, storage key, server route, hosted dependency, reward, camp damage, or trusted-erasure claim is introduced.

### Testing Requirements

* [ ] `apps/web/tests/battlefieldScannerState.test.ts` covers all scanner view model branches.
* [ ] `apps/web/tests/Battlefield.test.tsx` covers Golden Age, scan-not-run, running scouts, failed scan with existing camps, reduced-motion scout badge, zero-hero neutrality, and mock drill labeling.
* [ ] `apps/web/tests/gameProjection.test.ts` covers failed scan camp preservation and successful clean snapshot camp clearing.
* [ ] Focused Vitest command passes for the new and changed tests.
* [ ] `npm --workspace @factionos/web run typecheck` passes.
* [ ] `npm run format:check` passes or unrelated pre-existing issues are documented.

### Non-Functional Requirements

* [ ] Projection remains the only derived game-state authority for camps.
* [ ] Projection storage remains `localStorage["factionos-game-v1"]` only.
* [ ] Visible battlefield copy does not expose raw issue messages, prompts, transcripts, terminal output, provider payloads, file contents, absolute paths, environment values, secrets, scan roots, ignored patterns, or diagnostics.
* [ ] Scanner states are understandable through text, labels, and badges, not color or motion alone.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Primary user-facing surfaces contain product-facing copy only.

***

## 8. Implementation Notes

### Working Assumptions

* Package context is `apps/web`: the analysis script reports Session 07 as an `apps/web` candidate, the Phase 23 PRD scopes the work to the web cockpit game layer, and all code anchors are web component, store, projection, and test files.
* Battlefield scan state can be derived from existing Quest Board state: `QuestBoardState` already exposes normalized `scanStatus`, summary counts, and `hasCanonicalSnapshot`, so no new protocol event or persistent field is required.
* Dispatch Scouts can use the transition into `scanStatus.inProgress` plus `lastStartedAt` for presentation: this is a short-lived UI effect and does not need to become persisted projection state.
* Mock drill labeling can use `useSettingsStore.mockEnabled` with visible camp state: Phase 22 records that mock events are indistinguishable on the wire, so the durable-progress guard already keys off the mock setting.

### Conflict Resolutions

* The master PRD phase summary still lists Phase 23 as Not Started, while the analyzer, Phase 23 PRD, and completed session artifacts show Sessions 01-06 complete. Planning follows the analyzer and live Phase 23 artifacts because `plansession` treats analyzer JSON as authoritative state.
* The older game-design outline mentions `scanCodebase.ts` and Settings scan state as scan ceremony anchors, while current implementation exposes canonical Quest Board scan triggers and normalized scan status through `useGameStore`. The plan uses the current Quest Board path and keeps Settings as utility UI because that matches the live codebase and Session 07 scope.

### Key Considerations

* Failed scan state must be informative, not destructive: failure should not delete camp aggregates unless a successful scanner snapshot proves the issues are gone.
* Golden Age is a clean scanner outcome, not an empty-app fallback.
* The battlefield may summarize scanner state, but it must not own scanner configuration or diagnostics.

### Potential Challenges

* Distinguishing not-yet-scanned from clean: use `hasCanonicalSnapshot`, `lastCompletedAt`, and codebase issue counts together instead of checking only for zero camps.
* Avoiding duplicate UI state: keep short-lived dispatch state local to `Battlefield.tsx` and keep durable camp state inside `GameProjection`.
* Preserving reduced-motion parity: test static scout-state hooks directly so motion-only treatments cannot become the only signal.

### Relevant Considerations

* \[P22-apps/web] **Game projection is the single derived authority**: camp state continues to come from `gameProjection.ts`; battlefield scan state is presentation derived from that authority and Quest Board status.
* \[P22-apps/web] **Derived projection storage is narrow**: no new storage key or raw scanner data may enter projection persistence.
* \[P22-apps/web] **Do not add parallel game authorities**: scanner ceremony must not copy camp progress, rewards, enemy state, or camp links elsewhere.
* \[P22-apps/web] **Do not persist replay or drill progress**: mock drill labeling must remain visibly non-progress and durable writes must stay guarded.
* \[P18-apps/server] **Quest Board state is durable local evidence**: scanner lifecycle and codebase issue counts come from the existing Quest Board snapshot path.
* \[P07] **Redaction is boundary-specific**: new UI and tests must avoid raw commands, terminal output, file contents, provider payloads, secrets, and broad absolute paths.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Failed-scan UI accidentally clearing or hiding real existing camps.
* Golden Age appearing before the scanner has produced a completed clean snapshot.
* Reduced-motion users receiving less scanner status information than users with motion enabled.

***

## 9. Testing Strategy

### Unit Tests

* Test `battlefieldScannerState.ts` classification for canonical clean, no-snapshot, running, failed, Legion-present, mock drill, and zero-hero combinations.
* Test `gameProjection.ts` reducer behavior for failed scan preservation and successful clean snapshot removal.

### Integration Tests

* Extend `Battlefield.test.tsx` with store-seeded states covering Golden Age, scan-not-run, running scouts, failed scans with existing camps, reduced motion, zero heroes, and mock drill camps.

### Runtime Verification

* Run:

```bash
npm test -- apps/web/tests/battlefieldScannerState.test.ts apps/web/tests/Battlefield.test.tsx apps/web/tests/gameProjection.test.ts
npm --workspace @factionos/web run typecheck
npm run format:check
```

### Edge Cases

* Failed scan with an empty `codebaseIssues` payload and existing projection camps.
* Successful completed scan with zero codebase issues.
* No canonical Quest Board snapshot yet.
* Running scan with reduced motion enabled.
* Mock mode with visible camps.
* Zero visible heroes with camp, clean, failed, and running scan states.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase23-session04-store-persistence-boundaries`, `phase23-session05-quest-board-camp-focus`, `phase23-session06-battlefield-camp-layer`
* Depended by: `phase23-session08-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/archive/sessions/phase23-session07-scanner-and-golden-age-states/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.
