Skip to content

feat(clients): Explain links a known issue or a pre-filled report - #16702

Draft
saphid wants to merge 11 commits into
pingdotgg:mainfrom
saphid:feat/explain-known-issues
Draft

saphid wants to merge 11 commits into
pingdotgg:mainfrom
saphid:feat/explain-known-issues

Conversation

@saphid

@saphid saphid commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Model: Claude Opus 5.5 and Claude Sonnet 5.5. Rebased onto current main with Claude Opus 5.5 on 2026-10-12.

Draft, depends on #16685. This branch is built on #16685's Explain action; until that merges, this PR's diff also shows its commits. Review the last four commits (from c1ab963c96) for this change.

Problem

Explain (#16685) tells the user what probably went wrong, but not whether it is a problem other people already have. Someone hitting a known bug has no quick way to find its issue, and someone hitting a new one has to work out where and how to report it.

Change

When the user clicks Explain, the server also checks pingdotgg/t3code's issues for a match:

  • Known issue: if one matches, the banner shows Known issue: Add Expo mobile client and wire up dev:mobile workflow #123 <title> as a link.
  • Otherwise: the banner shows Report this issue, which opens GitHub's bug form in the browser with safe fields pre-filled, and copies the error, What happened and Likely fix to the clipboard for the user to check and paste. T3 posts nothing.

Before (#16685): the explanation, with no issue lookup.

Before: the banner shows What happened and Likely fix, with no known-issue or report link

After (this PR): Explain, then Report this issue, which copies the details and opens the form. Real-time recording, cropped to the banner.

After: Explain answers, the banner offers Report this issue, and after the click it says the error details were copied

After: the banner after clicking Report this issue, with the copied-details note

How it works:

  • The search sends no text from the error. GitHub search is public, so the server recognises the failure against a fixed list of 33 categories (whole-phrase patterns such as "failed to read attachment" or "connection refused") and searches with those categories' fixed terms, at most three, plus a fixed provider keyword, e.g. attachment read turn start claude repo:pingdotgg/t3code is:issue. Only which categories matched leaves the machine. No match means no search.
  • The model picks, the server checks. The top five candidates (number, title, state) go into the explanation prompt as an untrusted section; the model names one only if it clearly describes the same failure, and the server accepts the number only if it was a candidate. Links are built from the number, never taken from GitHub's response.
  • The report link carries no error text. The URL holds only a title of the same category terms ("[Bug]: Provider failure: attachment read, turn start"), a fixed instruction in the "Actual behavior" field, the provider keyword, runtime mode, OS and T3 version. The error, the explanation and the model name stay out of the URL, since GitHub receives a URL before the user reviews it. Clicking the link copies those details to the clipboard best effort, and the banner confirms only when the copy worked.
  • Best effort, never blocking. The search has a 3 s timeout. Failures (network, 403/429, bad response) yield no candidates and the explanation still arrives. After a rate limit, searches pause until GitHub's reset time, measured from when the response arrived. Identical concurrent searches share one request, and results are cached per query for 10 minutes.

Surfaces: web and desktop (desktop opens the link through its existing external-window handler). Mobile has no Explain action. The user guide's activity log page says exactly what the search and the link contain.

Scope and approval

A follow-up to #16685, which is itself a new feature without maintainer approval yet; the same applies here, and I'll follow maintainer direction on both. Kept separate so #16685 stays reviewable on its own.

Verification

  • vp test run on KnownIssueSearch.test.ts, ProviderFailureReportLink.test.ts, ProviderFailureExplanationService.test.ts, apps/server/src/textGeneration and apps/web/src/components/chat: all pass. They cover private names made of category words (Failed to read repo billing-migration: permission denied, Connection refused by auth.billing.internal) sending only fixed terms, a property test that every query word is a fixed term or provider keyword, 28 real failure strings mapping to their categories, out-of-list issue numbers ignored, a failed or rate-limited search still returning the explanation, backoff measured from response receipt, 20 concurrent identical searches making one request, emoji at every truncation point, and the report URL carrying none of the error text, explanation or model name.
  • tsc --noEmit: 0 errors in apps/server, apps/web, packages/contracts, packages/client-runtime. Lint and format clean, no suppressions.
  • Live client (web, headless Chrome, isolated dev server on 8c9fbc8fb5f with fix(server): provider failures say why a turn could not start #16303's ProviderFailure.ts laid over it so the failure names its reason): a real Claude attachment failure. The live search ran and the model matched no issue, so the report path is shown; clicking it opened a new tab with the pre-filled form and the clipboard held the three fields. The known-issue link state is covered by tests, not seen live, because no open upstream issue matches this failure.
  • Independent review by GPT-6 Astra (high): two full rounds plus a targeted re-review of the last commit. Round 1 found that words filtered from the error could still leak secrets or private names into the public search (blocker), error text in the report URL, and an emoji truncation crash. Round 2 found that vocabulary words could still spell private names (blocker), backoff measured from the request instead of the response, and uncoalesced concurrent searches. A targeted re-review of the category rewrite confirmed the privacy and timing fixes closed and found one race: an interrupt between registering a shared search and installing its cleanup could strand later identical searches. The last commit holds interruption off across that step and adds a guard test; it was not reviewed again. The same re-review caught a docs line still listing the model name in the link, also fixed.
  • Not checked: the GitHub form's rendering of the pre-filled fields (it needs a signed-in browser), and a text generation model other than Codex.

Built with Claude Sonnet 5.5 and Claude Opus 5.5 in Claude Code; cross-vendor review by GPT-6 Astra in T3 Code.

🤖 Generated with Claude Code

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Oct 7, 2026
github-actions Bot and others added 2 commits October 12, 2026 10:58
The error banner tells the user a turn failed, but working out why means
reading logs. An Explain action on the banner now asks the configured text
generation model what probably went wrong and what to try. The server builds
the context itself from the thread and runs the operation in an empty
temporary directory with tools off where the provider allows it.

Squashed from four commits so it rebases onto main's provider packages as
one change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@saphid
saphid force-pushed the feat/explain-known-issues branch 2 times, most recently from c73ff79 to 101b1ef Compare October 12, 2026 00:03
github-actions Bot and others added 9 commits October 12, 2026 11:23
The explain request needs the operate scope, so a read-only connection saw
an Explain action the server always rejected. The banner now gets an explain
target only when the connection can operate the thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Checks that each runs in an empty temporary directory that is removed
afterwards, refuses tool requests, decodes and bounds the structured answer,
rejects incomplete answers, and releases its host or session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A refused explanation logged its raw cause, whose detail can carry provider
CLI output. The warning now carries only the reason and the cause's tag and
operation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When Explain runs, the server also searches the upstream issues with a few
words from the failure (ids, paths and URLs stripped) and lets the text
model say which candidate, if any, describes the same failure. The banner
links that issue, or offers a GitHub bug form pre-filled with the failure,
explanation, provider, model and version for the user to review and submit.
T3 posts nothing, and a failed search never blocks the explanation.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…text out of report links

GitHub search is public, so the query is now built only from a fixed list of
diagnostic words and a canonical driver name, never from the error's own
text. The report link carries only those words, the provider, runtime mode,
OS and version; the error and explanation are copied to the clipboard for
the user to check and paste. Cut text on code points, never fail Explain
over the link, and back off after GitHub rate limits.

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

Words picked out of the error could still spell a private name, so the
query is now the fixed terms of recognised failure categories plus the
driver keyword. Identical concurrent searches share one request, and rate
limit waits start when the response arrives.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@saphid
saphid force-pushed the feat/explain-known-issues branch from 101b1ef to 90c79eb Compare October 12, 2026 00:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant