---
phase: 06.1
slug: gap-closure-d-39-d-46-uat-2026-05-11
status: draft
nyquist_compliant: false
wave_0_complete: false
created: 2026-05-11
---

# Phase 06.1 — Validation Strategy

> Per-phase validation contract for feedback sampling during execution.
> Source: `.planning/phases/06.1-gap-closure-d-39-d-46-uat-2026-05-11/06.1-RESEARCH.md` §Validation Architecture.

---

## Test Infrastructure

| Property | Value |
|----------|-------|
| **Framework** | vitest (unit) + @playwright/test 1.59.1 (e2e) |
| **Config files** | `apps/client/vitest.config.ts`, `apps/client/playwright.config.ts`, `packages/game-logic/vitest.config.ts`, `tools/asset-pipeline/vitest.config.ts` |
| **Quick run command** | `pnpm --filter @rebno/client test:unit` |
| **Full suite command** | `pnpm verify:phase-6` (composite gate — extend to include 06.1 unit + e2e) |
| **Estimated runtime** | ~45 s unit / ~3 min full e2e |

---

## Sampling Rate

- **After every task commit:** Run `pnpm --filter @rebno/<scope> test:unit` (filter to the workspace the task modified).
- **After every plan wave:** Run `pnpm verify:phase-6` (extended).
- **Before `/gsd-verify-work`:** Full suite green + Playwright two-player smoke green + operator-captured `06.1-CLI-08-milestone.mp4`.
- **Max feedback latency:** ~60 s for unit; full e2e ~3 min.

---

## Per-Task Verification Map

> Tasks resolved at plan-phase. Below is the requirement→test seed; planner expands per task with `<automated>` blocks.

| Req | Behavior | Test Type | Automated Command | File Exists | Status |
|-----|----------|-----------|-------------------|-------------|--------|
| REQ-AST-01 | bootstrap alpha-key produces alpha-channel PNG with zero sentinel pixels | unit | `pnpm --filter @rebno/asset-pipeline test test/alpha-key.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | `RUN_SPEED_PX_PER_TICK = 5` pinned | unit | `pnpm --filter @rebno/game-logic test test/run-speed.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | Shift+direction → axes(0,0) + facingHint set | unit | `pnpm --filter @rebno/client test src/__test__/input-dispatcher-shift.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | SpriteStateMachine advances `curspeed/10` per tick (0.5 @ curspeed=5) | unit | `pnpm --filter @rebno/client test src/__test__/sprite-state-rate.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | depth_set port: `layer=0,yOffset=43,y=200` → Phaser depth (sign-flipped) | unit | `pnpm --filter @rebno/client test src/__test__/depth-set.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | NaviMask bbox pinned `{9,40,26,46}` | unit | `pnpm --filter @rebno/game-logic test test/navi-mask-bbox.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | Per-axis sub-pixel collision wall-slide at corner | unit | `pnpm --filter @rebno/game-logic test test/wall-slide.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-04 | Walkable-region edge-block: player at room edge cannot step past | unit | `pnpm --filter @rebno/game-logic test test/walkable-edge.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-07 | BackgroundRenderer: `dxoff` wraps at `sprite_w*dscale`; `bgframe` wraps at 55 | unit | `pnpm --filter @rebno/client test src/__test__/background-renderer.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-08 | Floor tiles rendered with TSide1 on outer-cell bottoms | e2e | `pnpm --filter @rebno/client test:e2e test/e2e/cli-08-tiles.e2e.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-08 | `camera.scrollX/Y` changes after 200 ms held movement input | e2e | `pnpm --filter @rebno/client test:e2e test/e2e/cli-08-camera.e2e.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-08 | Nameplate visible above sprite; cyan local / white remote | e2e | `pnpm --filter @rebno/client test:e2e test/e2e/cli-08-nameplate.e2e.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-08 | Local + remote anim rate visually consistent (smoke) | e2e | `pnpm --filter @rebno/client test:e2e test/e2e/cli-08-anim.e2e.test.ts` | ❌ W0 | ⬜ pending |
| REQ-CLI-08 | UAT re-run Test 2 — two-player video captured | manual | `06.1-HUMAN-UAT.md` Test 2 | ❌ W0 | ⬜ pending |

*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*

---

## Wave 0 Requirements

- [ ] `tools/asset-pipeline/test/alpha-key.test.ts` — D-39 regression guard
- [ ] `packages/game-logic/tests/run-speed.test.ts` — pin `RUN_SPEED_PX_PER_TICK=5`
- [ ] `packages/game-logic/tests/navi-mask-bbox.test.ts` — pin `{9,40,26,46}`
- [ ] `packages/game-logic/tests/wall-slide.test.ts` — corner wall-slide assertion
- [ ] `packages/game-logic/tests/walkable-edge.test.ts` — edge-of-floor block
- [ ] `apps/client/src/__test__/sprite-state-rate.test.ts` — fractional frame advance
- [ ] `apps/client/src/__test__/depth-set.test.ts` — depth formula pin
- [ ] `apps/client/src/__test__/background-renderer.test.ts` — wrap math
- [ ] `apps/client/src/__test__/input-dispatcher-shift.test.ts` — Shift→axes(0,0)+facingHint
- [ ] `apps/client/src/__test__/nameplate-color.test.ts` — cyan local / white remote
- [ ] `apps/client/test/e2e/cli-08-tiles.e2e.test.ts` — Playwright tile-rendering
- [ ] `apps/client/test/e2e/cli-08-camera.e2e.test.ts` — Playwright camera-follow
- [ ] `apps/client/test/e2e/cli-08-nameplate.e2e.test.ts` — Playwright color rule
- [ ] `apps/client/test/e2e/cli-08-anim.e2e.test.ts` — anim-rate smoke
- [ ] `.planning/phases/06.1-gap-closure-d-39-d-46-uat-2026-05-11/06.1-HUMAN-UAT.md` — UAT re-run instructions
- [ ] Extend `pnpm verify:phase-6` composite to include 06.1 unit + e2e suites

---

## Manual-Only Verifications

| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| Two-player UAT re-run (camera follow, nametag legibility, anim smoothness, tiles rendered, bg scroll, edge-block) | REQ-CLI-08 | End-to-end visual/feel quality — not assertable in Playwright beyond smoke | `06.1-HUMAN-UAT.md` Test 2; capture `06.1-CLI-08-milestone.mp4` |
| Aseprite round-trip of bootstrap output PNG (D-39 ergonomics) | REQ-AST-01 | Editor-UX check, not code-assertable | Open any `assets/source/sprites/<id>.png` in Aseprite; confirm no artifacts |
| Fixedsys font pixel-crispness at render scale (D-45) | REQ-CLI-08 | Subjective visual quality; antialiasing config interaction | UAT screenshot review against operator-supplied Saber Mage reference |

---

## Validation Sign-Off

- [ ] All planned tasks have `<automated>` verify or Wave 0 dependencies
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
- [ ] Wave 0 covers all 15 MISSING references above
- [ ] No watch-mode flags in any test command
- [ ] Feedback latency < 60 s for unit / < 3 min for e2e
- [ ] `nyquist_compliant: true` set in frontmatter after planner confirms

**Approval:** pending
