> 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-session01-pure-camp-reconciliation/spec.md).

# Session Specification

**Session ID**: `phase23-session01-pure-camp-reconciliation` **Phase**: 23 - Legion I - Scanner Camps **Status**: Not Started **Created**: 2026-07-05 **Base Commit**: 07c28c3698ab936bc0f1c722756b4493b78a99ef **Package**: apps/web **Package Stack**: TypeScript

***

## 1. Session Overview

This session creates the pure Legion camp reconciliation module for the `apps/web` game layer. It turns current Quest Board scanner issues into stable, aggregate sector and camp records that fit the existing `GameProjection` shapes without importing React, store code, persistence, server modules, or new protocol authority.

It is next because Phase 23 depends on a pure reconciliation foundation before the later sessions can rank camps, fold scanner snapshots into the projection, persist them safely, inspect them through Quest Board, or render battlefield markers. Session 01 has no unmet session dependencies and directly unlocks Sessions 02 and 03.

The plan preserves the Phase 22 honesty boundary: scanner findings become only aggregate camp data, not rewards, progress, camp damage, missions, hosted state, new storage keys, or rich issue detail copied into projection state.

***

## 2. Objectives

1. Create `apps/web/src/lib/legionCamps.ts` as a pure TypeScript module for scanner issue to sector/camp reconciliation.
2. Convert `CodebaseIssue` snapshots into deterministic camp aggregates with safe relative sector labels, stable cells, sorted unique issue ids, HP, tiers, and entrenchment counters.
3. Keep projection-shaped output aggregate-only and free of raw issue messages, prompts, terminal output, file contents, absolute paths, environment values, or secrets.
4. Add focused Vitest coverage in `apps/web/tests/legionCamps.test.ts` for the reconciliation, sector budgeting, stability, entrenchment, and privacy invariants.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase22-session01-projection-contract` - provides the versioned `GameProjection`, sector, and camp shapes.
* [x] `phase22-session03-legion-enemy-reducer` - provides Legion reducer boundaries and the existing camp no-op posture.
* [x] `phase22-session08-erasure-docs-and-validation` - validates projection storage, replay, mock, and browser-local erasure boundaries.

### Required Tools Or Knowledge

* TypeScript discriminated types and type-only imports from `@factionos/protocol`.
* Existing `GameProjection` aggregate types from `apps/web/src/lib/gameProjection.ts`.
* Vitest test patterns from `apps/web/tests/gameProjection.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)

* The web game layer can reconcile current scanner issue snapshots into pure aggregate camps - implemented in `apps/web/src/lib/legionCamps.ts`.
* The web game layer can derive safe relative sectors and stable cells from issue file paths - implemented without absolute path persistence.
* The web game layer can classify camp HP and tier, preserve scar percentage, and update entrenchment counters across snapshots - implemented as pure deterministic functions.
* The web tests can prove severity weights, sector coalescing, bounded `Borderlands` grouping, stable ordering, stable cell assignment, tier thresholds, entrenchment, clean snapshots, and privacy-safe output.

### Out Of Scope (Deferred)

* Projection reducer wiring - Reason: Session 03 owns `suggestion_update` folding into `GameProjection`.
* Store persistence assertions - Reason: Session 04 owns persistence, replay, mock-mode, reset, and local erasure regressions.
* Quest Board UI or Banish behavior - Reason: Session 05 owns inspection and dismissal through existing issue cards.
* Battlefield rendering - Reason: Session 06 owns camp markers and Champion Mode presentation.
* Rewards, camp damage, mission links, protocol changes, hosted state, and new storage keys - Reason: Phase 23 explicitly forbids these behaviors.

***

## 5. Technical Approach

### Architecture

Create `legionCamps.ts` as a pure library that imports only type contracts from `@factionos/protocol` and `gameProjection.ts`. The module accepts current `CodebaseIssue` snapshots plus previous camps and sectors, then returns new `GameProjectionCamp` and `GameProjectionSector` records with deterministic record ordering.

Sector derivation starts from safe repository-relative path segments and uses workspace/top-level grouping first. If a repository has too few sectors, the module splits one level deeper where safe path data allows it. If it has too many sectors, the long tail is grouped into a safe `Borderlands` bucket before camp ids are created. Stable camp ids and sector cells come from the final safe sector key, preserving previous cells for unchanged sectors.

Camp records store only issue ids and aggregate presentation fields. HP is the sum of severity weights, tier comes from fixed thresholds, `maxHp` preserves a larger previous value for a surviving scarred camp, `scarredPct` persists only for camps that remain present, and `entrenchedScans` increments only when issue membership and HP are unchanged across consecutive snapshots.

### Design Patterns

* Pure module: keeps reconciliation reusable for reducer, store, and UI tests without side effects.
* Snapshot reconciliation: current issue snapshots replace the camp census so removed issues remove camps.
* Deterministic ordering: stable ids, sorted issue ids, and sorted record keys avoid replay drift and test flakiness.
* Aggregate-only privacy boundary: Quest Board owns rich issue detail; the projection-shaped result stores only ids and safe labels.

***

## 6. Deliverables

### Files To Create

| File                                 | Purpose                                                                     | Est. Lines |
| ------------------------------------ | --------------------------------------------------------------------------- | ---------- |
| `apps/web/src/lib/legionCamps.ts`    | Pure scanner issue to Legion camp reconciliation module.                    | \~320      |
| `apps/web/tests/legionCamps.test.ts` | Focused Vitest coverage for reconciliation behavior and privacy invariants. | \~260      |

### Files To Modify

| File | Changes                                                                     | Est. Lines |
| ---- | --------------------------------------------------------------------------- | ---------- |
| None | No existing files are planned for modification in this pure-module session. | 0          |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Scanner issue snapshots produce camps with expected HP, tier, sector label, stable cell, and sorted unique issue ids.
* [ ] Repeated identical snapshots increment entrenchment, changed membership or HP resets entrenchment, and removed issues remove camps.
* [ ] Tiny and large repositories coalesce into readable bounded sectors, including safe `Borderlands` grouping when needed.
* [ ] Empty snapshots return no camps, no stale sectors for absent issues, and no stale camp ids.
* [ ] The base `rankVisibleLegionCamps` helper exposes entrenched camp metadata without changing underlying camp data.

### Testing Requirements

* [ ] Unit tests cover severity weights, sector coalescing, small-repo deeper splitting, large-repo `Borderlands` grouping, relative label sanitization, stable ordering, stable cell assignment, tier thresholds, entrenchment increment/reset, entrenched presentation metadata, and clean snapshots.
* [ ] Focused test command passes for `apps/web/tests/legionCamps.test.ts`.
* [ ] Web typecheck passes after adding the new module and tests.

### Non-Functional Requirements

* [ ] Projection-shaped output stores only aggregate ids, safe sector labels, HP, tiers, counters, cells, and timestamps.
* [ ] No raw issue messages, suggested prompts, mission prompts, transcripts, replay entries, event bodies, terminal output, provider payloads, file contents, absolute paths, environment values, or secrets are copied into camp or sector output.
* [ ] No new protocol event, new storage key, hosted dependency, or trusted erasure claim is introduced.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.

***

## 8. Implementation Notes

### Working Assumptions

* Phase 23 PRD and stubs are authoritative for this plan: `.spec_system/PRD/phase_23/PRD_phase_23.md` and `session_01_pure_camp_reconciliation.md` exist with detailed source scope, while the docs path named in the master PRD is not present in this checkout. Planning can proceed because the live Phase 23 PRD and stubs carry the required objectives, dependencies, guardrails, and deliverables.
* Package context is `apps/web`: the analysis script reports the selected session package as `apps/web`, and all primary code anchors are web game projection or web tests.
* `CodebaseIssue` has enough data for safe sector derivation: `packages/protocol/src/suggestions.ts` exposes stable `id`, `severity`, `filePath`, and `createdAt` fields. Planning can proceed without protocol work because Phase 23 forbids new events or server routes.
* Session 01 owns a base `rankVisibleLegionCamps` helper for deterministic ordering and entrenched metadata. Session 02 remains responsible for roster-size limits, selected-context priority, and Champion Mode ranking.

### Conflict Resolutions

* The master PRD names `docs/ongoing-projects/war-effort-phase-2-legion-i-scanner-camps-session-plan.md`, but that file is absent. The chosen source is `.spec_system/PRD/phase_23/PRD_phase_23.md` plus the Phase 23 session stubs because they exist in the active spec system and match the analyzed current phase.
* Session 01's stub lists `rankVisibleLegionCamps`, while Session 02 owns ranking and presentation selectors. The chosen split is a minimal `rankVisibleLegionCamps` implementation in Session 01 for stable output and entrenched metadata, with richer roster limits and selected-context ranking deferred to Session 02.

### Key Considerations

* Keep `gameProjection.ts` as the single derived game-state authority.
* Keep this module pure; no React, store, persistence, server, browser storage, or network imports.
* Preserve all Phase 22 honesty rules: no replay or scanner traffic creates XP, loot, banners, achievements, camp damage, mission links, titles, essence, or War Tide.

### Potential Challenges

* Sector budgeting can become unstable if grouping is applied after ids are created: apply grouping before ids and cells are derived.
* Safe path handling can accidentally retain absolute prefixes: normalize to bounded relative labels before storing `dirKey`.
* Entrenchment can drift if issue ids are unsorted: sort and dedupe issue ids before comparing snapshots.

### Relevant Considerations

* \[P22-apps/web] **Game projection is the single derived authority**: This session creates a helper for the projection path instead of a parallel game authority.
* \[P22-apps/web] **Derived projection storage is narrow**: The output remains compatible with the existing aggregate projection boundary and does not add storage.
* \[P22-apps/web] **Do not add parallel game authorities**: Camp grouping logic stays in one pure module for later reducer and UI consumers.
* \[P22-apps/web] **Do not persist replay or drill progress**: This session does not add persistence, progress, rewards, or replay behavior.
* \[P18-apps/server] **Quest Board state is durable local evidence**: The module stores issue ids only and leaves rich issue details with Quest Board.
* \[P07] **Redaction is boundary-specific**: Safe relative labels and aggregate fields are required at this boundary.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* External scanner contracts may carry unsafe file paths, so path handling must sanitize and bound labels before they enter projection-shaped output.
* Large issue snapshots may produce unreadable board state, so sector coalescing must be bounded with deterministic ordering.
* Snapshot changes can accidentally preserve stale camps, so clean snapshots, removals, and entrenchment resets must be explicit.

***

## 9. Testing Strategy

### Unit Tests

* Test severity weights for `error`, `warning`, and `info`.
* Test camp tier thresholds for `camp`, `fort`, and `citadel`.
* Test sector derivation, small-repo deeper splitting, large-repo `Borderlands` grouping, safe label sanitization, stable ordering, and stable cell assignment.
* Test camp grouping, HP, `maxHp`, `scarredPct`, sorted unique issue ids, entrenchment increment, entrenchment reset, removed camps, and clean snapshots.

### Integration Tests

* None in this session. Reducer and store integration belong to Sessions 03 and 04.

### Runtime Verification

* Run `npm test -- apps/web/tests/legionCamps.test.ts`.
* Run `npm --workspace @factionos/web run typecheck`.
* Run `npm run format:check`.

### Edge Cases

* Empty issue snapshot.
* Duplicate issue ids.
* Unknown or malformed path labels.
* Absolute paths or home-directory-like paths.
* Too few sectors for a readable board.
* Too many sectors for a readable board.
* Identical consecutive snapshot.
* Changed issue membership with same HP.
* Same issue membership with changed severity and HP.
* Previous camp with higher `maxHp` and nonzero `scarredPct`.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase22-session01-projection-contract`, `phase22-session03-legion-enemy-reducer`, `phase22-session08-erasure-docs-and-validation`
* Depended by: `phase23-session02-ranking-and-presentation-selectors`, `phase23-session03-projection-folding`

***

## 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-session01-pure-camp-reconciliation/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.
