Skip to content

fix(init): tag wizard.outcome on all early-exit paths#1005

Merged
betegon merged 4 commits into
mainfrom
fix/wizard-outcome-missing-abandoned-bailed
May 22, 2026
Merged

fix(init): tag wizard.outcome on all early-exit paths#1005
betegon merged 4 commits into
mainfrom
fix/wizard-outcome-missing-abandoned-bailed

Conversation

@betegon
Copy link
Copy Markdown
Member

@betegon betegon commented May 22, 2026

Without this, a meaningful chunk of wizard runs land in Sentry with no
wizard.outcome tag, making the funnel gap unanalyzable. The dashboard
shows e.g. 15 started / 5 completed / 5 bailed / 4 errored = 1 missing,
and the missing ones are invisible.

What was happening

Five paths exited the wizard without ever calling setTag("wizard.outcome", ...):

Path File Where
ctrl+c during a spinner ink-ui.ts requestCancel()process.exit(130)
ctrl+c force-exit (stuck teardown) ink-ui.ts second process.exit(130)
User said no at the welcome prompt wizard-runner.ts WizardCancelledError in preamble()
User selected "No, exit" wizard-runner.ts !confirmed in preamble()
Git status check bailed wizard-runner.ts !gitOk in preamble()
resolveInitContext returned null wizard-runner.ts !context in runWizard()

Changes

  • ink-ui.ts: import setTag from @sentry/node-core/light, call
    setTag("wizard.outcome", "abandoned") before both process.exit(130)
    calls. Sentry is guaranteed initialized by the time InkUI runs (it's
    wrapped by withTelemetry). The tag is set synchronously before the
    setImmediate tick so the SDK has its best shot at flushing it.

  • wizard-runner.ts: add setTag("wizard.outcome", "bailed") to the
    four preamble/context early-return paths. These exit cleanly (event
    loop drains, beforeExit fires, Sentry flushes) so their tags will
    reliably reach Sentry.

Outcome taxonomy

  • abandoned — process was hard-killed mid-wizard (ctrl+c during spinner)
  • bailed — user deliberately stopped before the wizard did any work
  • errored — wizard ran but failed (already tracked)
  • completed — success (already tracked)

Several paths exited without setting wizard.outcome, leaving runs
with no outcome tag in Sentry and making the funnel gap unanalyzable:

- ctrl+c during a spinner (InkUI.requestCancel) → "abandoned"
- user said no at the welcome/confirm prompt (preamble) → "bailed"
- user selected "No, exit" at the experimental warning → "bailed"
- git status check bailed → "bailed"
- resolveInitContext returned null → "bailed"

The preamble paths flush cleanly (event loop drains, beforeExit fires)
so their tags will reliably reach Sentry. The InkUI path calls
process.exit(130) which skips beforeExit, but setting the tag before
the setImmediate tick gives the SDK its best chance to flush.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

PR Preview Action v1.8.1

QR code for preview link

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

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

@betegon betegon marked this pull request as ready for review May 22, 2026 13:20
… never-equals check

maskToken("*") must return "*" (the "short tokens are fully masked"
property requires all-asterisk output), which means the "output never
equals original input" property is unsatisfiable for inputs that are
already entirely asterisks. These two constraints are in fundamental
conflict for that edge case.

Fix: add a .filter() pre-condition to exclude all-asterisk tokens from
the never-equals property. Real auth tokens never consist entirely of
asterisks, so this doesn't weaken the practical guarantee.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Codecov Results 📊

✅ Patch coverage is 100.00%. Project has 4234 uncovered lines.
✅ Project coverage is 81.87%. Comparing base (base) to head (head).

Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    81.85%    81.87%    +0.02%
==========================================
  Files          328       328         —
  Lines        23347     23351        +4
  Branches     15114     15114         —
==========================================
+ Hits         19109     19117        +8
- Misses        4238      4234        -4
- Partials      1621      1620        -1

Generated by Codecov Action

betegon and others added 2 commits May 22, 2026 15:30
…al prompt

The !confirmed branch in preamble() was the one uncovered line in the
patch (75% patch coverage). Adds a test that responds "exit" to the
generic continue/exit select so that path executes.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…gration

vitest requires .rejects.toThrow() to be awaited; bun:test did not.
The missing await at the 404 test caused "expected undefined to be
defined" in CI after PR #997 landed.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@betegon betegon merged commit 48200d5 into main May 22, 2026
29 checks passed
@betegon betegon deleted the fix/wizard-outcome-missing-abandoned-bailed branch May 22, 2026 13:50
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