Skip to content

feat(studio): GPU live gallery cards via a leased PreviewHost service#118

Open
Yona-Appletree wants to merge 1 commit into
mainfrom
claude/gpu-live-gallery
Open

feat(studio): GPU live gallery cards via a leased PreviewHost service#118
Yona-Appletree wants to merge 1 commit into
mainfrom
claude/gpu-live-gallery

Conversation

@Yona-Appletree

Copy link
Copy Markdown
Member

Summary

Home gallery cards now render live GPU thumbnails. This wires the lp-gfx M3 browser machinery (previously exercised only by the dev preview-lab) into the product through a new reusable PreviewHost service, per the plan + interactive design session (2026-07-16) and ADR docs/adr/2026-07-16-preview-host.md.

![verified live: example card animating on the GPU tier with badge]

Verified end-to-end in-browser: the example card boots the worker pool, deploys, crossfades from its gradient to a live animating GPU-tier frame with a visible GPU badge; zero console errors.

What's here

  • DestroyRuntime/RuntimeDestroyed worker envelopes + fw-browser runtime disposal (same-bundle wire → no WIRE_PROTO_VERSION bump). Includes a latent-bug fix: runtime ids were len()+1 and would have re-issued a live id after a destroy — now monotonic.
  • lpa-studio-core::app::preview_host — the service (see ADR): pool of 2 explicit-tick preview workers (device-lost isolation, not CPU parallelism), slot leases over both content sources (embedded examples; library projects materialized by uid), one host-side deadline scheduler (per-slot ~12 fps, in-flight backpressure, visibility suspend, live-slot cap with LRU eviction), per-slot observable status, deliberate worker recycle with a 2-strike flap guard, and the reserved PreviewProfile seam (future: auto input playback, audio-reactive preview, preview-mode authoring). 18 unit tests on the pure policy layer.
  • Home gallery UI — layered CardThumb (live canvas → snapshot seam, sourceless until M6's save-time capture lands → gradient+initial), use_thumb_preview hook (lazy app-lifetime host; canvas generation remounts — transferControlToOffscreen is one-shot; IntersectionObserver → set_visible; error → remount + re-lease), tier badges per the fidelity-tiers ADR, new live-thumb-states story.

Review callouts

  • ADR review folded in here per your directive — the design decisions were all made interactively (pool-of-2, DestroyRuntime, visible-capped policy, PreviewProfile seam); the ADR formalizes them.
  • API deviations from the sketch (each reasoned, in the phase logs): native-safe PreviewTier instead of the wasm-gated lpa-link tier type; Example(String) ids; LibraryHost seam parameter; public policy layer (native dead-code avoidance); status_revision()/presented_frames() observational methods; recycle strike cap.
  • Story baselines: 6 home-gallery PNGs are real changes (overview + new story); 22 non-gallery PNGs re-rendered byte-different but verified visually identical (capture-environment drift; committed per the include-what-the-helper-updated rule). Separately: three consecutive studio-story-check runs flag different stories with sub-1% pixel flicker — pre-existing capture nondeterminism, filed as its own task.
  • M6 coordination: the presented channel visual.out is exactly M6's primary-visual contract; the snapshot layer awaits their save-time capture.

Validation

  • just check / just build-ci / just test green
  • cargo test -p lpa-studio-core 473 green (18 new); clippy -D warnings clean native + wasm32
  • Story baselines regenerated; in-browser functional verification (M2 Max)
  • Deferred: N-card CPU measurement (only one example card exists on a fresh store; awaits more seeded content)

Plan: ~/.photomancer/planning/lp2025/2026-07-16-gpu-live-gallery-cards/ (implementation log in _DONE.md)

🤖 Generated with Claude Code

Home gallery cards (Examples + Your projects) now render live
GPU-rendered thumbnails through a reusable preview service, replacing
CardThumb's static gradient. Consumes the lp-gfx M3 browser machinery
(worker WebGPU device, tiered runtimes, OffscreenCanvas zero-readback
surface path) that previously only the dev preview-lab exercised.

ADR: docs/adr/2026-07-16-preview-host.md (PreviewHost — leased, pooled,
budgeted project previews).

- DestroyRuntime/RuntimeDestroyed worker envelopes + fw-browser runtime
  disposal (same-bundle wire, no WIRE_PROTO_VERSION bump); fixes a
  latent runtime-id reuse bug (len()+1 -> monotonic ids).
- lpa-studio-core app::preview_host: pool of 2 explicit-tick preview
  workers (device-lost isolation, not CPU — GPU-bound per POC-A +
  preview-lab), slot leases over both content sources (embedded
  examples; library projects materialized by uid), one host-side
  deadline scheduler (per-slot ~12fps, in-flight backpressure,
  visibility suspend, live-slot cap with LRU eviction via
  DestroyRuntime), per-slot observable status, deliberate worker
  recycle with a 2-strike flap guard, PreviewProfile seam reserved for
  preview-mode customization (auto input playback, audio reactivity).
  18 unit tests on the pure policy layer.
- lpa-studio-web home: layered CardThumb (live canvas -> M6 snapshot
  seam (sourceless until primary-visual capture lands) -> gradient),
  use_thumb_preview hook (lazy app-lifetime host, canvas generation
  remounts, IntersectionObserver -> set_visible, error -> remount +
  re-lease), tier badges per the fidelity-tiers ADR, new
  live-thumb-states story.

Story baselines: home-gallery overview + live-thumb-states (ours); 22
non-gallery PNGs re-rendered byte-different but verified visually
identical (capture environment drift; nondeterminism filed as its own
task).

Verified live in-browser: example card boots the pool, deploys, and
animates on the GPU tier with badge; zero console errors. just check /
build-ci / test green; story-check green modulo the pre-existing
capture nondeterminism.

Plan: ~/.photomancer/planning/lp2025/2026-07-16-gpu-live-gallery-cards/

Co-Authored-By: Claude Opus 4.8 <[email protected]>
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.

1 participant