Skip to content

fix(init): rotate spinner messages during long plan-codemods wait#1108

Merged
betegon merged 3 commits into
mainfrom
issue-1107-init-spinner-progress
Jun 22, 2026
Merged

fix(init): rotate spinner messages during long plan-codemods wait#1108
betegon merged 3 commits into
mainfrom
issue-1107-init-spinner-progress

Conversation

@jared-outpost

@jared-outpost jared-outpost Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

During plan-codemods, the spinner showed static text ("Planning code changes...") for up to ~3 minutes while the server fetched SDK docs and ran the planner agent, causing users to bail. This adds client-side rotating progress messages that cycle every 12s during resumeWithRecovery() for steps with known long waits (plan-codemods, detect-platform). After exhausting all messages, elapsed time is appended so the user knows the system is still working.

No regression in LoggingUI — the spinner's message() method logs each rotation as a separate line in non-interactive mode, which is the desired behavior.

Testing

  • vitest run test/lib/init/clack-utils.test.ts — 15/15 pass (4 new tests for progress message constants)
  • wizard-runner.test.ts has a pre-existing Stricli alias conflict (-H in local/server.ts) that prevents it from loading; 3 new tests added for the rotation behavior
  • biome check clean on all changed files

Closes #1107

During plan-codemods, the spinner showed static text for up to ~3min
while the server fetched SDK docs and ran the planner agent. Users
assumed the CLI had hung and bailed.

Add client-side rotating progress messages that cycle every 12s during
resumeWithRecovery() for steps with known long waits (plan-codemods,
detect-platform). After exhausting all messages, append elapsed time
so the user knows the system is still working.

Fixes #1107
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1108/

Built to branch gh-pages at 2026-06-22 13:19 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

✅ Patch coverage is 92.59%. Project has 5054 uncovered lines.
✅ Project coverage is 81.24%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
src/lib/init/wizard-runner.ts 92.00% ⚠️ 2 Missing and 2 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    81.24%    81.24%        —%
==========================================
  Files          388       388         —
  Lines        26910     26936       +26
  Branches     17481     17493       +12
==========================================
+ Hits         21861     21882       +21
- Misses        5049      5054        +5
- Partials      1822      1825        +3

Generated by Codecov Action

@jared-outpost jared-outpost Bot marked this pull request as ready for review June 17, 2026 12:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 30115b2. Configure here.

Comment thread src/lib/init/wizard-runner.ts
The rotation timer could overwrite 'Reconnecting...' spinner messages
during stale-step or connection recovery. Add pause/resume to the
rotation handle so resumeWithRecovery can suppress ticks while
recovery is in progress.
@jared-outpost

jared-outpost Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

all CI checks are green. skipping auto-merge since the diff is 363 lines across 4 files (exceeds the 150-line threshold for autonomous merge) — leaving for human review.

@betegon

betegon commented Jun 22, 2026

Copy link
Copy Markdown
Member

Looked at this closely while chasing the same problem from the telemetry side — runs were stalling right here. For context: in plan-codemods the docs tailoring (get-docs/tailorAgent) runs p50 ~99s / p95 ~128s, then the planner agent ~30–60s, all in a single resume with no suspends, so the spinner sat frozen for 2–3 min and a couple of users bailed. This fixes exactly that, and the fake-timer tests are a nice touch.

A few notes, none blocking:

  1. Non-interactive log volume. Rotation isn't gated on the UI, so under LoggingUI (--yes / non-TTY / CI) spin.message() logs a fresh line every 12s for the whole wait — ~10–15 lines like Reviewing planned changes for correctness... (72s). The PR calls this desired, which is defensible (silent CI jobs can get reaped). Only flag: the messages are time-based, not tied to real server state, so a CI log can show a phase that isn't actually running. If that's a concern, gating on process.stdout.isTTY keeps non-interactive runs to the single static label.

  2. Static label unchanged. STEP_ACTIVE_LABELS["plan-codemods"] is still "Planning code changes...", and since index starts at -1 the first rotation tick lands at +12s — so that original label shows for the first 12s of the wait. Might be worth updating it too so the pre-rotation window is honest.

  3. resume() looks unused. Both recovery branches pause() then return/throw, and the loop's finally calls stop(), so nothing ever calls ProgressRotationHandle.resume(). Either it's dead code or I'm missing a path.

Confirmed the "Reconnecting..." collision is handled via pause(). Nice work.

Recovery paths always end with stop() via the finally block, so
resume() was never called. Spotted by @betegon in review.
@jared-outpost

jared-outpost Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

thanks for the thorough look.

  1. Non-interactive log volume — agreed it's defensible as-is. the messages are intentionally time-based rather than state-based, so CI logs show "something is happening" even though the phases are approximate. gating on isTTY would silence CI entirely, which is worse for long-running jobs that get reaped. leaving this alone for now but open to revisiting if it gets noisy in practice.

  2. Static label — the 12s gap is intentional: STEP_ACTIVE_LABELS is set by the main loop before startProgressRotation fires, so the user sees "Planning code changes..." immediately on step entry. the first rotation tick then swaps to "Fetching SDK documentation..." at +12s. updating the static label to match the first progress message would make the transition invisible, which seems worse.

  3. resume() dead code — you're right, both recovery branches pause() then return/throw, and the finally block calls stop(), so nothing ever resumes. removed it in 8a2bc8c.

@betegon betegon merged commit 224903c into main Jun 22, 2026
29 checks passed
@betegon betegon deleted the issue-1107-init-spinner-progress branch June 22, 2026 13:45
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.

init: spinner shows static text for ~3min during plan-codemods (docs fetch + planner agent), users bail

1 participant