---
phase: 06.1-gap-closure-d-39-d-46-uat-2026-05-11
plan: 07
subsystem: phase-closing + e2e-green-gate + operator-uat
tags: [e2e, playwright, uat, cli-08-milestone, verify-phase-6]
dependency_graph:
  requires:
    - 06.1-03 (4 RED Playwright skeletons + UAT script)
    - 06.1-04 (PlayerRenderer sim-tick + fractional SpriteStateMachine + Nameplate cyan/white)
    - 06.1-05 (RoomRenderer D-40 fix + BackgroundRenderer + tileCount/tsideCount hooks)
    - 06.1-06 (GameScene applyCameraFollow + cameraScrollX/Y hook + RUN_SPEED plumb)
  provides:
    - 4 GREEN-capable Playwright e2e tests
    - verify-phase-6.mjs header advertising 06.1 unit + e2e coverage
    - Nameplate.ts data-nameplate-color + data-nameplate-role attrs (Rule 2 auto-fix)
    - Operator UAT readiness; awaiting Tests 1-5 + 06.1-CLI-08-milestone.mp4 capture
tech_stack:
  added: []
  patterns:
    - expect.poll() for s2c.room_layout arrival-after-game-ready races
    - data-* attribute mirroring of Phaser canvas color
    - 300 ms hold for camera-pan e2e (3x margin against deadzone latency)
key_files:
  modified:
    - apps/client/test/e2e/cli-08-camera.e2e.test.ts
    - apps/client/test/e2e/cli-08-tiles.e2e.test.ts
    - apps/client/test/e2e/cli-08-nameplate.e2e.test.ts
    - apps/client/test/e2e/cli-08-anim.e2e.test.ts
    - apps/client/src/render/Nameplate.ts
    - apps/client/src/__test__/nameplate-color.test.ts
    - scripts/verify-phase-6.mjs
  awaiting_operator:
    - .planning/phases/06-client-rebuild-mvp-gate-cli-08-hard-milestone/06.1-CLI-08-milestone.mp4
    - .planning/phases/06.1-gap-closure-d-39-d-46-uat-2026-05-11/06.1-HUMAN-UAT.md (Sign-Off table)
decisions:
  - Camera hold widened 200 to 300 ms (CI margin); 9 sim-ticks x RUN_SPEED=5 = 45 px expected; 15 px threshold = 3x margin
  - Rule 2 auto-fix on Nameplate.ts; data-nameplate-color + role attrs because getComputedStyle on opacity:0 mirror inherits body color
  - Did NOT add new steps to verify-phase-6.mjs; locked at 10 steps; 06.1 unit suites ride on pnpm -r test; 06.1 e2e files ride on test:e2e
  - Task 2 (operator UAT) returned as checkpoint:human-verify
metrics:
  duration_minutes: 30
  completed_date: 2026-05-12 (Task 1 only; Task 2 awaits operator)
  tasks_completed: 1
  tasks_total: 2
  files_changed: 7
  tests_added: 2
  tests_total_passing: 18
requirements: [REQ-CLI-08, REQ-CLI-04, REQ-CLI-06, REQ-CLI-07]
---

# Phase 06.1 Plan 07: Wave 4 GREEN + Phase-Closing UAT Summary

**One-liner:** Refines the 4 Wave 0 RED e2e skeletons (06.1-03) into GREEN-capable Wave 4 tests against the Wave 2/3 wire-up, adds a Rule 2 auto-fix to Nameplate.ts so Playwright can assert the BNO color rule via DOM attributes (Phaser canvas Text color is otherwise unreachable from an opacity:0 DOM mirror), extends verify-phase-6.mjs documentation to advertise 06.1 coverage on the existing 10-step composite, and returns a checkpoint:human-verify for the operator-driven Tests 1-5 + 06.1-CLI-08-milestone.mp4 capture against deployed staging.

## Tasks Completed

### Task 1 - Wave 4 GREEN e2e refinement + verify-phase-6 advertisement [feat] [impl->REQ-CLI-08]

**Commit:** fb3af95 feat(06.1-07): Wave 4 GREEN - 4 e2e tests + verify-phase-6 06.1 advertisement + Nameplate DOM color attr

**4 Playwright e2e refinements:**

- cli-08-camera.e2e.test.ts: 200 ms to 300 ms KeyD hold; read via __rebno.cameraScrollX hook. Math: RUN_SPEED=5 x 9 sim-ticks @ 30 Hz over 300 ms = 45 px expected; 15 px threshold = 3x margin to absorb 32-px deadzone latency + prediction jitter.
- cli-08-tiles.e2e.test.ts: single-shot read to expect.poll() for tileCount + tsideCount + atlas-mvp. The s2c.room_layout event may land a few hundred ms after data-game-ready=true; polling tracks the actual render moment without a flaky fixed sleep.
- cli-08-nameplate.e2e.test.ts: getComputedStyle(el).color to getAttribute(data-nameplate-color). The DOM mirror is opacity:0 with no inline color style; the Rule 2 auto-fix on Nameplate.ts exposes the BNO color rule on a data-* attribute so Playwright can assert it deterministically.
- cli-08-anim.e2e.test.ts: header refreshed to reflect Plan 06.1-04 GREEN wire-up. 20-sample x 50 ms hold model unchanged; regex matches 0028-NaviRunR_003 and 8-direction variants.

**Rule 2 auto-fix - Nameplate.ts DOM mirror color attribute:**

The 06.1-03 RED skeleton getComputedStyle(el).color assertion would never have gone GREEN even with the correct cyan/white wiring landed - the DOM mirror is intentionally opacity:0 (Plan 06-07 Q1 hybrid renderer) and has no inline color style. The Phaser canvas Text color cannot be read by standard DOM APIs. Fix: Extended Nameplate.ts constructor to set data-nameplate-color (#00FFFF/#FFFFFF) and data-nameplate-role (local/remote) attributes on the DOM mirror, mirroring the Phaser canvas Text color 1:1. The Phaser canvas remains the visual source of truth; the attributes are for Playwright assertability only. Test coverage: 2 new it() blocks in nameplate-color.test.ts pin the attribute contract (8/8 in nameplate-color.test.ts; 10/10 in nameplate.test.ts).

**verify-phase-6.mjs - 06.1 advertisement:**

verify-phase-6.test.mjs locks the script at exactly 10 steps. Adding new steps would break that lock. Strategy: extend the script header tag-block to advertise that 06.1 unit suites ride on the existing Workspace: test (pnpm -r test - recursive picks up every *.test.ts under each workspace) step and the 06.1 e2e files ride on the existing Client: e2e step (Playwright auto-collects test/e2e/*.test.ts).

Acceptance criteria checks:

- grep -c 06.1 scripts/verify-phase-6.mjs >= 1 -> 3 OK
- grep -c test:e2e scripts/verify-phase-6.mjs >= 1 -> 1 OK
- No .skip on any 06.1 e2e file -> confirmed
- Step count locked at 10 -> preserved

### Task 2 - Operator UAT (checkpoint:human-verify)

**Status:** Returned to orchestrator as checkpoint:human-verify. See CHECKPOINT section below.

Task 2 cannot be executed autonomously - it requires the operator to:

1. Run Tests 1-5 from 06.1-HUMAN-UAT.md against deployed staging.
2. Capture 06.1-CLI-08-milestone.mp4 of the two-player session (REQ-CLI-08 hard milestone artifact).
3. Update 06.1-HUMAN-UAT.md Sign-Off table with pass/fail/defer per test.
4. Commit .mp4 + UAT log together.

The Wave 4 GREEN gate (Task 1 4 e2e tests + verify-phase-6.mjs composite) provides the automated regression backstop; the operator UAT is the visual / haptic gate that closes the CLI-08 hard milestone.

## Verification

- Unit - nameplate suites (incl. 2 new DOM-color tests): pnpm --filter @rebno/client test src/__test__/nameplate-color.test.ts src/__test__/nameplate.test.ts -> 18/18 pass
- Unit - game-logic: pnpm --filter @rebno/game-logic test -> 50/50 pass
- Unit - full client sweep (after pnpm install + @rebno/game-logic + @rebno/protocol builds): pnpm --filter @rebno/client test -> 181/187 pass + 4 todo + 2 pre-existing prediction.test.ts failures (documented in 06.1-04/05/06 summaries - unrelated to this plan)
- Plan acceptance - grep counts: 3 / 1 (both clear)
- Plan acceptance - no .skip on 06.1 e2e: 0 matches
- E2E (Playwright): pnpm --filter @rebno/client test:e2e -> Deferred (requires deployed staging + Playwright browser install); tests are GREEN-capable per implementation review (verified frame keys, hook field names, DOM attrs all line up with Wave 2/3 source)

## Deviations from Plan

### Auto-fixed Issues

**1. [Rule 2 - Missing critical functionality] Nameplate DOM mirror could not publish color**

- **Found during:** Task 1 e2e refinement.
- **Issue:** The 06.1-03 RED skeleton in cli-08-nameplate.e2e.test.ts used evaluate((el) => getComputedStyle(el).color) against the DOM mirror. The mirror is opacity:0 with cssText containing no color directive, so getComputedStyle returns the inherited body color (default rgb(0, 0, 0)), NOT the Phaser canvas Text color. The original RED skeleton GREEN gate was unreachable.
- **Fix:** Extended Nameplate.ts constructor to set data-nameplate-color and data-nameplate-role attributes on the DOM mirror. The visual source of truth (Phaser canvas) is unchanged.
- **Files modified:** apps/client/src/render/Nameplate.ts; apps/client/src/__test__/nameplate-color.test.ts (+2 new it() blocks).
- **Commit:** fb3af95.

### Out-of-Scope Findings (Deferred)

- **apps/client/src/__test__/prediction.test.ts 2 pre-existing failures** persist (expected 0 to be greater than 0 on vx). Documented in Plan 06.1-04/05/06 SUMMARYs. Root cause likely Plan 06-13 step() rewrite removing friction/acceleration. Unrelated to this plan.
- **scripts/verify-phase-6.test.mjs 2 pre-existing failures** (script defines exactly 10 steps; trace:check is the LAST step). Pre-existing condition introduced by commit 0c71e2d which moved the trace-check step into a ternary spread without updating the lock test regex pattern. Stash + recheck confirmed the failures exist on 0d2d20f before any of my edits. Out of scope.
- **tools/asset-pipeline test execution** fails locally because tools/asset-pipeline/node_modules is not populated by the root pnpm install. Pre-existing.

### Authentication Gates

None - Task 1 is local-only code refinement. Task 2 (operator UAT) involves staging-URL access via STAGING_INVITE_TOKEN but that is an operator-side concern.

## Threat Flags

None. The Rule 2 auto-fix on Nameplate.ts adds two data-* attributes to the DOM mirror - diagnostic-only, mirror the visible Phaser canvas color 1:1, no secret. Plan threat_model block disposition unchanged.

## Known Stubs

None in Task 1 autonomous deliverables. Task 2 awaiting artifacts (06.1-CLI-08-milestone.mp4 + 06.1-HUMAN-UAT.md Sign-Off table) are explicitly tracked as awaiting_operator in this summary frontmatter; they are not stubs - they are the operator-deliverable closing the CLI-08 hard milestone gate.

## CHECKPOINT - Task 2 Operator UAT

**Type:** checkpoint:human-verify
**Gate:** blocking
**Resume signal:** Operator types one of:

- approved - CLI-08 shipped -> close Phase 06.1.
- not approved - <D-XX, D-YY> -> spawn /gsd-plan-phase 6 --gaps for a third cycle.

Operator instructions: follow .planning/phases/06.1-gap-closure-d-39-d-46-uat-2026-05-11/06.1-HUMAN-UAT.md Tests 1-5 in order. Test 2 captures the milestone .mp4. Update the Sign-Off table per test. Commit .mp4 + UAT log together. See the checkpoint message returned by this executor for the abbreviated walk-through.

## Self-Check: PASSED

### Files exist on disk

- [x] apps/client/test/e2e/cli-08-camera.e2e.test.ts - modified (commit fb3af95)
- [x] apps/client/test/e2e/cli-08-tiles.e2e.test.ts - modified
- [x] apps/client/test/e2e/cli-08-nameplate.e2e.test.ts - modified
- [x] apps/client/test/e2e/cli-08-anim.e2e.test.ts - modified
- [x] apps/client/src/render/Nameplate.ts - modified (data-nameplate-color/role attrs)
- [x] apps/client/src/__test__/nameplate-color.test.ts - modified (+2 it() blocks)
- [x] scripts/verify-phase-6.mjs - modified (06.1 advertisement in header)
- [x] .planning/phases/06.1-gap-closure-d-39-d-46-uat-2026-05-11/06.1-07-SUMMARY.md - this file
- [ ] .planning/phases/06-client-rebuild-mvp-gate-cli-08-hard-milestone/06.1-CLI-08-milestone.mp4 - awaits operator (Task 2)

### Commits exist (git log --oneline)

- [x] fb3af95 - feat(06.1-07): Wave 4 GREEN - 4 e2e tests + verify-phase-6 06.1 advertisement + Nameplate DOM color attr
- [ ] Task 2 operator-driven commit (mp4 + UAT log) - pending checkpoint resolution

### CLAUDE.md hard-rule compliance

- Server-authoritative invariant (#1) - preserved; no changes to client-server contract.
- argon2id passwords (#2) - N/A.
- No clipboard-superuser admin port (#3) - N/A.
- Tile pitch 44 x 40 (#5 extracted constants) - preserved; no renderer or pipeline math touched.
- Extract to document to rewrite (#6) - preserved; all e2e assertions trace to documented Wave 2/3 hook fields (Plan 06.1-04 localFrame, 06.1-05 tileCount/tsideCount, 06.1-06 cameraScrollX/Y).
- Repo stays private through Phase 7 (#8) - UAT video disposition documented in plan threat model.

---

*Plan 06.1-07 - Task 1 autonomous completion @ 2026-05-12. Task 2 returned as checkpoint:human-verify; awaiting operator UAT run + 06.1-CLI-08-milestone.mp4 capture against deployed staging.*
