acdream/docs/research/2026-08-25-campaign-ct-test-script.md
Erik 996cd73675 fix(CT6): fix round — chrome-inclusive host clamp (BLOCKER B1) + 372px mount default
Opus dual-lens review of CT6 (ec50455a) found 1 blocker, 4 should-fix, 5
notes. All applied:

BLOCKER B1 — the shared gmPanelUI host (0x100005FE) IS retail's own
outer window frame, not a content element: its authored 310/372/310/1000
already include the 5px bevel on every side. RetailWindowFrame.Mount was
adding the NineSlice wrapper's OWN 10px chrome inset on top of that
already-chrome-inclusive source, clamping MinWidth to 320 while the
window's actual mounted outer width stayed 310 — silently below its own
minimum until RetailWindowManager.ResizeTo forcibly widened it despite
ResizeX=false. Fixed with a new
RetailWindowFrame.Options.DatConstraintSourceIsOuterFrame opt-out
(chrome inset = 0 for constraint resolution only, value stays
DAT-sourced); MountCharacter sets it true. Mounted clamp is now exactly
the host's four raw values: width fixed 310, height 372..1000. Added a
mount-time invariant (throws if the mounted outer extent falls outside
its own just-computed clamp) that would have caught this at the first
test run.

S4 (campaign-lead ruling) — the window must MOUNT at retail's authored
default, outer 372 (content 362, matching the host's own content parent
0x10000180), not 0x2100002E's own 300x600 content-authoring canvas
(which produced a stale 610px default pre-fix: 600 + 10 chrome inset).
372 is exactly the host's own authored MinHeight — retail opens at its
resize floor and can only be dragged taller. MountCharacter now sets
ContentHeight=362f explicitly. At this default the 9 attribute/vital
rows (180px) overflow the 160px list immediately — retail-correct, not
a regression.

S2 — 0x1000023E and 0x10000533 both author property 0x79
(HideWhenDisabled) TRUE (fixture-verified: BoolValue=true on both). A
fitting list HIDES the scrollbar entirely; it does not draw a full-track
"disabled" thumb. The code was already correct; four wrong descriptions
(plan ledger, CharacterStatController comment, CT7 script, test comment)
are corrected, plus a new IsPresentationVisible assertion pair in the
resize test.

S3 — CharacterTitlesController's `if (listBox.LayoutPolicy is null)`
Anchors fallback was unreachable on both the real DAT and the fixture
(0x10000532/0x10000539 both author HasOriginalParentSize=true, so
LayoutPolicy is always assigned). Deleted; added an InstalledDatFact pin
guarding the deletion against DAT drift.

N4 — renamed NineSlice_ChatShapedConstraints_... to
NineSlice_ContentShapedConstraints_InsetArithmeticClampsProgrammaticResize
(it tested inset arithmetic on a content-shaped source, not chat's real
contract) and added a true chat-contract pin mounting Chrome=Imported
with chat's real 300/100/2000/2000 constraints, asserting no inset
applies.

N5 — corrected the "nothing inferred, no register row" sentences in the
ground-truth doc and plan ledger: they were false pre-fix (the mounted
clamp WAS an inferred double-counted composition); true now that B1
removes the composition.

CT7 script §4 rewritten with exact clamps (no "≈"), the corrected
default-overflow scrollbar behavior, and an absolute starting-height
statement.

Verified: full hermetic solution suite green (15,441 tests, Release,
Lane exclusions per the release gate), InstalledDat lane green across
the whole solution (414 tests, ACDREAM_RUN_INSTALLED_DAT_TESTS=1,
Status!=KnownFailure) including two new pins
(TitlesListAndPage_AuthorHasOriginalParentSize,
Imported_ChatContract_ClampsAtAuthoredBoundsWithNoChromeInset).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 02:53:57 +02:00

8.3 KiB
Raw Blame History

Campaign CT — connected gate script (CT7, user-driven)

Purpose: live verification of the character-panel parity campaign (CT1CT6) against ACE. Launch: the normal connected launch (ACDREAM_RETAIL_UI=1, live ACE at 127.0.0.1:9000, ACDREAM_PAK_PATH=<worktree>\artifacts\owner-gate\acdream-v5.pak). Open the character panel (F9 / toolbar). Retail side-by-side comparison is the oracle for every visual item.

Useful ACE console helpers: title grants come from quests/admin — check @acecommands for a title-grant command; @grantxp for levels.


1. Header identity block (CT4) — Attributes AND Skills tabs

  1. Name line: the plain character name (rankless characters — the allegiance rank prefix is a registered deferral, AP-109).
  2. Heritage line: " " — e.g. "Female Aluvian War Mage" when a display title is set; just "Female Aluvian" when none. PASS: matches retail's composition and spacing exactly; a title beginning with "The" shows unmangled.
  3. PK line: "Non-Player Killer" (or "Player Killer" / "Player Killer Lite" on a PK/PKL character) in PURE WHITE. PASS: correct text + color on BOTH the Attributes and Skills tabs.
  4. Level number: pale gold with outline (authored color — compare against retail's level display side-by-side; the owner reported ours was previously off).
  5. Luminance pair: on a sub-200 character, NO luminance caption or value renders. (A level ≥ 200 character with MaximumLuminance shows "Luminance:" and " / " — verify only if such a character is available.)
  6. Live update: set a display title (see §2) — the heritage line updates the moment the server confirms, with no relog and no panel re-open.

2. Titles tab (CT3)

  1. Click the Titles tab. PASS: the page shows "Current Display Title:" + the current title (or "Unknown" only when the server's title id fails to resolve — normally a real title or the authored empty state), the "All Available Titles:" list, and the "Set as Display Title" button.
  2. List content: every earned title, alphabetically sorted, readable rows. With few titles the scrollbar shows retail's full-track thumb; with many (if available) the thumb sizes proportionally and scrolls.
  3. Ghost rule: with NOTHING selected the button is ghosted. Select the title that IS the current display title — button stays ghosted. Select a DIFFERENT title — button un-ghosts.
  4. Set round trip: click Set as Display Title. PASS: the display title text updates on the server's confirmation, the selection CLEARS (row highlight goes dark — retail behavior), the button re-ghosts, and the §1 heritage line updates live.
  5. Row selection visual: the selected row highlights with retail's row highlight art (full-row background swap), not a synthesized bar.

3. Attribute/skill rows (CT5)

  1. Icon alignment: row icons sit flush left (20x20 at the row's left edge), matching retail — the previous inset/smaller icons are gone. Compare a few rows side-by-side against retail.
  2. Value gutter: the numbers column ends with a visible margin before the panel border (the scrollbar band) — retail's 7px gutter.
  3. Row height: rows are retail-height (slightly tighter than before); section headers (Trained/Untrained/Unusable) unchanged.
  4. Selection highlight: clicking a row highlights with the retail full-row art; the spellbook's selection visuals are UNCHANGED (regression check — open the spellbook and select a spell).
  5. Raise buttons / tooltips / footer: regression sweep — raise ×1 and ×10 still work with correct ghosting, skill tooltips still show formula + description wrapped correctly, the footer numbers update.

4. Resize + scrollbar (CT6)

Ground truth (2026-08-25 live probe against layout 0x2100006E, host 0x100005FEdocs/research/2026-08-24-campaign-ct-dat-ground-truth.md §CT6, corrected by the CT6 fix round's BLOCKER B1): the resize clamp is authored on the SHARED gmPanelUI host, not the character content itself, and the host IS retail's own outer window frame — its authored values are chrome-INCLUSIVE, not a content size our own chrome adds on top of. Host authors MinWidth=MaxWidth=310 (fixed width — no horizontal Resizebar) and MinHeight=372, MaxHeight=1000. The MOUNTED window's outer bounds are EXACTLY those same numbers: width fixed 310px, floor 372px, ceiling 1000px — no inset is added on top (RetailWindowFrame.Options.DatConstraintSourceIsOuterFrame now tells the mount path this source already includes the bevel). Starting height: the window OPENS at retail's authored default, 372px — its own resize floor. It cannot open any shorter; it can only be dragged taller.

  1. Grab the bottom edge and drag up (shrink). PASS: the window stops shrinking at its authored floor (372px outer / the point where further dragging has no visible effect) — since the window already OPENS at that floor, this step should show no shrink at all (there is no room below the default to shrink into). It does NOT collapse arbitrarily small. Retail comparison: drag retail's own Character/ Skills window down from its own default; it should likewise refuse to shrink further immediately.
  2. Keep dragging down (grow). PASS: the window keeps growing until its authored ceiling (1000px outer) — same side-by-side comparison against retail's own ceiling.
  3. Left/right edges do not resize. Only the bottom edge (and top Dragbar for moving, not resizing) responds — matches retail's fixed-width authoring (no horizontal Resizebar).
  4. Scrollbar hand-off, Attributes tab. At the default window size (372px) the 9 attribute/vital rows (180px content) OVERFLOW the 160px list — the scrollbar is ACTIVE (visible + interactive) IMMEDIATELY on open, not after shrinking. PASS: this is the owner's item 2 fix — previously the scrollbar never appeared on Attributes at all. Grow the window until the rows fit without scrolling: the bar DISAPPEARS entirely (0x1000023E authors 0x79 hide-when-disabled TRUE — a fitting list hides the bar, it does not leave a full-track "disabled" thumb visible). Shrink back down and the bar reappears.
  5. Scrollbar hand-off, Skills tab. Same immediate-overflow-at- default check (a longer skills list only makes the overflow more obvious); grow until it fits and confirm the bar disappears the same way.
  6. Scrollbar hand-off, Titles tab. With several earned titles, the Titles list (authored 455px, inside the 575px page) is scroll-clipped into the same 372px-default window and its own scrollbar (0x10000533, also hide-when-disabled — fixture-verified) takes over the same way: active when titles overflow, hidden when the window is grown enough that they all fit.
  7. Footer stays bottom-docked. While shrinking/growing on the Attributes/Skills tabs, the footer (raise buttons / selected-stat info) stays pinned to the bottom edge — it does not float mid-window or get clipped early.
  8. Grow back restores. Drag back down to the original default (372px): the lists return to their default OVERFLOWING state (scrollbar reactivates — this is the default, not "all rows fit") and the window returns to its original proportions.
  9. Other windows (chat, social) still clamp at their own authored minimums — regression check (chat: min 300×100, max 2000×2000 per CharacterPanelLiveDatTests.ChatWindowRoot_AuthorsExplicitSizeConstraints).

5. Regression sweep (5 minutes)

  • Attributes/Skills tab switching unaffected; CA5 behaviors intact (raise round trips, live run-speed update on Quickness).
  • Logout/login: titles and display title persist; the header matches PlayerDescription's values.
  • Chat window: the CH-round fixes hold (input rails on focus, "Gen" caption, button flick, no vibrating text while dragging).

Report back

Per section: PASS/FAIL plus anything odd. The three answers that matter most:

  1. §2.4 — does the set-title round trip clear the selection and update the header live?
  2. §3.1/§3.2 — do icons and the value gutter now match retail side-by-side?
  3. §1.3 — is the PK line present, white, and correct on both tabs?