docs+fix(ui): Campaign AS CLOSED — connected gate PASSED; AS-GF1 probes stripped; #443 narrowed
Some checks failed
CI / linux-portable (push) Failing after 3m15s
CI / windows-gate (push) Failing after 6m54s
CI / release (push) Has been skipped

The owner ran the Campaign AS connected gate live and passed it. The two
gate findings resolved in-round: the extras-list "black rectangle" is
retail's own authored scroll-less clipped listbox (no scrollbar authored
on 0x10000335, verified against the live DAT; wheel-scroll/resize reveal
rows — AS-GF1 65f6f584 ruled it not a code defect), and the paperdoll
symptom narrowed from "renders nothing" to an intermittent FIRST-OPEN
DELAY: the probe round proved the private render layer healthy from the
first frames (nonzero handle, 34 MeshRefs, sane bounds/camera) for both
the examination clone and the inventory doll, with mesh residency/upload
latency the leading suspect. #443 stays open with that narrowed shape.

Per the probe-dies-with-its-investigation rule this strips
CreatureAppraisalViewportDiagnostics, its call sites, and the
launch-options row in one commit (recoverable via git show 65f6f584).
App hermetic suite green (6,337/0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-25 14:15:26 +02:00
parent 65f6f5848a
commit ddbd7e4096
5 changed files with 33 additions and 90 deletions

View file

@ -136,37 +136,19 @@ internal sealed class RetailCreatureAppraisalFrameView :
if (_controller.ActiveView is not (
AppraisalView.Creature or AppraisalView.Character))
{
CreatureAppraisalViewportDiagnostics.ReportGate(
$"no ActiveView (was {_controller.ActiveView})");
return false;
}
if (!IsEffectivelyVisible(_windowFrame))
{
CreatureAppraisalViewportDiagnostics.ReportGate("windowFrame hidden");
return false;
}
if (!IsEffectivelyVisible(_viewport))
{
CreatureAppraisalViewportDiagnostics.ReportGate("viewport hidden");
return false;
}
if (_controller.CurrentObjectId == 0u)
{
CreatureAppraisalViewportDiagnostics.ReportGate("no CurrentObjectId");
return false;
}
serverGuid = _controller.CurrentObjectId;
width = (int)_viewport.Width;
height = (int)_viewport.Height;
if (width <= 0 || height <= 0)
{
CreatureAppraisalViewportDiagnostics.ReportGate(
$"zero viewport extent ({width}x{height})");
return false;
}
CreatureAppraisalViewportDiagnostics.ReportGate("open");
return true;
return width > 0 && height > 0;
}
public void SetTextureHandle(uint textureHandle) =>
@ -225,18 +207,9 @@ internal sealed class RetailCreatureAppraisalCloneFactory :
boundsMin = Vector3.Zero;
boundsMax = Vector3.Zero;
if (!_entities.TryGet(serverGuid, out WorldEntity source))
{
CreatureAppraisalViewportDiagnostics.ReportSync(
$"entity not found (guid 0x{serverGuid:X8})");
return false;
}
if (source.MeshRefs.Count == 0)
{
CreatureAppraisalViewportDiagnostics.ReportSync(
$"no MeshRefs (guid 0x{serverGuid:X8})");
return false;
}
CreatureAppraisalViewportDiagnostics.ReportSync("synchronized");
WorldEntity clone = currentClone is not null
&& currentClone.SourceGfxObjOrSetupId == source.SourceGfxObjOrSetupId

View file

@ -1,52 +0,0 @@
using System;
namespace AcDream.App.Rendering;
/// <summary>
/// AS-GF1 (2026-08-25): a temporary, state-change-gated probe for the
/// creature-examination paperdoll regression (#443 — the animated paperdoll
/// stopped rendering for player targets sometime in Campaign AS, but
/// exhaustive review of the AS2-AS5 diff plus a worst-case hermetic
/// regression test (AppraisalUiControllerTests.
/// CharacterResponse_WorstCaseExtrasCombination_DoesNotThrowAndViewportGateStaysOpen)
/// proved <see cref="AcDream.App.UI.Layout.AppraisalUiController"/> never
/// blocks ActiveView/CurrentObjectId/the viewport's ancestor-visibility
/// chain, even under the combined AS3+AS4 worst case). This means the actual
/// failing condition is one of
/// <see cref="RetailCreatureAppraisalFrameView.TryGetVisibleTarget"/>'s four
/// gates or <see cref="RetailCreatureAppraisalCloneFactory.TrySynchronize"/>'s
/// two — none of which the Campaign AS diff touches — and could not be
/// reproduced hermetically (it needs a live entity + a live examine
/// exchange). Enable with <c>ACDREAM_PROBE_CREATURE_APPRAISAL_VIEWPORT=1</c>;
/// logs only on a REASON transition (not every frame) to stay cheap enough
/// to leave on for a whole session. Delete this class and its call sites in
/// the commit that lands the real fix.
/// </summary>
internal static class CreatureAppraisalViewportDiagnostics
{
public static bool Enabled { get; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_CREATURE_APPRAISAL_VIEWPORT") == "1";
// Two independent last-reason latches — TryGetVisibleTarget and
// TrySynchronize each run every frame and would otherwise "transition"
// against EACH OTHER's most recent line on every healthy frame,
// defeating the point of state-change-only logging.
private static string? _lastGateReason;
private static string? _lastSyncReason;
public static void ReportGate(string reason)
{
if (!Enabled || reason == _lastGateReason)
return;
_lastGateReason = reason;
Console.WriteLine($"[AS-GF1-PROBE] TryGetVisibleTarget: {reason}");
}
public static void ReportSync(string reason)
{
if (!Enabled || reason == _lastSyncReason)
return;
_lastSyncReason = reason;
Console.WriteLine($"[AS-GF1-PROBE] TrySynchronize: {reason}");
}
}