> 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/phase02-session04-battlefield-state-and-interaction-polish/spec.md).

# Session Specification

**Session ID**: `phase02-session04-battlefield-state-and-interaction-polish` **Phase**: 02 - Product Surface and 2D Battlefield Completion **Status**: Not Started **Created**: 2026-05-29 **Package**: apps/web **Package Stack**: React 18.3.1, Vite 6.4.2, TypeScript 5.9.3, Tailwind CSS 3.4.6, Zustand 4.5.4

***

## 1. Session Overview

This session finishes the app-side 2D battlefield interaction contract for the current React cockpit. It builds on the completed shell, hero, and mission workflow sessions by making battlefield selection, state treatment, reduced-motion behavior, asset fallbacks, and achievement bursts reliable from the central board itself.

The work stays in `apps/web` and stable battlefield documentation. It preserves the approved asset-driven DOM battlefield from `apps/web/public/battlefield/` and does not reintroduce Three.js, WebGL, canvas physics, game-loop infrastructure, or public-demo parity work owned by Session 05.

The expected outcome is a battlefield that remains readable and operable across active, awaiting input, verifying, error, spawning, dismissed, selected, and idle hero states. Native buttons, accessible names, state labels, clamped positioning, fallback rendering, and bounded celebration cleanup should be covered by focused Vitest and Testing Library tests.

***

## 2. Objectives

1. Keep battlefield hero tokens as native controls with stable accessible names, selected state semantics, pointer and keyboard selection, and empty-board deselection.
2. Make every supported hero state visually distinct through static labels, rings, badges, or shape treatment that does not depend only on color or animation.
3. Harden board positioning, label placement, background fallback, hero art fallback, reduced-motion handling, and achievement celebration cleanup.
4. Add focused tests and documentation for battlefield state, interaction, fallback, and reduced-motion behavior without expanding into public-demo parity or new asset generation.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase02-session01-product-surface-requirements-reconciliation` - Provides Phase 02 PRD, UX PRD, and product surface gap matrix.
* [x] `phase02-session02-cockpit-shell-and-navigation-cohesion` - Provides coherent cockpit shell layout and overlay boundaries.
* [x] `phase02-session03-hero-and-mission-workflow-completion` - Provides synchronized hero and mission selection behavior for battlefield consumers.

### Required Tools/Knowledge

* Node.js 20 and npm workspace commands.
* React 18, Testing Library, happy-dom, Vitest, Tailwind CSS, and Zustand.
* Current battlefield source files: `Battlefield.tsx`, `battlefield2d.ts`, `achievementCelebration.ts`, and `index.css`.
* Current requirements in `.spec_system/PRD/PRD.md`, `.spec_system/PRD/PRD_UX.md`, `.spec_system/PRD/phase_02/product_surface_gap_matrix.md`, and `docs/battlefield.md`.

### Environment Requirements

* Dependencies installed from the workspace lockfile.
* Existing focused battlefield tests can run before edits.
* The full app can be smoke checked without a running local server by using seed or mocked store state.

***

## 4. Scope

### In Scope (MVP)

* Developer can use the battlefield board as a reliable selection surface - Preserve native hero buttons, `aria-pressed`, keyboard activation, pointer activation, selected-label sync, and empty-board clear behavior.
* Developer can distinguish hero runtime states at a glance - Add or refine state labels, static indicators, rings, badges, and CSS treatment for active, awaiting input, verifying, error, spawning, dismissed, selected, and idle states.
* Developer can trust board placement and fallback behavior - Clamp missing or non-finite coordinates, keep labels inside the 16:9 board, render a readable fallback background, and show faction initials when hero art fails.
* Developer can use reduced-motion mode without losing meaning - Disable nonessential looping motion while preserving static state labels, rings, selection treatment, and achievement state.
* Maintainer can verify battlefield regressions - Add focused helper, component, and celebration tests plus docs for changed battlefield behavior.

### Out of Scope (Deferred)

* Reintroducing Three.js, WebGL, canvas physics, Phaser, PixiJS, GLTF loaders, or 3D assets - Reason: Phase 02 explicitly preserves the asset-driven 2D DOM battlefield.
* Creating new gameplay-loop, combat simulation, or multi-select command infrastructure - Reason: Later orchestration phases own agent command expansion.
* Changing or regenerating battlefield media assets - Reason: Session 05 owns asset parity, provenance, and public-demo asset validation.
* Updating `public-demo/` behavior or service worker cache lists - Reason: Session 05 owns public-demo parity.
* Settings, replay, notification, export, and scan UX polish - Reason: Session 06 owns those browser control flows.

***

## 5. Technical Approach

### Architecture

Keep `Battlefield.tsx` as the React surface that reads heroes, missions, achievements, selected hero state, and reduced-motion preference from existing Zustand stores. Add small local or pure helper decisions only where they make state labels, fallback copy, label placement, or interaction behavior easier to test.

Keep `battlefield2d.ts` responsible for coordinate normalization. Preserve the existing world-extent behavior while tightening tests for missing, non-finite, outlying, and server-spawned ring positions. Avoid moving protocol-owned hero or mission shapes into app-local duplicates.

Use CSS for visual state treatment. The component should emit stable data attributes and text labels, while `index.css` handles rings, pings, selected halo, dismissed treatment, fallback readability, and reduced-motion variants.

### Design Patterns

* Native DOM controls: Hero tokens remain buttons with explicit accessible names and `aria-pressed`.
* Data attributes plus CSS state: Component state stays inspectable in tests and CSS owns visual treatment.
* Pure coordinate helper tests: Boundary math stays testable without rendering the full app.
* Bounded async lifecycle: Achievement timers are capped, cleaned up on unmount, and compatible with reduced motion.
* Local-first fallback copy: Failed media and disconnected seed states stay readable without exposing local paths or implying hosted services.

### Technology Stack

* React 18.3.1
* Vite 6.4.2
* TypeScript 5.9.3
* Tailwind CSS 3.4.6
* Zustand 4.5.4
* Vitest 4.1.7, Testing Library, happy-dom

***

## 6. Deliverables

### Files to Create

| File                                                                                                    | Purpose                                                                                       | Est. Lines |
| ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------- |
| `.spec_system/specs/phase02-session04-battlefield-state-and-interaction-polish/implementation-notes.md` | Implementation evidence, decisions, validation commands, and manual notes                     | \~90       |
| `apps/web/tests/BattlefieldInteraction.test.tsx`                                                        | Focused component coverage for battlefield selection, labels, state indicators, and fallbacks | \~220      |

### Files to Modify

| File                                                            | Changes                                                                                                                         | Est. Lines |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `apps/web/src/components/battlefield/Battlefield.tsx`           | Harden token accessible names, selection semantics, state labels, fallback surfaces, label placement, and celebration lifecycle | \~180      |
| `apps/web/src/lib/battlefield2d.ts`                             | Refine coordinate and label-placement helpers if implementation needs pure helpers                                              | \~60       |
| `apps/web/src/components/battlefield/achievementCelebration.ts` | Keep burst diffing, caps, deterministic tones, and timer behavior testable                                                      | \~50       |
| `apps/web/src/index.css`                                        | Refine battlefield board, token, state, selected, fallback, and reduced-motion CSS                                              | \~150      |
| `apps/web/tests/Battlefield.test.tsx`                           | Extend existing component coverage for current battlefield contract                                                             | \~160      |
| `apps/web/tests/battlefield2d.test.ts`                          | Extend pure helper coverage for clamping, non-finite positions, and label placement                                             | \~80       |
| `apps/web/tests/achievementCelebration.test.ts`                 | Extend celebration diff, cap, reduced-motion, and cleanup coverage                                                              | \~80       |
| `docs/battlefield.md`                                           | Document completed battlefield state, interaction, fallback, and reduced-motion behavior                                        | \~60       |
| `apps/web/README_web.md`                                        | Record the app-side battlefield contract and deferred public-demo parity boundary                                               | \~35       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Battlefield hero tokens are native buttons with stable accessible names, `aria-pressed`, pointer activation, keyboard activation, and visible selected state.
* [ ] Selecting via battlefield, roster, and hero detail remains synchronized through existing store state.
* [ ] Clicking empty board space clears selected hero state without token click propagation accidentally clearing the new selection.
* [ ] Active, awaiting input, verifying, error, spawning, dismissed, selected, and idle states remain visually distinct through labels, rings, badges, glow, or static marks.
* [ ] Failed background and hero image loads keep the board and tokens visibly recoverable.
* [ ] Missing, non-finite, and out-of-range hero coordinates map to safe, clamped board positions.
* [ ] Achievement bursts stay bounded, nonblocking, timer-cleaned, and reduced-motion compatible.

### Testing Requirements

* [ ] Component tests cover battlefield selection, accessible names, selected state, empty-board clear, image fallbacks, state labels, and reduced-motion static treatment.
* [ ] Helper tests cover coordinate clamping, dynamic world limits, missing coordinates, non-finite coordinates, and edge label placement.
* [ ] Celebration tests cover new unlock diffing, concurrent cap behavior, timer cleanup, deterministic tone output, and reduced-motion expectations.
* [ ] Focused battlefield tests and `npm --workspace apps/web run typecheck` pass before validation.

### Non-Functional Requirements

* [ ] The 2D board keeps nonzero dimensions and stable 16:9 presentation under the existing shell constraints.
* [ ] State meaning does not rely on color alone or animation alone.
* [ ] Reduced-motion mode disables nonessential looping motion while preserving visible state.
* [ ] No new asset source, hosted service, public replay, or War Room federation claim is introduced.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Focused tests, web typecheck, and relevant Biome checks pass.

***

## 8. Implementation Notes

### Key Considerations

* `Battlefield.tsx` already renders hero tokens as buttons and uses `aria-pressed`; this session should harden labels, state indicators, failure paths, and interaction edge cases rather than replace the component.
* `battlefield2d.ts` already clamps coordinates and expands server-spawned rings; additional work should be limited to actual state and label-placement gaps found during implementation.
* `index.css` has existing animations and reduced-motion overrides; keep static labels and state indicators visible when animations are disabled.
* Session 05 owns app and public-demo asset parity, so this session should not change public-demo paths or service worker caches unless implementation uncovers a release blocker that the plan records explicitly.

### Potential Challenges

* CSS state readability: Mitigate by pairing color with text labels, badge shape, ring weight, or persistent selected label.
* Token click propagation: Keep empty-board deselection and token activation tests close to `Battlefield.tsx`.
* Reduced-motion behavior: Verify both store-driven reduced motion and CSS media-query-compatible static state.
* Timer cleanup: Use fake timers in tests and clean up celebration timers on unmount.
* Dirty worktree: Keep edits scoped and do not revert unrelated Phase 01, Phase 02, or package changes already present.

### Relevant Considerations

* \[P00-apps/web] **Responsive and accessibility debt**: This session directly addresses focus, labels, reduced motion, and non-overlap for the battlefield.
* \[P00] **Asset provenance gate**: Do not promote unknown or historical media; keep current approved app-owned assets unless Session 05 changes them.
* \[P01] **Local-first boundary is architectural**: Battlefield fallback behavior must work without hosted services, analytics, or remote collaboration.
* \[P01] **Stable docs are the current contract**: Update `docs/battlefield.md` if behavior changes and keep `EXAMPLES/` as evidence only.
* \[P01-packages/protocol] **Protocol leads cross-package work**: If shared hero state contracts must change, update `packages/protocol` before app-specific use. No protocol change is expected.

### Behavioral Quality Focus

Checklist active: Yes

Top behavioral risks for this session:

* Reopenable and revisitable battlefield state can leave stale selected hero context after empty-board clears, image failures, or store updates.
* Interactive token controls can lose keyboard, focus, or accessible selected-state semantics while visual polish is added.
* Async achievement timers can leak after unmount or keep duplicate bursts alive longer than intended.
* Reduced-motion users can lose state meaning if animation is the only visible state indicator.

***

## 9. Testing Strategy

### Unit Tests

* Test `mapHeroPositionToBattlefield` and related helper behavior for center, bounds, out-of-range, missing, non-finite, and dynamic world-limit inputs.
* Test achievement helper output for fresh unlock detection, deterministic ordering, tier tones, cap constants, and particle vectors.

### Integration Tests

* Render `Battlefield` with heroes in every supported state and verify accessible names, `data-state`, visible text indicators, selected state, fallback treatment, and click behavior.
* Render `Battlefield` with `HeroRoster` and `HeroDetailDrawer` to verify selection synchronization remains intact after battlefield changes.
* Use fake timers to verify achievement bursts appear for new unlocks, respect concurrent bounds, and clean up after lifetime or component unmount.

### Manual Testing

* Start the web app and inspect the battlefield with seed data on desktop and a mobile-width viewport.
* Select and clear heroes with pointer and keyboard, including bottom-edge and top-edge positions.
* Toggle reduced motion and verify active, awaiting input, verifying, error, spawning, dismissed, selected, and idle states remain readable.
* Simulate failed background and hero image loads through browser dev tools or test mocks and confirm fallback surfaces stay readable.

### Edge Cases

* No heroes on the board.
* Selected hero removed from store after selection.
* Hero with missing active mission record.
* Missing, `NaN`, infinite, or outlying coordinates.
* Background image failure before hero image load.
* Multiple simultaneous achievement unlocks beyond the concurrent cap.
* Reduced-motion enabled while a burst is created.

***

## 10. Dependencies

### External Libraries

* No new external libraries planned.

### Other Sessions

* **Depends on**: `phase02-session01-product-surface-requirements-reconciliation`, `phase02-session02-cockpit-shell-and-navigation-cohesion`, `phase02-session03-hero-and-mission-workflow-completion`
* **Depended by**: `phase02-session05-battlefield-asset-and-public-demo-parity`, `phase02-session07-product-surface-validation-and-documentation-closeout`

***

## Next Steps

Run the implement workflow step to begin AI-led 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/phase02-session04-battlefield-state-and-interaction-polish/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.
