fix(chat): avoid session-switch crashes without clipping Markdown lists - #1426
Conversation
Pin both Reactor packages to preview.12 and restore finite-width list layout through MarkdownOptions.ListItem. Preserve row-targeted scrolling and document removal gates in #1424. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 0b09606a-3b94-4974-87d1-2068b0e79e76
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: blocked before merge. Reviewed September 14, 2026, 10:29 PM ET / September 15, 2026, 02:29 UTC (Revision 2). ClawSweeper reviewWhat this changesPins the native chat rendering packages to preview.12 and adds a wrapping list layout, native layout tests, and workaround retirement guidance. Merge readiness⛔ Blocked before merge - 3 items remain This remains a useful mitigation absent from main. The additional app screenshot strengthens Markdown proof, but does not resolve the previous review’s long-history compatibility concern. No discrete introduced code defect was found. Priority: P0 Review scores
Verification
How this fits togetherThe native Windows chat timeline turns Gateway history and streaming messages into virtualized WinUI rows. Reactor controls row reuse and Markdown layout, while the application’s scroll controller targets the final message. flowchart LR
A[Gateway history and streaming] --> B[Chat timeline]
B --> C[Reactor row reuse]
B --> D[Sanitized Markdown]
D --> E[Wrapping list layout]
C --> F[Native chat view]
E --> F
G[Final message targeting] --> F
Decision needed
Why: Source supports the mitigation and screenshots demonstrate wrapping, but accepting an unverified renderer rollback for the crash-affected release requires explicit risk ownership. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Retain the narrow layout override and row-targeted scrolling only with native upgrade-compatibility evidence, then retire both package pins and the callback together through the existing tracking issue. Do we have a high-confidence way to reproduce the issue? No current-main runtime reproduction was established in this review. Released-build crash reports and the upstream native reproducer support the failure mechanism, but the exact application scenario still needs successful after-fix verification. Is this the best way to solve the issue? Yes, provisionally: the pinned callback matches the upstream layout fix and preserves final-row targeting, avoiding the reported short-scroll alternative; the rollback’s runtime safety remains conditional on native validation. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against ddb54a9614a5. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
Recording.2026-09-14.193250.mp4 |

What Problem This Solves
Mitigates release-blocking WinUI chat session-switch crashes while keeping Markdown list content readable. Related: #1421 and #1419. Follow-up/removal tracking: #1424 (keep open).
Draft, not release-ready: full 240-message session-switch/scrolling proof and independent review remain blocked below.
User Impact
Retains existing row-targeted scrolling and virtualization. Long list items wrap instead of being clipped. No settings, credential, protocol or migration changes.
Why This Change Was Made
The reported regression begins with Reactor preview.13's ElementFactory eviction/lifetime change, microsoft/microsoft-ui-reactor@8ee940c. It exposes microsoft/microsoft-ui-xaml#11865: ItemsView retains a pending bring-into-view target after it is collapsed and subsequently throws E_INVALIDARG. Waiting for a WinUI NuGet release is not viable for the current release mitigation.
Pin both Microsoft.UI.Reactor and Microsoft.UI.Reactor.Advanced to 0.1.0-preview.12. This reverses the dependency upgrades from #1376 (build(deps): upgrade Microsoft.UI.Reactor to 0.1.0-preview.14) and #1400 (fix(chat): prevent bubble text truncation), not unrelated changes from those PRs. Adapt the Markdown factory namespace and two hit-testing setters to preview.12's APIs, preserving behavior.
Why not the scrolling workaround?
#1407 (fix(chat): work around WinUI session-switch crash) stopped the crash in reported tests, but Barbara's 240 mixed-height message scenario stopped around message 233. The bottom extent changes as rows render, so scrolling to the current extent can stop short of the actual final message. That is also a release blocker. This PR leaves
ReactorItemsViewScrollControllerandStartBringItemIntoViewunchanged.Markdown workaround and retirement
Preview.15 supplied microsoft/microsoft-ui-reactor#1197 (Fix Markdown list content wrapping). Instead of adopting the newer row-lifetime behavior, use
MarkdownOptions.ListItemto replace the default two-child HStack with an Auto marker / Star content Grid, matching that upstream layout fix. Preserve the parser-produced marker, content, nesting, formatting and existing spacing. No fixed message widths, flattening, native layout handlers or styling changes.Old layout owner: Reactor preview.12's default list-row HStack. Temporary owner:
ReactorChatTimeline.BuildSafeMarkdown's ListItem callback. Preserved invariant: only the width constraint changes. The callback explicitly rejects an unexpected dependency shape. #1424 tracks upgrading both packages and removing this callback together after a shipped WinUI fix and full runtime proof.Evidence
Mounted native WinUI proof covers long ordered/unordered items at 240 DIPs, reflow at 600 DIPs, nested/loose lists, retained bold formatting and block content. Existing table/literal-fence and disposal tests pass.
Current-change narrow unordered-list capture, inspected locally. The full final words are visible:
Change Type
Scope
Required proof pools
windows-winui-interactive: session switching, actual final-message visibility, wrapping, streaming and scroll-away behavior.windows-11-arm64: dependency rollback affects native ARM64 runtime behavior; local build and mounted Markdown proof completed, full app proof outstanding.Validation
Exact code committed as
3cda150580b1ade5448d75400ba5c252925bb824, Windows ARM64 / .NET SDK 10.0.400.OPENCLAW_REPO_ROOTpoints to the isolated worktree;OPENCLAW_TRAY_DATA_DIRpoints to a dedicated temporary test directory. Built fresh Shared/Tray test projects before--no-restore..\build.ps1: all five projects and documentation validation passed.dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restore --verbosity quiet: 3,983 passed, 33 skipped, 0 failed.dotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restore --verbosity quiet: 2,976 passed, 0 skipped, 0 failed.git diff --cached --check: passed before commit.Initial rollback compilation errors were fixed at the three incompatible API call sites, followed by full validation. Explicit test-side layout completion fixes an initial not-yet-arranged observation; production code does not call UpdateLayout.
Real behavior proof
3cda150580b1ade5448d75400ba5c252925bb824(identical code validated before commit).BuildSafeMarkdown; assert ordered/unordered marker and full text, finite available width and multiline height at 240 DIPs; resize to 600 DIPs and assert reduced height with identical text. Mount nested/loose content and assert three Auto/Star rows, paragraphs, quote content and bold runs. Run table and disposal proof.the final words of the message.Other requested captures were not produced reliably; only the verified local narrow capture is included.MeasureOverride/UpdateLayoutin the unpackaged VSTest host, before switching. Its cause has not been established. The unsuccessful experiment is retained outside the PR, not shipped as a failing/skipped test, and not counted as crash-fix proof. Repeated live-app session switching, actual message-240 visibility, real Gateway history loading, streaming follow and reader-position preservation remain required before release. Markdown tests are not substitutes.python .\.agents\skills\autoreview\scripts\autoreview --mode localwas attempted with rollback/proof context. After staging to fit the complete bundle, default Codex review failed with HTTP 401 Unauthorized, confirmed with a same-engine streamed retry. No clean independent review is claimed.Security Impact
No new permissions, capabilities, network calls, command execution, data access or credential handling. Markdown sanitization, NoHtml parsing and inert image/link handling remain unchanged.
Compatibility and Migration
Both packages move together to preview.12. Existing styling is preserved. No configuration or migration is required. Keep the pin and callback until #1424's retirement gates pass.