Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b0d65e1
feat(spec): 047 — SpecKit specify output for Three.js game (#48)
TurtleWolfe May 15, 2026
059d581
feat(spec): 047 — SpecKit clarify amendments for Three.js game (#48)
TurtleWolfe May 15, 2026
9187299
feat(spec): 047 — wireframe gate PASS for Three.js game (#48)
TurtleWolfe May 15, 2026
2e8bf55
feat(spec): 047 — regen wireframes with canonical brand SVG symbols (…
TurtleWolfe May 16, 2026
7a692f4
feat(spec): 047 — SpecKit plan + research + quickstart for Three.js g…
TurtleWolfe May 16, 2026
e574caf
feat(spec): 047 — SpecKit tasks.md for Three.js game (#48)
TurtleWolfe May 16, 2026
2fa49d7
feat(spec): 047 — SpecKit analyze remediations for Three.js game (#48)
TurtleWolfe May 16, 2026
45bcdf2
feat(scene): #48 Phase 1 — setup deps + Pa11y exclusion note + useRed…
TurtleWolfe May 17, 2026
c57729b
feat(scene): #48 Phase 2 — getDaisyUIColorAsThree theme-utils helper …
TurtleWolfe May 17, 2026
0743eda
feat(scene): #48 US-1 — /game/3d route + canvas mount + orbit control…
TurtleWolfe May 17, 2026
a100f67
feat(scene): #48 US-2 — theme-aware materials via MutationObserver on…
TurtleWolfe May 17, 2026
6fe44d7
feat(scene): #48 US-3 + US-4 + US-5 — reduced-motion gating + Pa11y e…
TurtleWolfe May 17, 2026
5ecde6f
feat(scene): #48 FR-008 — WebGL-unavailable + context-lost fallback p…
TurtleWolfe May 17, 2026
e63d06b
feat(scene): #48 FR-007 — procedural brand-asset sculpt (cog + bracke…
TurtleWolfe May 17, 2026
6dde713
fix(e2e): #48 US-2 theme-switch test failed on all 3 browsers (root c…
TurtleWolfe May 17, 2026
56912c6
fix(theme): #48 DaisyUI 5 token names + oklch() wrapper format
TurtleWolfe May 17, 2026
1510247
test(e2e): #48 firefox WebGL flake — decouple wrapper-attribute tests…
TurtleWolfe May 17, 2026
8c872f0
test(e2e): #48 widen US-1 SSR-errors filter to ignore __cf_bm cookie …
TurtleWolfe May 17, 2026
8773dd0
feat(047): #48 Phase 10 Polish complete — full SpecKit cascade closed
TurtleWolfe May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion STATUS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ScriptHammer Status

**Snapshot**: 2026-05-13 · **Version**: v0.0.1 · **Stability**: Beta — Phase 0 (template hygiene) closed; E2E flake round 10 closed via concurrency mutex (#89); GrimGlow ThreeJS fork (Phase 0.5) green-lit; Family B (payment routes) is the next-leverage front
**Snapshot**: 2026-05-17 · **Version**: v0.0.1 · **Stability**: Beta — Phase 0 (template hygiene) closed; E2E flake round 10 closed via concurrency mutex (#89); **Phase 0.5 (#48 Three.js Game) shipping in PR #95** (feature 047 at `/game/3d` — full SpecKit cascade complete, 21/21 E2E shards green); Family B (payment routes) is the next-leverage front

This is the single screen-scan view of "what's planned, what's shipped, what's broken."
For the deeper per-feature audit see [`docs/prp-docs/PRP-STATUS.md`](docs/prp-docs/PRP-STATUS.md).
Expand Down
1 change: 1 addition & 0 deletions config/pa11yci.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"// Note2": "Next.js 15 streams metadata via JavaScript. The title element appears after hydration, not in initial HTML.",
"// Note3": "color-contrast (and color-contrast-enhanced for AAA) is ignored here because Pa11y's axe runner hardcodes violations.concat(incomplete) — it treats 'needs review' as failure. DaisyUI .btn gradients prevent axe from resolving a flat bg color, so every button lands in incomplete (14–61 false positives per page, ratio=0). The real contrast gate is tests/e2e/color-contrast.spec.ts, which runs the same axe rule on the same pages but asserts violations only, covering both scripthammer-light and scripthammer-dark (headless Chromium's prefers-color-scheme defaults to light, so this config never tested dark).",
"// Note4": "Standard bumped to WCAG2AAA per #21 (Phase 0 closure). Contrast checks remain delegated to the E2E spec; pa11y here covers the non-contrast AAA criteria (focus visibility, link purpose, etc.).",
"// Note5 (#48 — feature 047 Three.js Game)": "/game/3d is DELIBERATELY OMITTED from the urls allowlist below. Pa11y / axe-core cannot audit <canvas> content (no DOM tree inside WebGL surfaces), so scanning the route would either produce false positives or simply fail to detect anything useful. The existing /game (dice game) IS auditable but is also not in the current allowlist — feature 037-game-a11y-tests covers its automated coverage via E2E tests in tests/e2e/. The fallback panel rendered when WebGL is unavailable IS pa11y-auditable via the same DOM rules; manual review covers it (see features/enhancements/047-threejs-game/tasks.md T027 + T049 for the canvas-not-auditable a11y review template).",
"defaults": {
"standard": "WCAG2AAA",
"timeout": 30000,
Expand Down
4 changes: 2 additions & 2 deletions docs/prp-docs/PRP-STATUS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# PRP Implementation Status Dashboard

**Last Updated**: 2026-05-14 (v0.4.x stabilization milestones)
**Previous Update**: 2026-04-25 (full 47-feature audit)
**Last Updated**: 2026-05-17 (Phase 0.5 / #48 Three.js Game shipped — PR #95 047)
**Previous Update**: 2026-05-14 (v0.4.x stabilization milestones)
**Total PRPs**: 16 (legacy) + 49 (SpecKit features — 000-brand-identity and 000-landing-page split out from 000-rls)
**Completed**: 15 legacy PRPs (v0.3.0) + 18 SpecKit features Shipped + 5 Mostly Shipped (019 GA moved Shipped → 23 total)
**In Progress (Partial)**: 19 features (most of payments tier, blog/sidebar polish, OAuth UX fixes)
Expand Down
18 changes: 9 additions & 9 deletions features/IMPLEMENTATION_ORDER.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ Blog features in dependency order.

PWA and accessibility enhancements.

| Order | Feature | Name | Depends On |
| ----- | ------- | -------------------- | ---------- |
| 30 | **017** | Colorblind Mode | 001 |
| 31 | **018** | Font Switcher | 001 |
| 32 | **020** | PWA Background Sync | - |
| 33 | **021** | Geolocation Map | - |
| 34 | **028** | Enhanced Geolocation | 021 |
| 35 | **030** | Calendar Integration | 003 |
| 36 | **047** | Three.js Game | 001, 006 |
| Order | Feature | Name | Depends On |
| ----- | ---------- | ---------------------------------- | ---------- |
| 30 | **017** | Colorblind Mode | 001 |
| 31 | **018** | Font Switcher | 001 |
| 32 | **020** | PWA Background Sync | - |
| 33 | **021** | Geolocation Map | - |
| 34 | **028** | Enhanced Geolocation | 021 |
| 35 | **030** | Calendar Integration | 003 |
| 36 | **047** | Three.js Game (`/game/3d`, PR #95) | 001, 006 |

### Tier 7: Polish

Expand Down
58 changes: 58 additions & 0 deletions features/enhancements/047-threejs-game/build-report.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
├ ○ /_not-found 121 B 640 kB
├ ○ /accessibility 4.58 kB 644 kB
├ ○ /account 8.24 kB 648 kB
├ ○ /admin 4.25 kB 644 kB
├ ○ /admin/audit 3.26 kB 643 kB
├ ○ /admin/messaging 3.98 kB 643 kB
├ ○ /admin/payments 3.42 kB 643 kB
├ ○ /admin/users 2.56 kB 642 kB
├ ○ /api/blog/tags 121 B 640 kB 1d 1y
├ ○ /auth/callback 2.02 kB 641 kB
├ ○ /blog 121 B 640 kB
├ ● /blog/[slug] 10.9 kB 650 kB
├ ├ /blog/message-encryption-security-explained
├ ├ /blog/offline-payment-system-stripe-paypal
├ ├ /blog/authentication-supabase-oauth
├ └ [+4 more paths]
├ ○ /blog/seo 162 B 640 kB
├ ○ /blog/tags 165 B 640 kB
├ ● /blog/tags/[tag] 120 B 640 kB
├ ├ /blog/tags/security
├ ├ /blog/tags/encryption
├ ├ /blog/tags/privacy
├ └ [+30 more paths]
├ ○ /comment-policy 121 B 640 kB
├ ○ /contact 6 kB 645 kB
├ ○ /conversations 121 B 640 kB
├ ○ /cookies 469 B 640 kB
├ ○ /docs 121 B 640 kB
├ ○ /forgot-password 1.07 kB 641 kB
├ ○ /game 1 kB 640 kB
├ ○ /game/3d 744 B 640 kB
├ ○ /map 3.79 kB 643 kB
├ ○ /messages 23.9 kB 663 kB
├ ○ /messages/new-group 6.94 kB 646 kB
├ ○ /messages/setup 2.29 kB 642 kB
├ ○ /payment-demo 4.43 kB 644 kB
├ ○ /payment-result 2.67 kB 642 kB
├ ○ /privacy 452 B 640 kB
├ ○ /privacy-controls 3.33 kB 643 kB
├ ○ /profile 632 B 640 kB
├ ○ /reset-password 948 B 640 kB
├ ○ /schedule 1.48 kB 641 kB
├ ○ /sign-in 2.31 kB 642 kB
├ ○ /sign-up 2.57 kB 642 kB
├ ○ /status 3.18 kB 643 kB
├ ○ /themes 2.06 kB 642 kB
├ ○ /verify-email 176 B 640 kB
└ ○ /wireframes 573 B 640 kB
+ First Load JS shared by all 644 kB
---
Generated: 2026-05-18T02:36:06Z
Commit: 8c872f01f0b39976e9c3e99ff8aa04734c0999ba

NFR-001 verification: /game/3d First Load JS = 640 kB
Same baseline as /blog (640 kB), /themes (642 kB), /map (643 kB).
Per-route weight (744 B) is the page entry only; Three.js (~600 kB
R3F + drei + three) loads dynamically only on visit to /game/3d.
Route-split working correctly per research.md Decision 5.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Manual A11y Review Checklist: `/game/3d`

**Feature**: 047 — Three.js Game
**Created**: 2026-05-16 (T027)
**Reviewer**: _fill in name + date when running this review_
**Last review pass**: _none yet — runs in T049 of tasks.md_

## Why this exists

Pa11y / axe-core cannot audit `<canvas>` content because the WebGL surface has no DOM tree inside it. The route `/game/3d` is therefore deliberately omitted from the Pa11y allowlist in `config/pa11yci.json` (see "Note5" in that file).

The DOM chrome surrounding the canvas — page heading, breadcrumb, fallback panel, Retry button, status indicators — IS auditable and remains in scope. This manual review covers the canvas surface itself: keyboard interaction, screen-reader behavior, color contrast where applicable, and motion preferences.

## Review checklist

Run all four sections in the local browser before merging the implementation PR.

### 1. Keyboard focus path

- [ ] Tab into the page. Focus visits, in order: any header nav items, the breadcrumb link, then either the canvas (if WebGL is available) OR the Retry button (if the fallback panel is visible).
- [ ] When the fallback panel is visible: Enter on the focused Retry button triggers re-mount.
- [ ] Shift+Tab traverses the order in reverse without skipping the canvas / Retry button.
- [ ] No focus traps — Escape or repeated Tab eventually returns focus to the surrounding chrome.

### 2. Screen reader behavior

- [ ] The `<canvas>` element has `aria-label="3D scene preview"` (or equivalent meaningful label).
- [ ] When the fallback panel is visible, a screen reader reads: heading "3D Content Unavailable" → body paragraph naming WebGL → button "Retry rendering 3D scene".
- [ ] The page `<h1>` reads as "3D Game (Three.js)".
- [ ] The breadcrumb is announced as a navigation landmark.

### 3. Color contrast (DOM chrome only — canvas content is exempt)

- [ ] All DOM text on the page meets WCAG AAA contrast (7:1 normal, 4.5:1 large) against its background. The existing E2E spec at `tests/e2e/color-contrast.spec.ts` covers this if the route is added to its URL list — otherwise verify manually with a contrast tool (Chrome DevTools → Lighthouse, or axe DevTools).
- [ ] The Retry button (DaisyUI `.btn btn-primary`) meets contrast in both light and dark themes.
- [ ] Status indicators (e.g., "WebGL: unavailable" text in the fallback panel) meet contrast.

### 4. Motion preferences

- [ ] With `prefers-reduced-motion: reduce` set (OS preference or Chrome DevTools rendering emulation), the scene shows zero autonomous animation. The orbit camera does NOT rotate automatically.
- [ ] User-initiated camera motion (drag, scroll, touch) STILL works under reduced motion.
- [ ] Toggling the preference off at runtime resumes auto-orbit within 3 seconds of the toggle (no page reload needed).

## Automated proxies (run as part of T049)

Several items on this checklist have automated coverage that gives us high confidence without a human keystroke pass:

| Section | Item | Automated coverage | Status |
| ----------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- |
| 1. Keyboard | Tab order includes Retry button when fallback active | `tests/e2e/game-3d.spec.ts` FR-008 scenario: `retry.focus(); await expect(retry).toBeFocused()` | PASS in CI |
| 2. Screen reader | `<canvas aria-label="3D scene preview">` | `src/components/game/Scene/Scene.tsx:184` — attribute literal, type-checked | PASS |
| 2. Screen reader | Heading "3D Content Unavailable" announces in fallback | FR-008 scenario asserts `getByRole('heading', { name: /3d content unavailable/i })` | PASS in CI |
| 2. Screen reader | Retry button accessible name | FR-008 scenario asserts `getByRole('button', { name: /retry rendering 3d scene/i })` | PASS in CI |
| 3. Color contrast | DOM chrome contrast across themes | `tests/e2e/color-contrast.spec.ts` runs axe color-contrast on the audited routes (does not currently include /game/3d; tracked in Pa11y Note5 follow-up if needed) | INHERITED from sibling routes |
| 4. Motion | `prefers-reduced-motion: reduce` disables auto-orbit | `tests/e2e/game-3d.spec.ts` US-3 scenario asserts `data-autorotate-active === 'false'` when reduce is set | PASS in CI |
| 4. Motion | Reduced-motion off allows auto-orbit | Same spec, second test, asserts `'true'` | PASS in CI |

The remaining items (manual focus indicator visibility, screen-reader spoken text in a live screen reader, motion preference toggle without reload, etc.) require an actual human-eyes pass. They should be performed once before the next release the feature is included in.

## Sign-off

| Reviewer | Date | Pass/Fail | Notes |
| ----------------------------------- | ------------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Automated proxies (Claude Opus 4.7) | 2026-05-17 | PASS for items listed in the table above | Manual focus/screen-reader passes still owed before release; tracked as open item in feature 047 status |
| _human reviewer_ | _yyyy-mm-dd_ | _PASS / FAIL_ | _any caveats_ |

Once a human has run the manual passes: append name + date, mark T049 as `[X]` in `tasks.md`, and commit. The automated-proxy row records what CI verifies on every run.
39 changes: 39 additions & 0 deletions features/enhancements/047-threejs-game/checklists/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Specification Quality Checklist: Three.js Game

**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-05-14
**Feature**: [spec.md](../spec.md)

## Content Quality

- [x] No implementation details (languages, frameworks, APIs)
- Note: Spec references Three.js, R3F, drei, and DaisyUI by name. This is unavoidable because the feature is _defined by_ the choice of WebGL via R3F — there is no technology-neutral way to specify "render a 3D scene that integrates with the existing 32-theme system." The PRP at `047_threejs-game_feature.md` made the same choice. Acceptable trade-off.
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders (modulo the unavoidable WebGL/Three.js terms above)
- [x] All mandatory sections completed

## Requirement Completeness

- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable (every SC-\* has a quantitative or observable target)
- [x] Success criteria are technology-agnostic (SC items describe outcomes — render time, theme update, animation absence, build success, bundle size — not implementations)
- [x] All acceptance scenarios are defined (US-1 through US-5 each have Given/When/Then scenarios)
- [x] Edge cases are identified (WebGL unavailable, GPU context loss, runtime preference toggles, theme switch during animation, Pa11y exclusion regression, dice game regression, static export at build)
- [x] Scope is clearly bounded (Out of Scope section enumerates 8 explicit exclusions)
- [x] Dependencies and assumptions identified (Assumptions section + Dependencies section both present)

## Feature Readiness

- [x] All functional requirements have clear acceptance criteria (FR-_ map cleanly to US-_ acceptance scenarios)
- [x] User scenarios cover primary flows (P1 = visit + theme; P2 = reduced motion + Pa11y; P3 = mobile)
- [x] Feature meets measurable outcomes defined in Success Criteria (each SC-\* is independently verifiable)
- [x] No implementation details leak into specification beyond the unavoidable WebGL/R3F naming

## Notes

- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`.
- All items pass on first iteration; no rework required.
- `/speckit.clarify` completed 2026-05-15 — 4 questions resolved (v1 scene content, fallback UX, camera control bounds, analytics scope). All 11 taxonomy categories now Clear. Spec amended with FR-008 (fallback panel), NFR-006 (observability scope), expanded FR-005 (camera constraints + auto-orbit), and SC-009/SC-010 (fallback + auto-orbit success criteria).
- Wireframe gate per Constitution v1.0.2 Principle III completed 2026-05-15. Two wireframes generated and approved: `01-game-3d-main.svg` and `02-game-3d-fallback.svg`. Both PASS the v5.0 validator (zero errors). Twelve patch-classified issues resolved across the two SVGs (signature alignment, callout positioning to avoid button overlap, callout count parity with annotation groups, US-badge minimum, XML hygiene). Audit trails preserved at `wireframes/01-game-3d-main.issues.md` and `wireframes/02-game-3d-fallback.issues.md`. Spec.md `## UI Mockup` block records the sign-off.
- `/speckit.plan` is unblocked.
Loading
Loading