Skip to content

fix(chat): native chat shows literal details tags instead of collapsible sections - #1773

Open
paulcam206 wants to merge 23 commits into
openclaw:mainfrom
paulcam206:paulcam206-markdown-details-disclosures
Open

paulcam206 wants to merge 23 commits into
openclaw:mainfrom
paulcam206:paulcam206-markdown-details-disclosures

Conversation

@paulcam206

@paulcam206 paulcam206 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes: native chat shows literal <details>, <summary>, and </details> text instead of a collapsible section when an assistant message uses the common disclosure pattern.

I started this work after seeing a reply in Hub chat that came back as a <details>/<summary> block rendered as literal tags instead of a collapsible section. The BEFORE screenshots under Evidence reproduce that same literal-tag rendering with a canned message; they are not a capture of the original reply.

User Impact

User impact: assistant messages with <details><summary>...</summary>...</details> sections render as a native, keyboard-operable expand/collapse control named after the summary, with the Markdown body (paragraphs, lists, tables, quotes, code) revealed on expansion. Expansion state survives rerender, streaming body updates, and resize. Unsupported or incomplete forms stay literal text. No migration or user action required.

Why This Change Was Made

The active chat path (ReactorChatTimeline.BuildSafeMarkdown on Microsoft.UI.Reactor) uses NoHtml, so raw HTML is inert and <details> is never recognized. The change recognizes only balanced, block-level <details>/<summary> wrappers (the existing md4c parser distinguishes prose from code and containers), renders a native WinUI Expander with keyed Reactor expansion state, and passes the body through the existing sanitized Markdown renderer, so it follows the same rules as the rest of the message: http/https links and bare URLs are live (since #2093), while other link schemes, images and raw HTML stay inert. Summary text is plain header text, not an HTML surface; a link in it reads as text (url).

Supported: same-line or later-line non-empty summary, initial open, nested disclosures up to 16 levels. Left literal: unsupported attributes, empty summaries, summaries not closed before a blank line or another disclosure wrapper, deeper nesting, incomplete streaming wrappers, and disclosures inside code, quotes, lists, or table cells. An unclosed summary cannot borrow a later section's </summary>, so a following valid disclosure still renders. As in GitHub Markdown, a closing-wrapper line directly after a table ends the table and closes the disclosure.

The implementation-string rendering guards were replaced by behavioral parser/native tests. The independent CI profile-isolation contract is now restored separately: the UI job runs Set-CiUiTestEnvironment.ps1 from the pipeline revision, and test-ci-ui-profile.ps1 executes that same exporter, and the workflow step that loads it, against throwaway checkouts and environment files. It checks the emitted data, roaming AppData, local AppData, and repository-root bindings without reading workflow or implementation source. The default-root case runs from a different caller directory to prove that repository selection follows the exporter checkout.

Author scope acceptance: The PR author accepts the documented restricted, balanced, block-level native <details>/<summary> scope: "accept the narrow block-level syntax". Unsupported forms retain inert rendering and literal fallback.

Sole remaining repository sign-off: the repository's maintainers still need to decide whether to adopt this restricted rendering capability. The author's scope acceptance carries no repository-maintainer approval.

Evidence

Current head 5a1b8975 (merges of main 1ebcf004, 6ddc13b8 and 20d85144)

The author normal-merged main three times on top of the maintainer's merge 0abb30a4, without rewriting it: 422593ce merged 1ebcf004, 8890e1b8 merged 6ddc13b8, and the current head 5a1b897510c4128765eb06cfe94da54d972ae0a1 (tree b33f2873) merged main 20d851442129767678b3345b9d5b5ea8ae114410.

Previous head 0abb30a4 (maintainer merge of main 3d5f1427)

At maintainer @bkudiess's request, roboclaw-bot merged main 3d5f14270dd6bd8b260a723ff2e73a68ea858ca8 into this branch on 2026-11-12 with a normal push (refresh note). 0abb30a457652952c73aa78ff33cee67b3329525 is a two-parent merge with 6efff19a first. The author pushed nothing after it.

  • Conflict: only ReactorChatMarkdownContractTests.cs, which main improve(chat): refine composer sizing and context controls #2117 extended and this PR deletes. It stays deleted. Its new source-text check that Markdown reads the shared ChatThemeChanges contrast owner became behavior: the mounted web-parity proof now sets ChatThemeChanges.IsHighContrast and calls ChatThemeChanges.Refresh() directly, and expects mounted Markdown highlighters to clear and return.
  • What main changed around disclosures: improve(chat): refine composer sizing and context controls #2117 gives prose the primary text tone and moves High Contrast tracking into ChatThemeChanges, which ChatMarkdownPresentation.IsHighContrast now forwards to; it also wraps the transcript in a fade border. None of this touches the disclosure parser, Disclosures, MessageBlocks or BuildSafeMarkdown: those regions, ChatMarkdownDisclosures.cs, its unit tests and the disclosure proof are byte-identical to 6efff19a.
  • Negative control C (new): with ChatMarkdownPresentation.IsHighContrast turned into a private probe instead of forwarding to ChatThemeChanges, the web-parity proof fails at "High Contrast clears chat highlighters" in both themes (negctl-summary.txt). That is the gap the maintainer's retarget closes: the test previously set the Markdown probe directly, which bypasses the shared owner. Controls A and B were not repeated: the code they mutate and the assertions they target are byte-identical to 6efff19a, where both failed as intended (history below).

Native proof on 0abb30a4 (latest real Hub screenshots)

One throwaway crabbox Hyper-V guest, released afterwards: lease cbx_5fbc94545ce3, Windows 11 Enterprise Insider Preview 10.0.29683 x64, 6 vCPU, interactive session, fresh clone with head 0abb30a457652952c73aa78ff33cee67b3329525 and tree 226f73e6 checked before and after, merge base 3d5f1427, isolated OPENCLAW_TRAY_* roots, WindowsAppSDK 2.6.5 (project.assets.json resolves 2.6.5, Reactor 0.1.0-preview.17) and the signed WindowsAppRuntime 2.6.5 installer.

  • Hub ...Sha.0abb30a457652952c73aa78ff33cee67b3329525, OpenClaw.Tray.WinUI.exe SHA-256 7DEED6F0C71CBD63FE182DF8B938AE9663709ADA70AB27977287A0BA1501A90C. BEFORE: main 3d5f14270dd6bd8b260a723ff2e73a68ea858ca8, SHA-256 178D99C92F37CE5F39D30ED3CD4C9D15ADB68B0EA26711EDF285D7FFC63E2085, same guest, fixture host and transcript.
  • The same canned transcript as earlier heads: lists, inline code, a web link and a bare URL, a fenced code block, a nested open disclosure and the unclosed-summary review case. The fixture host's own --theme option sets the theme; the only harness change serves the transcript.
  • Assets: 16e785dd on branch proof/1773-0abb30a4-20261112 (summary.txt with TRX counts and hashes, per-theme UIA reports, the negative-control result, the disclosure test-host captures under visual/ and main's web-parity sample rendered by this head under visual-webparity/).
BEFORE: main 3d5f1427, Light AFTER: 0abb30a4, Light AFTER: 0abb30a4, Dark
Start of the conversation, both disclosures collapsed main collapsed light collapsed dark collapsed
"Sources and evidence" expanded: nested section starts open, web links are live, tags in code stay literal n/a light expanded dark expanded
Both disclosures expanded n/a light all expanded dark all expanded
Review case: unclosed summary, then a valid disclosure main review case light review case dark review case

UIA log, identical for Light and Dark: "Sources and evidence" Collapsed, Expand, Expanded; "Raw command output" Collapsed to Expanded; both collapsed again; in the review case the unclosed <details><summary>First stays literal and "Second" expands. On main there are no disclosure buttons.

Earlier-head evidence (superseded by the current head above; kept for history)

Earlier-head screenshots are linked rather than embedded.

Head 6efff19a (rebased on main 65de1e35, superseded by the maintainer merge 0abb30a4)

  • Rebased onto main 65de1e35, resolving conflicts with improve(chat): assistant Markdown follows the web chat's spacing, tones and code colors #2101 (web Markdown rhythm, list, marker and divider hooks, code colors) and feat(automations): native Automations page with web parity #1893 (CI). Disclosures adopted main's 14-pixel block rhythm, and a heading right after a disclosure keeps its lead-in. improve(chat): assistant Markdown follows the web chat's spacing, tones and code colors #2101's source-text checks were replaced by mounted list, marker and divider assertions in ReactorMarkdownWebParityProofTests.
  • Native proof, lease cbx_88fd03b6e5de: ./build.ps1 passed; Shared 5,772 passed; Tray 6,323 passed; parser 27; disclosure proofs 2/2; visual 4/4; main's Markdown UI proofs 7/7. Negative control A (old 8-pixel gap, list hooks removed) failed on the block gap (14 vs 8) and list gap (6 vs 2); B (divider hook removed, Markdown after a disclosure treated as leading) failed on the heading lead-in (7 vs 0) and the divider's accessibility view. Real Hub Light and Dark UIA checks passed. Hub ...Sha.6efff19a, SHA-256 D26C9EDA299EC7FB08616D65E5672163CEED631CE524C65859344B61103604B7. Assets on 08c7df27.
  • Hosted CI never ran on 6efff19a: its runs were created during GitHub's Actions incident on 2026-11-11 and stayed queued with no jobs.

Screenshots (main 65de1e35 BEFORE, 6efff19a Light and Dark: both collapsed, sources expanded, both expanded, review case): 1773-6efff19a/real-hub/ at the pinned proof commit.

Head fd03c448 (rebased on main e59374c0, superseded by 6efff19a)

  • main improve(chat): align native conversation and tool activity with web #2093 made assistant http/https links and bare URLs live and added after-reconcile inline styling. The disclosure renderer adopted main's sanitizer, Markdown options and styling, and fd03c448 kept summaries inert (a summary link reads docs (url)). AssistantMarkdown_DisclosureFollowsTheChatLinkAndContentPolicy replaced the inert-content proof; a negative control without the inert summaries failed exactly that proof.
  • Native proof, lease cbx_50d4db5c64c4: ./build.ps1 passed; Shared 5,615 passed; Tray 6,152 passed; parser 27; disclosure proofs 2/2; visual 4/4; real Hub Light and Dark UIA checks passed. Hub ...Sha.fd03c448, SHA-256 1382B1C0BB94D4E7F1BE89A0CC2A506266073A4580053398078B7367AC19C694. Assets on 101a82fc.
  • Hosted CI run 42889574113: 14 jobs passed, 7 skipped; the UI job passed (Tray UI 1,136 passed, disclosure proofs 2/2, Axe). The mock Gateway job failed one reconnect test that also failed on main e59374c0.

Screenshots (main e59374c0 BEFORE, fd03c448 Light and Dark: both collapsed, sources expanded, both expanded, review case): 1773-fd03c448/real-hub/ at the pinned proof commit.

Head ffdbc4a1 (rebased on main 045d13ac, superseded by fd03c448)

  • Conflicts with main refactor(ui): share responsive page presentation #2085 in three CI files were resolved by combining both sides: the Tray UI filter excludes the animation-preference categories and NativeMarkdownProof, and the PR still deletes the source-text UI-lane test that the behavioral contract script covers.
  • Local ClawSweeper found two promotion defects in this PR's CI changes, fixed in 1b0451c8 (the UI job loads Set-CiUiTestEnvironment.ps1 from the pipeline revision) and ffdbc4a1 (promotions of older alphas skip absent disclosure proofs). Both have negative controls.
  • Native proof on WindowsAppSDK 2.6.5, lease cbx_187c5faeb4e8: CI's disclosure step 2/2, visual run 4/4, real Hub Light and Dark UIA checks passed. Hub ...Sha.ffdbc4a1, SHA-256 ED5248EAE2D9385BEE4B940FA252FAF2C321790EEDBD43F77FBD4CE29DFD097D. Assets on bc79b83e.
  • Hosted CI run 42682198936: 17 passed, 7 skipped; the UI job failed only on main's unrelated mock-Gateway voice-reply timeout, so the disclosure step was skipped there.
main 4aee38a1, Light ffdbc4a1, Light ffdbc4a1, Dark
Start of the conversation, both disclosures collapsed main: literal tags light collapsed dark collapsed
"Sources and evidence" expanded: nested section starts open, tags in code stay literal n/a light expanded dark expanded
Both disclosures expanded n/a light all expanded dark all expanded
Both collapsed again through UI Automation n/a light recollapsed dark recollapsed
Review case: unclosed summary, then a valid disclosure main: literal light review case dark review case

Validated head 66a6d46b (rebased on main 4aee38a1)

Changes in this revisit:

  • Rebased the 13 PR commits onto main 4aee38a1bfaa2f7d241130a3548d94f0547a3c9c. git range-diff shows every patch unchanged. The empty ci: retrigger commit was dropped.
  • 7c906f93 fixes the review case: an unclosed <summary> followed by a valid disclosure. It stays literal instead of taking the later section's </summary>. Adds regression test UnterminatedSummary_StaysLiteralWithoutConsumingALaterDisclosure and one docs sentence.
  • bd6a235e (docs) records that a closing-wrapper line directly after a table ends the table and closes the disclosure. This matches GitHub's renderer and the existing NestedOpenDisclosure_PreservesCodeAndMarkdownBlocks test. A local review suggested treating that line as a table row. It was checked against GitHub's Markdown API and not adopted.
  • 66a6d46b stores this PR's five new files with LF endings, the repository convention; they had been committed as CRLF. Content is unchanged: git diff --ignore-cr-at-eol bd6a235e 66a6d46b is empty. A stock git diff --check over the PR range now passes.

Real Hub proof on 66a6d46b

  • Binaries: the unmodified Hub executable built from this head (AppVersion ...Sha.66a6d46b890d1dc4616702f5ced37da6a654060e) and from main 4aee38a1 for BEFORE.
  • Host: a throwaway crabbox Hyper-V guest running Windows 11 Enterprise Insider Preview 10.0.29683 x64 in an interactive session, with WindowsAppRuntime 2.6.4 installed.
  • Gateway: both apps ran against the loopback fixture Gateway serving the same canned transcript. The theme and transcript seam is applied only to a separate fixture-host clone.
  • Captures: UI Automation drove expand, collapse and scrolling. Each image is an owned-window PrintWindow capture.
  • Provenance: binary hashes, commands and the UIA logs are in PROVENANCE.md.
BEFORE: main 4aee38a1, Light AFTER: this PR, Light AFTER: this PR, Dark
Start of the conversation, both disclosures collapsed main: literal tags light collapsed dark collapsed
"Sources and evidence" expanded: nested section starts open, tags in code stay literal n/a light expanded dark expanded
Both disclosures expanded n/a light all expanded dark all expanded
Both collapsed again through UI Automation n/a light recollapsed dark recollapsed
Review case: unclosed summary, then a valid disclosure main: literal light review case dark review case

UIA log, identical for Light and Dark:

  • "Sources and evidence" (button): Collapsed, then Expand, then Expanded.
  • "Raw command output": Collapsed, then Expanded.
  • Collapse on both: Collapsed/Collapsed.
  • Review case: the unclosed <details><summary>First text is present literally, and "Second" is a separate button that goes from Collapsed to Expanded.

On main, the UIA tree has no disclosure buttons; both messages are plain text containing the literal tags.

Real Hub proof on 032965b2 (then-current head)

This is the unmodified current-head app (AppVersion ...Sha.032965b2; tree 2f98f612, the same tree as d70cff00). It ran in a throwaway crabbox Hyper-V guest: lease cbx_9558fdb99e8c, Windows 11 Insider 10.0.29683 x64, 1024x768, interactive session. The app was built in-guest against WindowsAppSDK 2.6.4, and the guest had the WindowsAppRuntime 2.6.4 installer (which also registered 2.6.5).

  • The app ran against the loopback fixture Gateway, which served the canned transcript. The fixture-host seam is applied only to a separate host clone; the app binary is the PR build.
  • UI Automation drove expand and collapse, and captures are owned-HWND PrintWindow images.
  • UIA log for both Light and Dark:
    • "Sources and evidence" (button): Collapsed → Expand → Expanded.
    • "Raw command output": Collapsed → Expanded.
    • Collapse on both → Collapsed/Collapsed.

This exercises the rebased rendering path: Microsoft.UI.Reactor.Advanced.Factories.Markdown on sanitized disclosure segments, with Reactor-owned list layout.

Screenshots (032965b2 Light and Dark): 1773-032965b2/ at the pinned proof commit.

The UIA reports and build receipt are on assets-only commit 280c191a, and the guest is deleted.

Not exercised on this head:

  • real Windows High Contrast in the real app (the HighContrast proof uses simulated theme resources in the native test host)
  • the installed MSIX Hub
  • Narrator or any screen reader
  • physical mouse or keyboard input
  • a live Gateway or model-produced message

Rebase on main (d70cff00; current head 032965b2 adds only an empty ci: retrigger commit)

Current head d70cff00ed49051cf34f47f4097c251e44595449 is 5f580bb6 rebased onto main at 2ff4d168 (after #1791, #1797 and Reactor preview.16). Main removed the preview.12 list-item workaround and moved to Microsoft.UI.Reactor.Advanced.Factories.Markdown; BuildInertMarkdown uses that factory on the already-sanitized disclosure segments. Main's ReactorChatMarkdownContractTests only matched timeline source text. This PR removes it, so a new commit replaces it with a rendered check in ReactorMarkdownDisclosureProofTests: after the host narrows to 240 px, a long list item must wrap inside it. The reactor-markdown-list-layout and reactor-markdown-presentation-closed ledger rows now cite behavioral guards.

Local: ./build.ps1 passed; OpenClaw.Shared.Tests 4809 passed, 25 skipped, 0 failed; OpenClaw.Tray.Tests 4807 passed, 0 failed; OpenClaw.Tray.UITests compiles; CI workflow contract and docs validation pass. Throwaway crabbox Hyper-V guest (lease cbx_8a675098b37e, exact head and tree 2f98f612, WindowsAppSDK 2.6.4): parser lane (ChatMarkdownDisclosureTests) passed; NativeMarkdownProof Light, Dark and HighContrast each 1/1 including the new list-wrap assertion; the inert-content case 1/1. The current-head real-Hub captures are in the section above; the older captures below are from 5f580bb6.

Hosted CI on d70cff00 / 032965b2: "UI, functional, and accessibility tests" fails on a cross-branch testhost crash, not this change.

  • d70cff00 (run 41531252889): the testhost crashed in ReactorChatLayoutProofTests.SandboxFlyout_ReflectsSettingsWithoutChangingDraftAndOpensSettings.
  • 032965b2 (run 41542375819): crashed again, this time in ReactorChatLayoutProofTests.ReasoningPicker_PreservesCurrentValueWithoutInventingSupportedOptions. Before the crash, 198+ UI tests passed, and the separate mock-Gateway lane passed 44/44.
  • This PR changes neither test nor the composer flyouts they drive.
  • Since Nov 1, the same ReactorChatLayoutProofTests testhost crash has also hit:
    • bkudiess-split-local-page-pins (8e0dc8e7), pollybot13/gateway-voice-successor-1915 (c98608cf): SandboxFlyout
    • fix/wsl-relay-msix-trust (9521eec1), dev/larroy/wipe-openclaw-state (e84a5bb3), openclaw/gateway-unresponsive-peer-pr (29b9ea46): ReasoningPicker
    • openclaw/nova-shrimp (e4affd6a): ComposerFlyouts
  • "Setup and connect E2E (WSL Latest)" failed on d70cff00 with all 23 tests failing and passed on 032965b2. bkudiess-remove-skills-page (b9eecbf9) had the identical all-fail on Nov 2. main at 2ff4d168 (run 41499696100) failed its Network recovery and Revocation recovery WSL E2E jobs.
  • The native disclosure proofs these lanes cover passed on this head in a throwaway guest (above).

Proof on 5f580bb6 (pre-rebase)

Head 5f580bb629e8b0afed2365e689e81305914eee41 is this branch rebased again onto main at ef1df54d (the only conflict was in docs/TEST_COVERAGE.md; both paragraphs are kept). It carries two fixes for the P2 review findings. First, "fix(chat): avoid rescanning sibling disclosure tokens" Parts now receives each disclosure body's token range, so sibling bodies never rescan one another. SiblingDisclosures_InspectAtMostOneTokenPerWrapper(2500/5000) counts part-building token visits. With the old for (var i = 0; i < tokens.Count; i++) loop restored, both cases fail; with the fix, they pass. No wrapper recognition or literal fallback changed. Second, "fix(chat): bound the summary terminator search to the summary limit": each opener now searches for </summary> only within the 4096-character summary window plus the terminator length, rather than the rest of the message. UnterminatedSummaries_SearchOnlyTheSummaryWindow (10,000 unterminated <details><summary>x lines, 200,000 characters) counts the characters searched; it fails with the old unbounded search and passes with the fix. SummaryLengthLimit_IsUnchangedByTheBoundedSearch keeps 4096 accepted and 4097 literal.

Local on this head: ./build.ps1 passed; OpenClaw.Shared.Tests 4807 passed, 25 skipped, 0 failed; OpenClaw.Tray.Tests 4786 passed, 0 failed; OpenClaw.Tray.UITests compiles; scripts/test-ci-workflow-contract.ps1 and scripts/validate-docs.ps1 pass.

Real behavior on WindowsAppSDK 2.6.4, run in a throwaway crabbox Hyper-V guest (lease cbx_76f84af0e023, Windows 11 Insider 10.0.29683 x64, 1024x768, interactive session, WindowsAppRuntime 2.6.4 installed). The exact head was cloned and pinned by commit and tree (d7c57f42), the app identity reports Sha.5f580bb6, and the app was built in-guest; deps.json resolves every Microsoft.WindowsAppSDK* package at 2.6.4.

  • NativeMarkdownProof, one process per theme, with OPENCLAW_VISUAL_TEST=1: Light, Dark and HighContrast each 1/1 passed; AssistantMarkdown_UntrustedContentRemainsInertInsideDisclosure 1/1 passed. The test asserts accessible expansion, state kept across rerender, streaming and resize, Copy on literal code, and inert content.
  • Real Hub executable: the unmodified PR-head OpenClaw.Tray.WinUI.exe against the loopback fixture Gateway serving the same canned transcript as before. The fixture-host seam that serves it was applied only to a separate host clone. UIA log, Light and Dark: header button "Sources and evidence" Collapsed → Expand → Expanded; "Raw command output" Collapsed → Expanded; Collapse on both → Collapsed/Collapsed. Captures are owned-HWND PrintWindow images.

Screenshots (5f580bb6 Light and Dark): 1773-5f580bb6/real-hub/ at the pinned proof commit.

Native proof captures (Light, Dark, HighContrast, expanded and collapsed), UIA reports, the transcript, the capture script and the host seam are on assets-only commit 5e4f981e (1773-5f580bb6/, method/). The guest has been deleted.

Rebase on main (c8b89482, superseded by the head above)

Current head c8b89482bfe2a5acbdecca5b089fb619337d2be0 is a rebase of 86f0c26a onto main at 4cbbe51c; it adds no new behavior. Conflicts were confined to CI/docs: the Tray UI filter now excludes both GatewayFixture (from main) and NativeMarkdownProof, the mock Gateway step and the Markdown disclosure proof step both run, docs/CHAT_VISUAL_DESIGN.md keeps main's question-dock/working-claw text plus the disclosure paragraphs, and the UiLane_... source-inspection test stays removed in favor of scripts/test-ci-ui-profile.ps1. On this head: ./build.ps1 passed; OpenClaw.Shared.Tests 4807 passed, 25 skipped, 0 failed; OpenClaw.Tray.Tests 4781 passed, 0 failed (includes ChatMarkdownDisclosureTests); scripts/test-ci-workflow-contract.ps1 and scripts/test-ci-ui-profile.ps1 passed. The windowed NativeMarkdownProof UI tests were not rerun locally (no desktop windows); CI runs them. Visual and earlier evidence below is from the pre-rebase revisions it names.

CI profile-isolation replacement (then-current head)

Pre-rebase head: 86f0c26. This correction changes only CI configuration and its behavioral regression scripts. It does not change disclosure rendering or expand the supported syntax. Author scope acceptance is recorded above; the repository-maintainer decision remains the sole outstanding sign-off.

The UI workflow now exports the same four existing roots through one executable owner, scripts/Set-CiUiTestEnvironment.ps1, immediately after checkout and before any build or test. scripts/test-ci-ui-profile.ps1 runs that real exporter with scratch state, checks its GitHub environment output, preserves an unrelated binding, and verifies default checkout selection from another working directory. It never starts the app, changes process/profile environment, or inspects source markers.

Copied output from the unchanged exporter:

PASS OPENCLAW_REPO_ROOT
PASS OPENCLAW_TRAY_DATA_DIR
PASS OPENCLAW_TRAY_APPDATA_DIR
PASS OPENCLAW_TRAY_LOCALAPPDATA_DIR
PASS unrelated environment preserved
PASS default repository follows checkout
UI profile isolation: 6 checks passed.

All eight broken-binding controls ran isolated copies of the exporter. Each failed for its intended observable contract, not a fixture failure:

OPENCLAW_REPO_ROOT, missing: rejected with "UI isolation contract failed for OPENCLAW_REPO_ROOT: missing or misdirected root."
OPENCLAW_REPO_ROOT, misdirected: rejected with "UI isolation contract failed for OPENCLAW_REPO_ROOT: missing or misdirected root."
OPENCLAW_TRAY_DATA_DIR, missing: rejected with "UI isolation contract failed for OPENCLAW_TRAY_DATA_DIR: missing or misdirected root."
OPENCLAW_TRAY_DATA_DIR, misdirected: rejected with "UI isolation contract failed for OPENCLAW_TRAY_DATA_DIR: missing or misdirected root."
OPENCLAW_TRAY_APPDATA_DIR, missing: rejected with "UI isolation contract failed for OPENCLAW_TRAY_APPDATA_DIR: missing or misdirected root."
OPENCLAW_TRAY_APPDATA_DIR, misdirected: rejected with "UI isolation contract failed for OPENCLAW_TRAY_APPDATA_DIR: missing or misdirected root."
OPENCLAW_TRAY_LOCALAPPDATA_DIR, missing: rejected with "UI isolation contract failed for OPENCLAW_TRAY_LOCALAPPDATA_DIR: missing or misdirected root."
OPENCLAW_TRAY_LOCALAPPDATA_DIR, misdirected: rejected with "UI isolation contract failed for OPENCLAW_TRAY_LOCALAPPDATA_DIR: missing or misdirected root."

These are mutation controls for the new coverage, not a claim that the pre-existing workflow actually omitted a binding. Removing or redirecting any one of the four exported roots is the realistic defect the replacement catches. The previous C# source-text assertions remain deleted.

Preserved visual evidence: the following captures retain their actual historical revision (f5ecc7b). They are not fresh screenshots from this correction.

October heads (f5ecc7b9 through 86f0c26a)

Real Hub (Release, unpackaged, win-x64) against the loopback fixture Gateway, BEFORE main 50d0b34a (SHA-256 FC037B1A2851847656F6EC444F8338A2FCE1E2AC8225D478EB7CC2A304E742AF), AFTER f5ecc7b9 (SHA-256 45DB8ECE6CC35552DF7E30CAC2F6A882E6A9CF7BD03CC344B39E481344346DAD), driven through UIA ExpandCollapsePattern. Assets, PROVENANCE.md and the local fixture seam are on branch paulcam206-disclosure-proof-assets, commit e498921.

Light Dark
BEFORE (main): literal tags before light before dark
AFTER: collapsed after light collapsed after dark collapsed
AFTER: "Sources and evidence" expanded, nested open disclosure, literal code, list after light expanded after dark expanded
AFTER: both disclosures expanded (second has a code block) after light all expanded after dark all expanded

Native proof captures from the synthetic WinUI test host (HighContrast is simulated resources, not the OS mode):

State Light Dark HighContrast (simulated)
Collapsed fixture collapsed light fixture collapsed dark fixture collapsed hc
Expanded with nested open disclosure fixture expanded light fixture expanded dark fixture expanded hc
  • Tests then: ./build.ps1 Debug and Release passed; Shared 4,427 passed, 35 skipped, 0 failed; Tray 4,257 passed, 0 failed (20 disclosure parser cases); NativeMarkdownProof 2/2 in one isolated process, run 4 times. The disclosure tests were trimmed by mutation and defect replay on 9cc2f8f3.
  • 86f0c26a restored behavioral UI-profile coverage: test-ci-ui-profile.ps1 6 checks, 8/8 broken-binding mutation controls rejected, workflow contract passed.
  • Author hand validation (secondary): on 2026-10-09 Paul reported "<details> disclosures work properly" in a standalone Debug preview built from ec4089b2 plus an uncommitted routed-input fix, not this branch or the Hub; the disclosure sources were byte-identical to 77e2b614. Preview SHA-256: OpenClaw.Tray.WinUI.dll A2A725B918C1BFCCBE2476D523DA39DFA8F0C7F1E6AC0C50766D39615D5BC783, OpenClaw.Chat.dll C1815C3A1FE909A37CB77ADB8E35E2E8DC66D6FE4D2A871AC014F335C014E2FE, OpenClaw.Shared.dll 3B6CBC0D4F99BD03AAAF77E14BD9358FE4E5C665B11A1AFD52562D8966C2883F.

Change Type

  • Bug fix
  • Feature
  • Refactor
  • Docs or instructions
  • Tests or validation
  • Security hardening
  • Chore or infrastructure

Scope

  • Tray or WinUI UX
  • Windows node capability
  • Local MCP or winnode
  • Gateway, connection, or pairing
  • Setup or onboarding
  • Permissions, privacy, or security
  • Tests, CI, or docs

Required proof pools

  • windows-winui-interactive: native chat rendering changed; collapsible disclosures, their UI Automation expand and collapse, and their Light and Dark presentation need current-head visible proof in the WinUI app. Results are under Validation and Real Behavior Proof; this declaration does not by itself claim the pool ran.

Validation

Current head 5a1b897510c4128765eb06cfe94da54d972ae0a1 (tree b33f2873): the author's normal merge of main 20d85144 into 8890e1b8.

On the author's machine, on 5a1b8975 (host-checks.txt):

  • ./build.ps1: passed.
  • ./scripts/test-ci-workflow-contract.ps1, ./scripts/test-ci-ui-profile.ps1 (9 checks), ./scripts/test-ci-gate-results.ps1, ./scripts/test-alpha-promotion.ps1 (34 cases) and ./scripts/validate-docs.ps1: passed.
  • dotnet test tests/OpenClaw.Tray.Tests --filter FullyQualifiedName~CiNugetCacheWorkflowTests: 4 passed.
  • git -c core.whitespace= diff --check 20d85144 5a1b8975: clean.
  • The four shard negative controls under Evidence each failed with their intended message.

In a throwaway crabbox Hyper-V guest at 8890e1b8 (git diff 8890e1b8 5a1b8975 -- src is empty), released afterwards: lease cbx_b770281f3f03, Windows 11 Enterprise Insider Preview 10.0.29683 x64, 6 vCPU, interactive session, fresh clone with head 8890e1b8 and tree 1d55cbaa checked before and after, isolated OPENCLAW_TRAY_* roots, WindowsAppSDK 2.6.5 and the signed WindowsAppRuntime 2.6.5 installer. Hub ...Sha.8890e1b8..., OpenClaw.Tray.WinUI.exe SHA-256 D609CFE52782941F180C286FFC8F1A79862D42800DDBEE4DEC61712913C5982C. Receipts: summary.txt at e617b1ab on branch proof/1773-5a1b8975-20261113.

  • ./build.ps1: passed.
  • dotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj --no-restore: 5,849 passed, 0 failed (29 opt-in native MXC, device-identity and CUDA integration tests not executed).
  • dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore: 6,384 passed, 0 failed.
  • dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-build --filter FullyQualifiedName~ChatMarkdownDisclosureTests: 27 passed.
  • ./scripts/validate-docs.ps1, ./scripts/test-ci-workflow-contract.ps1, ./scripts/test-ci-ui-profile.ps1 and the stock diff check: passed.
  • ./scripts/run-proof-tests.ps1 -Project tests\OpenClaw.Tray.UITests\OpenClaw.Tray.UITests.csproj -Filter 'Category=NativeMarkdownProof' -ResultName markdown-disclosure -RuntimeIdentifier win-x64 (CI's step): 2 passed (the link/content-policy proof and the expand, rerender and resize proof).
  • main's Markdown rendering proofs, dotnet test tests/OpenClaw.Tray.UITests --no-build -r win-x64 --filter "(FullyQualifiedName~OpenClaw.Tray.UITests.ReactorMarkdown|FullyQualifiedName~ReactorChatLayoutProofTests.CodeBlock_PreservesLiteralContentAndCopiesExactText)&Category!=NativeMarkdownProof": 7 passed.
  • The three Tray UI tests that failed in CI at 422593ce (WorkspaceWindowProofTests.NativePagesAndOwnerLinks_StayInOneWorkspaceWindow, UsagePageRenderingTests.MainStates_RenderTheApprovedHierarchyInBothThemes and ReactorQuestionProofTests.ProductionRoot_QuestionExpansionRetainsNativeComposerAndViewModelDraft), with fix(ci): Tray UI tests fail intermittently and the step times out on passing runs #2130's waits, three rounds: 35 of 35 passed in each.
  • Not repeated: the visual captures, negative control C and the real Hub Light and Dark runs. The renderer is byte-identical to 0abb30a4, where all of them passed or failed as intended (below).

Hosted CI on 5a1b8975: Build and Test run 43358006514 failed in one job; CodeQL (run 43358006441) passed. Every other job passed: both ordinary Tray UI shards (ui-tests: 1,041 passed and 6 skipped of 1,047, then the steady-resource, animation and Axe steps; tray-ui-shard: 334 passed and 3 skipped of 337), Core and CLI, Tray/setup/integration, the three WSL E2E lanes, release metadata, MSIX x64 and arm64, the Store bundle and the x64 publish smoke. CI's Run native Markdown disclosure proofs step ran at this head and reported 2 discovered, 2 executed, 2 passed.

  • Mock Gateway application and compatibility tests: the fixture UI step ran 125 tests: 124 passed, 1 failed. GatewayFixtureUiTests.SystemsDaily_InsetAndExpandedNativeFrames failed with "Systems observation 'SystemsRetry' must belong to the retained native window and process." (GatewayFixtureSystemsUiTests.cs:414, an ownership check inside a UI Automation wait on the Systems page). This PR's diff does not touch the Systems page, the ownership helper or the fixture harness. The same test failed with the same message on two unrelated pull requests the day before (job 131090299270, job 131463763249), and on main at 2a237069 with a NullReferenceException (job 130846584693). main's own mock Gateway job also failed at its current tip 8d5e27bd, on a different test (Automations_ScopesToAgentsAndCoversMainStates, a focus timeout; job 131663484058). The fixture tests that failed this job at 0abb30a4 and 422593ce were not among this run's failures.
  • CI Gate failed only because of that job. The failure is not waived here, and the author cannot rerun jobs in this repository.

Previous heads:

  • 8890e1b8 (merge of main 6ddc13b8), lease cbx_b770281f3f03: the guest results above. Hosted CI never ran on it: main merged fix(ci): Tray UI tests time out when the whole suite runs serially in one job #2135 while it was being validated, and the pull request was unmergeable when 8890e1b8 was pushed.
  • 422593ce (merge of main 1ebcf004), lease cbx_559a81184a85: ./build.ps1 passed; Shared 5,846 passed, 1 failed: InstalledFileWorkerResolverTests.TamperFailureRetainsUnprovenPreparationInsteadOfDeletingForeignObjects(obstacle: "added") is meant to observe its 64 MiB runtime copy mid-way but first saw it finished (67,108,864 bytes) after 5 min 37 s under full-suite load; this PR touches no FileTransfer code, and the failing case's 5 variants and its 94-test class passed on rerun in the same guest (receipts 5b1b5f85). Tray 6,372 passed; parser 27; disclosure proofs 2/2; main's Markdown UI proofs 7/7. Hosted run 43344451081 failed two jobs. Run Tray UI Tests finished in 14 min 15 s with 3 failures in code this PR does not touch, so CI skipped the disclosure step: WorkspaceWindowProofTests.NativePagesAndOwnerLinks_StayInOneWorkspaceWindow(theme: "Dark") timed out forwarding the chat deep link to the test app; UsagePageRenderingTests.MainStates_RenderTheApprovedHierarchyInBothThemes(theme: Dark, scenario: "stale") timed out waiting for UsageDaily; ReactorQuestionProofTests.ProductionRoot_QuestionExpansionRetainsNativeComposerAndViewModelDraft read an empty composer right after setting a draft in an empty conversation, before any message existed to render, which is the signature fix(ci): Tray UI tests fail intermittently and the step times out on passing runs #2130 records and instruments. The mock Gateway job failed SelectedAssistantAndConversationSurviveTransientRosterLossButNotAuthoritativeRemoval with "Timed out waiting for native Send action after reconnect", the same wait and message that failed on main at 3d5f1427 (job), 3f47e838 (job) and 3c75a324 (job). main's own run at 1ebcf004 (43335989231) failed both jobs too: its Tray UI step hit the 15-minute limit and its mock Gateway job failed two other tests.
  • 0abb30a4 (roboclaw-bot's merge of main 3d5f1427), lease cbx_5fbc94545ce3: ./build.ps1 passed; Shared 5,847 passed; Tray 6,371 passed with one load timeout in OpenClawChatDataProviderTests that passed its focused and class reruns (2/2, 621/621); parser 27; disclosure proofs 2/2 and visual 4/4; main's Markdown UI proofs 7/7; negative control C failed exactly its High Contrast assertion in both themes; real Hub Light, Dark and main BEFORE checks passed; local ClawSweeper patch correct, no findings. Hosted run 43298592551 failed two jobs: Run Tray UI Tests hit its 15-minute limit while passing (1,194 results, 0 failures), so CI skipped the disclosure step, and the mock Gateway job failed NewAgentUsesGatewayCreationAndRefreshesWithoutReplacingConversation with a NullReferenceException at GatewayFixtureUiTests.cs:1575, the same failure the test had on four unrelated PRs that day (improve(chat): refine composer sizing and context controls #2117, feat: add an animated desktop lobster with notification bubbles #1681, fix: keep agent creation on its original Gateway connection #1854, fix(ci): Tray UI tests fail intermittently and the step times out on passing runs #2130) and the race main fix(tests): mock Gateway fixture UI tests fail intermittently in CI #2132 fixed. The hosted ClawSweeper review of 0abb30a4 reported no findings (proof 5/6, patch 4/6).
  • 6efff19a (merge base 65de1e35), lease cbx_88fd03b6e5de: ./build.ps1 passed; Shared 5,772 passed; Tray 6,323 passed; parser 27; disclosure proofs 2/2 and visual 4/4; main's Markdown UI proofs 7/7; negative controls A and B failed exactly their intended assertions; local ClawSweeper patch correct, no findings. Hosted CI never ran: its runs were created during GitHub's 2026-11-11 Actions incident and stayed queued with no jobs.
  • fd03c448 (merge base e59374c0), lease cbx_50d4db5c64c4: ./build.ps1 passed; Shared 5,615 passed; Tray 6,152 passed; parser 27; disclosure proofs 2/2 and visual 4/4; the inert-summary negative control failed exactly the link/content-policy proof; hosted run 42889574113 14 passed, 7 skipped, with the UI job passing and one main-red mock Gateway reconnect test failing.
  • ffdbc4a1 (merge base 045d13ac): host CI gates and local ClawSweeper clean; guest native proof 2/2 and visual 4/4 on WindowsAppSDK 2.6.5; hosted run 42682198936 17 passed, 7 skipped, UI job failed only on main's mock-Gateway voice-reply timeout.
  • 3a4e19cd (merge base fc777f2f): hosted run 42271781790 19 passed, 7 skipped, 0 failed, disclosure proofs 2/2.
  • 66a6d46b (merge base 4aee38a1), lease cbx_9a6a8b6516bb: ./build.ps1 passed; Shared 4,927 passed (25 configured skips); Tray 5,087 passed; parser 27 passed; disclosure proofs 2/2; CI-shaped Tray UI lane 642 passed, 7 skipped (on content-identical bd6a235e); unclosed-summary negative control failed exactly its 2 new cases; hosted run 42158018045 19 passed, 7 skipped, 0 failed.

Real Behavior Proof

  • Environment tested: Windows 11 Enterprise Insider Preview 10.0.29683 x64, on throwaway crabbox Hyper-V guests in an interactive session (lease cbx_b770281f3f03 for the proof runs at 8890e1b8, cbx_5fbc94545ce3 for the real Hub screenshots at 0abb30a4), WindowsAppSDK 2.6.5 (project.assets.json resolves 2.6.5, Reactor 0.1.0-preview.17) and the signed WindowsAppRuntime 2.6.5 installer.
    • The app under test is the real Hub executable built from the PR head, run against the loopback fixture Gateway.
    • Windows x64 only: no ARM64, WSL, or installed-package run.
  • PR head or commit tested: the current head 5a1b897510c4128765eb06cfe94da54d972ae0a1: build, the CI contract checks and hosted CI, including its native disclosure proof step, ran here; the required closeout, that proof step and main's Markdown rendering proofs also ran in the guest at 8890e1b8, whose product source is identical (Validation). The real Hub screenshots are from 0abb30a457652952c73aa78ff33cee67b3329525, the maintainer's merge of main 3d5f1427; the disclosure renderer and its proofs are byte-identical between these heads.
    • Hub version ...Sha.0abb30a457652952c73aa78ff33cee67b3329525, OpenClaw.Tray.WinUI.exe SHA-256 7DEED6F0C71CBD63FE182DF8B938AE9663709ADA70AB27977287A0BA1501A90C.
    • BEFORE: main 3d5f14270dd6bd8b260a723ff2e73a68ea858ca8, SHA-256 178D99C92F37CE5F39D30ED3CD4C9D15ADB68B0EA26711EDF285D7FFC63E2085.
  • Exact steps or command run: dotnet <GatewayFixtureHost.dll> --app <OpenClaw.Tray.WinUI.exe> --artifacts <dir> --duration-seconds 240 --theme <Light|Dark>, with the canned transcript served through the harness seam.
    • UI Automation expanded, collapsed and scrolled the chat.
    • CI's native disclosure step and main's Markdown rendering proofs ran on the same build (Validation).
  • Evidence after fix: the results under Validation, and the screenshot table under "Native proof on 0abb30a4 (latest real Hub screenshots)", with BEFORE captures from main 3d5f1427.
  • Observed result on main: the messages show <details>, <summary> and </details> as plain text, in main's current styling.
  • Observed result on this head:
    • "Sources and evidence" and "Raw command output" render as native expanders that expand and collapse.
    • Disclosure bodies use main's current presentation: the 14-pixel block gap, list markers, the primary prose tone from improve(chat): refine composer sizing and context controls #2117, the code card with syntax colors and underline-free accent links.
    • The nested section starts open, and tag-like text inside code blocks stays literal.
    • In the review case, the unclosed <details><summary>First stays literal, and the following "Second" disclosure renders and expands.
  • Screenshot or artifact links verified? Yes.
    • The images are on the assets-only branch proof/1773-0abb30a4-20261112 in the author's fork, pinned to commit 16e785dd, fetched (HTTP 200) after upload. This body was read back and compared after the update.
  • Not verified or blocked:
    • Real Windows High Contrast and Narrator or any other screen reader; High Contrast is simulated in the test host.
    • Physical mouse or keyboard input; disclosures were driven through UI Automation, and no link was activated.
    • The installed MSIX Hub, and a real Gateway with a model-produced message.
    • Disclosures inside reasoning text (main's compactSecondaryReading path) use the same renderer and gap rule but were not exercised.
    • A passing required CI Gate at this head: its only failing job is the mock Gateway Systems test attributed under Validation, which the author cannot rerun.

Security Impact

  • New permissions or capabilities? No
  • Secrets or tokens handling changed? No
  • New or changed network calls? No
  • Command or tool execution surface changed? No
  • Data access scope changed? No
  • If any answer is Yes, explain the risk and mitigation: N/A. No raw HTML is rendered. Disclosure bodies use the same sanitized Markdown path and link policy as the rest of the assistant message (live http/https links since improve(chat): align native conversation and tool activity with web #2093, limited by Reactor to http/https/mailto; other schemes, images and raw HTML inert), so a disclosure adds no new link surface. Summaries are plain text. The link/content-policy proof checks both.

Compatibility and Migration

  • Backward compatible? Yes
  • Config or environment changes? Yes, CI-only: unchanged UI profile/root values are exported by a pipeline-owned setup step instead of inline workflow bindings, so release promotions of older alphas keep working. No user configuration changes.
  • Migration needed? No
  • If yes, list the exact upgrade steps: N/A

Review Conversations

  • I replied to or resolved every bot review conversation addressed by this PR.
  • I left unresolved only conversations that still need maintainer judgment.

The unclosed-summary thread is fixed in abf9ccef (originally 7c906f93) with its regression test, and it is resolved. No review threads remain open. The proof-pool declaration roboclaw-bot asked to correct now names windows-winui-interactive. ClawSweeper's review of 0abb30a4 reported no findings; its open items were the adoption decision below and the required CI Gate. It asked for the cause of the mock Gateway failure: that was the selector race main fixed in #2132, and it did not recur at 5a1b8975. The CI Gate's remaining failure at this head is attributed under Validation. The remaining decision is the repository-level one under "Why This Change Was Made": whether to adopt this restricted rendering capability.

@clawsweeper

clawsweeper Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Oct 20, 2026
@clawsweeper

clawsweeper Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex review: ready, awaiting a maintainer decision.

What this changes

This PR renders supported details and summary wrappers as native collapsible sections and preserves Markdown safety and presentation.

Example: An assistant sends <details><summary>Sources</summary> followed by evidence and a closing details wrapper.

  • Before: Chat displays the wrapper tags literally.
  • After: Chat displays a collapsed Sources control that reveals the evidence when expanded.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Strong native evidence and no actionable introduced defect; the unresolved adoption choice limits overall readiness, while the failed required CI Gate still prevents landing.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): Inspected real Hub BEFORE and AFTER captures on Windows x64 against the loopback Gateway fixture show collapsed, expanded and nested disclosures. The captured renderer is unchanged at the reviewed head, whose hosted native disclosure step passed; keyboard, Narrator, real High Contrast and installed-package behavior remain explicitly unclaimed.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Product

Kind: Feature · Worth it: Needs a maintainer decision · Fix scope: Complete
User problem: Assistant disclosure wrappers appear as literal tags and their evidence cannot be collapsed.
Reason: The demonstrated interaction has clear value, but recognizing additional syntax changes the existing rendering contract and still needs an owner decision.

Merge readiness

⏳ Ready, awaiting maintainer decision

This PR provides distinct native disclosure rendering that current main lacks, with no concrete introduced defect found; adoption remains a maintainer choice, and the required CI Gate remains red.

Priority: P2
Reviewed head: 5a1b897510c4128765eb06cfe94da54d972ae0a1
Owner decision: Required. See Decision needed.

Decision needed

  • Question: Should native assistant Markdown recognize this restricted details and summary syntax as collapsible sections?
  • Recommendation: Adopt the restricted extension: Approve balanced block-level disclosures with native controls, bounded nesting and literal fallback for unsupported forms.
  • Why: The existing renderer deliberately keeps HTML inert, and the recorded author acceptance and conflict repair do not establish repository approval for this new rendering capability.

Before merge

None.

Findings

None.

Agent review details

How this fits together

Assistant text enters ReactorChatTimeline, passes through sanitization and disclosure recognition, and becomes native WinUI Markdown controls and expanders.

flowchart LR
  A[Assistant text] --> B[Markdown sanitizer]
  B --> C[Disclosure recognition]
  C --> D[Markdown presentation]
  C --> E[Native expanders]
  D --> F[Chat timeline]
  E --> F
Loading

Technical review

Best possible solution:

Adopt the bounded disclosure extension in the existing Markdown owners if maintainers approve its supported syntax.

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

Current-main NoHtml rendering explains the literal wrappers, corroborated by the inspected BEFORE Hub capture; no target code or tests were executed during this review.

Is this the best way to solve the issue?

The parser reuses Markdown context recognition and the existing sanitizer and presentation owners, while native Expander state supplies the requested interaction without enabling general HTML.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 8d5e27bd8d3a.

Provenance checked

  • Markdown sanitization and inert HTML keeps the original intent (9acafa6: The Reactor migration retained sanitized native Markdown, with NoHtml and inert image and HTML callbacks; the later table change explicitly preserved these safety properties.)
  • Markdown presentation ownership and rhythm keeps the original intent (5164faa: Presentation was extracted into ChatMarkdownPresentation, then refined for web-aligned spacing and styling; disclosures reuse that owner and its current rhythm.)
  • Rendering and profile-isolation guards keeps the original intent (4ae1c36: Source guards protected safe Markdown rendering; the PR replaces them with parser and mounted-control assertions and separately exercises the real CI root exporter.)
  • Ordinary Tray UI shard partition keeps the original intent (dff0ec4: The suite was split to avoid serial-job timeouts; both shards retain their partition and exclude disclosures that run in a dedicated native proof process.)

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

Preflight source

Source unknown. Source comparison at the observed PR snapshot only. Completion is self-reported; body, policy, tests, execution, and report bytes are not verified.

Review metrics

Metric Value Why it matters
Production and test delta Production +417/-8 lines; tests and project wiring +594/-80 lines Growth implements restricted parsing and native state, with distinct malformed-input, rendering, safety and performance coverage.

Labels

Label changes:

  • add status: ⏳ waiting on maintainer: Only explicit maintainer approvals or decisions remain; merge is still blocked.

Label justifications:

  • P2: The change improves readability and interaction for assistant messages containing disclosure wrappers, with limited blast radius.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: ⏳ waiting on maintainer: Only explicit maintainer approvals or decisions remain; merge is still blocked.
  • proof: sufficient: Contributor real behavior proof is sufficient.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (15 earlier review cycles; latest 8 shown)
  • reviewed 2026-11-02T23:39:39.296Z sha 032965b :: needs real behavior proof before merge. :: none
  • reviewed 2026-11-03T00:31:44.229Z sha 032965b :: blocked before merge. :: none
  • reviewed 2026-11-06T04:21:32.692Z sha 66a6d46 :: blocked before merge. :: none
  • reviewed 2026-11-06T19:14:53.607Z sha 3a4e19c :: blocked before merge. :: none
  • reviewed 2026-11-09T20:02:36.915Z sha ffdbc4a :: needs real behavior proof before merge. :: none
  • reviewed 2026-11-09T21:05:15.143Z sha ffdbc4a :: ready, awaiting a maintainer decision. :: none
  • reviewed 2026-11-10T20:25:44.249Z sha fd03c44 :: ready, awaiting a maintainer decision. :: none
  • reviewed 2026-11-12T21:54:26.518Z sha 0abb30a :: blocked before merge. :: none

Reviewed November 12, 2026, 10:58 PM ET / November 13, 2026, 03:58 UTC (Revision 16).

@paulcam206 paulcam206 closed this Oct 20, 2026
@paulcam206 paulcam206 reopened this Oct 20, 2026
@paulcam206
paulcam206 marked this pull request as ready for review October 21, 2026 18:01
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added the status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. label Oct 21, 2026
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot removed the status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. label Oct 22, 2026
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@paulcam206

Copy link
Copy Markdown
Contributor Author

Native Windows validation of roboclaw/validate-pr-1773-20261027, run per the Oct 27 validation handoff in a throwaway Hyper-V guest. Report below follows the handoff's 7-point format. files\evidence\... bundles (TRX, logs, captures) are kept locally and available on request.

#1773 Windows validation report (roboclaw/validate-pr-1773-20261027)

1. Identity

  • PR fix(chat): native chat shows literal details tags instead of collapsible sections #1773 (fix(chat): native chat shows literal details tags instead of collapsible sections)
  • Branch roboclaw/validate-pr-1773-20261027, head 267b248a39d353d73afe46449ca18844cc517559, tree 9f5c9e6d0de21b1ea465f3bc8b00ca940eb9b193 (verified on host clone and in-guest clone, before and after).
  • Parent 86f0c26aadab95582402cefb7652291e06f5be74 (original PR head); co-author trailer present. Comparator for the control: same head with only the Parts loop restored to for (var i = 0; i < tokens.Count; i++).
  • No additional changes. git status --porcelain empty before and after all lanes.

2. Host

  • Throwaway Hyper-V guest, crabbox provider hyperv, lease cbx_a2e836d3ff6e, VM crabbox-63a4-cand1773-f7c85ca2, pinned crabbox 6bd7156a-win-scope (SHA256 02E320F0...2F40), template windows-readiness-template-v3.
  • Windows 11 Enterprise Insider Preview 10.0.29683, x64, 6 vCPU / 8 GB, display 1024x768 (Hyper-V video). Jobs ran in interactive console session 1 as the guest's crabbox admin (elevated) via scheduled task.
  • .NET SDK 10.0.403 (global.json 10.0.400 latestFeature), host/runtime 10.0.14, WindowsDesktop 10.0.14; PowerShell 7.6.9; Git for Windows (template); Windows SDK 10.0.26100.7705; VS 2022 BuildTools 17.14 with VC.Tools.x86.x64 + VC.Redist.14.Latest (CRT 14.44.35112); WindowsAppRuntime 2.5.1 installed (CI URL shape).
  • Binary receipts (Debug, win-x64):
    • src\OpenClaw.Tray.WinUI\bin\Debug\net10.0-windows10.0.22621.0\win-x64\OpenClaw.Tray.WinUI.exe sha256 44A4D0350A5B897EDACF372DD0DA2BF0134F22AE66B20788D8AAABEBAB8CDA0C, version 2026.10.8-roboclaw-validate-pr-1773-20261027.1+74...Sha.267b248a.
    • UITests OpenClaw.Tray.WinUI.dll sha256 C324574CA372F797AEE96DA20492B6E020297C5D241F3DBD01BAF4A23F749915; OpenClaw.Tray.UITests.dll 7CC05DCB...1AF9; OpenClaw.Tray.Tests.dll DEA245AD...D396.

3. Commands and results (attempt 2, evidence 1773-879c30ab8c9c436da197b787cf7bf3bb)

Lane Command Exit TRX total/executed/passed/failed/skipped
prereq diag .\scripts\setup-dev.ps1 -CheckOnly 0 n/a
build .\build.ps1 0 n/a
Shared dotnet build + dotnet test ...Shared.Tests --no-restore --logger trx;LogFileName=shared.trx 0 4462 / 4427 / 4427 / 0 / 35 not run (integration-gated, OPENCLAW_RUN_INTEGRATION unset; same as hosted default)
Tray same, tray.trx 0 4259 / 4259 / 4259 / 0 / 0
docs .\scripts\validate-docs.ps1 0 n/a
parser run-proof-tests.ps1 ... ChatMarkdownDisclosureTests -ResultName pr1773-parser 0 22 / 22 / 22 / 0 / 0; SiblingDisclosures_InspectAtMostOneTokenPerWrapper ran for both 2500 and 5000
native UI dotnet build ...UITests -c Debug -r win-x64; run-proof-tests.ps1 ... ReactorMarkdownDisclosureProofTests -RuntimeIdentifier win-x64 0 2 / 2 / 2 / 0 / 0 (Light theme case and inert-content case)

4. Negative control

  • Disposable local clone C:\v\c1773-negctl3 (only remote: the guest-local clone path; never pushed; guest has no GitHub credentials). Diff: one line in ChatMarkdownDisclosures.cs, loop restored to i = 0 .. tokens.Count, counter and tests kept.
  • dotnet test ...Tray.Tests --filter ChatMarkdownDisclosureTests: 22 / 22 / 20 passed / 2 failed. Only the two work-count cases failed: count: 2500 actual 12,502,500 (allowed 2500-5000), count: 5000 actual 50,005,000 (allowed 5000-10000). All 20 semantic cases (malformed, incomplete, list/quote/code, nesting, literal fallback) passed.
  • Proves: the new assertions detect the old quadratic traversal and the bounded loop is what reduces visits to O(n). It is an instrumented old-traversal control, not a pristine-base run, and not a wall-clock performance claim.

5. Visual/UIA evidence

  • Native UI lane asserts UIA expand/collapse and markdown state on rerender/resize in Light theme, plus inert untrusted content. No screenshots taken (OPENCLAW_VISUAL_TEST not set; Dark/HighContrast screenshot expansion not run pending capture-owner consent). No pixels claimed.

6. Retained failures (all environmental, none candidate-caused)

  • Attempt 1 (1773-5ccdf0fe...): build/test exit 1 from NU1301 No such host is known (api.nuget.org) during the 8:40 PM DNS outage.
  • Control attempts 1 and 2 (negctl, negctl2): GitVersion No base versions determined because my disposable clone was detached / lacked origin/main. Harness issue; fixed by mirroring the source clone's origin/main ref.

7. Reviews, decisions, unrun lanes

  • No new source written. No code repair needed.
  • Unrun: Dark/HighContrast screenshot expansion (needs capture-owner decision), ARM64 native run, Release/packaged app. Maintainer decision on adopting the restricted details/summary extension remains open.

8. Cleanup

  • Guest released via crabbox stop --provider hyperv cbx_a2e836d3ff6e; crabbox list --provider hyperv and Get-VM confirm the VM is gone.
  • Evidence: files\evidence\1773\evidence-1773.zip (sha256 18A02885003C5B26536BBC1522D3B92AAFB9950F881BC08B3BC9D2B0E8FC2117), unpacked under files\evidence\1773\unpacked. Contains no credentials; tray roots are synthetic test data.

@paulcam206
paulcam206 force-pushed the paulcam206-markdown-details-disclosures branch from 86f0c26 to c8b8948 Compare October 29, 2026 23:24
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@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. and removed proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Oct 29, 2026
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot removed the status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. label Oct 30, 2026
paulcam206 and others added 15 commits November 11, 2026 10:41
Audit by mutation of ChatMarkdownDisclosures plus replay of the five defect
states the review found: drop 18 unit cases that no mutant or historical
defect distinguishes, and reduce the native disclosure proof to Light plus the
inert-content case in one process. Dark and HighContrast become screenshot-only
captures under OPENCLAW_VISUAL_TEST=1.
Bound recursive part construction to the token indexes inside each disclosure. Keep wrapper recognition and literal fallback unchanged. Add deterministic breadth coverage for 2,500 and 5,000 siblings below the existing input cap.

Co-authored-by: paulcam206 <16614499+paulcam206@users.noreply.github.com>
Each disclosure opener searched the entire remaining message for </summary> before the length check rejected it, so many unterminated openers below the input cap caused quadratic scanning. Search only the window an accepted summary can occupy; the accepted summary length is unchanged.
…ist-wrap check

Resolving the rebase onto main removes ReactorChatMarkdownContractTests, which only matched timeline source text. Reactor now owns Markdown list layout, so the native disclosure proof asserts that a long list item wraps inside the narrowed host, and the ledger rows point at behavioral guards.
…sure

A summary that was never closed searched ahead for any </summary> within the
summary window, so an incomplete section took a later valid section's
terminator and emitted one disclosure whose heading held the first body, its
closer, and the next opener. A summary must now close before a blank line or
another disclosure wrapper; otherwise the section stays literal and the later
disclosure still renders.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A pipe-free closing-wrapper line directly after a table closes the disclosure,
matching GitHub Markdown (an HTML block start ends the table) and the existing
nested-disclosure table coverage. Record this so the table-cell exclusion is
not read as applying to that line.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The five files this PR adds were committed with CRLF while the repository
stores 98% of its C# and scripts with LF, so a stock git diff --check over
the PR range reported every line as trailing whitespace. Content is
unchanged; none of the files contains a multi-line string literal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Alpha promotions check out the candidate source, which can predate
Set-CiUiTestEnvironment.ps1. Running the exporter from that checkout would
fail the UI job before any test ran, where the old inline job bindings worked.
Load it from GITHUB_SHA like the crash-metadata helper and bind the roots to
the candidate checkout explicitly.

test-ci-ui-profile.ps1 now runs the workflow step against disposable history:
a candidate without the exporter, a candidate with a different copy, and a
failed extraction that must not write any roots.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Release promotions run the UI job against the candidate's checkout. An alpha
that predates the native Markdown disclosure renderer has no
NativeMarkdownProof tests, and the proof runner rejects a zero-test run, so the
promotion would fail on proofs the candidate never had. Run the step during a
promotion only when the candidate contains the proof tests. Ordinary CI always
runs it and still fails on zero tests; the workflow contract pins that
condition.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
main (openclaw#2093) now renders assistant http/https links and bare URLs as live
hyperlinks, sanitizing with preserveWebLinks. Disclosure bodies follow that
policy, but a summary is plain Expander header text, so a preserved web link
would read as "[docs](<https://...>)". Re-sanitize summaries inertly so they
read "docs (https://...)" as before.

Replace the disclosure inert-content proof with a behavioral proof of the
merged policy: web links and bare URLs inside and outside a disclosure are
live with exact targets, file: links, images and raw HTML stay inert, the
summary link reads as text, and the chat's underline-free link and
inline-code chip styling reaches disclosure bodies. This also covers the
source-text assertions main added to ReactorChatMarkdownContractTests, which
this PR deletes.
main openclaw#2101 moved assistant Markdown to the web chat's 14-pixel block gap,
with list, marker, divider and code-syntax hooks. A message that contains a
disclosure still stacked its parts at the old 8-pixel gap, so the text
around a disclosure and the blocks of its body sat tighter than the rest
of the message. Disclosures now share MessageBlocks' rhythm, including the
compact 8-pixel gap in thinking text.

Markdown after a disclosure is rendered as its own block stack, so its
first heading lost the 7-pixel lead-in a heading keeps after any other
block. The renderer now learns whether a part leads its message or
disclosure body, and only a leading part drops that lead-in.

This PR deletes the source-text ReactorChatMarkdownContractTests, which
openclaw#2101 extended. Its list, ordered-marker and thematic-break hook checks
become mounted assertions in ReactorMarkdownWebParityProofTests; code
syntax and highlighter cleanup were already covered there, and list
wrapping by the disclosure proof. The list-layout ledger row now states
that the ListItem hook only restyles and places the marker.
@paulcam206
paulcam206 force-pushed the paulcam206-markdown-details-disclosures branch from fd03c44 to 6efff19 Compare November 11, 2026 20:42
@roboclaw-bot

Copy link
Copy Markdown
Contributor

Scoped maintainer refresh requested by @bkudiess: merging captured main 3d5f14270dd6bd8b260a723ff2e73a68ea858ca8 into the existing contributor branch at 6efff19a105d92a4d2215269dd12614f70bf5616, preserving history and the restricted sanitized disclosure behavior. I will preserve newer Markdown/theme contracts, inspect automatic CI/profile-export merges, and obtain independent candidate review before a non-force branch update. This is conflict repair only: no PR merge, draft transition, title/body change, or new review request. Current-head Windows validation is unavailable on this Linux host; existing native evidence remains tied to its original head.

@roboclaw-bot roboclaw-bot added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Nov 12, 2026
Preserve current Markdown styling, links, shared theme ownership and CI lanes. Port the newer shared contrast-owner contract into the existing mounted Markdown behavior proof instead of retaining obsolete source-shape assertions.

Co-authored-by: bkudiess <7658216+bkudiess@users.noreply.github.com>
@roboclaw-bot

Copy link
Copy Markdown
Contributor

Refreshed #1773 (fix(chat): native chat shows literal details tags instead of collapsible sections) on the original contributor branch with a normal, non-force push.

  • Original head: 6efff19a105d92a4d2215269dd12614f70bf5616.
  • Main merged: 3d5f14270dd6bd8b260a723ff2e73a68ea858ca8.
  • New head: 0abb30a457652952c73aa78ff33cee67b3329525 (two-parent merge, original head first). Author history and the requested co-author credit are preserved.
  • GitHub now reports mergeable: true; the PR remains open and non-draft. This clears the textual conflict, not the remaining review, proof or CI gates.

Conflict choice: the sole modify/delete conflict was ReactorChatMarkdownContractTests.cs. Its obsolete source-shape suite remains replaced by the PR's behavioral parser/rendering coverage. Main's newer shared contrast-owner guard was not dropped: the mounted web-parity proof now toggles ChatThemeChanges.IsHighContrast and calls ChatThemeChanges.Refresh directly, asserting that mounted Markdown highlighters clear and return through the shared owner. The shared owner and current-main theme resources are retained unchanged.

Integration: the narrow balanced, sanitized details/summary parser and native Expander behavior are retained. #2093 link/inline-style policy and #2101 Markdown rhythm, list and code presentation remain in their existing owners. The five automatically merged owner/docs/project files were independently recomputed and matched the candidate byte-for-byte. The split Gateway fixture lane, isolated disclosure lane, production-resource/animation exclusions and pipeline-owned UI-profile export remain intact; no general HTML execution or redesign was added.

Review and validation: independent GPT-6 Astra review through the canonical shared helper covered the full 17-file candidate against the exact main SHA, P0-P3, with no actionable findings (scoped-clean, exit 0). This was static review, not native proof; merge-specific raw-parent attribution was not independently assessed. Eight local static integration checks, five automatic-merge comparisons and Git whitespace/ancestry checks passed. ./build.ps1, required Shared/Tray tests, focused parser/native Markdown tests, workflow/profile/docs PowerShell checks, prerequisite check and WinApp discovery were attempted but blocked on this Linux host (no PowerShell, .NET or WinApp). Zero native tests executed. No installs, cloud allocation or live UI run were performed. Existing screenshots/native receipts remain evidence for 6efff19a, not for this merge head.

New-head CI: Build and Test run 43298592551 and CodeQL run 43298591439 are pending/in progress. Required current-head Windows checks and behavior proof remain outstanding. The existing maintainer decision on adopting the restricted disclosure capability, and the previously noted proof-pool declaration correction, are unchanged. This branch is not being declared merge-ready.

Handing back after this scoped refresh. No merge into main, title/body edit, draft transition or hosted re-review request was made.

@roboclaw-bot roboclaw-bot removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Nov 12, 2026
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot removed the status: ⏳ waiting on maintainer Only explicit maintainer approvals or decisions remain; merge is still blocked. label Nov 12, 2026
# Conflicts:
#	scripts/test-ci-workflow-contract.ps1
# Conflicts:
#	.github/workflows/ci.yml
#	scripts/test-ci-workflow-contract.ps1
#	tests/OpenClaw.Tray.Tests/CiNugetCacheWorkflowTests.cs
@paulcam206

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added the status: ⏳ waiting on maintainer Only explicit maintainer approvals or decisions remain; merge is still blocked. label Nov 13, 2026

This branch has not been deployed

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

Labels

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: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on maintainer Only explicit maintainer approvals or decisions remain; merge is still blocked.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants