Skip to content

[Due for payment 2026-11-03] [$175] Full category description is displayed shortly instead of the rule title #104688

Open

Description

@applause-bot

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: v9.5.16-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #103810
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: Windows 11 Home / Chrome
App Component: Workspace Settings

Action Performed:

Preconditions: Control workspace has been created. Rules have been added to the workspace. User is logged in as an Admin.

  1. Open https://staging.new.expensify.com/
  2. Open workspace overwiev
  3. Click Rules
  4. Select Agents tab
  5. Click Add agent rule
  6. Scroll down to the Categories section
  7. Select one of the suggested rules
  8. Click Next and select Create rule
  9. Refresh the page

Expected Result:

The rule title should be displayed immediately after creation, without requiring a page refresh.

Actual Result:

After creating the agent rule, the full description is displayed instead of the rule title. The correct title is displayed in a bit.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome Safari

Screenshots/Videos

Bug7292580_1792616673302.Recording_2026-10-21_225417.1.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Julia Ponikarchuk
Bug ID: 7292580

Upwork Automation - Do Not Edit
Issue OwnerCurrent Issue Owner: @cretadn22

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 22, 2026
  2. applause-bot commented on Oct 22, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/812b10a920d32b640e52df37c67a54b5254c8c1e8683edfcd61f6074d741c053

  3. MelvinBot commented on Oct 22, 2026

    @MelvinBot
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    After you create an agent rule from a suggestion, the Agents list shows the rule's full prompt instead of its short title. The title only appears after a page refresh.

    What is the root cause of that problem?

    The app never sets a title when it creates an agent rule, so the list falls back to the prompt.

    The server stores a generated title, so a refresh shows it. The AddPolicyAgentRule response does not seem to push that title back to the client.

    What changes do you think we should make in order to solve the problem?

    1. Add an optional title argument to addPolicyAgentRule. Include it in the optimistic rule value when it is present.
    2. In AddAgentRulePage, remember the selected suggestion. In saveRule, pass its title only if the saved prompt still matches the suggestion's prompt. If the admin edited the prompt in the Write tab, don't pass the title.
    3. Add a test in tests/ui/AddAgentRulePageTest.tsx for both cases: unchanged prompt sends the title, and edited prompt doesn't.

    What alternative solutions did you explore? (Optional)

    Have the backend return the generated title in the AddPolicyAgentRule response. That also fixes rules typed by hand in the Write tab, which likely show the same symptom (not tested). That change is outside the App repo and needs an internal engineer.

    Investigation details

    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/104688) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.


    view run

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 22, 2026
  5. melvin-bot commented on Oct 22, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @cretadn22 (External)

  6. changed the title [-]Full category description is displayed instead of the rule title until page refresh[/-] [+][$175] Full category description is displayed instead of the rule title until page refresh[/+] on Oct 22, 2026
  7. melvin-bot commented on Oct 22, 2026

    @melvin-bot
  8. changed the title [-][$175] Full category description is displayed instead of the rule title until page refresh[/-] [+][$175] Full category description is displayed shortly instead of the rule title[/+] on Oct 22, 2026
  9. melvin-bot commented on Oct 22, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  10. bonnhatnguyen commented on Oct 22, 2026

    @bonnhatnguyen

    Contributor details
    Your Expensify account email: [email protected]
    Upwork Profile Link: https://www.upwork.com/freelancers/~0139ed4098bdc50182

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    When creating an agent rule from a suggestion, the Rules list row temporarily displays the full rule prompt/description instead of the concise rule title until a page refresh or server re-fetch occurs.

    What is the root cause of that problem?

    1. In src/libs/AgentRulesUtils.ts:24, the display title for an agent rule in the list resolves to:
      return (rule.title ?? rule.prompt).replaceAll(/\s+/g, ' ').trim();
    2. In src/libs/actions/Policy/Rules.ts:410-440, addPolicyAgentRule does not accept an optional title parameter and only sets prompt in optimisticData:
      [agentRuleID]: {
          ruleID: agentRuleID,
          created: new Date().toISOString(),
          prompt,
          pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
      }
    3. In src/pages/workspace/rules/AgentRules/AddAgentRulePage.tsx:164, when saveRule is called, it passes only values[INPUT_IDS.PROMPT] to addPolicyAgentRule.
      Because title is absent from the optimistic Onyx update, AgentRulesUtils falls back to rule.prompt (the full multiline description), causing the flash/glitch until the server-generated title is loaded.

    What changes do you think we should make in order to solve the problem?

    1. In src/libs/actions/Policy/Rules.ts:
      Update addPolicyAgentRule to accept an optional title?: string parameter and include it in optimisticData:

      -function addPolicyAgentRule(policyID: string, agentRuleID: string, prompt: string) {
      +function addPolicyAgentRule(policyID: string, agentRuleID: string, prompt: string, title?: string) {
           ...
           optimisticData: [
               {
                   onyxMethod: Onyx.METHOD.MERGE,
                   key: policyKey,
                   value: {
                       rules: {
                           agentRules: {
                               [agentRuleID]: {
                                   ruleID: agentRuleID,
                                   created: new Date().toISOString(),
                                   prompt,
      +                            title,
                                   pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
                               },
                           },
                       },
                   },
               },
           ],
    2. In src/pages/workspace/rules/AgentRules/AddAgentRulePage.tsx:
      Use useSuggestedAgentRules to resolve the matching suggestion's title:

      + import useSuggestedAgentRules from '@hooks/useSuggestedAgentRules';
      ...
      + const {data: suggestions} = useSuggestedAgentRules();

      In saveRule:

      const matchingSuggestion = suggestions.find((s) => s.prompt.trim() === values[INPUT_IDS.PROMPT]?.trim());
      addPolicyAgentRule(policyID, agentRuleID, values[INPUT_IDS.PROMPT], matchingSuggestion?.title);

      Why this solution is optimal:

      • If the admin selected a suggestion and did not edit the prompt, matchingSuggestion?.title provides the immediate, exact title in the optimistic state with zero flicker.
      • If the admin edited the prompt or typed a custom rule in the Write tab, matchingSuggestion is undefined, preserving standard server-side title generation without any mismatch.
      • It requires zero extra local state or FormProvider changes, and handles draft restore seamlessly.

    What alternative solutions did you explore? (Optional)

    • Storing selectedSuggestion in local component state or form draft: Rejected because it introduces additional state tracking and does not handle cases where the user navigates between tabs or partially edits the text. Matching against suggestions based on the final trimmed prompt is clean, stateless, and deterministic.

    What automated tests can you add to prevent this from re-occurring?

    In tests/ui/AddAgentRulePageTest.tsx:

    • Add a test verifying that creating an agent rule from a suggestion immediately sets title in the optimistic policy Onyx state (rules.agentRules[id].title === suggestion.title).
    • Add a test verifying that saving an edited/custom prompt passes title: undefined, relying on server title generation.
  11. melvin-bot commented on Oct 22, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  12. Abdallah-1551 commented on Oct 22, 2026

    @Abdallah-1551

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    When an admin creates an agent rule from a suggested rule (Workspace > Rules > Agents > Add agent rule), the new row in the Agents list shows the full multi-line prompt instead of the short rule title. The correct title only appears after the server data arrives or the page is refreshed. The title should be shown immediately after creation.

    What is the root cause of that problem?

    The client never sets a title on the optimistic rule, so the list falls back to the prompt.

    • src/libs/AgentRulesUtils.ts builds the row text from rule.title ?? rule.prompt, so a missing title makes it show the prompt.
    • addPolicyAgentRule in src/libs/actions/Policy/Rules.ts only accepts prompt. Its optimistic Onyx value is {ruleID, created, prompt, pendingAction: ADD}, with no title.
    • Each suggestion already has a title, but AddAgentRulePage.tsx only keeps suggestion.prompt in the form, and saveRule passes only values[INPUT_IDS.PROMPT].
    • The real title is generated server-side and arrives later, which causes the flash.

    This is not a regression from #103810. The create flow has never set a title.

    What changes do you think we should make in order to solve the problem?

    1. src/libs/actions/Policy/Rules.ts: accept an optional title and use it only for the optimistic data.

    -function addPolicyAgentRule(policyID: string, agentRuleID: string, prompt: string) {
    +function addPolicyAgentRule(policyID: string, agentRuleID: string, prompt: string, title?: string) {
     ...
       [agentRuleID]: {
           ruleID: agentRuleID,
           created: new Date().toISOString(),
           prompt,
    +      ...(title ? {title} : {}),
           pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
       },
    • Spread title conditionally so no title: undefined is merged into Onyx.
    • Do not add title to the API params. The server keeps generating the canonical title, and its response overwrites the optimistic one.
    • failureData needs no change because it already removes the optimistic rule.

    2. src/pages/workspace/rules/AgentRules/AddAgentRulePage.tsx: resolve the title from the suggestion that matches the saved prompt.

    const {data: suggestions} = useSuggestedAgentRules(); // same source the page already uses for the suggestion list
    
    const saveRule = (values) => {
        const prompt = values[INPUT_IDS.PROMPT];
        const matchingSuggestion = suggestions.find((suggestion) => suggestion.prompt.trim() === prompt?.trim());
        addPolicyAgentRule(policyID, agentRuleID, prompt, matchingSuggestion?.title);
        ...
    };

    I chose this stateless match over tracking the selected suggestion for these reasons:

    • If the admin picks a suggestion and leaves it unchanged, the exact title is available optimistically and the row shows no flicker.
    • If the admin edits the prompt or writes a custom one in the Write tab, nothing matches. No title is passed, so we never show a title that doesn't describe the prompt, and the server generates it as it does today.
    • It adds no new component state. It also works when the form draft is restored or the admin switches tabs.

    Known limitation: custom prompts typed by hand can still briefly show the prompt. Fixing that needs a backend change, such as returning the generated title in the AddPolicyAgentRule response. That is outside this issue's client scope and can be raised separately.

    What alternative solutions did you explore? (Optional)

    • Store selectedSuggestion in component state or the form draft. Rejected. It adds state that must be cleared or invalidated when the user edits the prompt, switches tabs, or the draft is restored, and the prompt match gives the same result more simply.
    • Always pass the selected suggestion's title, even if the prompt was edited. Rejected. It would show a title that no longer matches the content.
    • Backend returns the title in the add response. This would also cover custom prompts, but it is not a client fix and needs an internal engineer. It is worth a follow-up.
    • Truncate or normalize the prompt as a fallback in the list. Rejected. It still wouldn't show the real title and would only hide the symptom.

    Testing

    Automated tests in tests/ui/AddAgentRulePageTest.tsx, plus an action-level test in the Rules actions tests:

    1. Select a suggestion and tap Next, then Create rule. Assert that addPolicyAgentRule is called with suggestion.title, and that the optimistic policy rules.agentRules[id].title equals suggestion.title.
    2. Select a suggestion, edit the prompt in the Write tab, then create the rule. Assert that no title is passed and the optimistic rule has no title key.
    3. Write a fully custom prompt and create the rule. Assert that no title is passed.
    4. Check that the API request params do not include title.

    Manual tests:

    1. Follow the repro steps: Workspace > Rules > Agents > Add agent rule, pick a suggestion under Categories, Next, Create rule. The list row shows the short title immediately, with no flash of the full description, and still shows it after a refresh.
    2. Repeat after editing the suggestion text. The row falls back to the prompt until the server title arrives, and then updates to it.
    3. Simulate an offline create. The row shows the title with the pending (ADD) styling. Going back online keeps the row and swaps in the server title.
    4. Simulate a failed request. The optimistic rule is removed and the error is shown as before.
  13. 5 remaining items

  14. melvin-bot commented on Oct 26, 2026

    @melvin-bot

    Triggered auto assignment to @marcochavezf, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

  15. changed the title [-][$175] Full category description is displayed shortly instead of the rule title[/-] [+][Due for payment 2026-11-03] [$175] Full category description is displayed shortly instead of the rule title[/+] on Oct 27, 2026
  16. melvin-bot commented on Oct 27, 2026

    @melvin-bot

    @cretadn22

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.23-3 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-11-03. 🎊

    The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]. If no checklist is needed for this issue, you can click: [no checklist button]

  17. cretadn22 commented on Oct 29, 2026

    @cretadn22
    Contributor

    BugZero Checklist:

    • [Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to the comment on the PR: N/A
      Link to the comment on the Issue: N/A

    This doesn't appear to be a regression, it looks like a new requirement. When we implemented this, we didn't consider the behavior a bug.

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion: N/A

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

    • [BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.

      Link to issue:

    Regression Test Proposal

    Test:

    Preconditions: Control workspace has been created. Rules have been added to the workspace. User is logged in as an Admin.

    1. Open workspace overview
    2. Click Rules
    3. Select Agents tab
    4. Click Add agent rule
    5. Scroll down to the Categories section
    6. Select one of the suggested rules
    7. Click Next and select Create rule
    8. The default rule title should be displayed immediately after creation without requiring a page refresh
    9. Waiting a moment or refreshing the page will display the newly generated title.

    Do we agree 👍 or 👎

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

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.ExternalAdded to denote the issue can be worked on by a contributorWeeklyKSv2

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions