Skip to content

feat(android): syntax-highlighted code blocks in chat#100217

Merged
steipete merged 5 commits into
mainfrom
feat/android-code-highlighting
Jul 5, 2026
Merged

feat(android): syntax-highlighted code blocks in chat#100217
steipete merged 5 commits into
mainfrom
feat/android-code-highlighting

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fenced code blocks in Android chat render as flat monospace text, making code-heavy assistant replies hard to scan.

Part of #100195

Why This Change Was Made

Adds a minimal in-repo tokenizer (apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatCodeHighlight.kt) for kotlin/swift/typescript/javascript/python/bash/json with keyword/string/comment/number classes. An external highlighting library was evaluated and rejected: ~10 months without releases/commits, single maintainer, and no JSON support, versus ~300 lines of owned, testable code with no license-screen overhead. Token colors are new MobileColors code-palette slots (light+dark, ≥4.5:1 contrast against the code background). Streaming stays cheap: still-open fences render plain while a message streams (gated on CommonMark closingFenceLength + stream state), results are memoized per block content, and blocks over 200 lines or 20k chars fall back to plain rendering.

User Impact

Assistant code blocks in chat get readable, theme-aware syntax coloring in light and dark mode. Unknown languages, streaming partial blocks, and very large blocks keep today's plain rendering. No config or behavior surface changes.

Evidence

  • apps/android: ./gradlew :app:testPlayDebugUnitTest --tests '*ChatMarkdown*' --tests '*AndroidLicenseNotices*' — 20 tests, 0 failures (same green on :app:testThirdPartyDebugUnitTest)
  • New tests in ChatMarkdownTest.kt: known-language tokens, theme span colors, unknown-language plain fallback, open-fence detection, line/char bounds incl. exact 200-line boundary, escaped quotes, bash comment boundaries, nested block comments, multiline template literals/shell strings
  • Codex autoreview: 6 iterative rounds during development; 8 accepted findings fixed, each with a regression test; final run clean ("patch is correct", 0.88)

Known gap: unit-test proof only; no emulator screenshot pass of the rendered palette yet.

@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed July 5, 2026, 7:17 PM ET / 23:17 UTC.

Summary
Adds bounded Android syntax highlighting for fenced chat code blocks, wires streaming-complete state through Markdown rendering, updates token palette slots, tests, native i18n inventory, and a changelog entry.

PR surface: Docs +1, Other +518. Total +519 across 8 files.

Reproducibility: not applicable. as a bug reproduction: this is a feature PR. Source inspection confirms current main renders Android code blocks as plain monospace, and PR comments plus the real-behavior check report exact-head emulator proof for highlighted rendering.

Review metrics: 1 noteworthy metric.

  • Android dependency surface: 0 dependencies added, 0 license files changed. The Android scoped guide requires license-screen maintenance when app dependencies change; this PR keeps highlighting in owned Kotlin code instead.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100195
Summary: This PR is the Android implementation candidate for the broader mobile chat Markdown rendering issue; the merged Apple PR covers the adjacent iOS/macOS slice.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
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:

  • [P2] Resolve the CHANGELOG.md ownership decision before merge.

Risk before merge

  • [P1] The direct CHANGELOG.md entry remains despite release-owned policy and a prior ClawSweeper finding; maintainers should remove it or explicitly accept it as an exception before merge.
  • [P1] Live exact-head CI was still settling during inspection, so merge should wait for required checks even though this does not change the code-review priority.

Maintainer options:

  1. Remove release-owned changelog edit (recommended)
    Remove the direct CHANGELOG.md line and keep the release-note context in the PR body or squash metadata before merge.
  2. Accept a maintainer exception
    Merge with the changelog entry intact only if maintainers intentionally accept the release-note drift risk.

Next step before merge

  • [P2] Manual review is appropriate because the protected maintainer-labeled PR has an unresolved, disputed release-owned changelog edit rather than a safe automation-only repair.

Maintainer decision needed

  • Question: Should this protected maintainer-labeled Android chat highlighting PR keep the direct CHANGELOG.md entry, or should release-note context stay only in PR/squash metadata per release-owned changelog policy?
  • Rationale: The root policy is clear, but the author explicitly disputed the earlier changelog finding and the PR carries a protected maintainer label, so automation should not silently override maintainer intent.
  • Likely owner: steipete — They are assigned, authored the related native chat rendering work, and already responded to the changelog policy finding on this PR.
  • Options:
    • Remove the changelog entry (recommended): Keep the release-note wording in the PR body or squash message and let release generation create the final CHANGELOG.md entry.
    • Keep as maintainer exception: Accept this direct Unreleased entry as an intentional exception and own the duplicate or stale-note risk during release generation.

Security
Cleared: No concrete security or supply-chain concern found; the diff adds no dependencies, workflows, permissions, secrets handling, downloaded artifacts, lockfile changes, or package-resolution changes.

Review findings

  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:16
Review details

Best possible solution:

Land the Android chat highlighter after resolving the release-owned changelog decision and waiting for exact-head required checks to finish.

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

Not applicable as a bug reproduction: this is a feature PR. Source inspection confirms current main renders Android code blocks as plain monospace, and PR comments plus the real-behavior check report exact-head emulator proof for highlighted rendering.

Is this the best way to solve the issue?

Yes for the Android implementation shape: the bounded in-repo tokenizer avoids a new app dependency and preserves plain rendering for unknown, partial, and oversized blocks. The unresolved part is release-note ownership, not the renderer layer.

Full review comments:

  • [P3] Remove the release-owned changelog entry — CHANGELOG.md:16
    This PR still adds a direct CHANGELOG.md line, but root policy keeps the changelog release-owned and says feature release-note context belongs in the PR body, squash message, or direct commit metadata. This is the same unresolved prior ClawSweeper finding, and leaving it here risks duplicated or stale generated release notes.
    Confidence: 0.9

Overall correctness: patch is correct
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add merge-risk: 🚨 other: Merging the direct CHANGELOG.md edit can conflict with release-owned changelog generation even though runtime CI cannot catch that policy drift.

Label justifications:

  • P2: This is a normal-priority Android chat readability feature with limited blast radius, not a crash, data-loss, security, or first-run blocker.
  • merge-risk: 🚨 other: Merging the direct CHANGELOG.md edit can conflict with release-owned changelog generation even though runtime CI cannot catch that policy drift.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Exact-head PR comments and the Real behavior proof check report Android API 35 emulator/Testbox proof through onboarding, Gateway pairing, chat injection, and visible Kotlin token colors.
  • proof: sufficient: Contributor real behavior proof is sufficient. Exact-head PR comments and the Real behavior proof check report Android API 35 emulator/Testbox proof through onboarding, Gateway pairing, chat injection, and visible Kotlin token colors.
Evidence reviewed

PR surface:

Docs +1, Other +518. Total +519 across 8 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 1 1 0 +1
Config 0 0 0 0
Generated 0 0 0 0
Other 7 548 30 +518
Total 8 549 30 +519

What I checked:

Likely related people:

  • steipete: Authored the merged Apple chat syntax-highlighting/table PR, recent Android chat streaming/outbox work, and this protected maintainer-labeled Android companion PR. (role: recent feature owner and likely follow-up owner; confidence: high; commits: 3f380635f59b, 3f493aa6d015, 77575d74f68c; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCodeHighlighter.swift, apps/android/app/src/test/java/ai/openclaw/app/chat/ChatControllerStreamReplayTest.kt, apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMessageViews.kt)
  • Pluviobyte: Authored the merged Android change that routed chat content through ChatMarkdown, the central path this PR extends. (role: recent Android Markdown contributor; confidence: high; commits: df350e672009; files: apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMarkdown.kt, apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatScreen.kt, apps/android/app/src/test/java/ai/openclaw/app/ui/chat/ChatMarkdownTest.kt)
  • obviyus: History points to the earlier Android GFM/CommonMark chat renderer work that established the current Markdown/code-block boundary. (role: introduced Android CommonMark rendering path; confidence: medium; commits: ff4dc050cc84; files: apps/android/app/src/main/java/ai/openclaw/app/ui/chat/ChatMarkdown.kt, apps/android/app/build.gradle.kts, apps/android/gradle/libs.versions.toml)
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.
Review history (21 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-05T20:31:06.239Z sha 957039d :: needs changes before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T20:43:51.140Z sha df11e55 :: found issues before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T21:02:20.227Z sha 791a343 :: found issues before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T21:12:25.824Z sha 4f8c042 :: needs changes before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T21:22:46.690Z sha 4f8c042 :: needs changes before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T21:32:25.113Z sha d6b3d09 :: needs changes before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T22:01:59.683Z sha 2b9b791 :: needs changes before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T23:06:13.687Z sha 5b7061a :: found issues before merge. :: [P3] Remove the release-owned changelog entry

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 5, 2026
@steipete steipete self-assigned this Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot added app: android App: android size: L maintainer Maintainer-authored PR labels Jul 5, 2026
@steipete
steipete requested a review from a team as a code owner July 5, 2026 10:46
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord channel: slack Channel integration: slack channel: voice-call Channel integration: voice-call app: ios App: ios app: macos App: macos app: web-ui App: web-ui gateway Gateway runtime cli CLI command changes scripts Repository scripts commands Command implementations docker Docker and sandbox tooling agents Agent runtime and tooling extensions: anthropic channel: qa-channel Channel integration: qa-channel extensions: qa-lab extensions: memory-wiki extensions: codex size: XL and removed size: L labels Jul 5, 2026
@openclaw-barnacle openclaw-barnacle Bot added channel: imessage Channel integration: imessage scripts Repository scripts docker Docker and sandbox tooling channel: qqbot size: XL and removed size: L labels Jul 5, 2026
@clawsweeper clawsweeper Bot removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 5, 2026
@steipete
steipete force-pushed the feat/android-code-highlighting branch from ea739ed to 3edabe7 Compare July 5, 2026 12:00
@openclaw-barnacle openclaw-barnacle Bot added size: L and removed docs Improvements or additions to documentation channel: imessage Channel integration: imessage scripts Repository scripts docker Docker and sandbox tooling channel: qqbot size: XL labels Jul 5, 2026
@clawsweeper clawsweeper Bot added the rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. label Jul 5, 2026

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Fresh real-device-path visual proof on exact head 0d9b7e7c0d435ff9294c5b5eada85e7488661c0f:

  • Blacksmith Testbox tbx_01kws9et3s5zzm9fmnr8mvfh0p, Android API 35 Google APIs x86_64 emulator
  • built and installed the Play debug APK, then completed the supported setup-code onboarding, Gateway pairing, node approval, and Chat flow
  • created the session through the Android chat composer, then appended a fenced Kotlin assistant message through the documented Gateway chat.inject method
  • captured and inspected the emulator screenshot locally: fun rendered blue, the string rendered green, and the numeric literal rendered yellow, while identifiers remained neutral
  • screenshot stayed local and was not uploaded

This closes the prior visual-proof gap. The existing focused tests, APK build, changed-surface checks, exact-head CI, and fresh autoreview remain green.

@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready on exact head 1d322c0b063f4ad6113646ba5b2c066485fc25b5.

  • Fresh Codex autoreview: clean, patch correct (0.86).
  • GitHub Actions run 28747796736, attempt 2: all exact-head jobs passed, including Android Play/third-party unit suites, Play APK build, lint, dependency checks, and QA smoke.
  • Blacksmith Testbox tbx_01kwrtn5326f5vr904aa0s9kws: focused Markdown regression plus both-flavor unit suites and Play debug APK assembly passed.
  • Blacksmith Testbox tbx_01kws9et3s5zzm9fmnr8mvfh0p: API 35 emulator with a real Gateway-rendered Kotlin fence confirmed keyword, string, and number colors.
  • Review artifacts validated with no findings or proof gaps.

@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready at clean exact head f5c196dcad5f0e54e04effe0238e1f954f3c3f5c.

Proof:

  • Fresh Codex autoreview: clean with no accepted/actionable findings, confidence 0.86, after verifying the pinned CommonMark 0.28.0 nullable closing-fence contract.
  • GitHub Actions run 28758520358: all required jobs passed on the exact head, including both Android unit suites, Play APK build, lint, dependency checks, and QA smoke.
  • PR history was rewritten to the five intended Android commits only; the live GitHub diff is 8 files with no unrelated mainline carryover.
  • Blacksmith Testbox: focused Markdown tests, Play and third-party debug unit suites, and Play APK assembly passed.
  • API 35 emulator against a real Gateway rendered Kotlin fences with verified keyword, string, and number spans; screenshot retained locally only.
  • git diff --check passed.

No known proof gaps. Ready to merge.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Dependency graph guard cleared

This PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh /allow-dependencies-change comment after the guard blocks that new head SHA.

  • Current SHA: f5c196dcad5f0e54e04effe0238e1f954f3c3f5c

@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

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

Labels

app: android App: android maintainer Maintainer-authored PR merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. 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