#140 receipts: name the corruption case in a FIELD log

Two ungated one-liners, because no bench here reached the failing path and
the next playtest is a better instrument than more automation:

  [glasswin] destroy entry #N windows=M   -- N=2,M=0 is the double-destroy
  [glasswin] saved ... (live=L remembered=R) -- live=0 IS the corruption case
                                                (pre-cache that wrote a file
                                                holding only the plasma line)

Also lands the benches that did NOT reproduce it, with their failure modes
recorded in the headers so the next attempt does not repeat them:
layoutsave.sh (round trip -- passes on the fixed build), layoutteardown.sh
(graceful WM_CLOSE; still never reaches the dtor chain), layoutround.sh (MP
round boundary; the relay never started the mission inside the window).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NCJQkvq6G2JNrpVbA75tVZ
This commit is contained in:
Joe DiPrima
2026-08-07 01:23:33 -05:00
co-authored by Claude Opus 5
parent c04bec0a52
commit 43d30ca7e4
4 changed files with 213 additions and 1 deletions
+18 -1
View File
@@ -1030,8 +1030,15 @@ static void
++wrote;
}
fclose(f);
// #140 receipt (ungated): `live=` is the diagnostic that matters. A save
// that runs with live=0 is the corruption case -- before the remembered-
// geometry cache it wrote a file containing ONLY the plasma line, which is
// what testers reported. It stays in the log so the FIELD can tell us which
// caller does that (teardown ordering, a drag after a round boundary, ...),
// which no bench here managed to reach.
DEBUG_STREAM << "[glasswin] saved " << wrote << " window position(s) to "
<< layoutFileName << "\n" << std::flush;
<< layoutFileName << " (live=" << gWinCount
<< " remembered=" << gLastGeomCount << ")\n" << std::flush;
}
// Public save trigger for registered external windows -- their WndProc calls
@@ -1789,6 +1796,16 @@ void
void
BTGlassPanels_Destroy()
{
// #140 receipt (ungated, one line per teardown): this function has two
// callers on the desktop path and the ORDER is what broke the layout file.
// A run that shows `entry #2 windows=0` is the double-destroy, on the
// record, without needing to catch the cfg mid-corruption.
{
static int s_destroyN = 0;
DEBUG_STREAM << "[glasswin] destroy entry #" << ++s_destroyN
<< " windows=" << gWinCount << "\n" << std::flush;
}
// Backstop for a clean teardown (WM_EXITSIZEMOVE already caught every
// finished drag); no-op unless mode==save. GUARDED on there being windows:
// this function has TWO callers (~PadRIO and ~LBE4ControlsManager), so on