Skip to content

feat(gateway): replace the stalled boot bar with a checkpoint ladder - #3376

Merged
benjaminshafii merged 1 commit into
devfrom
feat/gateway-loading-ladder
Jul 31, 2026
Merged

feat(gateway): replace the stalled boot bar with a checkpoint ladder#3376
benjaminshafii merged 1 commit into
devfrom
feat/gateway-loading-ladder

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

Summary

The gateway boot takeover had a progress bar hardcoded to two thirds that only pulsed:

<div className="h-1.5 w-2/3 animate-pulse rounded-full bg-dls-accent/60" />

It never moved and never completed, so a slow sandbox read as frozen at 66%.

  • Checkpoint ladder replaces the bar. Progress is derived from the status we already poll, so it can never claim more than we can prove: a provisioning sandbox is still being reserved, while a waking or updating one demonstrably exists already. updating gets its own labels since it isn't a cold boot.
  • Only one thing animates. The card previously ran the dot ticker and a Loader2 spinner at the same time; now just the active row does.
  • Slow waits are handled. At 45s the copy escalates to "Still working on it…", an elapsed counter appears, and Retry / Sign out fade in. Previously those only existed after a hard failure, so a slow but healthy boot left people with nothing to do.
  • Ready has a payoff. The indicator shares a layoutId with the corner pill, so it travels into the pill instead of one element vanishing and another appearing. The context tracks whether the takeover is on screen so the two never claim the indicator at once.

Drive-by bug fix

The dot ticker computed to fully transparent. The --dls-*-rgb tokens are space-separated (96 100 108) but these rules used legacy comma rgba(), which is invalid CSS. The indicator was invisible everywhere it's used, including the composer wait state. Lines 454–458 of the same file already used the correct rgb(var(--x) / a) form; this matches it. Confirmed in-browser: now computes to rgba(96, 100, 108, 0.22).

Motion

Uses motion v12, already a dependency. AnimatePresence for state crossfades, pathLength for the check draw, layout so the card glides, spring for the pill settle, useReducedMotion to degrade to plain crossfades. Infinite loops (ticker, shimmer) stay in CSS so the gateway isn't holding the main thread while it polls. LazyMotion with domMax — layout animations require domMax, and app-sidebar.tsx already loads it, so no new bytes.

Test plan

Ran and passing:

  • npx tsc --noEmit — clean
  • bun test tests/cloud-workspace-overlay.test.tsx — 21 pass
  • bun test (full suite, on the combined branch) — 667 pass; the 6 failures are pre-existing and fail identically on an untouched baseline
  • pnpm build — clean

New tests cover the stage mapping (exactly one active checkpoint, none once ready), the 45s escalation boundary, elapsed formatting, and render-level assertions that the ladder is present and w-2/3 / animate-pulse are gone.

I verified appearance by rendering the takeover against the built stylesheet and screenshotting all three states — that is how the invisible dot ticker was caught, along with pending rings that were too low-contrast. Animation timing and the pill handoff are unverified in motion, since driving the live takeover needs a Den-authenticated gateway runtime. Worth a real boot before this leaves draft.

Open question

The ladder assumes three checkpoints, but mapCloudWorkspaceState collapses everything into single variants. This PR maps variants onto stages, which is honest but coarse. If Den can report a finer-grained boot stage, the ladder would reflect actual progress rather than an inferred position.

Made with Cursor

@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview Jul 31, 2026 10:37am
openwork-den Ready Ready Preview Jul 31, 2026 10:37am
openwork-den-worker-proxy Ready Ready Preview Jul 31, 2026 10:37am
openwork-landing Ready Ready Preview, v0 Jul 31, 2026 10:37am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
openwork-diagnostics Skipped Skipped Jul 31, 2026 10:37am

@benjaminshafii

Copy link
Copy Markdown
Member Author

Verification

Mounted the real CloudWorkspaceBootTakeover in a browser through the app's Vite pipeline, so Framer Motion actually runs. This matters because the earlier static render could not prove the animated pieces — a statically serialized pathLength: 0 checkmark is invisible by construction.

Per-state ladder (driven live through each variant)

  • provisioning — "Starting your workspace…", stage 1 active, stages 2 and 3 pending.
  • waking — "Waking your workspace…", stage 1 done with a fully drawn green checkmark, stage 2 active, stage 3 pending.
  • failed — amber card, alert icon, Retry + Sign out, no ladder. Card height change is handled by the layout animation.

Animations confirmed running (not just present in markup)

  • The checkmark completes its draw, so the pathLength animation genuinely runs in the browser.
  • The shimmer bar was captured mid-travel across separate screenshots.
  • The dot ticker renders and animates, confirming the rgb(var(--x) / a) fix — the previous rgba() syntax silently dropped the declaration and made the dots transparent.

Slow-boot escalation — waited out the real 45s threshold on the live timer rather than mocking it. At 1m 43s the card correctly showed data-cloud-workspace-wait="slow", "Still working on it…", the reassuring body copy, the ladder preserved, Retry + Sign out revealed, and "1m 43s elapsed".

Also run: typecheck, bun test (including new stage/escalation/render tests), and a production build — all green.

Not verified visually: the shared-layoutId handoff from the takeover indicator to the corner pill, which needs the full app shell to observe. It is gated by the takeoverActive context flag so only one component claims the id at a time, and that gating is covered by unit tests.

The boot takeover showed a progress bar hardcoded to two thirds that only
pulsed, so a slow sandbox read as frozen at 66%. It also ran two spinners
at once, and Retry appeared only after a hard failure, leaving a slow but
healthy boot with nothing to do.

Progress is now derived from the status we already poll, so it can never
claim more than we can prove: a provisioning sandbox is still being
reserved, while a waking or updating one demonstrably exists. Only the
active checkpoint animates. At 45s the copy escalates and Retry / Sign out
appear.

Also fixes the dot ticker, which computed to fully transparent: the
--dls-*-rgb tokens are space-separated but the rules used legacy comma
rgba(), so the indicator was invisible everywhere it was used, including
the composer wait state.

Co-authored-by: Cursor <cursoragent@cursor.com>
@benjaminshafii

Copy link
Copy Markdown
Member Author

@OmarMcAdam @src-opn re-requesting a look, please.

After your approval the single commit on this branch was rewritten to be signed — the default-branch ruleset requires verified signatures and the original commit was unsigned. The new commit was created through GitHub's API so it carries a verified signature, and the PR then auto-merged.

The rewrite was content-preserving: git diff between the originally-approved SHA and the merged tree returns zero lines, so what landed is byte-identical to what you approved. The approval carried over rather than being dismissed, which is why it merged without a second review.

Flagging it explicitly so the re-review is a conscious sign-off rather than an inherited one.

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