feat(website): the stage on the homepage — one real run, scrubbed by scroll (live-stage plan 3 of 3) - #1032
Merged
Conversation
blove
enabled auto-merge (squash)
September 6, 2026 04:28
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Eleven tasks: extend the frame's ready message with the hold and reload boundary; vendor the scroll-craft engine hash-pinned at 0b81622; the beat map (shares, the 35–70% hold, the threshold, the render tail, cue windows); rail copy in positioning.ts; the stills fallback; a DOM-only publisher; the pinned act with engine mount and analytics; the page swap; e2e; the scroll-craft harness in CI; verification and PR. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…oad boundary Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… fixture's reload run Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…windows Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…t re-authors Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…es forward on a missing beat Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…and is deeply readonly The rail's beat union is now the beat map's own type, so renaming a beat in stage-beats.ts breaks the rail at compile time instead of drifting. Tests assert the eyebrow matches the beat, every string is present, and the three hold lines in full. The verbatim-vs-page.tsx cross-check was deliberately not written: Task 8 deletes the page's FeatureBlocks and positioning.ts becomes the only source. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ibutes, milestones Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… analytics Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…urvives a throwing tick Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…omepage Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…, and is keyboard-skippable Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hold, the stills Four tests for the pinned act, the first time the vendored engine runs end to end in a real browser: the desktop upgrade (span 6, the /stage iframe, sticky .stage-pin, inline height = 6 viewports), scroll-driven --sc-p with the stream and render cues and the declared verify hold, the live-frame verify-state test (skipped unless STAGE_LIVE_FRAME=true until the demo /stage redeploys with hold/reloadEndMs), and the stills on phones and under reduced motion. The plan's hold position was 0.55 with a miscomputed window: with the authored shares (approve 2.4 of 6) the hold is 0.5567..0.6967, so 0.55 sits just outside it. The test scrolls to 0.68, inside the hold and on the last hold line's plateau. No component change was needed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… the hold where it is Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nt symlink survives Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rve substitution Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…I harness step builds once
Ready handshake: with a strict Referrer-Policy the frame had nowhere to
post `ready` and the publisher posted nothing before `ready`, so neither
side ever spoke. The bridge now remembers the last `ready` and re-posts
it the moment an allowlisted message teaches it the parent origin; the
stage component subscribes to seeks before posting `ready` so that
listener exists. The publisher says hello (`{ type, t: 0 }`) at most
once per 500 ms until `ready` arrives. Specs cover both sides.
CI harness step: the stage scroll verification built the website twice
(a standalone build, then the serve's own build dependency) and the
second run dropped the content symlink. The standalone build is gone;
the symlink is added after the readiness curl succeeds. The scroll-craft
README's local commands mirror the same ordering.
Minor: StageAct drops the unused `stage-frame-chrome` and
`stage-rail-heading` class names and gains `stage-rail-beat` /
`stage-rail-hold` test ids, which home-stage.spec.ts now locates by.
`StageMilestone` lives in stage-beats.ts (re-exported from the
publisher) and analytics/events.ts types `stage_event` and `beat` from
it instead of duplicating the unions.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
blove
force-pushed
the
blove/stage-homepage
branch
from
September 6, 2026 04:39
15a998c to
f7997ea
Compare
Contributor
blove
added a commit
that referenced
this pull request
Sep 6, 2026
…me reports pause (#1034) * fix(website): pin the stage hold one millisecond inside it so the frame reports pause Verified against production after #1032 deployed: the frame went ready, applied exactly through the interrupt (stream:930), but reported phase `stream` at the hold because the website pinned t at hold.startMs and the frame's phaseReachedAt treats a boundary instant as the outgoing run's. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(website): the pre-hold ramp ends on the pinned hold value so the seam is continuous Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Plan 3 of the homepage live stage (
docs/superpowers/specs/2026-09-05-homepage-live-stage-design.md§4.1, §4.3, §5.2, §6–§10). Plan 1 restructured the page (#1024); plan 2 built the seekable/stageroute in the demo app (#1030). This PR puts it on the homepage.What
data-sc-act="pin" data-sc-span="6") driven by scroll-craft's engine, vendored unmodified and hash-pinned at0b81622(MIT). Its CSS is not vendored; the sticky and cue rules live under the website's style contract. The engine is mounted on the act's parent: its act scan isquerySelectorAll, which matches descendants only.stage-beats.ts: shares (1.3 / 1.2 / 2.4 / 1.1 vh), the piecewise monotonic scroll → time map, the 35–70% hold inside Approve where recorded time is pinned at the interrupt, the threshold at 70% that dispatches the resume, the render tail on the mounted form, and the rail's cue windows — one table, two views.{ type: 'tplane-stage', t }to the iframe whentchanges and the act is on screen; the frame's{ applied, phase }lands indata-sc-verify-state, the hold indata-sc-verify-hold, so the harness sees the bespoke stage. It shape-checks the frame'sreadyand survives a throwing tick./stageready message now carriesholdandreloadEndMs. Until the canonical demo redeploys, production/stagesends neither, the website ignores that message, and the section falls back to the stills after 8 s — the intended degradation for the minutes the two deploys are apart.marketing:stage_progresswithenter | beat | threshold | complete.FeatureBlocks leave the homepage (they stay for the library pages); their copy is single-sourced inpositioning.ts.shoot.mjsruns in CI againstnx serve --configuration=productionat desktop; it fails on dead scroll outside the declared hold and on cues that never peak; contact sheets are an artifact. Phone and reduced-motion passes are opt-in because the harness requires a pinned act and those viewports render the stills.Tests
Beat map (monotonic incl. every seam, boundaries, hold, threshold, tail, cues), publisher (posts on change only, origin check, verify attributes, milestones once each, malformed ready ignored, throwing tick survives, hook deps through a ref), Stage mode switch + engine root, stills, style contract, analytics, positioning; e2e for the upgrade and 600vh pin, scroll-driven cues and the hold, the stills, and (env-gated
STAGE_LIVE_FRAME) the live frame's verify state. Verified locally: website unit suite, lint (0 errors), production builds of the website and the demo app (initial bundle unchanged at 1.65 MB), demo stage suite 60/60, website e2e 16 passed / 1 skipped, and the harness at desktop: no dead scroll, all cues clear 4.5:1.🤖 Generated with Claude Code