Skip to content

[CP Staging][Payment due @mkhutornyi] Render agent rule change logs in NewDot #admins - #96773

Merged
puneetlath merged 6 commits into
mainfrom
yuwen-660979-agent-rule-changelog
Jul 29, 2026
Merged

[CP Staging][Payment due @mkhutornyi] Render agent rule change logs in NewDot #admins#96773
puneetlath merged 6 commits into
mainfrom
yuwen-660979-agent-rule-changelog

Conversation

@yuwenmemon

@yuwenmemon yuwenmemon commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@puneetlath please review

Explanation of Change

Renders the three new agent-rule change-log system messages in NewDot's #admins room, so admins get a visible audit trail whenever an agent rule is added, updated, or deleted. Add/update messages show the rule title and full prompt; delete shows just the title (the title is server-generated and may be empty, so each message falls back to a generic phrasing).

The backend that emits these POLICYCHANGELOG_{ADD,UPDATE,DELETE}_AGENT_RULE actions is the companion Auth PR https://github.com/Expensify/Auth/pull/23134. Deploy this NewDot PR first so the messages render as soon as Auth starts emitting them; an unhandled subtype simply renders nothing (no crash). OldDot's own rendering is the companion Web-Expensify PR https://github.com/Expensify/Web-Expensify/pull/54776.

Fixed Issues

For https://github.com/Expensify/Expensify/issues/660979
PROPOSAL:

Tests

  1. On a Control workspace, open Workspace > Rules > AI and add an agent rule.
  2. Open the workspace #admins room and confirm a system message records the rule being added, showing its title and prompt.
  3. Edit the rule's prompt and confirm an "updated" system message appears with the title and new prompt.
  4. Delete the rule and confirm a "deleted" system message appears showing the title.
  5. Confirm the #admins room's LHN preview shows the concise "added/updated/deleted an agent rule" text.
  6. Verify that no errors appear in the JS console.
Screenshot 2026-07-23 at 12 42 49 AM Screenshot 2026-07-23 at 12 43 44 AM Screenshot 2026-07-23 at 12 44 30 AM

(Requires the companion Auth PR on the same environment to emit the actions.)

  • Verify that no errors appear in the JS console

Offline tests

These are server-emitted system messages, so no new offline behavior is introduced — an already-synced #admins room shows the cached messages while offline.

QA Steps

Same as tests (run on staging once the companion Auth change is deployed there).

  • 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 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

@OSBotify

This comment has been minimized.

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

(Yuwen's Agent) Squawk received 🦜 — adopted the suggested translations for all 9 locales in a104f43.

@codecov

codecov Bot commented Jul 22, 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/CONST/index.ts 94.81% <ø> (ø)
src/libs/AgentRuleChangeLogUtils.ts 100.00% <100.00%> (ø)
src/libs/OptionsListUtils/index.ts 86.98% <100.00%> (+0.05%) ⬆️
...es/inbox/report/ContextMenu/ContextMenuActions.tsx 39.53% <100.00%> (+17.68%) ⬆️
...x/report/actionContents/PolicyChangeLogContent.tsx 100.00% <100.00%> (ø)
src/libs/ReportNameUtils.ts 81.60% <50.00%> (-0.45%) ⬇️
src/libs/SidebarUtils.ts 80.11% <50.00%> (-0.28%) ⬇️
... and 8 files with indirect coverage changes

@yuwenmemon
yuwenmemon marked this pull request as ready for review July 22, 2026 23:37
@yuwenmemon
yuwenmemon requested review from a team as code owners July 22, 2026 23:37
@melvin-bot
melvin-bot Bot requested a review from joekaufmanexpensify July 22, 2026 23:37
@yuwenmemon
yuwenmemon requested a review from puneetlath July 22, 2026 23:37
@melvin-bot
melvin-bot Bot requested review from youssef-lr and removed request for a team July 22, 2026 23:37
@melvin-bot

melvin-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

@youssef-lr 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]

@yuwenmemon yuwenmemon changed the title Render agent rule change logs in NewDot #admins [HOLD WEB#54776] Render agent rule change logs in NewDot #admins Jul 23, 2026

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

👍

puneetlath
puneetlath previously approved these changes Jul 23, 2026
@OSBotify

This comment has been minimized.

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

(Yuwen's Agent) Squawk received 🦜 — adopted most of these, but held back a few on closer inspection:

  • ja.ts: skipped both. The deleted fallback swap ("エージェントルール" → "担当者ルール") changes the term itself ("agent" → "person in charge"), which would read inconsistently against the same line's own title-branch and the added/updated lines right above it. The colon-width change on added's fallback also would've diverged from its own title-branch's full-width colon.
  • fr.ts: took the added NBSP-before-colon fix, but not updated's fallback (would've mixed a narrow NBSP into a block that uses a regular NBSP everywhere else) or deleted's apostrophe (that one flips a curly ’ to a straight ' — regression, not a fix).
  • it.ts: took the dell'agentedell'agente apostrophe fix, and applied it to the other two occurrences in the same block too for consistency. Skipped the deleted line's switch to guillemets since every sibling in this file (deleteCategory/deleteTag/deleteTax) quotes with straight "...".
  • zh-hans.ts: took the added/updated fixes, but kept "移除" instead of reverting to "删除" for deleted — that's deliberate, matching the "removed" (not "deleted") wording the companion Auth/Web-Expensify PRs already settled on.

Everything else (de.ts, nl.ts, pl.ts) applied as suggested.

@mkhutornyi

Copy link
Copy Markdown
Contributor

If this requires C+ review, I can help

@NicolasBonet

Copy link
Copy Markdown
Contributor

I believe we don't have need to hold this anymore? @yuwenmemon ?

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

Yeah, the web PR got deployed to staging, so I think we're probably good to move forward here.

@yuwenmemon yuwenmemon changed the title [HOLD WEB#54776] Render agent rule change logs in NewDot #admins Render agent rule change logs in NewDot #admins Jul 27, 2026
@yuwenmemon
yuwenmemon requested a review from mkhutornyi July 27, 2026 22:17
@yuwenmemon

Copy link
Copy Markdown
Contributor Author

@mkhutornyi great, can you review ASAP?

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

There are some translation copy bugs

  • de.ts — updated fallback drops the auxiliary verb: eine Agentenregel aktualisiert zu: … should be hat eine Agentenregel aktualisiert zu:. Every other string in the block (and its neighbors) starts with hat.
  • pl.ts — voice flips between branches within the same key: dodał(a) vs dodano, usunął(-ę) vs usunięto. Also usunął(-ę) looks like a typo for usunął(-ęła).
  • nl.ts — three different quote styles across three adjacent lines: "${title}", „${title}”, ‘${title}’. Neighboring nl strings use ‘…’.
  • es.ts — la regla de agente (added/deleted) vs la regla del agente (updated).
  • it.ts — la regola dell'agente vs una regola agente across branches.

@MelvinBot can you confirm?

@MelvinBot

Copy link
Copy Markdown
Contributor

Confirmed — all five are real. Each is in the strings added by this PR (workspaceActions.agentRule), verified against e2e6f62:

  • de.ts ✅ — de.ts:8610: updated fallback reads eine Agentenregel aktualisiert zu: — missing the leading hat. All three keys' other branches start with hat (hat die Agentenregel … aktualisiert, hat eine Agentenregel hinzugefügt, etc.), so this is the one straggler. Should be hat eine Agentenregel aktualisiert zu:.

  • pl.ts ✅ — pl.ts:8541-8543: voice flips inside each key — added is dodał(a) (personal) vs dodano (impersonal); deleted is usunął(-ę) vs usunięto. Worth noting updated is impersonal zaktualizowano in both branches, so the block mixes personal (added/deleted title branch) with impersonal everywhere else — pick one voice across all three. And yes, usunął(-ę) is a typo: (-ę) yields "usunę" (1st-person future, "I will delete"); the feminine past is "usunęła", so it should be usunął(-ęła) to match the dodał(a) pattern.

  • nl.ts ✅ — nl.ts:8561-8563: three quote styles across the three adjacent lines — "${title}" (straight), „${title}”, then ‘${title}’. The neighboring nl convention for quoting an interpolated value is ‘…’ (e.g. nl.ts:1142), so all three should use ‘${title}’.

  • es.ts ✅ — es.ts:8072-8074: added/deleted use la regla de agente but updated uses la regla del agente. Should be consistent.

  • it.ts ✅ — it.ts:8590-8593: inconsistent both ways — with-title branches say la regola dell'agente (add/update) but la regola agente (delete, missing dell'), and the no-title fallbacks say una regola agente (add/delete) vs una regola dell'agente (update). Normalize to regola dell'agente throughout.

(Note: these are per-locale typographic quotes in the content — the „ ” « » ‘ ’ etc. are correct for each locale; the bugs above are the inconsistencies/typos within a locale, not the choice of curly quotes itself.)

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

(Yuwen's Agent) All 5 confirmed — fixed in c8da262:

  • de.ts: updated fallback now starts with hat.
  • pl.ts: updated's title-branch is now personal (zaktualizował(a)) to match added/deleted's title-present=personal / fallback=impersonal pattern; usunął(-ę) typo fixed to usunął(-ęła) (feminine of usunąć isn't a simple suffix).
  • nl.ts: added/updated now use '…' to match deleted and the established nl convention.
  • es.ts: updated now says la regla de agente (was la regla del agente), matching added/deleted.
  • it.ts: normalized all six branches to regola dell'agente.

All re-verified via jest + typecheck-tsgo, pushed.

@MelvinBot

Copy link
Copy Markdown
Contributor

Review

Solid, well-scoped PR. All five render paths are wired consistently (main content, LHN last-message, sidebar alternate text, thread report name, and context-menu copy), all 10 locales are covered, OriginalMessage is properly typed, and there's good unit-test coverage. Routing is complete — the new types land in POLICY_CHANGE_LOG_ARRAY automatically and isHandledPolicyChangeLogAction picks them up via the resolver map. The messages render as plain text through Text (ReportActionItemBasicMessage), so a prompt containing HTML-ish characters is safe. Unhandled subtypes fall through to null, so deploying ahead of Auth is fine as described.

A couple of things worth a look before merge:

1. LHN preview isn't concise for add/update — contradicts Test step 5

Test step 5 says the LHN preview should show "the concise 'added/updated/deleted an agent rule' text." But the LHN reuses the same full builder for add/update, so it renders the entire prompt inline:

Only the empty-title delete fallback (removed an agent rule) is actually concise; add/update always include the prompt even in the fallback (en.ts:41-42). Since prompts are free-form natural language and can be long, the LHN preview will be a truncated prompt rather than a short summary. This matches how existing card-rule change logs behave, so it may be intentional — but either add a short LHN variant or reword Test step 5 so QA doesn't flag it as a regression.

2. Minor: verify the empty-title fallbacks are actually reachable

The PR notes the title is server-generated and "may be empty," and every builder has a prompt-only / generic fallback (nicely tested). Just confirm the companion Auth PR emits ruleTitle: '' (not omitted vs. null) — getOriginalMessage(...) ?? {} plus message.ruleTitle ?? '' handles both, so this is likely fine, just worth a sanity check end-to-end.

Nothing blocking. The typography looks locale-appropriate (e.g. «…» in fr/es, 「…」 in ja, „…" in de/pl), and es already mixes guillemets so that's consistent with the file.

@mkhutornyi

Copy link
Copy Markdown
Contributor

Please merge main. Typecript check is fixed in #97370

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: ccf37fc6ae

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

@MelvinBot

Copy link
Copy Markdown
Contributor

Regression scan

No behavioral regression to existing functionality found. Every change is additive and keyed on three brand-new action types (ADD/UPDATE/DELETE_AGENT_RULE) that don't exist in production until the companion Auth PR ships. No existing action type's rendering, LHN preview, report name, or copy behavior is altered — the new if/else if branches and resolver-map keys only fire for the new names.

Things I specifically checked for regressions and cleared:

  • Shared hot paths stay safe for existing actions. The new types join POLICY_CHANGE_LOG_ARRAY (derived via Object.values), so they now pass isPolicyChangeLogAction and flow through replaceBaseURLInPolicyChangeLogAction. That's a no-op unless the message HTML contains %baseURL, and it only touches the new actions — existing actions are unaffected.
  • No consumer gap. Coverage for the new actions is a superset of the sibling Expensify-card-rule feature — same five render surfaces (main content, sidebar, report name, context-menu copy, OriginalMessage typing) plus the LHN last-message path in OptionsListUtils/index.ts:996, which the card-rule feature doesn't wire. So the new messages won't render blank/raw in any surface the sibling feature already covers.
  • No new import cycle at load time. The new AgentRuleChangeLogUtils.ts imports getOriginalMessage/isActionOfType from ReportActionsUtils and is imported into 5 hot files, but only uses those imports at call time (not module-init), so no top-level circular-init hazard is introduced.
  • Additive CONST/type changes. New keys in POLICY_CHANGE_LOG and new OriginalMessageMap members don't change inference or behavior for existing members.

Two watch items (not regressions, and one is unverified):

  1. LHN preview length — as noted in my earlier review, add/update reuse the full builder, so the LHN preview shows the entire prompt rather than a concise summary. Consistent with existing change-log behavior, but worth a UX decision.
  2. Notification noise (unverified) — I did not confirm whether these system messages trigger admin push/email notifications. If they do, every agent-rule add/update/delete would notify all admins. Worth verifying against the desired behavior before staging — this is a new-feature consideration, not a regression of existing behavior.

@yuwenmemon

Copy link
Copy Markdown
Contributor Author

@mkhutornyi thanks! Done!

@yuwenmemon
yuwenmemon force-pushed the yuwen-660979-agent-rule-changelog branch from 9bc1149 to dcc21c2 Compare July 29, 2026 19:14
@melvin-bot melvin-bot Bot changed the title Render agent rule change logs in NewDot #admins [Payment due @mkhutornyi] Render agent rule change logs in NewDot #admins Jul 29, 2026
@melvin-bot

melvin-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

🎯 @mkhutornyi, thanks for reviewing and testing this PR! 🎉

A payment issue will be created for your review once this PR is deployed to production.
E/E issue linked to the PR - no internal issue.

If payment is not needed (e.g., regression PR review fix etc), react with 👎 to this comment to prevent the payment issue from being created.

@puneetlath
puneetlath merged commit 5f2041f into main Jul 29, 2026
44 checks passed
@puneetlath
puneetlath deleted the yuwen-660979-agent-rule-changelog branch July 29, 2026 21:10
@github-actions

Copy link
Copy Markdown
Contributor

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

@yuwenmemon yuwenmemon changed the title [Payment due @mkhutornyi] Render agent rule change logs in NewDot #admins [CP Staging][Payment due @mkhutornyi] Render agent rule change logs in NewDot #admins Jul 29, 2026
@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 pushed a commit that referenced this pull request Jul 29, 2026
…gelog

[Payment due @mkhutornyi] Render agent rule change logs in NewDot #admins

(cherry picked from commit 5f2041f)

(cherry-picked to staging by puneetlath)
@OSBotify OSBotify added the CP Staging marks PRs that have been CP'd to staging label Jul 29, 2026
@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Cherry-picked to staging by https://github.com/puneetlath in version: 9.4.46-1 🚀

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

@MelvinBot

Copy link
Copy Markdown
Contributor

🤖 Help site review — docs update required

This PR adds a user-visible admin behavior that the help site doesn't currently document: whenever an Agent rule is added, updated, or deleted, a system message is now recorded in the workspace's #admins room as an audit trail.

The existing Create Agent Rules article covers creating, writing, and deleting Agent rules, but it doesn't mention that these changes are logged in #admins. I've drafted a doc update that adds a task-based section (## How to review Agent rule changes in the #admins room) to that article, following the HelpDot authoring guidelines, naming conventions, and template, and reusing the UI-exact terminology already in the article (Agent rules, RuleBot, #admins room).

Draft help site PR: #97398

No other help site articles reference the agent-rule change log, so this is the only docs change needed for this PR.

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

@vincdargento

Copy link
Copy Markdown

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

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

Labels

CP Staging marks PRs that have been CP'd to staging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants