Show Explain button on receipt scan failed system messages#93532
Open
Beamanator wants to merge 2 commits into
Open
Show Explain button on receipt scan failed system messages#93532Beamanator wants to merge 2 commits into
Beamanator wants to merge 2 commits into
Conversation
The .reasoning field is now populated on RECEIPTSCANFAILED actions by Auth #21123, but ReceiptScanFailedContent renders via the bare ReportActionItemBasicMessage which does not check hasReasoning(). Switch to ReportActionItemMessageWithExplain when reasoning is present so users see the inline Explain link and can thread on the message.
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
Contributor
Author
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation of Change
When SmartScan fails to parse a receipt, Auth posts a
RECEIPTSCANFAILEDreport action in the transaction thread. As of Auth PR 21123 (merged 2026-06-13), that action now carries areasoningfield onoriginalMessage— an LLM-friendly description of what was/wasn't extracted — andhasReasoning(action)is what activates the inlineExplainaffordance everywhere else in the App.The gap before this PR:
ReceiptScanFailedContentrendered the action with a plainReportActionItemBasicMessage, which has nohasReasoning()awareness. Soreasoningwas being delivered but the inlineExplainlink never appeared. (The right-click / long-press context menu'sExplainentry — which gates onhasReasoning(reportAction)directly inContextMenuActions.tsx— was already working, but the much more discoverable inline affordance was not.)This PR:
ReceiptScanFailedContent.tsx— whenhasReasoning(action)is true, renders throughReportActionItemMessageWithExplain(passingaction,childReport, andoriginalReport), matching the pattern used byMovedTransactionAction,ExportIntegration,ModifiedExpenseContent,UnreportedTransactionAction, andApprovalFlowContent. Otherwise falls back to the existingReportActionItemBasicMessagerendering.ActionContentRouter.tsx— threadsoriginalReportdown toReceiptScanFailedContent(required by the WithExplain wrapper'sexplain()call).src/types/onyx/OriginalMessage.ts— addsreasoning?: stringtoOriginalMessageSmartScanFailedfor type accuracy. (Behaviour unchanged: the runtimehasReasoning()check is'reasoning' in originalMessage, so this is type hygiene, not a behavioral fix.)The user-visible message string is unchanged —
translate('violations.smartscanFailed', {canEdit, missingFields})still drives the human-readable copy (Receipt scanning failed — missing <fields>. Enter details manually.) for both branches.Parent feature: the
Explainfeature rollout.Fixed Issues
$ https://github.com/Expensify/Expensify/issues/612790
PROPOSAL:
Tests
These are reproducible against a local dev build where the merged Auth PR is deployed (i.e. the Auth service on staging/prod, or the local Auth checkout past commit
d67a2a0b).Receipt scanning failed — missing <field(s)>. Enter details manually.— the exact field list reflects what couldn't be extracted (one of merchant, date, amount, or multiple).Explainlink is appended after that message (rendered as a muted, clickable link).Explainlink.reasoningfield round-tripping through the Explain flow.Explainoption (this path was already working pre-PR viaContextMenuActions.tsxand must not break).RECEIPTSCANFAILEDaction from before the merged Auth PR (i.e. noreasoningfield onoriginalMessage), confirm it renders the same as before — message text only, no inlineExplainlink.Explainlink is present on a freshly-failed scan.Explainopens a Concierge thread with a field-aware reply.Explainentry still works (regression).reasoningrender without the inline link (backward compat).Offline tests
Tapping
Explainis a normal Concierge round-trip; offline behaviour mirrors any otherExplainaction (e.g.Moved transaction,Exported to integration):Explainlink render in the transaction thread.Explainlink still render from cached Onyx data.Explainwhile offline — the action should be queued (no immediate Concierge response).QA Steps
QA can run against staging once the merged Auth PR has deployed.
Receipt scanning failed — missing <field(s)>. Enter details manually.and the exact missing-field list matches what was undetectable.Explainlink is present immediately after the message text.Explain.Explainentry is also still present (regression check).PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline testssectionQA stepssectionreasoning; offline tap-Explain behavior)toggleReportand notonIconClick) — N/A, no new callbackssrc/languages/*files and using the translation method — no new copy added; existingviolations.smartscanFailedtranslation reusedSTYLE.md) were followedhasReasoning+ReportActionItemMessageWithExplainpatternAvatar, I verified the components usingAvatarare working as expected) — the neworiginalReportprop onReceiptScanFailedContentis required and supplied at the only call site inActionContentRouter.tsx; no other consumers existReceiptScanFailedContent's prop type gained the requiredoriginalReportfield; updated at its single call siteStyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases) — N/A, modifies an action-specific renderer, not a generic componentReportActionItemMessageWithExplainwrapper; no new buttons, no padding/spacing changes, no new form input stylesDesignlabel and/or tagged@Expensify/designso the design team can review the changes. — N/A, reuses an existing affordance unchangedScrollViewcomponent to make it scrollable when more elements are added to the page. — N/A, no new pagemainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari