Re-resolve workspace detail children while waiting for layout - #442
Merged
Merged
Conversation
The settle loop added in #441 polled cached AutomationElement references. These children are served by a custom fragment provider that destroys and recreates them when the loop panel re-lays out, and a dead fragment reports an empty AutomationId and empty BoundingRectangle instead of throwing, so a cached reference can never recover from a remount. The loop burned its whole budget and then failed with a blank id in the message. Re-resolve the four children from the live tree on every attempt and require one observed generation to satisfy existence and layout together, then rebind the variables so the later Invoke cannot run against a stale fragment. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Colin Neilens <coneilen@microsoft.com>
This was referenced Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
#441 added a settle loop so the workspace right-panel detail children are laid out before their bounds are asserted. It waited on the correct condition but against the wrong objects, so it did not fix the failure.
These four children are served by a custom fragment provider (
AccessibilityProvider.cpp), and the provider destroys and recreates them when the loop panel re-lays out. That invalidates anyAutomationElementreference captured beforehand. A dead fragment does not throw — it reports an emptyAutomationIdand an emptyBoundingRectangleindefinitely. #441's loop polled references captured before the wait, so once a remount happened it could never recover: it burned the full 10s budget and then failed.The decisive tell was in the failure text itself:
The AutomationId interpolates blank. All four children are selected by an
AutomationIdregex (^workspace-detail-sparkline-and friends), so every one of them provably had a matching, non-empty id at the moment the mount loop selected it. An id that is non-empty at selection and blank at assertion cannot be a slow layout — it is a different, dead object. This also explains the earlier observation that one commit produced two different failure sites in this block with no code change: it is a remount race, and which assertion you land on depends on when the remount falls relative to the mount loop's break.Fix
Re-resolve the four children from the live tree on every attempt, and require a single observed generation of the tree to satisfy existence and layout together. The four variables are then rebound to those live references so the
InvokePatterncall further down cannot run against a stale fragment either — the same latent bug, one assertion later.The bounds assertion itself is unchanged and still runs.
Evidence
RED: CI run 35950217001 on the pre-fix code -> FAIL
workspace right panel child has empty boundsatuia-live-gate.ps1:447, with the AutomationId interpolated blank, after #441's settle loop had already been given its full 10s budget. That blank id is the proof the polled reference was dead rather than merely unlaid-out.GREEN: the same
windows-shelllive gate now advances past the workspace right-panel block, resolving all four detail children in one generation of the tree and invoking the collapse control against a live reference -> see thewindows-shellcheck on this PR.REGRESSION:
Tools\windows\Tests\WindowsShell.Tests.ps1 -ZigExecutable $env:GRAPHCODE_ZIG0152-> All 266 tests passed, Windows shell scaffold contract: PASS (40 source files executed).Verification
Requirepredicate onmainis still present: 378 on main, 379 here, the single addition being the new$null -ne $resolvedDetailsguard. No predicate weakened or dropped.Add-Typeblock and its declaration counts are unaffected.