Skip to content

Make Use suggestion the main button when the AI rules builder refuses a rule - #104942

Open
yuwenmemon wants to merge 6 commits into
mainfrom
yuwen-683438-tryThisInsteadButton
Open

yuwenmemon wants to merge 6 commits into
mainfrom
yuwen-683438-tryThisInsteadButton

Conversation

@yuwenmemon

@yuwenmemon yuwenmemon commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

@JS00001 @rushatgabhane

Explanation of Change

When the AI rules builder refuses a description, the small Try this instead button didn't read as related to the suggestion. Following Danny's proposal, the refusal drops its "Rules can't do that." header, the explanation ends with "Try the suggestion below instead:", the suggestion shows in quotes, and a green Use suggestion button sits beside a neutral second button.

On New rule, the second button reads Create anyway and drafts the admin's own description as an agent rule, instead of sending it back to Concierge to be refused again. The editors' Describe modal has no agent rule to fall back to, so it keeps Next.

The form's submit button only comes in green or red, so FormProvider gets an opt-in isSubmitButtonNeutral prop. The backend sends impossible answers only after Web-Expensify#56886 merges, so the test steps swap in an answer locally.

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/683438
PROPOSAL: N/A

Tests

Precondition: Paste the snippet below into the dev console after each page load.

  1. As a workspace admin on a Control workspace, open Rules > New rule.
  2. Run answer = {state: 'impossible', reason: 'noCapability', explanation: "Agents can't send text messages.", suggestedPrompt: 'When a report is submitted, send the approver a direct message that notifies them.'}.
  3. Describe "Text the approver's phone whenever a report is submitted" and tap Next.
  4. Verify the refusal has no "Rules can't do that." header, the explanation ends with "Try the suggestion below instead:", the suggestion shows in quotes, and a neutral Create anyway and a green Use suggestion sit side by side.
Create anyway and Use suggestion side by side on New rule, with no header above the explanation 5. Tap Create anyway. 6. Verify the agent rule page opens with your own description and a banner that includes the explanation. Agent rule page after Create anyway 7. Tap Back, then Discard changes, and repeat steps 2 and 3. 8. Run `answer = {state: 'agentRule', agentRulePrompt: 'When an expense report is submitted, send its approver a direct message notifying them that the report was submitted.'}`, then tap Use suggestion. 9. Verify the agent rule page opens with the reworded instruction. Agent rule page after Use suggestion 10. Go back to New rule, open Flag for review, tap Describe, run the step 2 answer again, and describe the same rule. 11. Verify the modal shows a neutral Next and a green Use suggestion side by side. Next and Use suggestion side by side in the editor's Describe modal, with no header above the explanation 12. Run `answer = {state: 'impossible', reason: 'noCapability', explanation: "Agents can't send text messages.", suggestedPrompt: ''}` and describe the rule again. 13. Verify only a green Next shows, because there is no suggestion to try.
Console snippet that swaps the GenerateRule answer locally
window.answer = null;
const originalSet = Onyx.set;
const originalMerge = Onyx.merge;
const originalUpdate = Onyx.update;
const swap = (value) => (value?.generationID && value.state && window.answer ? {generationID: value.generationID, ...window.answer} : value);
Onyx.set = (key, value) => originalSet(key, key === 'generatedRule' ? swap(value) : value);
Onyx.merge = (key, value) => originalMerge(key, key === 'generatedRule' ? swap(value) : value);
Onyx.update = (updates) => originalUpdate(updates.map((update) => (update.key === 'generatedRule' ? {...update, value: swap(update.value)} : update)));
  • Verify that no errors appear in the JS console

Offline tests

  1. Repeat Tests steps 1–4, then go offline.
  2. Verify Create anyway and Use suggestion are both disabled, the same as Next on New rule while offline.

QA Steps

Refusals reach staging only after Web-Expensify#56886 is live. Then:

  1. Open Rules > New rule as a workspace admin on a Control workspace.
  2. Describe "Text the approver's phone whenever a report is submitted" and tap Next.
  3. Verify the suggestion shows in quotes, with a neutral Create anyway and a green Use suggestion side by side.
  4. Tap Create anyway and verify the agent rule page opens with your description.
  5. Go back, describe the rule again, tap Use suggestion, and verify the agent rule page opens with a rule that messages the approver.
  • 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 verified any copy / text that was added to the app 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 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 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.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • 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: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

@yuwenmemon
yuwenmemon requested review from a team as code owners October 25, 2026 22:35
@melvin-bot
melvin-bot Bot requested a review from Pujan92 October 25, 2026 22:35
@melvin-bot

melvin-bot Bot commented Oct 25, 2026

Copy link
Copy Markdown

Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers!

@melvin-bot
melvin-bot Bot requested review from garrettmknight and removed request for a team October 25, 2026 22:35
@melvin-bot

melvin-bot Bot commented Oct 25, 2026

Copy link
Copy Markdown

@Pujan92 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]

@melvin-bot
melvin-bot Bot removed the request for review from a team October 25, 2026 22:35
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-25T22:46:29.950156Z 97068b7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 97068b76d3

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

size={CONST.BUTTON_SIZE.LARGE}
onPress={() => describeSuggestedRule(refusalSuggestedPrompt)}
isDisabled={isOffline}
style={styles.flex1}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Let the translated primary action use enough width

On narrow mobile screens, especially in locales with longer shipped labels such as German or Japanese, this flex1 combines with the submit button's flex1 to give each action only half of the row. Because Button.Text defaults to a single line, “Try this instead” is then ellipsized even though the much shorter Next button has unused space. Allow the buttons to size according to their labels or stack/wrap them at narrow widths.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(Yuwen's Agent) Fixed in fc22789. The two buttons now size to their labels and share the row, and they wrap onto two full-width rows when a translated label doesn't fit beside the other one.

JS00001
JS00001 previously approved these changes Oct 26, 2026
@dannymcclain

Copy link
Copy Markdown
Contributor

I can't quite put my finger on it exactly, but the suggestion flow feels a little confusing to me. The "Try this instead" button doesn't feel super related to the suggestion.

CleanShot 2026-10-26 at 8 06 49 AM@2x

Would love to get @Expensify/design's thoughts here, but could we do something like this to make it more clear?

Agents can't send text messages. Try the suggestion below instead:

"When a report is submitted, send the approver a direct message that notifies them"
[ Create anyway / Next ] [ Use suggestion ]

@shawnborton

Copy link
Copy Markdown
Contributor

Totally agree with that Danny, I really like what you are proposing above.

@yuwenmemon yuwenmemon changed the title Make Try this instead the main button when the AI rules builder refuses a rule Make Use suggestion the main button when the AI rules builder refuses a rule Oct 26, 2026
@yuwenmemon

Copy link
Copy Markdown
Contributor Author

@dannymcclain @shawnborton updated! Check out the new screenhots in the PR description

@shawnborton

Copy link
Copy Markdown
Contributor

I think Danny was suggesting to kinda combine this part rather than have it on two lines? But will let him confirm!
CleanShot 2026-10-26 at 9 10 43 PM@2x

@dubielzyk-expensify

Copy link
Copy Markdown
Contributor

Really like that suggestion, Danny.

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

@dannymcclain can you confirm? Remove the "Rules can't do that." header altogether?

@garrettmknight

Copy link
Copy Markdown
Contributor

Might be moot if we're removing, but I was thinking of updating to 'Rules can't do that yet' and capturing the request somewhere to review? Could be a really great way to figure out what rules we don't support that people are asking for. Regardless of the copy, can we store these unsupported requests somewhere?

@dannymcclain

Copy link
Copy Markdown
Contributor

Yeah I was suggesting removing the "Rules can't do that" header altogether. It feels a little... crude? Unrefined? I dunno how to say it haha, it just feels like we're REALLY calling attention to the limitation when I don't think we need to be so overt about it.

I don't feel super duper strongly if others disagree - I just think it stands out in a negative way and we don't really need it.

@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

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.

Files with missing lines Coverage Δ
src/components/Form/FormWrapper.tsx 88.07% <100.00%> (-2.41%) ⬇️
src/components/FormAlertWithSubmitButton.tsx 97.91% <100.00%> (+0.77%) ⬆️
src/pages/workspace/rules/DescribeRuleForm.tsx 94.83% <100.00%> (+0.77%) ⬆️
... and 4393 files with indirect coverage changes

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

Okay updated!

@dannymcclain

Copy link
Copy Markdown
Contributor

LGTM!

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

@JS00001 / @rushatgabhane bump here!

@Pujan92

Pujan92 commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

@yuwenmemon do I need to review this?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants