Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
72d7c12
fix(rules): reject a generated rule of another rule type
yuwenmemon Oct 12, 2026
075958f
feat(rules): describe a rule from New rule and fall back to an agent …
yuwenmemon Oct 12, 2026
4062716
test(rules): adapt describe-rule tests to main's modal and editors
yuwenmemon Oct 12, 2026
48bbc2f
docs(rules): state the category constraint in RulesNewPage
yuwenmemon Oct 12, 2026
8f945f2
fix(rules): wrap the agent rule fallback banner at word boundaries
yuwenmemon Oct 13, 2026
dbcbc6a
refactor(rules): remove the unreachable non-admin agent rule error
yuwenmemon Oct 13, 2026
beb83b0
feat(rules): show agent rule and impossible answers in the rules builder
yuwenmemon Oct 14, 2026
c505a67
fix(rules): drop review and save from the agent rule fallback banner
yuwenmemon Oct 14, 2026
f3c9aaf
chore(rules): merge yuwen-683436-describeRuleAgentFallback
yuwenmemon Oct 14, 2026
d78b0c9
feat(rules): describe a rule inline on New rule instead of in a modal
yuwenmemon Oct 14, 2026
d4de8c2
fix(rules): drop the unused DescribeRuleFormProps export
yuwenmemon Oct 14, 2026
4a191af
feat(rules): open Describe your rule as a page in the RHP
yuwenmemon Oct 14, 2026
6982ac1
fix(rules): apply Polyglot Parrot translation refinements
yuwenmemon Oct 14, 2026
e2b8f2e
chore(rules): merge the RHP describe page and port the answers to it
yuwenmemon Oct 14, 2026
0fc0a23
fix(rules): add an Add agent rule row under the Agents tab list
yuwenmemon Oct 14, 2026
3113c5c
chore(rules): merge the Agents tab add row from #103810
yuwenmemon Oct 14, 2026
9d8ce8b
style(rules): match the add agent rule row's bottom spacing
yuwenmemon Oct 14, 2026
67677b7
chore(rules): merge the add agent rule row spacing from #103810
yuwenmemon Oct 14, 2026
e68d940
chore(rules): merge the describeRule beta gate from #103810
yuwenmemon Oct 14, 2026
e7d1e52
chore(rules): merge the Back fix and layout props from #103810
yuwenmemon Oct 14, 2026
5f95c1a
chore(rules): merge the New rule describe section from #103810
yuwenmemon Oct 15, 2026
6988737
chore(rules): merge the describe box padding from #103810
yuwenmemon Oct 15, 2026
ce07804
chore(rules): merge the $2,000 describe example from #103810
yuwenmemon Oct 15, 2026
dfd0894
chore(rules): merge the navigation types trim from #103810
yuwenmemon Oct 15, 2026
9edaf57
chore(rules): merge the optional describe box from #103810
yuwenmemon Oct 16, 2026
397fd6c
chore(rules): merge category tax rate handling from #103810
yuwenmemon Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,17 @@ const CONST = {
UNSUPPORTED: 'unsupported',
MULTIPLE_RULES: 'multipleRules',
UNINTELLIGIBLE: 'unintelligible',
AGENT_RULE: 'agentRule',
IMPOSSIBLE: 'impossible',
FAILED: 'failed',
},
IMPOSSIBLE_REASON: {
NO_TRIGGER: 'noTrigger',
NO_CAPABILITY: 'noCapability',
MISSING_DATA: 'missingData',
RETROACTIVE: 'retroactive',
HISTORY_LIMIT: 'historyLimit',
},
RULE_TYPE: {
REQUIRE_FIELDS: 'requireFields',
FLAG_FOR_REVIEW: 'flagForReview',
Expand Down Expand Up @@ -10274,6 +10283,7 @@ const CONST = {
SPEND_RULE_SECTION_ITEM: 'WorkspaceRules-SpendRuleSectionItem',
SPEND_RULE_SAVE: 'WorkspaceRules-SpendRuleSave',
SPEND_RULE_DESCRIBE: 'WorkspaceRules-SpendRuleDescribe',
DESCRIBE_RULE_TRY_SUGGESTION: 'WorkspaceRules-DescribeRuleTrySuggestion',
SPEND_RULE_DELETE: 'WorkspaceRules-SpendRuleDelete',
SPEND_RULE_RESTRICTION_TYPE: 'WorkspaceRules-SpendRuleRestrictionType',
AGENT_RULE_ITEM: 'WorkspaceRules-AgentRuleItem',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8749,6 +8749,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
createRule: 'Regel erstellen',
fallbackBanner:
'Dies ist keine Standardregel, daher haben wir sie als Agentenregel erstellt. Agentenregeln greifen, nachdem sich eine Ausgabe oder ein Bericht geändert hat, zum Beispiel indem sie die Ausgabe zurückhalten oder den Bericht ablehnen.',
fallbackBannerWithExplanation: (explanation: string) => `Dies ist keine Standardregel, daher haben wir sie als Agentenregel erstellt. ${explanation}`,
},
tabs: {
general: 'Allgemein',
Expand Down Expand Up @@ -8835,6 +8836,14 @@ 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.',
categoryHasRule: 'Für diese Kategorie gibt es bereits eine Regel. Bearbeite die bestehende Regel oder beschreibe eine Regel für eine andere Kategorie.',
},
impossible: {
noTrigger: 'Regeln können nicht durch dieses Ereignis ausgelöst werden.',
noCapability: 'Das können Regeln nicht.',
missingData: 'Expensify hat diese Informationen nicht.',
retroactive: 'Regeln gelten nur für neue Aktivitäten.',
historyLimit: 'Regeln können nicht so weit zurückblicken.',
tryThisInstead: 'Stattdessen das versuchen',
},
},
expenseDefaultsTable: {
tableColumnType: 'Typ',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/el.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8925,6 +8925,14 @@ ${reportName}`,
multipleRules: 'Έναν κανόνα τη φορά — δοκιμάστε να περιγράψετε έναν μόνο κανόνα, π.χ.: αποκλεισμός αγορών λιανικής σε όλες τις κάρτες.',
categoryHasRule: 'Αυτή η κατηγορία έχει ήδη κανόνα. Επεξεργαστείτε τον υπάρχοντα κανόνα ή περιγράψτε έναν κανόνα για άλλη κατηγορία.',
},
impossible: {
noTrigger: 'Οι κανόνες δεν μπορούν να ξεκινήσουν από αυτό το συμβάν.',
noCapability: 'Οι κανόνες δεν μπορούν να το κάνουν αυτό.',
missingData: 'Το Expensify δεν έχει αυτές τις πληροφορίες.',
retroactive: 'Οι κανόνες ισχύουν μόνο για νέα δραστηριότητα.',
historyLimit: 'Οι κανόνες δεν μπορούν να κοιτάξουν τόσο πίσω.',
tryThisInstead: 'Δοκιμάστε αυτό',
},
},
expenseDefaultsTable: {
tableColumnType: 'Τύπος',
Expand Down Expand Up @@ -9209,6 +9217,7 @@ ${reportName}`,
createRule: 'Δημιουργία κανόνα',
fallbackBanner:
'Αυτός δεν είναι ένας τυπικός κανόνας, οπότε τον διαμορφώσαμε ως κανόνα πράκτορα. Οι κανόνες πράκτορα εφαρμόζονται αφού αλλάξει μια δαπάνη ή μια αναφορά, για παράδειγμα κρατώντας τη δαπάνη ή απορρίπτοντας την αναφορά.',
fallbackBannerWithExplanation: (explanation: string) => `Αυτός δεν είναι ένας τυπικός κανόνας, οπότε τον διαμορφώσαμε ως κανόνα πράκτορα. ${explanation}`,
suggestionsTab: 'Προτεινόμενο',
writeTab: 'Επεξεργασία',
findSuggestion: 'Βρείτε έναν κανόνα',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9110,6 +9110,14 @@ const translations = {
multipleRules: 'One rule at a time, please — try describing a single rule, like: block retail purchases on all cards.',
categoryHasRule: 'That category already has a rule. Edit the existing rule or describe a rule for another category.',
},
impossible: {
noTrigger: "Rules can't start from that event.",
noCapability: "Rules can't do that.",
missingData: "Expensify doesn't have that information.",
retroactive: 'Rules only apply to new activity.',
historyLimit: "Rules can't look back that far.",
tryThisInstead: 'Try this instead',
},
},
expenseDefaultsTable: {
tableColumnType: 'Type',
Expand Down Expand Up @@ -9409,6 +9417,7 @@ const translations = {
createRule: 'Create rule',
fallbackBanner:
"This isn't a standard rule, so we drafted it as an agent rule. Agent rules act after an expense or report changes, for example by holding the expense or rejecting the report.",
fallbackBannerWithExplanation: (explanation: string) => `This isn't a standard rule, so we drafted it as an agent rule. ${explanation}`,
agentCreatedTitle: 'RuleBot has been added to your workspace!',
agentCreatedDescription: (agentsRoute: string) =>
`<muted-text>To enforce your agent rules, we’ve created an agent for you and added it as an admin to your workspace.<br><br>Edit your agent’s details in <a href="${agentsRoute}">Account &gt; Agents</a>.</muted-text>`,
Expand Down
9 changes: 9 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8754,6 +8754,7 @@ ${reportName}`,
createRule: 'Crear regla',
fallbackBanner:
'Esta no es una regla estándar, así que la redactamos como una regla de agente. Las reglas de agente actúan después de que un gasto o informe cambia, por ejemplo reteniendo el gasto o rechazando el informe.',
fallbackBannerWithExplanation: (explanation: string) => `Esta no es una regla estándar, así que la redactamos como una regla de agente. ${explanation}`,
},
tabs: {
general: 'General',
Expand Down Expand Up @@ -8840,6 +8841,14 @@ ${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.',
categoryHasRule: 'Esa categoría ya tiene una regla. Edita la regla existente o describe una regla para otra categoría.',
},
impossible: {
noTrigger: 'Las reglas no pueden empezar 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.',
tryThisInstead: 'Prueba esto en su lugar',
},
},
expenseDefaultsTable: {
tableColumnType: 'Tipo',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8772,6 +8772,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
createRule: 'Créer une règle',
fallbackBanner:
'Ce n’est pas une règle standard, nous l’avons donc rédigée comme une règle d’agent. Les règles d’agent agissent après la modification d’une dépense ou d’une note de frais, par exemple en bloquant la dépense ou en rejetant la note de frais.',
fallbackBannerWithExplanation: (explanation: string) => `Ce n’est pas une règle standard, nous l’avons donc rédigée comme une règle d’agent. ${explanation}`,
},
tabs: {
general: 'Général',
Expand Down Expand Up @@ -8858,6 +8859,14 @@ 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.',
categoryHasRule: 'Cette catégorie a déjà une règle. Modifiez la règle existante ou décrivez une règle pour une autre catégorie.',
},
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.',
tryThisInstead: 'Essayez plutôt ceci',
},
},
expenseDefaultsTable: {
tableColumnType: 'Type',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8700,6 +8700,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 creata come regola agente. Le regole agente agiscono dopo che una spesa o un report vengono modificati, ad esempio bloccando la spesa o rifiutando il report.',
fallbackBannerWithExplanation: (explanation: string) => `Questa non è una regola standard, quindi l’abbiamo creata come regola agente. ${explanation}`,
},
tabs: {
general: 'Generale',
Expand Down Expand Up @@ -8786,6 +8787,14 @@ 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.',
categoryHasRule: "Questa categoria ha già una regola. Modifica la regola esistente o descrivi una regola per un'altra categoria.",
},
impossible: {
noTrigger: 'Le regole non possono partire da questo 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',
},
},
expenseDefaultsTable: {
tableColumnType: 'Tipo',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8589,6 +8589,7 @@ ${reportName}`,
createRule: 'ルールを作成',
fallbackBanner:
'これは標準ルールではないため、エージェントルールとして作成しました。エージェントルールは、経費やレポートに変更があった後に動作し、例えば経費を保留にしたり、レポートを却下したりします。',
fallbackBannerWithExplanation: (explanation: string) => `これは標準ルールではないため、エージェントルールとして作成しました。${explanation}`,
},
tabs: {
general: '一般',
Expand Down Expand Up @@ -8675,6 +8676,14 @@ ${reportName}`,
multipleRules: '一度に1つのルールのみです。「すべてのカードで小売店での購入をブロックする」のように、1つのルールを説明してください。',
categoryHasRule: 'このカテゴリにはすでにルールがあります。既存のルールを編集するか、別のカテゴリのルールを説明してください。',
},
impossible: {
noTrigger: 'ルールはそのイベントをきっかけに開始できません。',
noCapability: 'ルールではそれを実行できません。',
missingData: 'Expensify にはその情報がありません。',
retroactive: 'ルールは新しいアクティビティにのみ適用されます。',
historyLimit: 'ルールはそこまで過去をさかのぼれません。',
tryThisInstead: '代わりにこちらを試す',
},
},
expenseDefaultsTable: {
tableColumnType: '種類',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8674,6 +8674,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
createRule: 'Regel maken',
fallbackBanner:
'Dit is geen standaardregel, dus hebben we hem opgesteld als een agentregel. 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 hebben we hem opgesteld als een agentregel. ${explanation}`,
},
tabs: {
general: 'Algemeen',
Expand Down Expand Up @@ -8760,6 +8761,14 @@ 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.',
categoryHasRule: 'Deze categorie heeft al een regel. Bewerk de bestaande regel of beschrijf een regel voor een andere categorie.',
},
impossible: {
noTrigger: 'Regels kunnen niet starten vanaf die gebeurtenis.',
noCapability: 'Regels kunnen dat niet doen.',
missingData: 'Expensify heeft die informatie niet.',
retroactive: 'Regels gelden alleen voor nieuwe activiteit.',
historyLimit: 'Regels kunnen niet zo ver terugkijken.',
tryThisInstead: 'Probeer dit in plaats daarvan',
},
},
expenseDefaultsTable: {
tableColumnType: 'Type',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8699,6 +8699,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 albo odrzucając raport.',
fallbackBannerWithExplanation: (explanation: string) => `To nie jest standardowa reguła, więc przygotowaliśmy ją jako regułę agenta. ${explanation}`,
},
tabs: {
general: 'Ogólne',
Expand Down Expand Up @@ -8785,6 +8786,14 @@ 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.',
categoryHasRule: 'Ta kategoria ma już regułę. Edytuj istniejącą regułę lub opisz regułę dla innej kategorii.',
},
impossible: {
noTrigger: 'Reguły nie mogą uruchamiać się od tego zdarzenia.',
noCapability: 'Reguły nie mogą tego zrobić.',
missingData: 'Expensify nie ma tych informacji.',
retroactive: 'Reguły dotyczą tylko nowej aktywności.',
historyLimit: 'Reguły nie mogą sięgać tak daleko wstecz.',
tryThisInstead: 'Spróbuj zamiast tego',
},
},
expenseDefaultsTable: {
tableColumnType: 'Typ',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8681,6 +8681,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 criamos como uma regra de agente. As regras de agente entram em ação depois que uma despesa ou um relatório é alterado, por exemplo, ao reter a despesa ou rejeitar o relatório.',
fallbackBannerWithExplanation: (explanation: string) => `Esta não é uma regra padrão, então a criamos como uma regra de agente. ${explanation}`,
},
tabs: {
general: 'Geral',
Expand Down Expand Up @@ -8767,6 +8768,14 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
multipleRules: 'Uma regra por vez, por favor — tente descrever uma única regra, como: bloquear compras no varejo em todos os cartões.',
categoryHasRule: 'Essa categoria já tem uma regra. Edite a regra existente ou descreva uma regra para outra categoria.',
},
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.',
tryThisInstead: 'Tente isto em vez disso',
},
},
expenseDefaultsTable: {
tableColumnType: 'Tipo',
Expand Down
Loading
Loading