# PRD-to-Architecture Spine Reconciliation

**Date:** 2026-07-07
**Reviewed:** PRD v1 (19 FRs, 5 UJs) vs Architecture Spine draft

## 1. Functional Requirement Coverage

All 19 FRs are explicitly mapped in the spine's Capability-to-Architecture table, each assigned to a source file and an architectural decision (or marked with no AD where none applies, e.g. solver). No FR is missing or orphaned.

| FR | Mapped? | Location | Notes |
|----|---------|----------|-------|
| FR-1 | Yes | client/src/hooks/usePersistence.ts | AD-7 |
| FR-2 | Yes | client/src/screens/Screen1.tsx | AD-7 |
| FR-3 | Yes | client/src/components/Grid.tsx | AD-7 |
| FR-4 | Yes | client/src/components/Keyboard.tsx | AD-7 |
| FR-5 | Yes | client useGame → server guess.ts | AD-5, AD-6 |
| FR-6 | Yes | server/src/validate.ts | AD-5 |
| FR-7 | Yes | server/src/feedback.ts | AD-6 |
| FR-8 | Yes | client/src/hooks/useGame.ts | AD-7 |
| FR-9 | Yes | client/src/hooks/useGame.ts | AD-7 |
| FR-10 | Yes | server/src/daily-word.ts | AD-2 |
| FR-11 | Yes | server/src/routes/play-again.ts | AD-8 |
| FR-12 | Yes | client/src/hooks/useStats.ts | AD-7 |
| FR-13 | Yes | client/src/screens/Screen3.tsx | AD-7 |
| FR-14 | Yes | client/src/screens/Screen3.tsx | AD-7 |
| FR-15 | Yes | client/src/screens/Screen3.tsx | AD-7 |
| FR-16 | Yes | solver/src/ | (no AD; algorithm selection deferred) |
| FR-17 | Yes | solver/src/ → data/word-bank.json | AD-4 |
| FR-18 | Yes | data/word-bank.json | AD-4 |
| FR-19 | Yes | client/src/hooks/usePersistence.ts | AD-7 |

## 2. User Journey Coverage

All 5 user journeys are realized through the FR mappings above. The three-screen flow (Screen1→Screen2→Screen3) is reflected in the source tree. No user journey falls through the cracks at the FR level.

## 3. Gaps Found

### GAP-1: Responsive / mobile design (severity: medium)

**PRD source:** Vision ("Works on mobile and desktop via web browser"), MVP Scope section 6.1 ("Works on mobile and desktop via web browser").

**Problem:** The spine contains no architectural decision, convention, or structural element addressing responsive design. There is no viewport strategy, no breakpoint system, no mobile-first or desktop-first decision, and no mention of touch vs. pointer interaction handling. The on-screen keyboard (FR-4) partially addresses mobile input but says nothing about layout adaptation.

**Risk:** Without an architectural stance, mobile and desktop implementations may diverge or mobile may be an afterthought, directly violating an MVP scope commitment.

### GAP-2: Physical keyboard event handling (severity: medium)

**PRD source:** MVP Scope section 6.1 ("Physical keyboard support"), FR-5 describes "physical keyboard or on-screen keyboard" input.

**Problem:** The spine maps FR-5 to `client/src/hooks/useGame.ts` and `server/src/routes/guess.ts`. The `Keyboard.tsx` component handles the on-screen keyboard, but physical keyboard events (keydown for letters, Enter to submit, Backspace to delete) have no designated architectural home. These are a distinct input modality with their own event handling lifecycle (document-level keydown listeners, focus management).

**Risk:** Physical keyboard support may be bolted on late without a clear ownership boundary, or may conflict with on-screen keyboard state management.

### GAP-3: Screen navigation / routing (severity: low)

**PRD source:** User journeys describe Screen1→Screen2→Screen3 transitions. The PRD section 4.1 describes "Tapping Play navigates to Screen 2." Section 4.5 describes the Play Again button navigating back to Screen 2.

**Problem:** The spine lists `client/src/screens/Screen1.tsx`, `Screen2.tsx`, `Screen3.tsx` but makes no architectural decision about screen navigation: state-based conditional rendering vs. client-side router (React Router) vs. URL-driven. The transition triggers (Play button, game-over detection, Play Again button) are not architecturally placed.

**Risk:** Low. This is a three-screen app; any approach will work. However, if the team later adds screens (post-v1), an unstated routing approach may cause rework.

### GAP-4: Feedback latency / optimistic UI (severity: medium-high)

**PRD source:** JTBD ("clear, immediate feedback on every guess"), AD-6 states "Feedback scoring on server" and "The client only renders the colors it receives."

**Problem:** AD-6 mandates that feedback is computed server-side only. Every guess incurs a network round-trip before the player sees green/yellow/gray tiles. The PRD calls for "immediate" feedback. There is no architectural discussion of this tension: should the client also compute feedback locally for instant display (optimistic rendering, later confirmed by the server response), or is the latency budget acceptable? The decision is made (server-only) without acknowledging the UX trade-off.

**Risk:** If round-trip latency is perceptible (200ms+ on slow connections), the game will feel sluggish, undermining the "immediate feedback" JTBD and "quick, satisfying" feel. This is the most architecturally significant gap because AD-6 makes a binding decision that directly affects a stated UX quality.

### GAP-5: Network failure / offline resilience (severity: low-medium)

**PRD source:** Implicit in the SPA architecture — the game should degrade gracefully or inform the user when the server is unreachable.

**Problem:** The spine has no architectural concern for network failure modes. What happens when POST /api/guess fails? Does the client retry? Show an error? The Consistency Conventions mention error shapes (`{ error: string }`) but only for validation errors (400) and not-found (404), not for connectivity failures.

**Risk:** Network failures produce an unhandled state in the UI. Given this is a hobby project, the risk is low, but the PRD's "clear, immediate feedback" JTBD implies reliability.

### GAP-6: Accessibility (severity: low-medium)

**PRD source:** Not explicitly stated in the PRD, but the game's core mechanic relies entirely on color discrimination (green/yellow/gray). This is a well-known accessibility issue with Wordle clones.

**Problem:** The spine contains no accessibility architecture: no ARIA conventions, no color-blind mode/alternative indicators (patterns, symbols, high-contrast mode), no keyboard navigation model, no screen-reader announcements for guess results.

**Risk:** The game will be inaccessible to color-blind users and screen-reader users. While the PRD does not mandate accessibility, it is a significant UX gap that the architecture should at minimum acknowledge as deferred rather than silently omit.

### GAP-7: Win celebration animation (severity: low)

**PRD source:** UJ-1 climax: "the row confirms green, a brief celebration."

**Problem:** The spine maps win detection to `client/src/hooks/useGame.ts` and results display to `Screen3.tsx`, but there is no architectural concern for the celebration animation itself. Is it a CSS animation? A library? A component? The PRD explicitly calls for this UX moment.

**Risk:** Low. A celebration animation is a small UI detail. But the PRD explicitly names it as part of the user journey climax, and the architecture provides no home for it.

## 4. Qualitative Concerns Check

| Concern | PRD Source | Spine Coverage |
|---------|-----------|----------------|
| "Quick, satisfying" feel | Vision, JTBD | Partial — stateless server supports simplicity, but no latency budget or optimistic UI (see GAP-4) |
| "Clear, immediate feedback" | JTBD | Partial — feedback scoring is defined (AD-6), but "immediate" is undermined by server-only computation (see GAP-4) |
| "Jump straight in without friction" | JTBD (returning player) | Covered — FR-1 cookie detection, no-loading-screen architecture implied by SPA |
| "Brief celebration" | UJ-1 climax | Not covered (see GAP-7) |
| Mobile + desktop parity | Vision, MVP Scope | Not covered (see GAP-1) |
| Learning-project simplicity | Vision, SM-C1 | Well-covered — AD-1 (stateless), AD-4 (no database), AD-9 (monorepo) all push toward simplicity |
| Color-blind accessibility | Implicit (green/yellow mechanic) | Not covered (see GAP-6) |

## 5. Summary

**All 19 FRs and 5 UJs are explicitly mapped.** The spine's strength is its thorough functional coverage. No requirement falls through at the FR level.

**Seven gaps identified.** Two are architecturally significant:

- **GAP-4 (feedback latency)** is the most consequential — AD-6 makes a binding server-only decision that directly conflicts with the PRD's "immediate feedback" UX requirement. Recommend adding an architectural note acknowledging the tension and either committing to an acceptable latency budget with measurement, or adopting optimistic client-side feedback with server confirmation.
- **GAP-1 (responsive design)** is an MVP scope item with no architectural expression. Recommend adding a responsive strategy decision (e.g., mobile-first with CSS breakpoints, or a specific component library's grid system).

The remaining gaps (physical keyboard routing, screen navigation, network resilience, accessibility, celebration animation) are lower severity but worth acknowledging in the spine, even if only as deferred or implementation-detail notes.
