From d1c1368a5eaea734ecd630d1b9dd92f4839e869e Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 9 Aug 2026 22:38:34 +0200 Subject: [PATCH] =?UTF-8?q?fix(chat):=20CH2=20SpewBox=20lease=20was=20acqu?= =?UTF-8?q?ired=20but=20never=20transferred=20=E2=80=94=20startup=20crash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The composition scope's completion contract threw 'unpublished resources: spew box' on every graphical launch with the retail UI: scope.Acquire's returned lease was discarded, so it could never be Transfer()ed alongside its siblings. Suite missed it because the composition tests run with RetainedUi absent, so the acquire block never executed. Ownership after transfer matches the wait-notice no-tunnel arm: the retained-UI root's teardown reclaims the element tree. Co-Authored-By: Claude Opus 5 --- .../Composition/LivePresentationComposition.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/AcDream.App/Composition/LivePresentationComposition.cs b/src/AcDream.App/Composition/LivePresentationComposition.cs index b3396241..d6802e3d 100644 --- a/src/AcDream.App/Composition/LivePresentationComposition.cs +++ b/src/AcDream.App/Composition/LivePresentationComposition.cs @@ -1078,10 +1078,15 @@ internal sealed class LivePresentationCompositionPhase // Campaign CH slice CH2: the SpewBox is retail's OTHER on-screen // interface-text surface (research doc §1.1/§7.3/§7.4) — modeled // directly on the PortalWaitNoticeController lease immediately - // above, wired into the same retained-UI host. + // above, wired into the same retained-UI host. Like the wait notice + // in its no-tunnel arm, the transferred controller is reclaimed by + // the retained-UI root's own teardown (its Dispose only detaches + // children from that root). + CompositionAcquisitionScope.CompositionAcquisitionLease< + SpewBoxController>? spewBoxLease = null; if (interaction.RetainedUi is { } spewBoxRetainedUi) { - scope.Acquire( + spewBoxLease = scope.Acquire( "spew box", () => new SpewBoxController( spewBoxRetainedUi.Host.Root, @@ -1300,6 +1305,7 @@ internal sealed class LivePresentationCompositionPhase portalDepthLease.Transfer(); portalTunnelLease?.Transfer(); portalWaitNoticeLease?.Transfer(); + spewBoxLease?.Transfer(); skyLease.Transfer(); particleLease.Transfer(); bindingsLease.Transfer();