Skip to content

Handle agent rule and impossible answers in the AI rules builder - #103952

Draft
yuwenmemon wants to merge 26 commits into
yuwen-683436-describeRuleAgentFallbackfrom
yuwen-683438-describeRuleAgentOutcomes
Draft

yuwenmemon wants to merge 26 commits into
yuwen-683436-describeRuleAgentFallbackfrom
yuwen-683438-describeRuleAgentOutcomes

Conversation

@yuwenmemon

@yuwenmemon yuwenmemon commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

HOLD ON #103810

Once Send RuleBot's capabilities and triggers to the AI rules builder ships, GenerateRule answers agentRule or impossible where it said unsupported, and today's app would show a generic error. This handles both answers.

From New rule, an agentRule answer drafts the agent rule with the reworded instruction, and the banner explains how it differs from the request. Inside a rule editor it shows the existing unsupported error. An impossible answer stays on the form, on New rule or in an editor's modal, with the reason, the explanation and a suggested description, and Try this instead resubmits the suggestion.

The agent rule page reads the explanation from the generatedRule answer by its generationID. Therefore closing the modal no longer clears that key, and the next request clears it. Deploy order: this App version reaches both stores first. Then Web-Expensify#56886 merges with MINIMUM_APP_VERSION raised to it.

Fixed Issues

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

Tests

The backend sends these answers only after Web-Expensify#56886, so the snippet below swaps the backend's answer for answer in the browser and keeps its generationID.

Precondition: Enable the describeRule beta on the test account.

  1. As a workspace admin on a Control workspace, open Rules > New rule, and paste the snippet into the dev console.
  2. Run answer = {state: 'impossible', reason: 'noCapability', explanation: "Rules can't send text messages.", suggestedPrompt: 'When a report is submitted, comment on it and mention the approver'}.
  3. Describe "Text the approver whenever a report is submitted" and tap Next.
  4. Verify New rule stays open with "Rules can't do that.", the explanation, the suggestion and Try this instead under the text box.
Impossible answer on New rule 5. Run `answer = {state: 'agentRule', agentRulePrompt: 'Hold any gift card expense and ask the submitter to explain it', explanation: "Agent rules can't block a card charge, so this holds the expense after it posts."}`, then tap Try this instead. 6. Verify the agent rule page opens with the reworded instruction and a banner that includes the explanation. Agent rule answer: reworded instruction and explanation banner 7. Tap Back, then Discard changes. Go back to New rule, open Flag for review, tap Describe, run the step 5 answer again, and describe "Block gift cards". 8. Verify "That rule isn't supported yet" appears and the editor form is unchanged. Agent rule answer inside an editor: unsupported error
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. Go offline on New rule and describe a rule.
  2. Verify Next stays disabled and nothing is sent.

QA Steps

Precondition: Enable the describeRule beta on the test account.

Staging gets the new answers only after Web-Expensify#56886, which waits for this release. Until then, check that the describe flow still works:

  1. Open a Control workspace > Rules > New rule, and describe "Flag meals expenses over $500 for review" under "Or just describe it below".
  2. Verify the Flag for review editor opens prefilled.
  3. Go back and describe "Block gift cards and require receipts over $50".
  4. Verify the agent rule page opens with the description prefilled.
  • 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

@OSBotify

This comment has been minimized.

# Conflicts:
#	src/languages/de.ts
#	src/languages/el.ts
#	src/languages/en.ts
#	src/languages/es.ts
#	src/languages/fr.ts
#	src/languages/it.ts
#	src/languages/ja.ts
#	src/languages/nl.ts
#	src/languages/pl.ts
#	src/languages/pt-BR.ts
#	src/languages/zh-hans.ts
@OSBotify

Copy link
Copy Markdown
Contributor

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

View the translation diff
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 5d5bdc9a..67ec4e7b 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -8724,7 +8724,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 createRule: 'Regel erstellen',
                 fallbackBanner:
                     'Das ist keine Standardregel, daher haben wir sie als Agentenregel entworfen. Agentenregeln greifen, nachdem sich eine Ausgabe oder ein Bericht ändert, zum Beispiel indem sie die Ausgabe zurückhalten oder den Bericht ablehnen.',
-                fallbackBannerWithExplanation: (explanation: string) => `Das ist keine Standardregel, daher haben wir sie als Agentenregel entworfen. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `Dies ist keine Standardregel, daher haben wir sie als Agentenregel formuliert. ${explanation}`,
             },
             tabs: {
                 general: 'Allgemein',
@@ -8806,12 +8806,12 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     multipleRules: 'Bitte eine Regel nach der anderen – beschreibe eine einzelne Regel, z. B.: Einzelhandelskäufe auf allen Karten blockieren.',
                 },
                 impossible: {
-                    noTrigger: 'Regeln können nicht durch dieses Ereignis ausgelöst werden.',
-                    noCapability: 'Das können Regeln nicht.',
-                    missingData: 'Expensify hat diese Informationen nicht.',
+                    noTrigger: 'Regeln können nicht bei diesem Ereignis beginnen.',
+                    noCapability: 'Regeln können das nicht.',
+                    missingData: 'Expensify hat diese Information nicht.',
                     retroactive: 'Regeln gelten nur für neue Aktivitäten.',
-                    historyLimit: 'Regeln können nicht so weit zurückblicken.',
-                    tryThisInstead: 'Stattdessen das versuchen',
+                    historyLimit: 'Regeln können nicht so weit in die Vergangenheit zurückblicken.',
+                    tryThisInstead: 'Versuchen Sie es stattdessen damit',
                 },
             },
             expenseDefaultsTable: {
diff --git a/src/languages/el.ts b/src/languages/el.ts
index ad639e01..8f0a53ba 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -8894,12 +8894,12 @@ ${reportName}`,
                     multipleRules: 'Έναν κανόνα τη φορά — δοκιμάστε να περιγράψετε έναν μόνο κανόνα, π.χ.: αποκλεισμός αγορών λιανικής σε όλες τις κάρτες.',
                 },
                 impossible: {
-                    noTrigger: 'Οι κανόνες δεν μπορούν να ξεκινήσουν από αυτό το συμβάν.',
+                    noTrigger: 'Οι κανόνες δεν μπορούν να ξεκινούν από αυτό το συμβάν.',
                     noCapability: 'Οι κανόνες δεν μπορούν να το κάνουν αυτό.',
-                    missingData: 'Το Expensify δεν έχει αυτές τις πληροφορίες.',
+                    missingData: 'Η Expensify δεν έχει αυτές τις πληροφορίες.',
                     retroactive: 'Οι κανόνες ισχύουν μόνο για νέα δραστηριότητα.',
                     historyLimit: 'Οι κανόνες δεν μπορούν να κοιτάξουν τόσο πίσω.',
-                    tryThisInstead: 'Δοκιμάστε αυτό',
+                    tryThisInstead: 'Δοκιμάστε αυτό αντί για αυτό',
                 },
             },
             expenseDefaultsTable: {
@@ -9185,7 +9185,7 @@ ${reportName}`,
                 createRule: 'Δημιουργία κανόνα',
                 fallbackBanner:
                     'Αυτός δεν είναι τυπικός κανόνας, οπότε τον συντάξαμε ως κανόνα πράκτορα. Οι κανόνες πράκτορα ενεργούν αφού αλλάξει μια δαπάνη ή μια αναφορά, για παράδειγμα θέτοντας τη δαπάνη σε αναστολή ή απορρίπτοντας την αναφορά.',
-                fallbackBannerWithExplanation: (explanation: string) => `Αυτός δεν είναι τυπικός κανόνας, οπότε τον συντάξαμε ως κανόνα πράκτορα. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `Αυτός δεν είναι ένας τυπικός κανόνας, οπότε τον συντάξαμε ως κανόνα αναπληρωτή. ${explanation}`,
                 suggestionsTab: 'Προτεινόμενο',
                 writeTab: 'Επεξεργασία',
                 findSuggestion: 'Βρείτε έναν κανόνα',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 7b32f0dc..6d3548fe 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -8729,7 +8729,7 @@ ${reportName}`,
                 createRule: 'Crear regla',
                 fallbackBanner:
                     'Esta no es una regla estándar, así que la redactamos como regla de agente. Las reglas de agente actúan después de que cambia un gasto o un informe, por ejemplo, reteniendo el gasto o rechazando el informe.',
-                fallbackBannerWithExplanation: (explanation: string) => `Esta no es una regla estándar, así que la redactamos como regla de agente. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `Esta no es una regla estándar, así que la redactamos como una regla de agente. ${explanation}`,
             },
             tabs: {
                 general: 'General',
@@ -8811,11 +8811,11 @@ ${reportName}`,
                     multipleRules: 'Una regla a la vez, por favor. Prueba a describir una sola regla, como: bloquear compras en comercios minoristas en todas las tarjetas.',
                 },
                 impossible: {
-                    noTrigger: 'Las reglas no pueden empezar a partir de ese evento.',
+                    noTrigger: 'Las reglas no pueden comenzar a partir de ese evento.',
                     noCapability: 'Las reglas no pueden hacer eso.',
                     missingData: 'Expensify no tiene esa información.',
                     retroactive: 'Las reglas solo se aplican a la actividad nueva.',
-                    historyLimit: 'Las reglas no pueden revisar tan atrás.',
+                    historyLimit: 'Las reglas no pueden retroceder tanto.',
                     tryThisInstead: 'Prueba esto en su lugar',
                 },
             },
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 458065d4..7d3720b4 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -8828,11 +8828,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     multipleRules: 'Une règle à la fois, s’il vous plaît — essayez de décrire une seule règle, comme : bloquer les achats en magasin sur toutes les cartes.',
                 },
                 impossible: {
-                    noTrigger: 'Les règles ne peuvent pas se déclencher à partir de cet événement.',
-                    noCapability: 'Les règles ne peuvent pas faire cela.',
-                    missingData: 'Expensify ne dispose pas de cette information.',
-                    retroactive: 'Les règles s’appliquent uniquement aux nouvelles activités.',
-                    historyLimit: 'Les règles ne peuvent pas remonter aussi loin.',
+                    noTrigger: 'Les règles ne peuvent pas commencer à partir de cet événement.',
+                    noCapability: 'Les règles ne peuvent pas faire ça.',
+                    missingData: 'Expensify n’a pas ces informations.',
+                    retroactive: 'Les règles ne s’appliquent qu’à la nouvelle activité.',
+                    historyLimit: 'Les règles ne peuvent pas remonter aussi loin en arrière.',
                     tryThisInstead: 'Essayez plutôt ceci',
                 },
             },
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 90c352f6..db33b9ca 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -8675,7 +8675,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 createRule: 'Crea regola',
                 fallbackBanner:
                     'Questa non è una regola standard, quindi l’abbiamo preparata come regola agente. Le regole agente intervengono dopo che una spesa o un rapporto cambia, ad esempio mettendo in sospeso la spesa o rifiutando il rapporto.',
-                fallbackBannerWithExplanation: (explanation: string) => `Questa non è una regola standard, quindi l’abbiamo preparata come regola agente. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `Questa non è una regola standard, quindi l’abbiamo redatta come regola dell’agente. ${explanation}`,
             },
             tabs: {
                 general: 'Generale',
@@ -8757,12 +8757,12 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     multipleRules: 'Una regola alla volta, per favore: prova a descrivere una singola regola, ad esempio bloccare gli acquisti al dettaglio su tutte le carte.',
                 },
                 impossible: {
-                    noTrigger: 'Le regole non possono partire da questo evento.',
+                    noTrigger: 'Le regole non possono iniziare da quell’evento.',
                     noCapability: 'Le regole non possono farlo.',
-                    missingData: 'Expensify non dispone di queste informazioni.',
-                    retroactive: 'Le regole si applicano solo alle nuove attività.',
-                    historyLimit: 'Le regole non possono risalire così indietro.',
-                    tryThisInstead: 'Prova invece questo',
+                    missingData: 'Expensify non ha queste informazioni.',
+                    retroactive: 'Le regole si applicano solo alla nuova attività.',
+                    historyLimit: 'Le regole non possono risalire così indietro nel tempo.',
+                    tryThisInstead: 'Prova questo invece',
                 },
             },
             expenseDefaultsTable: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index a886ad7b..6d2a587b 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -8564,7 +8564,7 @@ ${reportName}`,
                 createRule: 'ルールを作成',
                 fallbackBanner:
                     'これは標準ルールではないため、エージェントルールとして下書きしました。エージェントルールは、経費やレポートが変更された後に動作します。たとえば、経費を保留したり、レポートを却下したりします。',
-                fallbackBannerWithExplanation: (explanation: string) => `これは標準ルールではないため、エージェントルールとして下書きしました。${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `これは標準ルールではないため、エージェントルールとして作成しました。${explanation}`,
             },
             tabs: {
                 general: '一般',
@@ -8646,12 +8646,12 @@ ${reportName}`,
                     multipleRules: '一度に1つのルールのみです。「すべてのカードで小売店での購入をブロックする」のように、1つのルールを説明してください。',
                 },
                 impossible: {
-                    noTrigger: 'ルールはそのイベントをきっかけに開始できません。',
-                    noCapability: 'ルールではそれを実行できません。',
-                    missingData: 'Expensify にはその情報がありません。',
+                    noTrigger: 'そのイベントを開始条件としてルールを作成することはできません。',
+                    noCapability: 'ルールではそれはできません。',
+                    missingData: 'Expensify はその情報を持っていません。',
                     retroactive: 'ルールは新しいアクティビティにのみ適用されます。',
-                    historyLimit: 'ルールはそこまで過去をさかのぼれません。',
-                    tryThisInstead: '代わりにこちらを試す',
+                    historyLimit: 'ルールはそれほど前までさかのぼることができません。',
+                    tryThisInstead: '代わりにこちらをお試しください',
                 },
             },
             expenseDefaultsTable: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 7e0678aa..048cda3c 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -8649,7 +8649,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 createRule: 'Regel maken',
                 fallbackBanner:
                     'Dit is geen standaardregel, dus we hebben er een agentregel van gemaakt. Agentregels treden in werking nadat een uitgave of rapport verandert, bijvoorbeeld door de uitgave vast te houden of het rapport af te wijzen.',
-                fallbackBannerWithExplanation: (explanation: string) => `Dit is geen standaardregel, dus we hebben er een agentregel van gemaakt. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `Dit is geen standaardregel, dus we hebben het opgesteld als een agentregel. ${explanation}`,
             },
             tabs: {
                 general: 'Algemeen',
@@ -8731,10 +8731,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     multipleRules: 'Eén regel per keer graag — beschrijf één enkele regel, bijvoorbeeld: retailaankopen op alle kaarten blokkeren.',
                 },
                 impossible: {
-                    noTrigger: 'Regels kunnen niet starten vanaf die gebeurtenis.',
-                    noCapability: 'Regels kunnen dat niet doen.',
+                    noTrigger: 'Regels kunnen niet vanaf die gebeurtenis starten.',
+                    noCapability: 'Regels kunnen dat niet.',
                     missingData: 'Expensify heeft die informatie niet.',
-                    retroactive: 'Regels gelden alleen voor nieuwe activiteit.',
+                    retroactive: 'Regels zijn alleen van toepassing op nieuwe activiteit.',
                     historyLimit: 'Regels kunnen niet zo ver terugkijken.',
                     tryThisInstead: 'Probeer dit in plaats daarvan',
                 },
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 949a810f..4a53bd34 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -8674,7 +8674,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 createRule: 'Utwórz regułę',
                 fallbackBanner:
                     'To nie jest standardowa reguła, więc przygotowaliśmy ją jako regułę agenta. Reguły agenta działają po zmianie wydatku lub raportu, na przykład wstrzymując wydatek lub odrzucając raport.',
-                fallbackBannerWithExplanation: (explanation: string) => `To nie jest standardowa reguła, więc przygotowaliśmy ją jako regułę agenta. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `To nie jest standardowa zasada, więc przygotowaliśmy ją jako zasadę agenta. ${explanation}`,
             },
             tabs: {
                 general: 'Ogólne',
@@ -8756,12 +8756,12 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     multipleRules: 'Jedna reguła naraz — opisz pojedynczą regułę, na przykład: zablokuj zakupy detaliczne na wszystkich kartach.',
                 },
                 impossible: {
-                    noTrigger: 'Reguły nie mogą uruchamiać się od tego zdarzenia.',
-                    noCapability: 'Reguły nie mogą tego zrobić.',
+                    noTrigger: 'Reguły nie mogą zaczynać się od tego zdarzenia.',
+                    noCapability: 'Zasady nie mogą tego zrobić.',
                     missingData: 'Expensify nie ma tych informacji.',
-                    retroactive: 'Reguły dotyczą tylko nowej aktywności.',
+                    retroactive: 'Zasady obowiązują tylko dla nowej aktywności.',
                     historyLimit: 'Reguły nie mogą sięgać tak daleko wstecz.',
-                    tryThisInstead: 'Spróbuj zamiast tego',
+                    tryThisInstead: 'Spróbuj tego zamiast tego',
                 },
             },
             expenseDefaultsTable: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 6387738b..f5890ad7 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -8656,7 +8656,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 createRule: 'Criar regra',
                 fallbackBanner:
                     'Esta não é uma regra padrão, então a redigimos como uma regra de agente. As regras de agente agem depois que uma despesa ou um relatório muda, por exemplo, retendo a despesa ou rejeitando o relatório.',
-                fallbackBannerWithExplanation: (explanation: string) => `Esta não é uma regra padrão, então a redigimos como uma regra de agente. ${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `Esta não é uma regra padrão, então nós a elaboramos como uma regra de agente. ${explanation}`,
             },
             tabs: {
                 general: 'Geral',
@@ -8739,10 +8739,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 },
                 impossible: {
                     noTrigger: 'As regras não podem começar a partir desse evento.',
-                    noCapability: 'As regras não podem fazer isso.',
-                    missingData: 'O Expensify não tem essa informação.',
-                    retroactive: 'As regras se aplicam apenas a novas atividades.',
-                    historyLimit: 'As regras não podem olhar tão para trás.',
+                    noCapability: 'Regras não podem fazer isso.',
+                    missingData: 'A Expensify não tem essa informação.',
+                    retroactive: 'As regras se aplicam apenas à nova atividade.',
+                    historyLimit: 'As regras não conseguem analisar tão longe no passado.',
                     tryThisInstead: 'Tente isto em vez disso',
                 },
             },
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 747b58a0..153d0ee2 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -8350,7 +8350,7 @@ ${reportName}`,
                 gotIt: '知道了',
                 createRule: '创建规则',
                 fallbackBanner: '这不是标准规则,因此我们将其起草为代理规则。代理规则会在报销或报表发生变化后执行操作,例如暂挂该报销或拒绝该报表。',
-                fallbackBannerWithExplanation: (explanation: string) => `这不是标准规则,因此我们将其起草为代理规则。${explanation}`,
+                fallbackBannerWithExplanation: (explanation: string) => `这不是一条标准规则,因此我们将其拟定为代理规则。${explanation}`,
             },
             tabs: {general: '常规', cardRestrictions: '卡片限制', expenseDefaults: '报销默认设置', requireFields: '字段要求', flagForReview: '标记以供审核', agents: '代理人'},
             bulkActions: {
@@ -8425,12 +8425,12 @@ ${reportName}`,
                     multipleRules: '请一次描述一条规则,例如:在所有卡上阻止零售消费。',
                 },
                 impossible: {
-                    noTrigger: '规则无法从该事件开始。',
-                    noCapability: '规则无法执行该操作。',
+                    noTrigger: '规则不能从该事件开始。',
+                    noCapability: '规则无法执行此操作。',
                     missingData: 'Expensify 没有该信息。',
                     retroactive: '规则仅适用于新的活动。',
-                    historyLimit: '规则无法回溯那么久。',
-                    tryThisInstead: '改为尝试这个',
+                    historyLimit: '规则无法追溯到那么久以前。',
+                    tryThisInstead: '试试这个',
                 },
             },
             expenseDefaultsTable: {

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

View workflow run

@yuwenmemon
yuwenmemon force-pushed the yuwen-683436-describeRuleAgentFallback branch from 9d8ce8b to 950f129 Compare October 14, 2026 20:38
@codecov

codecov Bot commented Oct 15, 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 95.90% <ø> (ø)
src/libs/actions/Policy/Rules.ts 82.14% <100.00%> (+59.38%) ⬆️
...es/workspace/rules/AgentRules/AddAgentRulePage.tsx 90.54% <100.00%> (+0.39%) ⬆️
src/pages/workspace/rules/DescribeRuleForm.tsx 93.81% <100.00%> (+1.22%) ⬆️
... and 823 files with indirect coverage changes

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants