Skip to content

feat: add 👍/👎 feedback prompt under the latest Concierge response - #100454

Merged
yuwenmemon merged 24 commits into
Expensify:mainfrom
oqildev:feat/96775-concierge-feedback-prompt
Sep 18, 2026
Merged

yuwenmemon merged 24 commits into
Expensify:mainfrom
oqildev:feat/96775-concierge-feedback-prompt

Conversation

@oqildev

@oqildev oqildev commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Renders Was that response useful? 👍 👎 beneath the newest Concierge-authored comment. Each thumb writes a real emoji reaction and nothing else — the backend reads the reaction and, on a thumbs down, opens the feedback thread itself. Because the prompt is gated on that same reaction it resolves optimistically, stays resolved across reloads, and becomes eligible again if the user retracts the reaction from the pill row.

Eligibility is decided by getLatestConciergeFeedbackActionID, which requires the action to exist in Onyx rather than merely look like a Concierge comment. Two client-built actions are shaped identically to a finished answer — the greeting from buildConciergeGreetingReportAction and the paced reply from buildConciergeDraftReportAction — but never reach Onyx, and toggleEmojiReaction bails on both, so a prompt on either would render buttons that do nothing. The list also stands down while a synthetic draft is on screen, so the prompt never lands on a half-written answer.

Two open points from the design discussion, neither blocking:

  1. Tooltip. The design comment asked whether these need one and it was never settled. Implemented with tooltips (Useful response / Not useful response — only the thumbs-up label was mocked, so the other is the symmetric counterpart). Removing them is a one-liner.
  2. Hover contrast. Sampling the mock gives hoverComponentBG, and that is what I shipped first. Measured in the running app it is #F2EDE7 on #FCFBF91.13:1, which is not perceivable on a 28px target at 100% zoom (the mock reads clearly because it is a ~2.2× enlargement). I moved to buttonDefaultBG (1.26:1), the fill the add-reaction bubble beside this prompt already uses, so the state is actually visible. No neutral fill in the light palette reaches 3:1 — the strongest is buttonPressedBG at 1.76:1 — so if a more prominent state is wanted, a 1px border would read far better than any fill. Happy to switch back to hoverComponentBG if mock fidelity is preferred.

Fixed Issues

$ #96775
PROPOSAL: #96775 (comment)

Tests

  1. Open any chat with Concierge and ask a question, e.g. How do I submit an expense?
  2. Verify no prompt appears under the greeting or under your own message
  3. Wait for the reply — verify Was that response useful? 👍 👎 appears beneath it
  4. Tap 👍 — verify a real 👍 1 reaction pill appears, the prompt is replaced by Thanks for the feedback!, and the thanks fades after a few seconds
  5. Ask another question — verify the prompt moves to the new reply and the older one keeps only its reaction pill
  6. Tap 👎 — verify a real 👎 1 pill appears and no thread is created by the client (the N Replies indicator arrives from the backend)
  7. Reload — verify the prompt stays hidden on both messages
  8. Remove the reaction from the pill — verify the prompt becomes eligible again
  9. Web only: hover a thumb and verify the tooltip and the background fill; repeat in dark mode
  • Verify that no errors appear in the JS console

Offline tests

  1. Go offline
  2. Tap 👍 on the latest Concierge reply
  3. Verify the reaction pill appears and the prompt hides immediately — toggleEmojiReaction writes optimistically

QA Steps

Same as Tests.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
android-native.mp4
Android: mWeb Chrome
android-mweb.mp4
iOS: Native
ios-native.mp4
iOS: mWeb Safari
ios-mweb.MOV
MacOS: Chrome / Safari
chrome-web.mp4
safari-web.mp4

Renders "Was that response useful?" with two thumbs beneath the newest
Concierge-authored comment. Each thumb writes a real emoji reaction and
nothing else -- the backend reads the reaction and, on a thumbs down,
opens the feedback thread itself. Because the prompt is gated on that
same reaction it resolves optimistically, stays resolved across reloads,
and becomes eligible again if the user retracts the reaction.

Eligibility is decided by getLatestConciergeFeedbackActionID, which
requires the action to exist in Onyx rather than merely look like a
Concierge comment. Two client-built actions are shaped identically to a
finished answer -- the greeting from buildConciergeGreetingReportAction
and the paced reply from buildConciergeDraftReportAction -- but never
reach Onyx, and toggleEmojiReaction bails on both, so a prompt on either
would render buttons that do nothing. The list also stands down entirely
while a synthetic draft is on screen, since the draft's pacing status
flips independently of the server write.
The prompt was suppressed whenever `isSyntheticDraftVisible` was true. That flag stays true until the
paced draft's HTML equals the persisted action's HTML byte for byte, and the two are produced by
different parsers -- the draft by a client-side `getParsedComment`, the persisted one by the server.
When they never converge the flag never clears, so the prompt stayed hidden for the life of the mount
and only appeared after navigating away and back. Observed live in the Concierge DM.

Gate on the pacing status instead, which is what the neighbouring
`shouldDisableContextMenuForConciergeDraft` already uses and which always settles. The window between
pacing finishing and the server write landing is covered by the helper's Onyx-membership check.

While here, drop the helper's fallback to an older answer. If the newest Concierge comment is not in
Onyx the prompt now shows nothing at all, rather than moving back onto the previous reply and asking
the user to rate a message they were not looking at.
The previous commit swapped this gate to the pacing status on the theory that
`isSyntheticDraftVisible` could stick, based on a misread bug report. It does not stick: the effect
above re-seeds the draft from the persisted action, so the reveal target is the persisted HTML and
the two converge by construction.

The swap also cost something. The pacing status clears before the reveal finishes, so the prompt
could appear under an answer whose text was still animating in -- the case this gate exists to avoid.

Keeps the previous commit's other change, which stands on its own: when the newest Concierge comment
is absent from Onyx the helper returns nothing instead of falling back to an older answer.
Hover was being applied through the `style` callback, which only sees React Native's raw `state.hovered`.
`GenericPressable` merges that with its own tracking and applies the result to `hoverStyle`, so move the
fill there (and to `pressStyle`) instead.

Sampling the hover circle in the design comment gives #F1EDE8 on a #FCFBF9 page, which is
`theme.hoverComponentBG` on `theme.appBG`. The fill is meant to be this quiet, so the token stays.

The tooltip in the same mock reads "Useful response", so rename the strings to match. Only the thumbs up
label is mocked; the thumbs down wording is the symmetric counterpart and is worth confirming with design.
The design comment's hover fill samples as `hoverComponentBG`, but that mock sits on a plain white page.
Over the chat surface the token is indistinguishable from its background -- not visible even at 200% zoom
-- so an affordance that is meant to be seen is not. Use the default button surface instead, which is what
a ghost button takes on hover. Worth confirming with design, and a one line change to put back.

The glyph also sat high in the square. It was borrowing the reaction pill's text style, whose line height
is tuned for a container sized by its own padding. Stretching that line box to the thumb's height centres
the box but not the emoji inside it, since emoji carry a tall ascent. Dropping the line height lets the
text keep its natural size and hands centring back to the container's flex alignment.
Reverts the previous commit's switch to the default button surface. The reason given for it -- that the
chat surface is warmer than the page background and swallows `hoverComponentBG` -- was never measured:
neither `chatItem` nor `chatContentScrollView` sets a background, so both inherit `appBG`, which is the
same surface the design comment's mock sits on.

That leaves the design's own token as the right one, and the codebase agrees: `SearchFiltersClearButton`
is the same shape -- transparent, 28px, pill radius -- and hovers to `styles.hoveredComponentBG`. Use that
style directly rather than a local copy of it, so the two stay in step.

The fill is faint at 100% zoom. That is worth raising with design, not worth diverging over.

Keeps the glyph centring fix from the previous commit.
The design comment asked for a hover state on these thumbs. Matching the mock's sampled fill exactly gives
`hoverComponentBG`, which measures 1.13:1 against the chat surface (both verified from the running app:
surface rgb(252,251,249), fill rgb(242,237,231)). On a 28px target that is below what the eye resolves, so
the state Danny asked for does not read at all -- fidelity to the swatch at the cost of the feature.

`buttonDefaultBG` is 1.26:1 and is already the fill on the add-reaction bubble that sits beside this
prompt, so the thumbs match their neighbour and the hover is visible. No neutral fill in the light palette
reaches 3:1 -- the strongest is `buttonPressedBG` at 1.76:1 -- so this is as far as the token set goes.

Worth confirming with design, along with whether a 1px border would suit better: an edge reads far more
readily than a fill at the same contrast.
@oqildev
oqildev requested review from a team as code owners September 6, 2026 17:25
@melvin-bot

melvin-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

Hey, I noticed you changed src/languages/en.ts in a PR from a fork. For security reasons, translations are not generated automatically for PRs from forks.

If you want to automatically generate translations for other locales, an Expensify employee will have to:

  1. Look at the code and make sure there are no malicious changes.
  2. Run the Generate static translations GitHub workflow. If you have write access and the K2 extension, you can simply click: [this button]

Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running:

npx bun ./scripts/generateTranslations.ts --help

Typically, you'd want to translate only what you changed by running npx bun ./scripts/generateTranslations.ts --compare-ref main

@melvin-bot
melvin-bot Bot requested review from DylanDylann and joekaufmanexpensify and removed request for a team and DylanDylann September 6, 2026 17:25
@melvin-bot

melvin-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

@DylanDylann Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 563aa1e016

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread src/pages/inbox/report/ReportActionsList.tsx Outdated
Comment thread src/pages/inbox/report/actionContents/ConciergeFeedbackPrompt.tsx Outdated
Opening a report at a deep link or an old unread anchor renders a single pagination window. The newest
Concierge reply inside that window is not the newest in the report, so the prompt attached to it and
invited a rating of an answer the user had already moved past.

Gate the derivation on `hasNewerActions` in both lists that compute it. Covered by a test that fails
without the gate: the same seeded reply is the feedback target on a fully loaded report and is not one
while newer pages are outstanding.

Reported by Codex on the PR.
`renderThumb` built a nested Tooltip/Pressable/Text tree from inside the prompt's body, which hides the
real render tree from the return statement and leaves the thumb's markup tangled with the prompt's
reaction state. Give it explicit props instead, so the prompt reads as what it renders and the thumb owns
its own styling.

Flagged by the coding-standards reviewer as CLEAN-REACT-PATTERNS-4.
@codecov

codecov Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/CONST/index.ts 91.52% <ø> (ø)
...equestReportView/MoneyRequestReportActionsList.tsx 86.54% <100.00%> (+0.32%) ⬆️
src/hooks/useReportActionsListModel.ts 100.00% <ø> (ø)
src/libs/DebugUtils.ts 69.06% <100.00%> (+0.06%) ⬆️
src/libs/EmojiUtils.tsx 86.13% <ø> (ø)
src/libs/ReportActionsUtils.ts 82.09% <100.00%> (+0.07%) ⬆️
src/pages/inbox/report/ReportActionItem.tsx 90.85% <100.00%> (+0.05%) ⬆️
src/pages/inbox/report/ReportActionsList.tsx 89.58% <100.00%> (+0.14%) ⬆️
...ges/inbox/report/ReportActionsListItemRenderer.tsx 83.33% <100.00%> (+0.98%) ⬆️
...nbox/report/actionContents/ActionContentRouter.tsx 87.70% <ø> (ø)
... and 3 more
... and 19 files with indirect coverage changes

@dubielzyk-expensify

Copy link
Copy Markdown
Contributor

Videos look good to me. I'll run an adhoc though.

For the removal flow. I see that the Concierge message has a thread already. Is this expected? I assumed that only showed up when there was a 👎 added. Also do we even want this ability? I guess if it doesn't change mess with our data in anyways and only shows the latest rating then it's fine? cc @Expensify/design as well

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

🚧 dubielzyk-expensify has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

This comment has been minimized.

@dubielzyk-expensify

Copy link
Copy Markdown
Contributor

What's the spacing between thumbs? 12px? If so can we make it 8? If not, then just leave it.

CleanShot 2026-09-07 at 10 31 02@2x

It also doesn't create a thread on the 👎 , is that expected?

CleanShot 2026-09-07 at 10 31 59@2x

Nevermind. It did appear, but I wouldn't expect to see the 👍 and 👎 on the Please let us know what we can improve. message itself:

CleanShot 2026-09-07 at 10 33 00@2x

@shawnborton

Copy link
Copy Markdown
Contributor

Nevermind. It did appear, but I wouldn't expect to see the 👍 and 👎 on the Please let us know what we can improve. message itself:

Hmm yeah I think this was my understanding as well. Agree with the rest of your comments though.

…thumbs

A thumbs down makes the backend open a thread on the rated message and post its own request for detail
into it. That request is a Concierge comment like any other, so it became the newest one in the thread and
the prompt attached to it -- the user was asked to rate being asked for feedback. Recognise the thread by
the reaction the user left on its parent action and render nothing there.

The thumbs also sat about 10px further apart than the mock. The row's gap separates the label from the
thumbs, which it should, but it was also pushing the two thumbs apart on top of the padding each 28px
target already carries. Group them so they sit flush, as they do in the mock: glyph to glyph goes from
22px to 14px, against the mock's 12.3px.
@oqildev

oqildev commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

@dubielzyk-expensify @shawnborton — all three are addressed in b1501bf.

1 - 👍/👎 on Please let us know what we can improve.: I agreed, and I now recognise the feedback thread by the reaction on its parent action and render nothing there.

2 - Scope: I kept that narrow rather than suppressing the prompt in every thread, since Concierge also answers questions in threads off the DM, so tell me if you'd rather it never appear in one.

3 - Spacing: I measured it at 22px glyph to glyph, not 12, because the row's 8px gap was pushing the thumbs apart on top of the 7px each 28px target carries.

4 - Spacing fix: I grouped the thumbs so they sit flush like the mock, which takes them to 14px against the mock's 12.3px; a literal 8px would need the targets to overlap, so say the word if you'd rather I shrink them.

5 - Thread on the removal flow: that one is expected, an earlier 👎 opened it before I switched to 👍, and per the issue the thread stays as chat history while only the current rating shows.

@DylanDylann

DylanDylann commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Screen.Recording.2026-09-18.at.11.30.40.mov
Android: mWeb Chrome
Screen.Recording.2026-09-18.at.11.05.02.mov
iOS: HybridApp
Screen.Recording.2026-09-18.at.11.31.04.mov
iOS: mWeb Safari
Screen.Recording.2026-09-18.at.11.02.58.mov
MacOS: Chrome / Safari
Screen.Recording.2026-09-18.at.11.00.59.mov

@DylanDylann

Copy link
Copy Markdown
Contributor

@yuwenmemon Regarding the delay in displaying the feedback thread. Currently, the feedback thread report only appears in Onyx if I reopen the report (which triggers the OpenReport command). What do you think about returning the feedback thread report in AddEmojiReaction response?

This is my last concern before approval

…e-feedback-prompt

# Conflicts:
#	src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
@yuwenmemon

Copy link
Copy Markdown
Contributor

I have a PR in for this: https://github.com/Expensify/Auth/pull/24549

I think it's probably safe to send this for now if that's the only blocker then?

@yuwenmemon yuwenmemon 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.

Thanks!

@yuwenmemon
yuwenmemon merged commit 7d60165 into Expensify:main Sep 18, 2026
35 of 36 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🚧 yuwenmemon has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/yuwenmemon in version: 9.4.90-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor

🤖 Yes — help site changes were required. This PR added a user-facing Was that response useful? prompt with 👍 / 👎 buttons under the newest Concierge response, and nothing under docs/articles described it.

Draft help site PR: Docs updates for E/A#100454 add article on rating Concierge responses

What it changes

It's a separate article rather than a new section in Concierge-Basics.md because the authoring guidelines require one primary workflow per article, and Concierge-Basics.md already covers several.

Copy was verified in the running app, not read off the diff: the prompt renders as Was that response useful?, the two buttons expose Useful response and Not useful response, and 👍 adds a 👍 1 reaction pill and swaps the row for Thanks for the feedback!.

Two things to check, and one thing I couldn't do
  1. Unverified line. The article says a Not useful response rating may get a threaded follow-up from Concierge. That comes from your PR description (the backend opens the feedback thread) — I only exercised 👍 in the app, so confirm it or tell me to drop it.
  2. First reply in a fresh thread. The prompt did not appear under the very first Concierge reply in a brand-new thread; it appeared reliably from the second reply onward. Might be the hasNewerActions gating in src/pages/inbox/report/ReportActionsList.tsx not settling yet. Not a docs problem, but worth a look since the article tells members the prompt appears under the most recent response.
  3. I couldn't assign the PR to you. GitHub reports oqildev as not assignable on Expensify/App (read access only), so the assignee field is empty. The HelpDot label is applied and PullerBear is requested. Please self-assign, or ask someone with write access to assign you.

@oqildev, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR Ready for review

@mitarachim

Copy link
Copy Markdown

Deploy Blocker #101671 was identified to be related to this PR.

@mitarachim

Copy link
Copy Markdown

Deploy Blocker #101672 was identified to be related to this PR.

@mitarachim

Copy link
Copy Markdown

Deploy Blocker issue #101673 is repro on all PRs. Could you please double check if it's not introduced by #100454

@mitarachim

Copy link
Copy Markdown

Deploy Blocker #101675 was identified to be related to this PR.

@mitarachim

Copy link
Copy Markdown

Deploy Blocker #101676 was identified to be related to this PR.

@mitarachim

Copy link
Copy Markdown

Hello @oqildev, we found an issue regarding Feedback prompt is displayed below under the greeting , and we believe this should be considered a Fail in Step 2.

Screenshot 2026-09-21 at 2 53 54 PM

Steps :

  1. Open the staging.new.expensify.com website.
  2. Sign up with a new account.
  3. Select any option during onboarding.
  4. After completing onboarding, navigate to Concierge chat.
  5. Note that a "Was that response useful" prompt appears below greeting.
Bug7263671_1789776597043.Prompt.mp4

However, we’re not 100% sure, since the video in the PR also shows something similar.

Could you please confirm whether this behavior is expected or not?

cc : @joekaufmanexpensify @DylanDylann @yuwenmemon

@izarutskaya

Copy link
Copy Markdown

@oqildev Let us know if we need to create issue for this?

@oqildev

oqildev commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@mitarachim @izarutskaya
Thanks for checking. That isn't the greeting my test step meant: the client-built greeting is "Hi there, how can I help?", it never reaches Onyx and never gets the prompt. In your video the prompt sits under "It's great to meet you!", which is a real Concierge comment from onboarding, so it's eligible per the issue: the prompt goes under the most recent Concierge-authored message in any chat, with no agentZero filtering.

My step 2 wording was ambiguous and I'll reword it. No issue needed unless we decide the prompt shouldn't appear under the onboarding messages, which is a product call rather than a bug, cc @joekaufmanexpensify.

@joekaufmanexpensify

Copy link
Copy Markdown
Contributor

Yeah, I agree. I think the "greeting" in the QA steps is not referring to onboarding. Based on the description in the issue, I would say this seems expected, as it says this should cover all concierge messages. In fact, I could see it potentially being a helpful source of feedback on onboarding as the customer may often associate it with the entire set of onboarding messages.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/lakchote in version: 9.4.90-2 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

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.