Skip to content

fix(web): align markdown details summaries logically

MacroscopeApp / Macroscope - UI Consistency failed Aug 31, 2026 in 7m 24s

UI Consistency: 1 issue found

apps/web/src/components/ChatMarkdown.tsx — the new dir="auto" on the .chat-markdown root still counts the synthesized skill-mention chip label (SkillChip in apps/web/src/components/chat/SkillInlineText.tsx renders formatProviderSkillDisplayName(...) as bare text with no dir). Since mentions typically lead a message, $code-review <Hebrew prose> resolves the whole RTL message to ltr, the same defect the dir="ltr" exclusions on code/pre/tables/file chips and the <bdi> alert label were added to prevent. Suggested fix: wrap the chip label in <bdi> (or give the label span dir="ltr").

Everything previously flagged in this PR is now resolved: the <details> trigger uses text-start, the GitHub-alert block uses border-s-2 ps-3 with a <bdi> label and no forced dir, and the extra footnote padding override that shadowed --list-gutter is gone.

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.

Verified in this run:

  • apps/web/src/index.css markdown block (lines ~1579–1858): all direction-sensitive declarations converted to logical equivalents (padding-inline-start, border-inline-start, margin-inline, text-align: start). The task-list checkbox rewrite (margin: 0 0 0.15em + margin-inline: calc(-1 * var(--list-gutter)) 0.35em) is byte-equivalent in LTR and correctly ordered in the cascade; --list-gutter remains consumed by .chat-markdown ol { padding-inline-start: var(--list-gutter, 1.25rem) } with no more-specific override.
  • Tailwind v4 logical utilities used (border-s-2, ps-3, text-start) are already established in this codebase (DiffCommentAnnotation.tsx, MessagesTimeline.tsx:2490, MarkdownDetails ps-6), so no emitted-CSS risk.
  • Direction-scan exclusions checked against the HTML dir=auto algorithm (subtrees with an explicit dir, and <bdi>, are skipped): inline code, fallback pre, MarkdownCodeBlock (which wraps every Shiki path), MarkdownTable container, and both MarkdownFileLink branches are excluded; th/td resolve per cell. Only the skill chip label remains unhandled.
  • Physical-utility sweep of ChatMarkdown.tsx found only the codeblock header (pr-1.5 pl-3, inside the dir="ltr" codeblock) and the artifact badge overlay, both LTR-anchored chrome; not reported.
  • Not reported as findings: the collapsed <details> chevron not being mirrored in RTL (the repo uses no rtl: variants anywhere, so this would introduce a new pattern) and per-cell text-align: start producing ragged columns in mixed-direction tables (appears intentional and is covered by the new test).

🔍 Agent activity — 23 tool calls

💭 I'm checking whether previous review findings were addressed in the latest commit. The text-left and dir="ltr" issues both look fixed now, so I'm moving on to verify the footnote padding-left issue from earlier.

1. browse_code — apps/web/src/index.css

2. git_tools — apps/web/src/index.css 9b2d043..ef11976

💭 The CSS looks good now with that footnote padding fix removed. I want to check ChatMarkdown.tsx for remaining physical-property classes like padding-left, margin-left, text-left, or border-left that could break in RTL layouts.

3. git_tools — (pl-|pr-|ml-|mr-|text-left|text-right|border-l|border-r|left-|right-)

4. git_tools — apps/web/src/components/ChatMarkdown.tsx 9b2d043..ef11976

💭 I'm scanning through remaining elements affected by the dir="auto" change—footnotes, hover states, task list checkboxes, headings, and horizontal rules all look fine since they don't have directional issues. I still need to check the codeblock header positioning and an avatar badge with a right-offset class near line 247, plus other physical-direction classes like ps-/pe- and text-left that get composed elsewhere, such as in chip class names. I also want to look at whether absolutely positioned elements with right-based offsets get affected by dir="auto", and whether the auto-direction detection could get thrown off by code content mixed into the markdown text. That confirms why dir="ltr" was added to code, pre, and file link elements — it excludes their text from the auto-direction algorithm. I'm also noticing a related edge case: messages starting with a URL would force LTR direction since URLs begin with Latin characters, which is a minor pre-existing limitation of the dir=auto approach rather than a new issue. I want to check whether other markdown-adjacent components, like message bubble alignment, have similar direction-handling concerns. Now I'm searching apps/web/src for any inline styles or CSS using physical properties like paddingLeft, marginLeft, borderLeft, or textAlign within markdown-related elements, and also checking whether ".chat-markdown" selectors appear in other CSS files beyond what I've already reviewed.

5. git_tools — chat-markdown

6. browse_code — apps/web/src/components/ChatMarkdown.tsx

💭 I'm checking how dir="auto" propagates on the root container versus the table's dir="ltr", and thinking about whether the horizontal scroll position inside the ScrollArea starts correctly for RTL content. Header cells, blockquote alerts, and link hover backgrounds all seem fine under the inherited dir behavior. I'm also verifying the shiki code block correctly inherits dir="ltr" from its container, which looks correct. Checking whether dir="ltr" gets misapplied to non-code elements inside the code renderer — it appears it's only applied at the final return, so that's fine too. I'm now scanning for any other web surfaces beyond ChatMarkdown that might rely on the same class and dir="auto" behavior, but so far ChatMarkdown seems to be the only consumer, so I want to identify what areas still haven't been checked. I'm looking at markdown details/collapsible sections next — the chevron icon direction seems like a possible RTL issue: in the closed state, the chevron points right regardless of language direction, which would be visually backwards in RTL and should probably mirror to point left.

7. browse_code — apps/web/src/components/ChatMarkdown.tsx

💭 I'm noticing the details element already uses logical padding, so that's pre-existing. The chevron icon rotates on open but doesn't mirror direction in RTL, which is a real gap worth flagging since it sits near a changed line. I want to keep checking other spots before deciding what's substantial enough to flag — the ScrollArea's LTR container looks fine, and the MarkdownFileLink's forced LTR direction seems intentional and correct for its inline chip content within an RTL paragraph. I'm also considering whether other markdown surfaces in the app, like thread titles or streaming reasoning text, should have gotten the same dir="auto" treatment but didn't, and whether the code renderer's LTR direction correctly extends to code blocks rendered through shiki. I want to check the CSS around lines 1520-1600, specifically the shiki and pre code selectors and the chat-markdown-file-link chip class, to see if there's any leftover physical spacing logic that conflicts with the new dir="ltr" chip fix.

8. browse_code — apps/web/src/index.css

9. browse_code — apps/web/src/index.css

💭 I'm checking whether the CSS looks clean and scanning for remaining directional issues elsewhere, like the footnote backref arrow, the markdown-clipboard file, and the dir="auto" placement on that wrapper div, plus how user messages are rendered in MessagesTimeline. Then I'm digging into whether <bdi>{alert.label}</bdi> could cause a regression, since bdi elements are inherently excluded from a parent's dir=auto text-content computation per the HTML spec, which could affect how directionality is calculated for surrounding text. Headings should still work fine since they're plain text nodes. I'm now checking whether other chat components besides ChatMarkdown might render text inconsistently—like the message composer, edit view, or streaming "thinking" text—since those may not get the same dir=auto treatment as markdown messages, which could create scope-creep concerns beyond the PR's intended focus.

10. git_tools — ChatMarkdown|whitespace-pre-wrap

💭 I notice MessagesTimeline has plain-text message branches at a few line numbers that use whitespace-pre-wrap divs, skipping markdown rendering entirely—these would stay LTR while markdown-rendered messages get dir="auto", creating a real inconsistency where the same user message could render RTL or LTR depending on which branch it hits. I want to look at that section of MessagesTimeline more closely to confirm.

11. browse_code — apps/web/src/components/chat/MessagesTimeline.tsx

💭 This still seems fine since directional resolution works per markdown segment even for split Hebrew messages. Not a strong finding either way, so I want to check whether these changes introduce a regression in the default LTR mode, particularly around how table cells were previously rendered. I trace through the th/td renderers—since they only destructure node and spread the rest, children still flow through correctly via props. Table alignment styles from remark-gfm still get applied as inline styles, and dir="auto" on cells with numeric or empty content shouldn't cause issues. The code renderer's dir="ltr" is duplicative but harmless for block code, though I notice inline code containing RTL text like Hebrew could have subtle bidi reordering at the edges—a minor edge case, not worth blocking on. I'm now scanning ChatMarkdown.tsx for other elements that render outside the dir=ltr containers, like the CodexArtifactTemplateCard's badge positioning, to check if any physical-direction assumptions in the changed files would actually break in RTL layouts. The badge on the artifact card is positioned physically rather than logically, so in RTL it might sit on the wrong side visually—but this is a minor aesthetic issue rather than a functional bug. I also want to check the skill inline chips and footnote backref styling for similar physical-class usage, though a broader grep already suggests the file mostly uses logical properties, with only a few exceptions. Looking at index.css now, the chat-markdown rules seem largely converted to logical properties too, aside from a hover background-position rule (which is fine since it uses repeat-x) and a checkbox margin that's already using margin-inline correctly. I want to double-check if there's a lingering text-align property around line 1831, and scan for any remaining physical CSS properties tied to markdown selectors that I might've missed in earlier passes. I'm also wondering about the scroll-fade mask on table containers, but that should be fine under ltr direction. Checking a few tests for correctness — one expects specific class/dir attributes, another checks for absence of a border class — both seem reasonable, if a bit brittle. There's also the question of whether copied markdown content preserves the dir attribute, though that's a minor concern. Now I want to check if other physical properties exist elsewhere in the chat message container now that it uses dir=auto. I'm not finding a strong new issue on this pass — the message footer chrome uses LTR-anchored margins, but that's unrelated code, and it seems fine for chrome elements to stay LTR-anchored. Given I haven't found solid findings, I'm leaning toward concluding there's nothing further to flag here. Let me push a bit more before settling — checking whether web's dir="auto" resolution on the whole message versus mobile's exclusion of code/images could create a parity gap, though so far the exclusion logic seems roughly consistent between the two. I'm now looking closer at how markdown autolinks and regular links render as anchor elements to see if there's a real directionality gap there. In RTL, the collapsed chevron should point right, away from the expansion direction, following standard disclosure conventions—so I want to check whether this codebase already uses rtl: variants anywhere, since adding one here would be a new pattern. I also need to think through how rtl:rotate-180 would interact with the existing rotate-90 open-state rotation, since Tailwind's rotate utilities could conflict. I'm mildly convinced the mirrored chevron is borderline rather than a solid finding, so I want to keep scanning. I'm checking the ScrollArea fade and the MarkdownTable footer's expand/copy button layout for LTR/RTL issues, but nothing seems changed there — except I notice the dir="ltr" forced on the table container might be worth investigating further since it wraps footer chrome inside a message block. I'm also verifying that dir="ltr" on the code block wrapper and inline code renderer applies to the correct element, and that it doesn't interfere with the file-link chip or shiki rendering — I want to check that section of the code more closely.

12. browse_code — apps/web/src/components/ChatMarkdown.tsx

13. git_tools — rtl:|dir="auto"|dir="rtl"

💭 Since there are no existing rtl: variants in the codebase, adding one just for the chevron feels like introducing an inconsistent pattern for a purely cosmetic detail. I'm now wondering whether StartTruncatedPath's use of dir="rtl" for its truncation trick might actually be relevant if it's used within chat markdown rendering. Actually, tracing through table cell alignment: with text-align: start and dir="auto" on individual cells, a Hebrew data cell in an otherwise English table would right-align while its English header stays left-aligned in the same column — a genuine visual inconsistency worth checking against how GitHub handles this same case. I also want to check how broadly dir="auto" on the root of ChatMarkdown ripples out, since that component gets reused across surfaces like proposed plan cards and review comment cards, not just chat messages — this is a wide-reaching change that's presumably intentional but worth confirming.

14. git_tools — ChatMarkdown$|from "(../)*components/ChatMarkdown"|from "./ChatMarkdown"|from "../ChatMarkdown"

💭 I'm checking the other consumers—ProposedPlanCard, MessagesTimeline, PullRequestMarkdown, FileMarkdownPreview—since these are all prose surfaces where dir=auto should work fine, and confirming there's no layout chrome that would break. I'm now scanning for any remaining physical-property rules left in the stylesheet. The markdown CSS block itself looks fully converted, and I don't see leftover direction issues in related classes like the file link chip or footnote refs. Now I'm shifting to checking for actual behavioral bugs rather than direction leftovers—verifying that the pre, th, and td component overrides correctly spread props while excluding node and children. I'm also considering whether adding dir="auto" to the outer ChatMarkdown div affects markdown-clipboard serialization during copy, but that seems fine since it builds markdown from the DOM directly. Now I'm focusing on the dir="ltr" attribute on the MarkdownFileLink anchor to see if that's where a subtler issue might be hiding.

15. browse_code — apps/web/src/components/ChatMarkdown.tsx

💭 I'm also thinking about skill mention chips in markdown—since names like "@code-review" are Latin text, a Hebrew message starting with a skill mention would have its direction flipped to LTR since that's the first strong character detected, unlike file-link chips which explicitly force dir="ltr" and are excluded from detection. This seems like an inconsistency: file chips are excluded but skill chips aren't, and mobile's textDirection.ts only excludes code/images too, so this parity gap could cause a real message like "@review שלום עולם" to render LTR when it should be RTL. Let me trace through renderSkillInlineMarkdownChildren and SkillInlineText to confirm the skill chip's text is actually a plain text node inside the markdown flow.

16. git_tools — renderSkillInlineMarkdownChildren|function SkillInlineText|SkillMentionChip|data-skill-mention

17. browse_code — apps/web/src/components/chat/SkillInlineText.tsx

💭 I realize SkillChip labels lack directional isolation, so a Hebrew message starting with a skill mention like "$review בדוק את הקוד" would render LTR since the skill name's first character is a strong LTR char—the same bug class the PR already fixed for file chips, code, and alert labels using <bdi>. This matters because skill mentions commonly appear at the start of user messages. Checking scope, SkillInlineText.tsx falls under apps/web/src/**/*.tsx so it's covered, though it's not itself a changed file—but the dir="auto" addition in ChatMarkdown.tsx makes this pre-existing issue newly relevant. I'm weighing whether to comment on the ChatMarkdown.tsx line again (since I already left a different comment there) versus flagging the specific lines in SkillInlineText.tsx with a suggested fix. But since GitHub review comments require a diff position and SkillInlineText.tsx isn't part of the changed diff, I need to post inline on ChatMarkdown.tsx line 2481 instead, describing the skill chip directionality gap there. I'm also re-verifying the HTML spec's auto directionality algorithm for excluded descendants like bdi and dir-attributed elements—confirming that plain text nodes without dir do get included when calculating the strong directional character, which supports my conclusion. I'm weighing severity: this is a real correctness gap that mirrors the same class of issue the PR already fixed elsewhere (adding bdi/dir=ltr for chips and code), so it's a legitimate finding worth flagging, likely as a moderate-to-real regression risk since it could flip an entire Hebrew message to LTR when a skill chip label leaks in. I'm double-checking whether skill chips actually appear in user messages before Hebrew text — tracing how the token regex matches and how the raw "$name" text gets replaced by the display name in the DOM, confirming that either way the first strong character would end up Latin, making the message render LTR regardless of the chip. This weakens the finding somewhat — it's arguably the standard dir=auto limitation rather than a real inconsistency, though the PR did go out of its way to protect other technical tokens from hijacking direction, so I'd call this a legitimate but medium-confidence gap. I should also check other inline chips like TerminalContextInlineChip, which render outside ChatMarkdown as siblings rather than within it. That dotted underline hover effect isn't a real finding since it looks the same in RTL. But the code block's overflow-x auto with dir="ltr" forcing initial scroll position is worth flagging as the actual fix. I'm also checking whether the shiki fallback rendering has similar dir handling.

18. browse_code — apps/web/src/components/ChatMarkdown.tsx

💭 I'm confirming that shiki-rendered code blocks are already excluded from dir=auto since they sit inside the ltr-marked codeblock container, and now I'm checking the fallback pre case and moving on to how blockquotes handle direction outside the alert path. Overall the web changes look solid, with a few minor weak spots remaining like the skill chip, mirrored chevron, and artifact badge positioning. I'm also considering whether ChatMarkdown's dir=auto root could cause issues in other consumers like FileMarkdownPreview or PullRequestMarkdown, but those seem fine, and I'm checking whether the collapsed user message truncation or the markdown clipboard copy logic could be affected by the new dir attributes—neither seems to be a real concern since they don't rely on text direction. Now I want to look at how table headers and cells render in this new setup. Checking whether react-markdown's table styling handles alignment correctly with the added dir=auto attributes, and whether the table scroll-fade masks still work properly in LTR mode—both seem fine. I'm settling on the skill-chip direction leak as the most concrete remaining issue, since a message like "$review תקן את הבאג" would still display with LTR-aligned Hebrew text, which is exactly the bug this fix is meant to address, and skill mentions are a common enough feature that this matters. I keep going back and forth on whether the skill-chip token counts as "markup that shouldn't decide direction" — but since the token itself is Latin, unlike synthesized text, it's a weaker parallel to the excluded [!NOTE] case. After several passes each surfacing something, I need to decide whether this finding is substantial enough to fail on, or whether I should give an "all clear," so I'm scanning the test file and CSS once more for anything sturdier — checking the task-list item styling next. I'm also checking the text-align: start for table cells, the border-inline-start swap on blockquotes to confirm no other rule sets border-left elsewhere, and verifying Tailwind's border-s/ps utilities work correctly for the alert component's RTL support.

19. git_tools — border-s-|border-e-|text-start|ps-[0-9]|pe-[0-9]|ms-[0-9]|me-[0-9]

20. git_tools — tailwind

💭 Logical utilities like border-s-2 and ms-7 are already used consistently elsewhere in the chat components, confirming this pattern is the norm. I'm now fairly confident the web changes are complete, with remaining candidates like the skill chip label, chevron mirroring, and artifact badge being marginal cases worth one last targeted check. Actually, let me reconsider the dir="auto" behavior more carefully on the ChatMarkdown wrapper. Since dir=rtl sets base direction and text alignment defaults to start (right for RTL), RTL messages become right-aligned automatically, which works fine for user bubbles positioned on the right—and I've confirmed headings, lists, images, and footnotes all correctly inherit or use padding-inline-start rather than hardcoded directions, so nothing here breaks in RTL. I also checked the footnote reference markup and backref arrow—both are direction-neutral and unaffected. Given the "defaults to failure" instruction is really about resolving ambiguity rather than mandating failure by default, and I haven't found any actual UI consistency issues, I'm leaning toward concluding "All clear," though I want to briefly consider whether the new test assertions in MessagesTimeline.test.tsx (which check for a specific count of matching class/dir attribute strings) are brittle in a way that matters, even though attribute-order fragility isn't itself a UI consistency finding. Revisiting the SkillChip case one more time: the PR's core rule is that synthesized or technical UI text shouldn't dictate message direction, and SkillChip substitutes a display name like "Code Review" in place of a $token inside the message—so a Hebrew message containing that token could render LTR, which is exactly the bug class this PR is meant to prevent. The fix would be small: wrapping the chip label in a <bdi> or forcing dir="ltr" on it. That said, I need to check whether SkillInlineText.tsx is actually part of the diff, since GitHub's review API only allows inline comments on lines within changed files—commenting on an untouched file would fail. If it's not in the diff, I'd have to attach the comment to the dir="auto" line in ChatMarkdown.tsx instead, even though I've already left one comment there in a prior pass. I'm also weighing whether this is worth flagging as a genuine i18n gap versus nitpicking, and checking whether skill mention chips also appear in assistant-authored messages, not just user ones. I want to also check the MarkdownExternalLinkContent host rendering to see if it visibly displays the domain text before the link label, which could be a similar text-direction leak issue worth checking.

21. git_tools — MarkdownExternalLinkContent

💭 I'm weighing whether the chevron mirroring in MarkdownDetails is a stronger candidate than the skill chip, then checking whether the dir="ltr" attribute on the code element could actually be a functional regression rather than just polish. Tracing through cases: a table cell containing only inline code falls back to the container's LTR direction, a root message consisting solely of a code block also inherits LTR from its parent, and both seem fine. The trickier case is inline code containing Hebrew text within a quoted string — since dir="ltr" forces that snippet to render left-to-right, I want to check how the mobile implementation handles the same scenario for code blocks versus inline code renderers. Confirming mobile matches web by forcing LTR alignment on inline code too, so both platforms are consistent here. Weighing whether to flag remaining polish-level nits (chip label, chevron mirroring, badge) given the codebase has no rtl: usage and mobile shares the same mention-token behavior — leaning toward not flagging these as scope creep, though the skill chip case still nags at me as possibly the one inconsistency worth raising since everything else (inline code, code blocks, file-link chips, table structure, alert labels) was deliberately handled. The skill chip is the one remaining synthesized label the app generates rather than the user authoring, and a Hebrew message starting with a skill mention would realistically render LTR — exactly the defect this PR is meant to fix, fixable with the same bdi wrap used for alert labels. I'll flag it as a single finding tied to the dir="auto" line in ChatMarkdown.tsx, and since the fix touches a different file (SkillInlineText.tsx) I'll include a small illustrative snippet rather than a formal unified diff. Given this is a clear consistency finding, I'll mark the check as failing overall, consistent with how similar cases have been handled. I need to confirm the exact line number for the review comment — line 2481 with side RIGHT, matching where the prior comment was placed. I want to double check whether formatProviderSkillDisplayName actually transforms the display text into something different from what's typed, which would strengthen the case for flagging this.

22. browse_code — Show the implementation of formatProviderSkillDisplayName in @t3tools/client-runtime providerSkills module — what string does it return for a skill (e.g. name "code-review" with or without displayName)?

💭 I'm confirming the chip shows an app-derived display name substituted for the token, so I'll leave one inline comment explaining the issue and mark the review as failing. My comment will note that dir="auto" derives direction from the first strong character in the rendered text, only skipping subtrees with their own dir attribute or <bdi> tags—which is exactly why forcing dir="ltr" on this element causes the problem. The remaining piece is SkillChip rendering a synthesized skill name as plain text within the mention, which typically leads the message and flips the whole Hebrew text to LTR resolution. The fix is identical to the alert label pattern: wrap the chip label in <bdi> so the generated name gets excluded from direction detection. I'm checking that the target line (2481, the dir="auto" line) is actually in the diff on the right side, confirming it's part of the last added hunk, then I'll post the review comment on ChatMarkdown.tsx and submit the final failing verdict.

23. modify_pr — One finding: the new dir="auto" message direction still counts a synthesized chip label, so skill-mention messages resolve to the wrong direction. Details inline.


Agent Credits: 206 credits

Token usage: 42 uncached input · 1,131,346 cache-read input · 111,948 cache-write input · 27,810 output
Agent Credits may also include non-token charges from external tools such as web research.