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>
156 lines
8.3 KiB
Markdown
156 lines
8.3 KiB
Markdown
# Campaign CT — connected gate script (CT7, user-driven)
|
||
|
||
**Purpose:** live verification of the character-panel parity campaign
|
||
(CT1–CT6) 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**: "<Gender> <Heritage> <DisplayTitle>" — 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 "<available> / <maximum>" — 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
|
||
`0x100005FE` — `docs/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?
|