Skip to content

feat(seer): Handle single Autofix runs that stop for credits - #131092

Draft
billyvg wants to merge 9 commits into
masterfrom
billyvong/seer-single-run-out-of-credits
Draft

billyvg wants to merge 9 commits into
masterfrom
billyvong/seer-single-run-out-of-credits

Conversation

@billyvg

@billyvg billyvg commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Why?

A single Autofix run that runs out of Seer credits ends with failure_reason: out_of_credits, but the drawer didn't recognize it. Depending on where the run stopped, a card said "Seer failed … This one is on us" or "Seer proposed a fix but couldn't apply it automatically" next to Seer's raw error message. Its retry ignored the credit check, and the drawer showed no out-of-credits CTA. #129566 handles this for multi-step runs; this does the same for single runs.

Stacked on #129566, so until that merges this diff includes it. Only the last commit is new.

How?

The section a single run stopped in now carries the run's failure_reason, so the cards, sidebar previews and feedback list show the out-of-credits status from #129566. A single run is retried by starting a new one, so the cards' Re-run starts a new single run and waits on the autofix_root_cause credit check. The drawer's autofix-continue alert covers that retry too.

Decisions

  • A single run's PR update that stopped for credits gets no retry on the card, and no credit check runs for it. Single runs take PR feedback in the chat.
  • The drawer alert uses the autofix-continue copy, since the run stopped part way, though its retry starts a new run.
Screenshot
Before: a single run that stopped for credits while editing Before: the code changes card says Seer couldn't apply the fix and shows Seer's raw error
After: out of credits After: the out-of-credits alert, the partial fix, why the run stopped, and a disabled Re-run
After: once the organization can afford a new run After: no alert, and Re-run is enabled

The screenshots come from the SeerDrawerContent stories, viewed by a billing member. The before shot is the same story with #129566's cards.

🤖 Generated with Claude Code

billyvg and others added 9 commits November 13, 2026 13:16
Runs and PR creates that stopped because the org ran out of Seer credits looked like generic errors and offered a retry that fails the same way. Autofix now reads failure_reason=out_of_credits and pr_creation_error_code=out_of_credits and shows the out-of-credits CTA instead.

The drawer cards and the chat autofix card keep what the step wrote before it stopped, including a partial diff, and drop their re-run and Try again buttons. The PR card and chat card stop offering a PR retry, and the inbox disables it with an explanation. The PR failure toast and tooltips use out-of-credits copy, and the chat swaps Seer's plain-text error block for the CTA.

Fixes CW-2328

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Steps and PRs that stopped because the org ran out of Seer credits no longer render the out-of-credits CTA. The credit gates own it on each surface: the alert at the top of the Autofix tab and drawer, the alert above the chat composer and the muted alert in the issue sidebar. A stopped step or failed PR now shows one muted (drawer) or danger (chat card) line saying why it stopped, and the chat transcript swaps Seer's error block for that line.

Their retries stay on screen and follow useSeerCreditCheck for the operation they would spend: disabled with an out-of-credits tooltip while the org can't afford it, enabled again once it can. That covers Re-run, Add context & retry and the card header's Re-run step in the drawer, Retry PR in the drawer and inbox, and Try again and Draft a pull request in the chat card.

Refs CW-2328

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both cards gained an out-of-credits state with no story. Each story file shows the card stopped
for credits with Re-run disabled, the same run after a top-up, and a run that stopped before Seer
wrote anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Credit checks also need token-billed-seer-enabled as of #129545, so the tests, stories and
SeerCreditCheckStub that turn on seer-credit-checks turn it on too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backend's SeerOperation calls the PR step autofix_open_pr and rejects autofix_create_pr, so
the PR retry gates always failed open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The autofix embed rendered a stopped step's text with ArtifactPartialDetails, whose SeerMarkdown
imports the embeds, so knip --cycles failed. The embed now renders that text with its own
markdown, like the rest of its steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#129565 landed `AUTOFIX_CREDIT_OPERATIONS` and `useAutofixCreditCheck`, which
map each autofix action to the operation the credit check prices. The
retries here kept their own copy of that map. `useOutOfCreditsRetry` now
takes the autofix action and checks it through `useAutofixCreditCheck`, so
both gates read one map.

The retry also waits on `hasCheckedSinceMount` instead of `isPending`, as the
#129565 gates do. A cached answer from an earlier mount no longer enables a
retry before this mount's recheck answers.

SeerExplorerContent reuses `isRunOutOfCredits`, which #130463 added, for the
transcript's out-of-credits line. The chat window story for a run that
stopped for credits now shows the composer's out-of-credits alert, which
that recheck brings up.

The chat window stories answered the credit usage meter's wallet request
with an empty list when they had no wallet fixture, so the meter crashed
and took every story in the file with it. Those requests now fail, as
they do for an org without token-billed Seer, and a story without a
wallet is viewed by a member without billing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the organization has run out of Seer credits, the Autofix endpoint
refuses a step or PR with a 402 and `code: seer_out_of_credits`.
`startStep` and `createPR` treated that like any other failure. They
toasted the backend's detail, and a refused kickoff with no run yet
painted a failed run that said "This one is on us".

Both now recheck every Seer credit check, so the credit gates bring up the
out-of-credits CTA and disable their buttons, and toast out-of-credits
copy for the step, or for the repo's PR. A refused kickoff no longer
paints a failed run, since the start card offers the CTA instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single run that ran out of Seer credits showed "Seer failed ... This
one is on us" with a Re-run that ignored the credit check. Single-run
sections never carried the run's `failure_reason`, so nothing could tell
a credit stop from any other failure.

- The section a single run stopped in now carries `failure_reason`, as
  multi-step sections already do, so the cards, sidebar previews and
  feedback list show the out-of-credits status.
- The root cause and code changes cards retry a single run that stopped
  for credits with a new single run, held on the `autofix_root_cause`
  credit check that starting one costs. Before, the root cause card
  called the step reset that single runs reject.
- A single run's PR update that stopped gets no retry on the card, since
  single runs take PR feedback in the chat. Nothing is checked for it.
- The drawer shows the autofix-continue alert for a single run that
  stopped for credits, since its Re-run is the next billable action.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Nov 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

decision-model-linter

voice

static/app/components/events/autofix/v3/rootCauseCard.tsx

  • warn miscapitalizesProductName = TRUE (0.70): Use the canonical spelling for this named Sentry product or feature. Leave generic descriptions lowercase and preserve package names and identifiers.

static/app/components/events/autofix/v3/solutionCard.tsx

  • warn miscapitalizesProductName = TRUE (0.73): Use the canonical spelling for this named Sentry product or feature. Leave generic descriptions lowercase and preserve package names and identifiers.

decision-model-linter: 217 calls on 40 files, 579,977 input tokens, $0.024, model typesafe/jev-1.13-20260917

@github-actions

Copy link
Copy Markdown
Contributor

📊 Type Coverage Diff

Metric Before After Delta
Coverage 96.03% 96.03% ±0%
Typed 142,321 142,432 🟢 +111
Untyped 5,890 5,893 🔴 +3
🔍 3 new type safety issues introduced

Non-null assertions (!) (1 new)

File Line Detail
static/app/components/seer/outOfCredits/messages.tsx 88 states[0]!

Type assertions (as) (2 new)

File Line Detail
static/app/components/events/autofix/useExplorerAutofix.tsx 343 `as
| null
| undefined` — `e as | {responseJSON?: {code?: unknown}; status?: number} | null | undefined` |

| static/app/components/seer/outOfCredits/__stories__/seerCreditCheckStub.tsx | 27 | as never — queryFn as never |

This is informational only and does not block the PR.

This branch was successfully deployed

1 active deployment
Preview — fb73ec29 Deployed Nov 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant