Skip to content

#542 AC11: "WebGPU required" screen + renderer-unavailable telemetry - #581

Merged
MaximumTrainer merged 2 commits into
next/svelte-webgpufrom
claude/project-thread-lddi4g
Oct 25, 2026
Merged

MaximumTrainer merged 2 commits into
next/svelte-webgpufrom
claude/project-thread-lddi4g

Conversation

@MaximumTrainer

Copy link
Copy Markdown
Owner

Requested by Dan · project thread

What this does

Closes #542 AC11 / FR11: when the hand-written WebGPU engine declines (no navigator.gpu, software adapter only, or an attach throw), the ride view swaps the 3D stage for a dedicated "WebGPU required" screen and records a single renderer-unavailable crash so the triage pipeline can see how often users hit this path. The rest of the site (routes, settings, summary, import) stays reachable through the screen's "Back to routes" link, per D11.

Changes

  • CrashKind grows renderer-unavailable; the redactor's allowlist accepts it.
  • Canvas3DHost raises an onBackend signal to its parent on every backend transition and fires one reportCrash({ kind: 'renderer-unavailable' }) on unavailable. A sync throw inside attach is now caught alongside a rejected promise, so both paths reach AC11.
  • /row/+page.svelte renders <WebGpuUnsupported> whenever canvasBackend === 'unavailable'.
  • New WebGpuUnsupported.svelte — small, keyed off a backHref prop so it's unit-testable without $app/paths.

Tests

  • crashRedactor.renderer-unavailable.test.ts — pins the new kind through the allowlist and the verdict reason.
  • canvas3dHost.renderer-unavailable.test.ts — the host calls reportCrash exactly once on both the null-return and the attach-throw branches, and does not call it when the engine attaches.
  • webGpuUnsupported.svelte.test.ts — the component names WebGPU in the heading, points at a Back-to-routes link, and tells the viewer which browsers to try.
  • playwright/tests/webgpu-unsupported-row.spec.ts — stubs navigator.gpu to undefined before the page scripts run, starts a demo from the Row screen, asserts the ride view shows .webgpu-unsupported, and verifies the back link returns the viewer to a working site. shard-weights.json carries a 20 s weight.

Vitest green: 3628 pass / 8 skipped on branch at b4e92d5 (base next/svelte-webgpu).

The local Playwright run was blocked here by a Chromium build mismatch in the cloud container (PW 1.56.1 expects build 1194; image has 1243 and the proxy forbids downloading another). CI's pretest:e2e installs the matching version so the spec runs on branch CI.


Generated by Claude Code

When the hand-written WebGPU engine declines (no navigator.gpu, software
adapter only, or an attach throw), the ride view now swaps the 3D stage
for a dedicated "WebGPU required" screen and records a single
`renderer-unavailable` crash so the triage pipeline can see how often
users hit this path. The rest of the site (routes, settings, summary,
import) stays reachable through the screen's "Back to routes" link, per
D11 and FR11.

- CrashKind grows `renderer-unavailable`; the redactor allowlists it.
- Canvas3DHost raises an `onBackend` signal to its parent on every
  backend transition and fires one reportCrash on `unavailable`.
- /row swaps to <WebGpuUnsupported /> when backend is 'unavailable'.
- Unit tests pin the new kind through the redactor, the host's one-call
  telemetry on both the null-return and the attach-throw branches, and
  the component's heading + supported-browser copy + back-link.
- A Playwright spec (webgpu-unsupported-row) stubs navigator.gpu to
  undefined before scripts run, starts a demo from the Row screen, and
  asserts the ride view shows .webgpu-unsupported and the back link
  returns the viewer to a working site.

Local Playwright run blocked here by a Chromium build mismatch in the
container (PW 1.56.1 expects build 1194; image has 1243; proxy forbids
download). CI's `pretest:e2e` installs the matching version, so the spec
runs green on CI runners and on Dan's laptop via the engine thread's RC
session. Vitest green: 3628 pass / 8 skipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5D9BTXmu7SeMa3LghJD8b
@MaximumTrainer MaximumTrainer self-assigned this Oct 24, 2026
…project-thread-lddi4g

# Conflicts:
#	src/lib/ui/Canvas3DHost.svelte
#	src/routes/row/+page.svelte
@MaximumTrainer
MaximumTrainer merged commit 71e9894 into next/svelte-webgpu Oct 25, 2026
4 checks passed
@MaximumTrainer
MaximumTrainer deleted the claude/project-thread-lddi4g branch October 25, 2026 06:19
MaximumTrainer added a commit that referenced this pull request Oct 25, 2026
* #542 AC1: remove the React tree from next/svelte-webgpu

The Svelte + WebGPU port is at parity (PRs #581–#586). Everything the
React/three.js shell owned is gone: `src/App.tsx`, `src/main.tsx`,
`src/components/` (bar `routeMapProjection.ts` and the pure-TS scenery
config / helpers that `src/lib/scenery/` and the Svelte UI still read),
`src/hooks/`, `src/context/`, all 66 `*.tsx` tests and the handful of
`*.ts` tests that only measured a React-era contract. The scenery
`__tests__` were parity suites pinned on each React implementation, so
they go too.

Pure-TS modules under `src/components/rower3d/` that Svelte, `src/lib`
or the renderer still import stay: `conditions`, `constants`, `crewModel`,
`ghost`, `navigableWidth`, `rowerAppearance`, `sceneQuality`,
`sceneryAssets`, `sceneryClearance`, `sceneryConfig`, `sceneryCrossings`,
`sceneryRegion`, `sceneryTrack`, `segmentScenery`, `themeConfig`. They
move into `src/lib/` in a later slice.

Config fallout:
 * `index.html` — repo-root entry only existed to boot React; SvelteKit
   owns the HTML host via `src/app.html`.
 * `tsconfig.app.json` — `jsx: react-jsx` is dead with no `.tsx` left.
 * `tsconfig.playwright.json` — drops `renderBudget`/`strokePose`
   includes (and the two spec files that read them, which only ran on
   the React engine).
 * `eslint.config.js` — drops the react-hooks + react-refresh plugins.
 * `setupTests.ts` — drops the `@testing-library/jest-dom` shim; no
   preserved test uses its matchers.
 * `playwright.config.next.ts` — removes two deleted specs from the
   next-branch testIgnore.

What stays for the follow-up:
 * `package.json` dependencies on `react`, `react-dom`, `@react-three/*`,
   `postprocessing`, `react-chartjs-2`, `@testing-library/react`,
   `@react-three/test-renderer`, `@types/react`, `@types/react-dom`,
   `@vitejs/plugin-react`, `eslint-plugin-react-hooks`,
   `eslint-plugin-react-refresh` — nothing in the surviving tree
   imports them, but ripping them out touches `package-lock.json` and
   deserves its own PR.

Local gates: `tsc`, `eslint`, `vitest` (213 files · 2081 pass · 8 skip),
`tsc -p tsconfig.playwright.json`, `svelte-check` (clean — remaining
warnings are pre-existing node_modules + tsconfig composite notes).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5D9BTXmu7SeMa3LghJD8b

* #542 AC1: re-base coverage floors after the React sweep

Removing the React tree is a measurement change on the same shape as
`#542 P0`'s Vitest 1 -> 3 upgrade: the tests that only existed to pin
the three.js scene went with the production code they covered, and the
parity suites under `src/lib/scenery/__tests__/` that happened to count
toward preserved files' per-file 100 floors are gone too.

New measurement over the surviving tree: 89.11 / 89.11 / 85.77 / 90.66
(lines / statements / branches / functions). Floors land a point under
each reading, following the "set a floor clear of its measurement so
the gate stops answering 'did the last digit move'" rule the comments
above these numbers have followed since #340.

Also drops the per-file 100 floors for files that left with React —
`wakeTexture.ts`, `foliageMaterial.ts`, the rower3d `landscapeLayout.ts`
and `foliagePlan.ts`, the three R3F `*.tsx` wrappers — plus the
`**/foliageTexture.ts` floor whose only remaining match (the Svelte
`src/lib/scenery/foliageTexture.ts`) is at 15 % because its parity test
left too. The engine-side test that owns its measurement re-lands with
the renderer work it belongs to.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5D9BTXmu7SeMa3LghJD8b

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants