Skip to content

Add markdown rendering (incl. tables) to native chat bubbles#546

Merged
shanselman merged 5 commits into
openclaw:masterfrom
RBrid:user/rbrid/MarkdownInNativeChat1
May 27, 2026
Merged

Add markdown rendering (incl. tables) to native chat bubbles#546
shanselman merged 5 commits into
openclaw:masterfrom
RBrid:user/rbrid/MarkdownInNativeChat1

Conversation

@RBrid
Copy link
Copy Markdown
Contributor

@RBrid RBrid commented May 26, 2026

Adds block-level Markdown — headings, lists (incl. GFM task lists), tables, blockquotes, fenced/inline code, thematic breaks, strikethrough, underline — to OpenClaw native chat bubbles. The existing inline-only sanitizer remains the fast path for plain-prose bubbles; bubbles containing block markdown route through a new md4c-based pipeline.

Pipeline

  1. Vendored md4c SAX parser at src/OpenClaw.Shared/Markdown/Md4c/* — copied verbatim from microsoft-ui-reactor @ 01bb3fbc (see VENDORED.md).
  2. ChatMarkdownAstBuilder translates md4c callbacks into a pure-data ChatMarkdownDocument AST.
  3. ChatMarkdownRenderer maps the AST to a FunctionalUI Element tree.
  4. OpenClawChatTimeline.SafeMarkdownText gates on ContainsBlockMarkdown and falls back to a plain TextBlock if rendering fails.

Security posture (preserved end-to-end)

  • Links flattened to inert display (href) text — never a clickable Hyperlink.
  • Images flattened to [Image: alt] — no BitmapImage / no remote fetch.
  • Raw HTML suppressed via md4c NoHtml flag; residual MdRawTextBlock rendered as inert monospace.
  • Hard 256 KB char input cap; oversized payloads truncate to a single inert paragraph.
  • Renderer constructs no Hyperlink / BitmapImage / click or pointer handler.

Robustness

  • Builder Build() fully resets state per call so reuse can't bleed style/link/image/code/table state.
  • Nested links and images-in-links handled via stacks so outer span buffers survive inner spans.
  • TextCallback handles SoftBr / Br / NullChar before link/image depth capture so line breaks and U+FFFD aren't lost inside link display / image alt.
  • EmitInlineText routes flattened text into outer link/image buffers when the LeaveSpan emit still sits inside an outer span.
  • Soft line breaks render as a space Run; hard breaks render as a LineBreak (preserves CommonMark semantics).
  • ContainsBlockMarkdown is a cheap O(n) heuristic — handles up to 3 leading spaces (CommonMark), requires whitespace/EOL after #, detects 3+ -/*/_ thematic breaks, and fenced code with leading indent.
  • Bounded 64-entry LRU AST cache in ChatMarkdownRenderer.Render(string) keyed by source so per-tick FunctionalUI re-renders don't reparse stable bubbles. Element trees are always rebuilt (WinUI parent-slot rule).

Tests

  • 18 md4c parser smoke tests.
  • 24 AST builder tests covering tables, lists, headings, link/image flattening, raw-HTML suppression, the 256 KB cap.

Validation

  • ./build.ps1
  • Shared tests: 2000 passed / 29 skipped
  • Tray tests: 843 passed

Review

Reviewed via two passes of the Hanselman dual-model adversarial review (claude-opus-4.6 + gpt-5.2-codex):

  • Pass 1: 12 findings (2 HIGH-consensus, 10 single-model) — all addressed.
  • Pass 2: clean; both models verified the pass-1 fixes hold and the security invariant survives mixed inline-link/block-trigger inputs.

Renders block-level Markdown — headings, lists (incl. GFM task lists), tables, blockquotes, fenced/inline code, thematic breaks, strikethrough, underline — inside OpenClaw native chat bubbles. The previous inline-only sanitizer remains the fast path for plain-prose bubbles; bubbles containing block markdown route through a new md4c-based pipeline.

Pipeline:

  1. Vendored md4c SAX parser at src/OpenClaw.Shared/Markdown/Md4c/* (copied verbatim from microsoft-ui-reactor @01bb3fbc; see VENDORED.md).

  2. ChatMarkdownAstBuilder translates md4c callbacks into a pure-data ChatMarkdownDocument AST.

  3. ChatMarkdownRenderer maps the AST to a FunctionalUI Element tree.

  4. OpenClawChatTimeline.SafeMarkdownText gates on ContainsBlockMarkdown and falls back to plain TextBlock if rendering fails.

Security posture (preserved end-to-end):

  * Links flattened to inert `display (href)` text — never a clickable Hyperlink.

  * Images flattened to `[Image: alt]` — no BitmapImage / no remote fetch.

  * Raw HTML suppressed via md4c NoHtml flag; residual MdRawTextBlock rendered as inert monospace.

  * Hard 256 KB char input cap; oversized payloads truncate to a single inert paragraph.

  * Renderer constructs no Hyperlink / BitmapImage / click or pointer handler.

Robustness:

  * Builder Build() fully resets state per call so reuse can't bleed style/link/image/code/table state.

  * Nested links and images-in-links handled via Stack<(StringBuilder, string?)> / Stack<StringBuilder> so outer span buffers survive inner spans.

  * TextCallback handles SoftBr/Br/NullChar before link/image depth capture so line-breaks and U+FFFD aren't lost inside link display / image alt.

  * EmitInlineText routes flattened text into outer link/image buffers when the LeaveSpan emit still sits inside an outer span.

  * Soft line breaks render as a space Run; hard breaks render as a LineBreak (preserves CommonMark semantics).

  * ContainsBlockMarkdown is a cheap O(n) heuristic — handles up to 3 leading spaces (CommonMark), requires whitespace/EOL after #, detects 3+ `-/*/_` thematic breaks, and fenced code with leading indent.

  * Bounded 64-entry LRU AST cache in ChatMarkdownRenderer.Render(string) keyed by source so per-tick FunctionalUI re-renders don't reparse stable bubbles. Element trees are always rebuilt (WinUI parent-slot rule).

Tests:

  * 18 md4c parser smoke tests.

  * 24 AST builder tests covering tables, lists, headings, link/image flattening, raw-HTML suppression, the 256 KB cap.

Validation: ./build.ps1, Shared 2000 passed/29 skipped, Tray 843 passed.

Reviewed via two passes of the Hanselman dual-model (claude-opus-4.6 + gpt-5.2-codex) adversarial review — 12 findings addressed in pass 1, pass 2 clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 26, 2026

Codex review: found issues before merge. Reviewed May 26, 2026, 7:11 PM ET / 23:11 UTC.

Summary
Adds block-level Markdown rendering, including tables, to native chat bubbles through a vendored md4c parser, shared AST builder, WinUI renderer, chat timeline routing, and parser/builder tests.

Reproducibility: not applicable. this is a feature PR rather than a reported current-main bug. The after-change screenshots demonstrate the intended native chat rendering path.

Review metrics: 3 noteworthy metrics.

  • Changed surface: 14 files, 11289 additions, 8 deletions. The PR adds a large new parsing/rendering surface, so review needs to cover more than the visible UI screenshots.
  • Vendored parser payload: 7 source files, 9016 added lines. Most of the diff is third-party parser code that needs trustworthy source and license provenance before merge.
  • Behavior proof: 8 screenshots across 2 comments. The PR discussion includes visual after-change evidence for native chat Markdown rendering and list spacing.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦪 silver shellfish
Result: blocked by patch quality or review findings.

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

Rank-up moves:

  • Provide a public upstream source/ref or checked-in source attestation plus the required license/third-party notice for the vendored parser.
  • After the provenance fix, rerun ./build.ps1, shared tests, and tray tests and update the PR body with the fresh results.

Mantis proof suggestion
A live visual smoke would help maintainers verify native chat bubbles, tables, list spacing, and inert link/image text in the app after the provenance blocker is fixed. A maintainer can ask Mantis to capture proof by posting a new PR comment that starts with the OpenClaw Mantis account mention, followed by:

visual task: verify native chat bubbles render headings, lists, tables, code blocks, and inert link/image text without layout overlap.

Risk before merge

  • Merging without verifiable parser provenance would leave maintainers unable to audit, re-sync, or license-review roughly nine thousand lines of vendored parser code that processes untrusted chat text.
  • The PR branch reports validation, but this read-only review did not rerun the build or tests because doing so would create artifacts in the target checkout.

Maintainer options:

  1. Verify vendored parser provenance (recommended)
    Ask the contributor to replace the current VENDORED.md claim with a public repo/ref or checked-in upstream archive/hash, include the required license notice, and rerun the required build/shared/tray validation.
  2. Accept private provenance explicitly
    Maintainers may merge only if they independently have access to the claimed upstream source and record that the parser source and license are acceptable for this security boundary.
  3. Pause for a trusted parser source
    If the upstream cannot be verified, pause or close this branch and reopen with a parser dependency or vendored source that maintainers can audit directly.

Next step before merge
Human review is needed because automation cannot choose or confirm the authoritative upstream parser source, license notice, and acceptable security-boundary risk.

Security
Needs attention: The functional sanitizer design looks intentionally inert, but the vendored parser source and license provenance are not verifiable from the PR.

Review findings

  • [P1] Make the vendored parser source and license verifiable — src/OpenClaw.Shared/Markdown/Md4c/VENDORED.md:4-5
Review details

Best possible solution:

Keep the Markdown renderer direction, but require a public immutable upstream source plus license/third-party notice for the vendored parser before merge.

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

Not applicable; this is a feature PR rather than a reported current-main bug. The after-change screenshots demonstrate the intended native chat rendering path.

Is this the best way to solve the issue?

No; the feature direction is plausible, but this is not the best mergeable form until the vendored parser source, exact upstream commit, and license/notice are verifiable.

Full review comments:

  • [P1] Make the vendored parser source and license verifiable — src/OpenClaw.Shared/Markdown/Md4c/VENDORED.md:4-5
    VENDORED.md points to microsoft/microsoft-ui-reactor, but public checks for that repo, the stated commit, and raw upstream paths return 404. Since this PR adds a large parser for untrusted chat content, maintainers need a verifiable upstream ref plus the required license/notice before this can be accepted.
    Confidence: 0.94

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 4133ae1c7065.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.

Label justifications:

  • P2: This is a normal-priority user-facing rendering improvement with limited blast radius but significant review surface.
  • merge-risk: 🚨 security-boundary: The PR parses untrusted chat content through newly vendored parser code, so merge safety depends on trusted provenance and preserved inert rendering.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (screenshot): The PR discussion includes inspected screenshots showing after-change native Markdown rendering, including headings, lists, code blocks, and decoded entities.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR discussion includes inspected screenshots showing after-change native Markdown rendering, including headings, lists, code blocks, and decoded entities.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR discussion includes inspected screenshots showing after-change native Markdown rendering, including headings, lists, code blocks, and decoded entities.
Evidence reviewed

Security concerns:

  • [medium] Unverifiable vendored parser provenance — src/OpenClaw.Shared/Markdown/Md4c/VENDORED.md:4
    The new md4c parser is copied into the repository, but the documented upstream repository and commit could not be verified publicly; this blocks auditability, re-sync, and license review for security-sensitive parsing code.
    Confidence: 0.94

What I checked:

  • AGENTS.md policy read: The repository AGENTS.md was read fully; it requires build, shared tests, and tray tests after changes, and this read-only review did not run mutating validation commands. (AGENTS.md:1, 4133ae1c7065)
  • Current main lacks the requested renderer: Current main routes chat bubble text through the existing inline sanitizer only; there is no block Markdown renderer or shared Markdown parser path in main. (src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs:91, 4133ae1c7065)
  • PR adds a security-sensitive parser boundary: The PR branch introduces DefaultFlags with GitHub Markdown, NoHtml, and CollapseWhitespace, then uses the AST builder for block Markdown rendering. (src/OpenClaw.Shared/Markdown/ChatMarkdownAstBuilder.cs:51, 607818da2f4c)
  • PR keeps links/images inert in the new AST contract: The added AST type intentionally omits link href and image src fields, so downstream renderers cannot turn parsed chat Markdown into hyperlinks or remote image fetches. (src/OpenClaw.Shared/Markdown/ChatMarkdownAst.cs:13, 607818da2f4c)
  • Vendored provenance is not verifiable: VENDORED.md points at microsoft/microsoft-ui-reactor and commit 01bb3fbcdc21e20db48aa9b6aaf3f70b651de919, but public GitHub checks for that repository/commit/raw paths returned 404 and repository search did not find the claimed repo. (src/OpenClaw.Shared/Markdown/Md4c/VENDORED.md:4, 607818da2f4c)
  • Proof inspected: A downloaded PR screenshot is a 1132x1219 PNG showing rendered headings, bullet and ordered lists, a code block, and decoded entities in a native chat bubble.

Likely related people:

  • Scott Hanselman: Git blame shows the current inert chat Markdown sanitizer and SafeMarkdownText security posture came from commit 02ee756. (role: introduced current security boundary; confidence: high; commits: 02ee756f69ba; files: src/OpenClaw.Tray.WinUI/Chat/ChatMarkdownSanitizer.cs, src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs)
  • kenehong: Recent git history shows repeated chat timeline and bubble layout work in the affected WinUI chat surface. (role: recent chat UI contributor; confidence: medium; commits: 4231feab9c0e, 77375498451c; files: src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs, src/OpenClaw.Tray.WinUI/Chat)
  • Christine Yan: Recent git history shows chat UI polish, caching, alignment, scroll, and multi-agent navigation work in the same chat area. (role: recent chat UI contributor; confidence: medium; commits: a482ca9e1713, 9478e953dc38; files: src/OpenClaw.Tray.WinUI/Chat/OpenClawChatTimeline.cs, src/OpenClaw.Tray.WinUI/Chat)
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: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels May 26, 2026
@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 26, 2026

ClawSweeper PR egg

🔥 Warming up: real-behavior proof passed; findings, security review, or rank-up moves are still in progress.

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.
What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

Regis Brid and others added 3 commits May 26, 2026 14:07
md4c does NOT emit explicit P open/close events for the raw inline
text inside tight list items (the CommonMark-compliant behavior).
The AST builder was assuming a P would always wrap text inside Li,
so it never drained _inlines at LeaveBlock(Li). The result in real
chat traffic was:

  * every bullet rendered empty (Li.Children was empty)
  * the accumulated tight-list text bled into the next real
    paragraph in the bubble, producing a megaparagraph of all the
    list content jammed together.

Two fixes in ChatMarkdownAstBuilder:

1. LeaveBlock(Li): drain any pending _inlines into an implicit
   MdParagraph child before constructing the MdListItem, so the
   simple tight-list case renders content under the bullet.

2. EnterBlock(*): if the current parent is Li or Quote and we have
   pending inlines, flush them into an implicit MdParagraph FIRST.
   This handles the nested-block-inside-tight-Li case (e.g. a
   nested Ul) where the outer Li's text would otherwise bleed into
   the first nested item.

Adds two regression tests in ChatMarkdownAstBuilderTests:

  * TightList_LiContentSurfacesAsImplicitParagraph - asserts each
    bullet has a paragraph child with the expected inlines, and
    that the trailing paragraph contains ONLY its own text.
  * TightList_NestedItemsAlsoSurfaceContent - asserts the outer Li
    contains both a paragraph and the nested MdList, and that the
    nested items also have paragraph content.

Root cause was not caught by either Hanselman review pass because
the existing list tests only counted items and the loose-list path
(blank lines between items) does get explicit P from md4c.

Validation:
  build.ps1: green
  Shared tests: 2002 passed / 29 skipped
  Tray tests: 843 passed

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
md4c emits MarkdownTextType.Entity events for syntactically-valid
HTML entity references (e.g. &amp;, &#x41;, &copy;). The AST builder
previously fell through to the default case and dropped them,
producing rendering like "AT&amp;amp;T" instead of "AT&amp;T".

Add an Entity case that decodes the token via a new DecodeEntity
helper and routes it through the existing image-alt / link-display
/ inline-text paths, matching how Normal text is handled.

DecodeEntity covers:
- Decimal numeric refs (&#NN;)
- Hex numeric refs (&#xHH; / &#XHH;, either case)
- Named entities via the existing internal Md4cEntity.EntityLookup
  table (including two-codepoint sequences like &fjlig; -> "fj")
- CommonMark folding: NUL, surrogates, and codepoints above
  U+10FFFF collapse to U+FFFD; the in-loop > 0x10FFFF guard
  prevents int overflow on long hex inputs
- Codepoint0 == 0 sentinel (md4c's "no replacement") returns the
  raw token verbatim
- Unknown named entities pass through verbatim
- SafeConvertFromUtf32 defensively rejects out-of-range values so
  a corrupted entity table can never throw

Add 13 regression tests covering: ampersand, copyright, common
named entities (theory with 8 cases), decimal and hex numeric refs,
supplementary-plane codepoints (surrogate pair), NUL, surrogate
folding, unknown entities, entity inside a strong span, max-valid
codepoint boundary, above-max replacement, and two-codepoint
named entity decoding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tables in chat bubbles previously had no borders, making columns
visually ambiguous. The HTML dashboard renders tables with cell
borders; bring the native chat in line.

Each cell paints a 1px top stroke (when rowIndex > 0) and a 1px
left stroke (when colIndex > 0); an outer Border on the grid closes
the bottom and right edges. The result is a uniform 1px grid with
no double-thickness lines at internal cell boundaries.

Color is #40808080 (semi-transparent gray) so it reads well in both
light and dark themes without depending on a theme resource. The
header row gets a subtle Theme.CardBackground tint and slightly
larger cell padding.

A single SolidColorBrush is cached lazily in a static property
(TableGridBrush) and reused by every cell border and the outer
wrapper, avoiding per-cell brush allocation on each table render.
WinUI 3 brushes are shareable across elements; the renderer runs
on the dispatcher thread so the lazy-init is single-threaded.

ParseHex parses the hex constant into a Windows.UI.Color and falls
back to Microsoft.UI.Colors.Transparent on malformed input.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@RBrid
Copy link
Copy Markdown
Contributor Author

RBrid commented May 26, 2026

A few testing screenshots:

image image image image image image image

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 26, 2026
@RBrid RBrid marked this pull request as ready for review May 26, 2026 22:40
ClawSweeper flagged that list bullets and numbers rendered flush
against their content. The previous implementation packed two
trailing spaces into the marker TextBlock and used a zero-spacing
HStack, but WinUI's text layout collapses trailing whitespace
inside a TextBlock so no actual gap appeared on screen.

Strip the trailing whitespace from the marker strings and give the
marker TextBlock an explicit MinWidth so the content column starts
at a stable x-coordinate. Bullets use 10 px (tight, browser-like);
ordered markers use 18 px so "10." still leaves a small gap before
the content and single-digit numbers stay visually aligned with
multi-digit ones in the same list.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@RBrid
Copy link
Copy Markdown
Contributor Author

RBrid commented May 26, 2026

Improved spacing after bullet points and list numbers:

image

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels May 26, 2026
@shanselman shanselman merged commit 0a164fc into openclaw:master May 27, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants