Skip to content

feat(ios): render inline LaTeX math in completed chat prose#101388

Merged
steipete merged 1 commit into
mainfrom
feat/ios-inline-math-nash
Jul 7, 2026
Merged

feat(ios): render inline LaTeX math in completed chat prose#101388
steipete merged 1 commit into
mainfrom
feat/ios-inline-math-nash

Conversation

@steipete

@steipete steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Related: #100699

What Problem This Solves

Inline LaTeX (\(...\)) in assistant responses still rendered as raw TeX after #100829 shipped display math — inline was the declared follow-up because SwiftUI Text runs cannot embed views.

Why This Change Was Made

Inline math now renders in completed iOS/macOS chat prose via SwiftMath-rendered images interpolated into Text (the Text(Image(...)) concatenation path), with baseline alignment driven by SwiftMath's own display-list descent (MTMathImage/MTMathListDisplay.descent, verified against the dependency source). Delimiters are strictly \(...\) — single-dollar spans stay text (currency). A code-aware scanner (confirmed backtick-run pairing, escape handling) splits prose outside inline code; unclosed or newline-containing spans stay literal, spans are capped (16 per block, 200 bytes each), and every span passes the same parse guards as display math via the shared cache (ASCII-only, nesting/command bounds, unsafe color commands) — anything rejected renders as literal text, never dropped. The streaming boundary is enforced at construction: only completed prose builds inline content, so the streaming reveal pipeline and per-delta costs are untouched. Rendered images are cached (bounded, keyed by latex/size/color) and Dynamic-Type-sized via ScaledMetric.

User Impact

Inline formulas in finished messages render as proper math on iOS and macOS; streaming text, code spans, currency amounts, and malformed spans are unaffected.

Evidence

  • 258 tests / 6 focused suites green at the rebased head, including 15 new inline-math tests (scanner cases incl. backtick exclusion and escapes, caps, guard reuse, streaming-stays-literal boundary, Markdown/link preservation, allocation bounds) and the untouched display-math/reveal/replay suites.
  • iOS xcodebuild build-for-testing green; inline-math transcript case added to the render smoke suite; SwiftMath image/baseline APIs cited from the checked-out dependency source.
  • Full-suite noise on this machine (Keychain-polluted GatewayNodeSessionTests) is pre-existing machine state in untouched files — flagged separately for a test-isolation fix.
  • swiftformat --lint clean on touched files; i18n inventory unchanged; structured review (codex) clean.

@openclaw-barnacle openclaw-barnacle Bot added app: ios App: ios scripts Repository scripts size: L maintainer Maintainer-authored PR labels Jul 7, 2026
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 1:40 AM ET / 05:40 UTC.

Summary
The PR adds inline \(...\) LaTeX detection and SwiftMath image interpolation to the shared iOS/macOS chat renderer, moves the math parse cache into a shared helper, wires assistant typography, adds Swift tests and an iOS smoke case, and includes the new Swift file in the iOS filelist.

PR surface: Other +735. Total +735 across 7 files.

Reproducibility: not applicable. this is a feature PR, not a bug report with a failing reproduction. Source inspection shows current main leaves inline math as prose, while the PR adds the completed-prose rendering path and focused regression tests.

Review metrics: 1 noteworthy metric.

  • Inline math bounds: 16 spans per block, 200 bytes per span, 80 cached rendered images. These concrete caps bound untrusted assistant LaTeX scanning, parsing, and bitmap rendering work before merge.

Stored data model
Persistent data-model change detected: persistent cache schema: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownBlockViews.swift. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🌊 off-meta tidepool
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Next step before merge

  • [P1] No repair job is appropriate because this active protected PR has no narrow code defect from review and should continue through ordinary maintainer and CI review.

Security
Cleared: No concrete security or supply-chain regression was found; the PR does not change dependencies, workflows, secrets, or package resolution, and it bounds untrusted LaTeX rendering through existing parse guards and image-size caps.

Review details

Best possible solution:

Land a scoped shared iOS/macOS chat renderer change that renders completed inline math, keeps streaming cheap, preserves Markdown/code/currency literals, bounds SwiftMath parsing/rendering, and carries focused renderer proof.

Do we have a high-confidence way to reproduce the issue?

Not applicable: this is a feature PR, not a bug report with a failing reproduction. Source inspection shows current main leaves inline math as prose, while the PR adds the completed-prose rendering path and focused regression tests.

Is this the best way to solve the issue?

Yes: the PR is an appropriate owner-boundary solution because it extends the shared chat renderer after block segmentation, reuses display-math parse guards, avoids the streaming reveal path, and keeps single-dollar currency text untouched.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against cc085da581fa.

Label changes

Label changes:

  • add P3: This PR adds mobile chat transcript polish for inline math rather than fixing a blocked setup path, data loss, security bypass, or broken channel workflow.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: This maintainer-labeled PR is not held to the external-contributor proof gate; the PR body still provides build/test evidence for the changed renderer path.

Label justifications:

  • P3: This PR adds mobile chat transcript polish for inline math rather than fixing a blocked setup path, data loss, security bypass, or broken channel workflow.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: This maintainer-labeled PR is not held to the external-contributor proof gate; the PR body still provides build/test evidence for the changed renderer path.
Evidence reviewed

PR surface:

Other +735. Total +735 across 7 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 7 811 76 +735
Total 7 811 76 +735

What I checked:

Likely related people:

  • steipete: Authored the merged display-math PR, the streaming reveal path, and the current inline-math follow-up across the shared chat renderer files. (role: feature owner and recent area contributor; confidence: high; commits: 2a741bebb54f, 83f052772429, 3f380635f59b; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownRenderer.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownBlockViews.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownBlockSegmenter.swift)
  • joshavant: Recent path history shows work on chat soft line breaks and branded typography checks that are adjacent to this renderer and typography-sensitive change. (role: adjacent typography and renderer contributor; confidence: medium; commits: 47845e16511d, ea3c6dc5f733; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMarkdownRenderer.swift, apps/ios/Tests/OpenClawTypographyTests.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels Jul 7, 2026
@steipete
steipete merged commit 48e77b6 into main Jul 7, 2026
140 of 147 checks passed
@steipete
steipete deleted the feat/ios-inline-math-nash branch July 7, 2026 07:46
sheyanmin pushed a commit to sheyanmin/openclaw that referenced this pull request Jul 8, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: ios App: ios maintainer Maintainer-authored PR P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: L status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant