docs(issues): file #398 and #399 from the launcher gate launch

#399 (HIGH, process class): no test constructs MainWindow — the launcher
test project is ViewModel-only with no Avalonia headless package, which is
how a crash on every modal open/close passed 14,012 green tests and reached
the user gate. Fix direction is Avalonia.Headless.XUnit plus a view test
that drives every modal open/close, catching the class rather than one
spelling.

#398 (MODERATE): the top-level guard prints only ex.Message, so the fatal
NullReferenceException fixed at d54b8a78 surfaced with no file, line, or
frame; diagnosis needed a temporary code edit and rebuild. Fix direction is
a redaction-scanned crash file under the data root.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-15 07:32:06 +02:00
parent d54b8a789e
commit ef9d610459

View file

@ -24,6 +24,55 @@ What does NOT go here:
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
## #399 — Launcher: no test ever constructs MainWindow, so code-behind defects reach the user gate
**Status:** OPEN
**Severity:** HIGH (process class: this gap let #398 — a crash on every
modal open/close — pass 14,012 green tests and reach the user gate)
**Filed:** 2026-08-15 (found while launching the launcher for the LA11 gate)
**Component:** tests/AcDream.Launcher.Tests
`tests/AcDream.Launcher.Tests` is ViewModel-only — its csproj has no
Avalonia headless package, and no test instantiates `MainWindow` or any
view. `LauncherWindowViewModelTests` proved the modal state machine while
the code-behind that consumes it was never executed once, which is exactly
how #398's null `x:Name` fields survived every automated gate.
**Fix direction.** Add `Avalonia.Headless.XUnit` to the launcher test
project and a focused view test that constructs `MainWindow`, asserts every
`x:Name` field the code-behind dereferences is non-null, and drives each
modal (editor kinds, first-run wizard, update prompt) through open and
close so the focus/restore paths actually run. That catches the class —
any null named control or throwing handler — not just #398's spelling.
**Acceptance:** a headless view test fails against the pre-#398 code
(`AvaloniaXamlLoader.Load`) and passes after, and runs in the portable
Windows+Ubuntu CI lane alongside the existing launcher tests.
## #398 — Launcher: fatal startup/dispatcher exceptions are reported without a stack
**Status:** OPEN
**Severity:** MODERATE (diagnosability)
**Filed:** 2026-08-15
**Component:** `src/AcDream.Launcher/Program.cs`
`Program.Main`'s top-level guard prints only `ex.Message` before returning
74. For the `MainWindow` NullReferenceException fixed at `d54b8a78` that
produced `Launcher startup failed safely: Object reference not set to an
instance of an object.` with no file, line, or frame — diagnosis required
temporarily editing the guard to print the full exception and rebuilding.
An alpha user hitting a crash can give us nothing actionable.
**Fix direction.** Keep stderr terse, but write the full exception
(`ToString()`, including inner exceptions) to a crash file under the
resolved data root, and print that path. Must honor the LA11 redaction
contract: the crash file is subject to the same credential-value scanning
as the status stream, and must never contain a password or a raw command
line.
**Acceptance:** a fatal startup exception produces a crash file with the
stack, stderr names its path, and the redaction suite covers the new sink.
## #397 — Windows: LauncherProcessSupervisor.Stop has no reliable graceful-stop signal for a no-window console host
**Status:** IN-PROGRESS — the isolated process-group implementation and real