> 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-session04-combat-playback-effects-layer/implementation-notes.md).

# Implementation Notes

**Session ID**: `phase24-session04-combat-playback-effects-layer` **Package**: apps/web **Started**: 2026-07-08 16:23 **Last Updated**: 2026-07-08 18:02

***

## Session Progress

| Metric              | Value   |
| ------------------- | ------- |
| Tasks Completed     | 22 / 22 |
| Estimated Remaining | 0 hours |
| Blockers            | 0       |

***

## Task Log

### 2026-07-08 - Session Start

**Environment verified**:

* [x] Prerequisites confirmed
* [x] Tools available
* [x] Directory structure ready

***

### Task T001 - Verify Phase 24 Session 04 prerequisites and package-local commands

**Started**: 2026-07-08 16:21 **Completed**: 2026-07-08 16:23 **Duration**: 2 minutes

**Notes**:

* Confirmed current session resolves to `phase24-session04-combat-playback-effects-layer` with package scope `apps/web`.
* Confirmed prior Phase 24 sessions 01-03 are complete in `.spec_system/state.json` and the Session 04 phase stub scopes implementation to combat playback effects.
* Confirmed `apps/web/package.json` exposes the package-local `typecheck` command and root npm test routing is available.

**Files Changed**:

* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Created session progress log and recorded prerequisite evidence.

**Verification**:

* Command/check: `bash .../skills/apex-spec/scripts/analyze-project.sh --json`
  * Result: PASS - current session, package registry, and incomplete Session 04 were reported.
  * Evidence: `current_session` was `phase24-session04-combat-playback-effects-layer`; `current_session_dir_exists` was `true`; package registry included `apps/web`.
* Command/check: `bash .../skills/apex-spec/scripts/check-prereqs.sh --json --env --package apps/web`
  * Result: PASS - spec system, jq, git, package directory, manifest, and npm workspace manager passed.
  * Evidence: checker returned `"overall": "pass"` with no issues.
* Command/check: `bash .../skills/apex-spec/scripts/check-prereqs.sh --json --tools "node,npm" --package apps/web`
  * Result: PASS - node and npm binaries available.
  * Evidence: checker reported Node `v24.14.0` and npm `11.16.0`; the session spec requests Node 26.2.0+, so runtime checks will verify actual compatibility.
* Command/check: Targeted inspection of `.spec_system/PRD/phase_24/session_04_combat_playback_effects_layer.md`, `.spec_system/specs/phase24-session04-combat-playback-effects-layer/spec.md`, and `apps/web/package.json`
  * Result: PASS - implementation scope and package-local commands are present.
  * Evidence: phase stub lists Session 04 effects deliverables; spec header declares `Package: apps/web`; package manifest has `typecheck`.
* UI product-surface check: N/A - prerequisite verification only; no user-facing surface changed.
* UI craft check: N/A - prerequisite verification only.

***

### Task T002 - Inventory battlefield layer ordering, store event log, missions, camp links, and ranked camp placement seams

**Started**: 2026-07-08 16:23 **Completed**: 2026-07-08 16:26 **Duration**: 3 minutes

**Notes**:

* Confirmed `Battlefield.tsx` already selects `heroes`, `missions`, `eventLog`, `gameProjection`, `rankedCamps`, and `reduceMotion` seams needed for a selector-fed layer.
* Confirmed `CampLayer.tsx` exports `resolveCampPlacement` and `campPlacementStyle`; `CampPlacement` is currently file-private and needs export for typed effects placement reuse.
* Confirmed `useGameStore.applyEvent` captures `ReplayEntry { at, event }`, folds `gameProjection.campLinks`, appends `tool_use` into mission tool uses, and records failed `tool_result` without creating a new storage key.
* Confirmed existing visual order: camp layer `z-[15]`, scanner/live Legion layer around `z-[16]`, hero token wrapper `z-20`, remote participant overlay after heroes, and achievement bursts `z-[1000]`; Session 04 can mount above hero tokens and below remote/achievement overlays.

**Files Changed**:

* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded inventory evidence and implementation seam decisions.

**Verification**:

* Command/check: Targeted inspection of `apps/web/src/components/battlefield/Battlefield.tsx`
  * Result: PASS - layer order, store selectors, hero coordinate mapping, and ranked camp calculation are available.
  * Evidence: `Battlefield` computes `rankedCamps`, `liveLegionHeroCoordinates`, `liveLegionHeroNames`, and renders camps before heroes and achievements after heroes.
* Command/check: Targeted inspection of `apps/web/src/components/battlefield/CampLayer.tsx`
  * Result: PASS - camp placement helper exists and can be exported without changing camp authority.
  * Evidence: `resolveCampPlacement` derives bounded left/top percentages from `RankedLegionCamp`.
* Command/check: Targeted inspection of `apps/web/src/store/useGameStore.ts` and `apps/web/src/lib/gameProjection.ts`
  * Result: PASS - event buffer, mission rows, and camp links provide sufficient evidence for linked combat playback.
  * Evidence: `applyEvent` records event log entries; `reduceMissionStart` binds `campLinks`; `campMissionsFromLinks` inverts links deterministically for joint assault.
* UI product-surface check: N/A - inventory only; no rendered surface changed.
* UI craft check: N/A - inventory only.

***

### Task T003 - Create pure combat playback effect types, constants, caps, and display-state contracts

**Started**: 2026-07-08 16:26 **Completed**: 2026-07-08 16:31 **Duration**: 5 minutes

**Notes**:

* Added the pure `combatPlaybackEffects.ts` module with explicit input, transient effect, camp-state, assault-hero, and presentation contracts.
* Added visible caps for strikes, counterattacks, burn-down effects, assault heroes, recent-event windows, and display-only HP chip damage.

**Files Changed**:

* `apps/web/src/lib/combatPlaybackEffects.ts` - Created pure combat playback effects contracts and tuning constants.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T003 evidence.

**Verification**:

* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - web TypeScript project compiled with the new model shell.
  * Evidence: `tsc -b --noEmit` exited 0.
* Command/check: Targeted inspection of `apps/web/src/lib/combatPlaybackEffects.ts`
  * Result: PASS - contracts are pure exports with no store, React, DOM, persistence, protocol events, or storage side effects.
  * Evidence: file contains only type imports, exported constants, interfaces, and `emptyCombatPlaybackPresentation`.
* UI product-surface check: N/A - pure model contracts only; no rendered surface changed.
* UI craft check: N/A - pure model contracts only.

***

### Task T004 - Implement linked event selection from ReplayEntry, missions, and camp links

**Started**: 2026-07-08 16:31 **Completed**: 2026-07-08 16:38 **Duration**: 7 minutes

**Notes**:

* Added `buildCombatPlaybackPresentation` to select only recent `tool_use` and failed `tool_result` events whose mission is linked to a visible camp with hero and camp coordinates.
* Added explicit supported-event handling for `tool_use`, `tool_result`, and `task_verification`; unsupported or unlinked events are ignored safely.
* Added base camp states with linked mission IDs and deterministic joint-assault hero trims, without writing to projection, storage, or rewards.

**Files Changed**:

* `apps/web/src/lib/combatPlaybackEffects.ts` - Implemented linked event selection, base effect derivation, caps, and camp state scaffolding.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T004 evidence.

**Verification**:

* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - event discriminants, linked mission contracts, and presentation output types compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* Command/check: Targeted inspection of `apps/web/src/lib/combatPlaybackEffects.ts`
  * Result: PASS - unlinked missions, missing camps, missing coordinates, unsupported events, successful tool results, and stale entries produce no transient effects.
  * Evidence: `buildLinkedMissionContexts`, `isRecentPlaybackEntry`, and switch cases gate every derived effect.
* UI product-surface check: N/A - pure model only; no rendered surface changed.
* UI craft check: N/A - pure model only.

***

### Task T005 - Implement combo, stage-prop, HP-drain, counterattack, and verification-only kill derivation

**Started**: 2026-07-08 16:38 **Completed**: 2026-07-08 16:45 **Duration**: 7 minutes

**Notes**:

* Threaded Session 01 combo helpers through linked strikes so repeated camp/category hits escalate into bounded combo stages.
* Added stage-prop tiers from mission elapsed time and display-only HP drain from editing or command-execution strikes without mutating projection camp HP.
* Added verification-only burn-down derivation that requires a successful `task_verification` with an unambiguous mission or plan reference and skips failed or cancelled missions.
* Kept counterattack derivation presentation-only and label-bounded.

**Files Changed**:

* `apps/web/src/lib/combatPlaybackEffects.ts` - Added combo, stage props, display HP drain, and verification-only burn-down derivation.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T005 evidence.

**Verification**:

* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - pure derivation compiles with combo state, mission elapsed-time, and verification matching paths.
  * Evidence: `tsc -b --noEmit` exited 0.
* Command/check: Targeted inspection of `apps/web/src/lib/combatPlaybackEffects.ts`
  * Result: PASS - HP changes are display-only, burn-down requires successful matched verification, failed/cancelled missions cannot burn camps, and raw task IDs are not rendered.
  * Evidence: `damageByCampFromEvents`, `verificationMatchesLinkedMission`, and `burnDownEffectFromVerification` only return presentation state.
* UI product-surface check: N/A - pure model only; no rendered surface changed.
* UI craft check: N/A - pure model only.

***

### Task T006 - Export or adapt camp placement data for effects rendering

**Started**: 2026-07-08 16:45 **Completed**: 2026-07-08 16:48 **Duration**: 3 minutes

**Notes**:

* Exported the existing camp placement type and added `campPlacementCoordinates` for effects-layer coordinate reuse.
* Left `CampLayer` rendering, camp buttons, scanner camp state, and camp authority unchanged.

**Files Changed**:

* `apps/web/src/components/battlefield/CampLayer.tsx` - Exported placement contracts and coordinate helper.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T006 evidence.

**Verification**:

* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - exported placement contracts compile with existing CampLayer usage.
  * Evidence: `tsc -b --noEmit` exited 0.
* Command/check: Targeted inspection of `apps/web/src/components/battlefield/CampLayer.tsx`
  * Result: PASS - helper delegates to `resolveCampPlacement` and does not alter camp rendering or store/projection state.
  * Evidence: only type/helper exports were added; existing JSX and handlers are unchanged.
* UI product-surface check: N/A - helper export only; no rendered surface changed.
* UI craft check: N/A - helper export only.

***

### Task T007 - Create reusable playback fixtures

**Started**: 2026-07-08 16:48 **Completed**: 2026-07-08 16:53 **Duration**: 5 minutes

**Notes**:

* Added reusable linked camp, mission, tool event, verification event, hostile path, and combat playback input fixture builders.
* Added a small fixture sanity test that proves linked strike fixtures derive presentation state without mutating camp HP authority.

**Files Changed**:

* `apps/web/tests/combatPlaybackEffects.test.ts` - Created pure playback fixtures and initial contract sanity coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T007 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - fixture test file executes cleanly.
  * Evidence: Vitest reported 2 files passed and 2 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - fixture builders compile with protocol, projection, and playback contracts.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: N/A - test fixtures only; no rendered product surface changed.
* UI craft check: N/A - test fixtures only.

***

### Task T008 - Define layer test ids and presentation fixtures

**Started**: 2026-07-08 16:48 **Completed**: 2026-07-08 16:54 **Duration**: 6 minutes

**Notes**:

* Added component-level presentation fixtures for strikes, counterattacks, combo state, HP chips, stage props, assault heroes, and burn-down state.
* Defined the stable test-id vocabulary the combat playback layer will render against.

**Files Changed**:

* `apps/web/tests/CombatPlaybackLayer.test.tsx` - Created presentation fixtures, layer test-id constants, and initial fixture sanity coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T008 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - component fixture test file executes cleanly.
  * Evidence: Vitest reported 2 files passed and 2 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - fixture presentation contracts compile against `combatPlaybackEffects.ts`.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: N/A - fixture definitions only; no rendered product surface changed.
* UI craft check: N/A - fixture definitions only.

***

## Checkpoints

### Checkpoint 1 - After T008

**Recorded**: 2026-07-08 16:55

**Checks Run**:

* `npm test -- apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx` - PASS, 2 files and 2 tests passed.
* `npm --workspace @factionos/web run typecheck` - PASS, `tsc -b --noEmit` exited 0.

**Spec Drift Review**:

* Re-read Session 04 success criteria and confirmed the completed work still targets linked-only playback, no new protocol/storage/reward authority, bounded visuals, privacy, and reduced-motion parity.

**Next Task**:

* T009 - Create `CombatPlaybackLayer` as a pointer-events-none battlefield layer with product-facing labels only.

***

### Checkpoint 2 - After T016

**Recorded**: 2026-07-08 17:34

**Checks Run**:

* `npm test -- apps/web/tests/Battlefield.test.tsx apps/web/tests/CombatPlaybackLayer.test.tsx` - PASS, 2 files and 35 tests passed.
* `npm --workspace @factionos/web run typecheck` - PASS, `tsc -b --noEmit` exited 0.

**Spec Drift Review**:

* Re-read the Session 04 success criteria during T016 and confirmed the runtime surface remains linked-only, nonblocking, display-only, and reward-free.

**Next Task**:

* T017 - Write pure tests for linked-only strikes, classification, combo, stage props, HP drain, and verification-only kills.

***

### Task T009 - Create CombatPlaybackLayer as a pointer-events-none battlefield layer

**Started**: 2026-07-08 16:55 **Completed**: 2026-07-08 17:00 **Duration**: 5 minutes

**Notes**:

* Added `CombatPlaybackLayer` with pointer-events-none layer semantics, z-order above hero tokens, product-facing summary, strike, counterattack, HP, combo, stage-prop, assault-trim, and burn-down labels.
* Added a minimal component render test to verify noninteractive behavior and absence of banned product-surface diagnostics.
* Fixed the render test assertion after the expected duplicate `Combo 2` labels appeared in both the camp chip and strike badge.

**Files Changed**:

* `apps/web/src/components/battlefield/CombatPlaybackLayer.tsx` - Created the stateless combat playback layer component and test-id helpers.
* `apps/web/tests/CombatPlaybackLayer.test.tsx` - Added render coverage for pointer-events-none and product-facing copy.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T009 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - component fixture and render checks passed.
  * Evidence: Vitest reported 1 file passed and 2 tests passed after the assertion fix.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - component props, styles, and test contracts compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - rendered `CombatPlaybackLayer` component; visible copy is product combat state and the test asserts no debug, fixture, runtime, ready, viewport, or route copy in the layer.
* UI craft check: PASS - component follows adjacent battlefield layer patterns: absolute pointer-events-none surface, compact chips/badges, sr-only summary, reduced-motion data state, and stable z-order below remote and achievement overlays.

***

### Task T010 - Implement timer-managed transient effects with cleanup

**Started**: 2026-07-08 17:00 **Completed**: 2026-07-08 17:05 **Duration**: 5 minutes

**Notes**:

* Added internal active-effect state to `CombatPlaybackLayer` so strikes, counterattacks, and burn-downs render immediately and then expire on bounded timers.
* Added timer map cleanup for effects leaving scope and for component unmount.
* Reused `STRIKE_MAX_DURATION_MS` for strike/counterattack lifetimes and `CELEBRATION_LIFETIME_MS` for burn-down lifetime.

**Files Changed**:

* `apps/web/src/components/battlefield/CombatPlaybackLayer.tsx` - Added active-effect caps, scoped timers, no-op key stability checks, and unmount cleanup.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T010 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - existing layer render checks continue to pass with timer-managed active effects.
  * Evidence: Vitest reported 1 file passed and 2 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - timer refs, active-effect narrowing, and caps compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - rendered layer remains product-facing after timer state change; visible copy still contains combat labels only.
* UI craft check: PASS - transient effects stay pointer-events-none and retain compact battlefield badge styling.

**BQC Fixes**:

* Resource cleanup: Added timer clearing for expired effects, effects removed from active scope, and layer unmount (`apps/web/src/components/battlefield/CombatPlaybackLayer.tsx`).

***

### Task T011 - Implement reduced-motion static twins

**Started**: 2026-07-08 17:05 **Completed**: 2026-07-08 17:09 **Duration**: 4 minutes

**Notes**:

* Added a reduced-motion last-strike badge and static razed test id while keeping HP chips and stage props visible.
* Confirmed reduced-motion strikes render without motion classes while static HP, last-strike, prop, and razed indicators remain visible.

**Files Changed**:

* `apps/web/src/components/battlefield/CombatPlaybackLayer.tsx` - Added reduced-motion last-strike and razed static indicators.
* `apps/web/tests/CombatPlaybackLayer.test.tsx` - Added reduced-motion static twin render coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T011 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - reduced-motion static twin coverage passed.
  * Evidence: Vitest reported 1 file passed and 3 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - reduced-motion indicator test ids and component types compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - rendered reduced-motion component shows product state only: last strike, HP, siege, and razed badges.
* UI craft check: PASS - reduced-motion badges use adjacent battlefield chip styling and preserve pointer-events-none behavior.

***

### Task T012 - Wire combat playback into Battlefield

**Started**: 2026-07-08 17:09 **Completed**: 2026-07-08 17:14 **Duration**: 5 minutes

**Notes**:

* Wired `Battlefield` to derive combat playback from `eventLog`, `missions`, `gameProjection.campLinks`, ranked camps, exported camp coordinates, hero coordinates, hero names, and `reduceMotion`.
* Mounted the effects layer after hero tokens and before remote participant overlays, keeping it noninteractive and below remote/achievement surfaces.

**Files Changed**:

* `apps/web/src/components/battlefield/Battlefield.tsx` - Added combat playback selectors, presentation derivation, and layer mount.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T012 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/Battlefield.test.tsx apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - existing Battlefield coverage and layer coverage passed after wiring.
  * Evidence: Vitest reported 2 files passed and 33 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - Battlefield selector and presentation wiring compiles.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - Battlefield render tests pass with the layer mounted; the layer remains product-facing and noninteractive.
* UI craft check: PASS - z-order is above hero tokens (`z-20`) and below remote overlay (`z-30`) and achievement bursts (`z-[1000]`).

***

### Task T013 - Add joint-assault rendering with deterministic trims and visible caps

**Started**: 2026-07-08 17:14 **Completed**: 2026-07-08 17:18 **Duration**: 4 minutes

**Notes**:

* Confirmed `CombatPlaybackLayer` renders assault trims from camp-state assault heroes.
* Added pure coverage proving multiple linked missions on one camp are sorted deterministically and capped at the visible assault-hero limit.

**Files Changed**:

* `apps/web/tests/combatPlaybackEffects.test.ts` - Added joint-assault cap and deterministic ordering coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T013 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - pure joint-assault and layer render coverage passed.
  * Evidence: Vitest reported 2 files passed and 5 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - joint-assault fixture contracts compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - assault trims are aria-hidden visual markers with no debug or raw event copy.
* UI craft check: PASS - assault trims are capped compact markers anchored to the camp status surface.

***

### Task T014 - Integrate verified-kill burn-down with celebration visual constants

**Started**: 2026-07-08 17:18 **Completed**: 2026-07-08 17:22 **Duration**: 4 minutes

**Notes**:

* Reused `CELEBRATION_LIFETIME_MS`, `CELEBRATION_SPARK_VECTORS`, and `celebrationToneForTier("gold")` for burn-down presentation only.
* Kept Battlefield integration selector-fed and read-only; no achievement, reward, XP, loot, or store write path was added.

**Files Changed**:

* `apps/web/src/components/battlefield/CombatPlaybackLayer.tsx` - Added burn-down spark rendering from existing celebration visual constants.
* `apps/web/tests/CombatPlaybackLayer.test.tsx` - Added burn-down spark and no-reward-copy coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T014 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/CombatPlaybackLayer.test.tsx apps/web/tests/Battlefield.test.tsx`
  * Result: PASS - burn-down visual reuse and existing Battlefield integration passed.
  * Evidence: Vitest reported 2 files passed and 34 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - celebration visual constant reuse compiles.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - burn-down renders as camp raze feedback only and the test asserts no achievement, reward, loot, or XP copy.
* UI craft check: PASS - burn-down reuses existing burst timing and spark vector treatment without adding another reward surface.

***

### Task T015 - Add combat playback CSS classes, keyframes, HP chips, stage props, and reduced-motion overrides

**Started**: 2026-07-08 17:22 **Completed**: 2026-07-08 17:29 **Duration**: 7 minutes

**Notes**:

* Added scoped combat playback CSS for strike kinds, HP chips, combo chips, stage props, last-strike badges, assault trims, burn-down sparks, and reduced-motion overrides.
* Added keyframes for strike, counterattack, burn-down, and burn sparks while keeping static reduced-motion equivalents visible.

**Files Changed**:

* `apps/web/src/index.css` - Added combat playback classes, motion keyframes, and reduced-motion overrides.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T015 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - layer render and reduced-motion tests pass with the new CSS class names.
  * Evidence: Vitest reported 1 file passed and 4 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - CSS class additions did not affect TypeScript contracts.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - rendered tests still assert product-facing copy only after class additions.
* UI craft check: PASS - classes follow battlefield chip/badge styling, use mixed accent colors, preserve pointer-events-none behavior, and include reduced-motion static treatment.

***

### Task T016 - Preserve nonblocking layer order around hero tokens, remote overlays, and achievement bursts

**Started**: 2026-07-08 17:29 **Completed**: 2026-07-08 17:33 **Duration**: 4 minutes

**Notes**:

* Added Battlefield integration coverage that mounts a linked combat event and asserts the combat playback layer uses `z-[25]`.
* Confirmed the layer sits above the hero token wrapper (`z-20`) and below remote participant overlays (`z-30`) and achievement bursts (`z-[1000]`).

**Files Changed**:

* `apps/web/tests/Battlefield.test.tsx` - Added combat playback layer-order integration coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T016 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/Battlefield.test.tsx apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - Battlefield layer-order coverage and layer coverage passed.
  * Evidence: Vitest reported 2 files passed and 35 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - layer-order fixture event and store setup compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - Battlefield renders combat playback as a product layer with no blocking interaction surface.
* UI craft check: PASS - layer order is stable: camps/live threats below, hero tokens visible, combat effects above heroes, remote and celebration surfaces above effects.

***

### Task T017 - Write pure tests for linked-only strikes, classification, combo, stage props, HP drain, and verification-only kills

**Started**: 2026-07-08 17:34 **Completed**: 2026-07-08 17:39 **Duration**: 5 minutes

**Notes**:

* Added pure derivation coverage for linked strike classification, combo progression, stage props, display-only HP drain, verification-only burn-down, and unlinked no-op behavior.

**Files Changed**:

* `apps/web/tests/combatPlaybackEffects.test.ts` - Added focused pure derivation tests.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T017 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts`
  * Result: PASS - pure derivation tests passed.
  * Evidence: Vitest reported 1 file passed and 6 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - pure test contracts compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: N/A - pure tests only; no rendered surface changed.
* UI craft check: N/A - pure tests only.

***

### Task T018 - Write privacy and contract tests

**Started**: 2026-07-08 17:39 **Completed**: 2026-07-08 17:43 **Duration**: 4 minutes

**Notes**:

* Added tests for custom tool fallback, hostile path and input-preview privacy, unmatched verification, failed verification, unsupported events, and successful tool-result no-op behavior.

**Files Changed**:

* `apps/web/tests/combatPlaybackEffects.test.ts` - Added privacy and contract boundary coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T018 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts`
  * Result: PASS - privacy and contract tests passed.
  * Evidence: Vitest reported 1 file passed and 9 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - privacy test fixtures compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: N/A - pure tests only; no rendered surface changed.
* UI craft check: N/A - pure tests only.

***

### Task T019 - Write component tests for caps, cleanup, reduced motion, joint assault, and counterattack flashes

**Started**: 2026-07-08 17:43 **Completed**: 2026-07-08 17:50 **Duration**: 7 minutes

**Notes**:

* Added component coverage for visual caps per effect kind, strike expiry, burn-down lifetime, unmount timer cleanup, reduced-motion static twins, joint-assault trims, and counterattack flashes.

**Files Changed**:

* `apps/web/tests/CombatPlaybackLayer.test.tsx` - Expanded component coverage for caps, timers, reduced motion, joint assault, and counterattacks.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T019 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/CombatPlaybackLayer.test.tsx`
  * Result: PASS - component tests passed.
  * Evidence: Vitest reported 1 file passed and 8 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - fake-timer and fixture test contracts compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - component tests continue to assert no debug/runtime/scaffolding copy and verify product-facing static twins.
* UI craft check: PASS - visual caps, reduced-motion parity, and nonblocking assault/counterattack presentation are covered at component level.

**BQC Fixes**:

* Resource cleanup: Added unmount cleanup coverage for combat playback timers (`apps/web/tests/CombatPlaybackLayer.test.tsx`).

***

### Task T020 - Write Battlefield integration tests for mission\_start, linked tool\_use, failed tool\_result, and task\_verification

**Started**: 2026-07-08 17:50 **Completed**: 2026-07-08 17:56 **Duration**: 6 minutes

**Notes**:

* Added an end-to-end Battlefield test that seeds a pending camp link, dispatches `mission_start`, linked `tool_use`, failed `tool_result`, and successful `task_verification` through `useGameStore.applyEvent`, then verifies strike, counterattack, burn-down, and razed HP presentation.

**Files Changed**:

* `apps/web/tests/Battlefield.test.tsx` - Added applyEvent-backed combat playback integration coverage.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T020 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/Battlefield.test.tsx`
  * Result: PASS - Battlefield integration tests passed.
  * Evidence: Vitest reported 1 file passed and 32 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - integration fixture and store-event contracts compile.
  * Evidence: `tsc -b --noEmit` exited 0.
* UI product-surface check: PASS - integration verifies product combat effects render from real store events without adding blocking controls.
* UI craft check: PASS - event-path rendering keeps combat effects in the existing Battlefield visual stack.

***

### Task T021 - Run focused automated checks

**Started**: 2026-07-08 17:56 **Completed**: 2026-07-08 17:58 **Duration**: 2 minutes

**Notes**:

* Ran the focused playback test command across pure model, component, and Battlefield integration coverage.

**Files Changed**:

* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T021 evidence.

**Verification**:

* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx apps/web/tests/Battlefield.test.tsx`
  * Result: PASS - focused playback test suite passed.
  * Evidence: Vitest reported 3 files passed and 49 tests passed.
* UI product-surface check: PASS - focused rendered tests include product-surface assertions for the combat playback layer.
* UI craft check: PASS - focused rendered tests include reduced-motion, layer order, and nonblocking presentation coverage.

***

### Task T022 - Run web typecheck plus ASCII and LF validation

**Started**: 2026-07-08 17:58 **Completed**: 2026-07-08 18:02 **Duration**: 4 minutes

**Notes**:

* Formatted touched web source and test files with Biome.
* Re-ran focused playback tests after formatting.
* Ran web typecheck and ASCII/LF validation across touched implementation, test, CSS, and session files.

**Files Changed**:

* `apps/web/src/lib/combatPlaybackEffects.ts` - Biome formatting applied where needed.
* `apps/web/src/components/battlefield/CombatPlaybackLayer.tsx` - Biome formatting applied where needed.
* `apps/web/src/components/battlefield/CampLayer.tsx` - Placement helper retained after format pass.
* `apps/web/src/components/battlefield/Battlefield.tsx` - Biome formatting applied where needed.
* `apps/web/src/index.css` - Biome formatting applied where needed.
* `apps/web/tests/combatPlaybackEffects.test.ts` - Biome formatting applied where needed.
* `apps/web/tests/CombatPlaybackLayer.test.tsx` - Biome formatting applied where needed.
* `apps/web/tests/Battlefield.test.tsx` - Biome formatting applied where needed.
* `.spec_system/specs/phase24-session04-combat-playback-effects-layer/implementation-notes.md` - Recorded T022 evidence.

**Verification**:

* Command/check: `npx biome format --write apps/web/src/lib/combatPlaybackEffects.ts apps/web/src/components/battlefield/CombatPlaybackLayer.tsx apps/web/src/components/battlefield/CampLayer.tsx apps/web/src/components/battlefield/Battlefield.tsx apps/web/src/index.css apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx apps/web/tests/Battlefield.test.tsx`
  * Result: PASS - formatter completed successfully.
  * Evidence: Biome reported 8 files formatted and 6 fixed.
* Command/check: `npm test -- apps/web/tests/combatPlaybackEffects.test.ts apps/web/tests/CombatPlaybackLayer.test.tsx apps/web/tests/Battlefield.test.tsx`
  * Result: PASS - focused playback suite still passed after formatting.
  * Evidence: Vitest reported 3 files passed and 49 tests passed.
* Command/check: `npm --workspace @factionos/web run typecheck`
  * Result: PASS - web typecheck passed.
  * Evidence: `tsc -b --noEmit` exited 0.
* Command/check: `LC_ALL=C grep -nP '[^\x00-\x7F]' ...`
  * Result: PASS - no non-ASCII bytes found in touched session files.
  * Evidence: command printed `ASCII check passed`.
* Command/check: `grep -n $'\r' ...`
  * Result: PASS - no CRLF line endings found in touched session files.
  * Evidence: command printed `LF check passed`.
* Command/check: Final ASCII/LF rerun after completion checklist update
  * Result: PASS - touched implementation, test, CSS, task, and notes files remained ASCII-only with LF line endings.
  * Evidence: command printed `ASCII check passed` and `LF check passed`.
* UI product-surface check: PASS - final focused tests include rendered product-surface assertions.
* UI craft check: PASS - final focused tests include reduced-motion, z-order, cap, and nonblocking checks.

***


---

# 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-session04-combat-playback-effects-layer/implementation-notes.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.
