fix(source): align the visible caret before native focus

Hosted diagnostics show GettingFocus captures the correct 5311 offset but later pointer/caret processing resets it to zero. Position only an unselected read-only caret in the visible text before focus; retain active find and viewport guards. Exact full UI acceptance remains required.

Allow the enlarged full published/installed suites a bounded five minutes and retain process output before reporting timeout failure. An owned headless timeout probe and both script-analyzer passes passed.

Refs #10, #11

Co-Authored-By: Codex (GPT-6) <noreply@openai.com>
Signed-off-by: James Maes <jmaes@dmdbrands.com>
This commit is contained in:
James MaesandCodex committed 2026-10-11 01:12:44 -05:00
1 parent 82898bd278
commit 1c4d1adaca
3 files changed
+48 -5

No files matched your search

+6 -4
View File
@@ -77,15 +77,17 @@ function Invoke-SmokeProcess
$stderr = $process.StandardError.ReadToEndAsync()
try
{
if(-not $process.WaitForExit($TimeoutSeconds * 1000))
$timedOut = -not $process.WaitForExit($TimeoutSeconds * 1000)
if($timedOut)
{
$process.Kill($true)
throw "Process timed out: $File"
if(-not $process.WaitForExit(10000)) { throw "Timed-out process did not terminate: $File" }
}
$script:smokeProcessNumber++
$log = Join-Path $outputRoot "process-$script:smokeProcessNumber.log"
$text = $stdout.GetAwaiter().GetResult() + $stderr.GetAwaiter().GetResult()
Set-Content -LiteralPath $log -Value $text
if($timedOut) { throw "Process timed out: $File. Log: $log" }
if($process.ExitCode -ne 0) { throw "Process failed ($($process.ExitCode)): $File. Log: $log`n$text" }
}
finally { $process.Dispose() }
@@ -183,7 +185,7 @@ try
if($loose.Installed -or $loose.AppKitSupported -or $null -ne $loose.Version) { throw 'Loose publish output unexpectedly supports updates.' }
$records.Add(@{ kind = 'loose'; result = $loose })
$env:K22_UITEST_EXE = Join-Path $buildRoot "publish/0.1.0/$mainExe"
Invoke-SmokeProcess -File 'dotnet' -Arguments @('test', "$repositoryRoot/tests/$name.UiTests", '--no-build', '--logger', 'trx;LogFileName=published-ui.trx', '--results-directory', $outputRoot) -TimeoutSeconds 180
Invoke-SmokeProcess -File 'dotnet' -Arguments @('test', "$repositoryRoot/tests/$name.UiTests", '--no-build', '--logger', 'trx;LogFileName=published-ui.trx', '--results-directory', $outputRoot) -TimeoutSeconds 300
foreach($initial in @($versions[0], $versions[2]))
{
$portableDirectory = Join-Path $outputRoot "portable-$($initial.channel)"
@@ -234,7 +236,7 @@ try
$after = Get-SmokeResult -Exe $installedProbe -ResultPath (Join-Path $outputRoot "$channel-after.json")
if($after.Version -ne $initial.target -or $after.Channel -ne $channel -or $null -ne $after.UpdateVersion -or $after.AppKitVersion -ne $initial.target) { throw 'Post-upgrade identity or channel is incorrect.' }
$env:K22_UITEST_EXE = $currentExe
Invoke-SmokeProcess -File 'dotnet' -Arguments @('test', "$repositoryRoot/tests/$name.UiTests", '--no-build', '--filter', 'FullyQualifiedName!~CheckForUpdates_InALooseBuild', '--logger', "trx;LogFileName=installed-$channel-ui.trx", '--results-directory', $outputRoot) -TimeoutSeconds 180
Invoke-SmokeProcess -File 'dotnet' -Arguments @('test', "$repositoryRoot/tests/$name.UiTests", '--no-build', '--filter', 'FullyQualifiedName!~CheckForUpdates_InALooseBuild', '--logger', "trx;LogFileName=installed-$channel-ui.trx", '--results-directory', $outputRoot) -TimeoutSeconds 300
$records.Add(@{ kind = 'installed'; channel = $channel; before = $before; after = $after; restarted = $true; appSha256 = $installedHash })
}
finally
+23
View File
@@ -11,6 +11,29 @@ Owner authorized signed/DCO commits, pushes, repository configuration and ticket
No merges, tags/releases or new Azure attempts. Human review acknowledgement remains
required. Local desktop reservation is unanswered; hosted runner UI tests are authorized.
## Source caret alignment probe — 2026-10-11
82898bd / CI 38117005710 isolated source job 114403773700 reproduced FAILURE
in 18 seconds. Original timeout is now retained: source focus before=5310.933,
last=5310.933; after physical pointer press, actual native offset resets to 0.
The provider cannot retrieve the offscreen last-heading glyph. This rejects the
hypothesis that GettingFocus captured an already-reset offset; deferred restoration
ran too early to prevent later native caret work. Original full assertions stay intact.
The single-variable probe positions a zero-length caret at the first visible native
character before focus, using bounded binary search over real native character
rectangles. Active find/nonempty selections remain independent. The previous snapshot-
guarded viewport restoration remains. DEBUG-src-focus records the native caret index;
remove probes/temporary CI job after actual original acceptance proves the fix.
Full/native/installed producers on 82898bd remain observed until terminal before push.
The enlarged 48-case suite's measured native failure duration is 178 seconds and
published acceptance exceeded 180 seconds before producing TRX. Full published/
installed UI suites receive a bounded 300 seconds (all cases/assertions unchanged).
The process helper retains stdout/stderr after timed-out child termination before
throwing; a 10-second termination bound still fails closed. Other command timeouts
remain unchanged. A headless owned-child timeout probe checks retained evidence.
## Tight native source diagnostics after editor acceptance
f650e36 / CI 38116258625 native job 114401630861 finished FAILURE:
@@ -54,9 +54,27 @@ public sealed partial class MainWindow
return;
}
double position = scroller.VerticalOffset;
if(SourceText.SelectionLength == 0 && SourceText.Text.Length > 0)
{
int first = 0;
int last = SourceText.Text.Length - 1;
while(first < last)
{
int middle = first + (last - first) / 2;
if(SourceText.GetRectFromCharacterIndex(middle, trailingEdge: false).Y < position)
{
first = middle + 1;
}
else
{
last = middle;
}
}
SourceText.Select(first, 0);
}
if(string.Equals(Environment.GetEnvironmentVariable("MARKDOWNVIEWR_INPUT_TRACE"), "1", StringComparison.Ordinal))
{
App.Log.Info(FormattableString.Invariant($"Input trace: source focus before={position:R}, last={_sourceLastY:R}."));
App.Log.Info(FormattableString.Invariant($"[DEBUG-src-focus] source focus before={position:R}, last={_sourceLastY:R}, caret={SourceText.SelectionStart}."));
}
Core.Documents.DocumentSourceText? snapshot = _sourceDocument;
DispatcherQueue.TryEnqueue(() =>