diff --git a/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml b/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml
index ef047402..d2b71067 100644
--- a/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml
+++ b/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml
@@ -45,12 +45,6 @@
on — hovering an ordinary bag slot — runs the real client's code, unedited.
── Named, not hidden: what still does not work through the sourced files ────────────────────
- · `MerchantItemButton_OnClick`. The reference's `ContainerFrameItemButton_OnClick` closes its
- shift-right-click-at-a-vendor arm with a `SplitStack` closure that calls that global, and
- benilla's merchant window publishes `BenillaMerchantItem_OnClick` instead. Confirming a stack
- split with a vendor open therefore raises. That is the same "a Benilla name shadows the
- reference's" class this whole seam exists to close, one window over, and it is left loud
- rather than guarded (1203): the fix is to publish the merchant global, not to hide the call.
· `REPAIR_COST` is read by the reference's repair-mode arm. It is a `GlobalStrings.lua` key and
this client sources that file too, so it resolves at runtime — and the arm is unreachable
today regardless, since `GameTooltip:SetBagItem`'s repairCost is an INTERIM 0.
diff --git a/crates/benilla-app/assets/ui/GameMenuFrame.xml b/crates/benilla-app/assets/ui/GameMenuFrame.xml
index 7911677b..41c37c41 100644
--- a/crates/benilla-app/assets/ui/GameMenuFrame.xml
+++ b/crates/benilla-app/assets/ui/GameMenuFrame.xml
@@ -30,9 +30,9 @@
Options", SOUNDOPTIONS_MENU "Sound Options", UIOPTIONS_MENU "Interface Options",
MACROS "Macros", LOGOUT "Logout", EXIT_GAME "Exit Game",
RETURN_TO_GAME "Return to Game", MAIN_MENU "Main Menu". Declared as the real globals
- (they are addon-visible API, decision 0068) and read back into each button's label in its
- OnLoad — the ref's `text="LOGOUT"` attribute IS a global lookup, which this engine's
- literal `text=` is not.
+ (they are addon-visible API, decision 0068) and carried on each button's own
+ `text=` attribute — which this engine resolves as a global-string lookup exactly as
+ the reference does (decision 0995, `loader/widgets.rs`'s `resolve_text`).
· **The sounds** — the ref's own OnClick lines: igMainMenuOption (the five option buttons),
igMainMenuLogout, igMainMenuQuit, igMainMenuContinue. All four kits verified present in
SoundEntries.dbc (patch-2.MPQ) alongside the igMainMenuOpen/Close pair already in use.
@@ -94,10 +94,9 @@
scripts, so it never actually moves).
`frameStrata="DIALOG"` is what puts it over the world UI, and that is kept.
**The "no frame-level raise" half of that reason is gone**: the raise law is built
- (`script::object::toplevel`, wow-re `ui/scratch/toplevel-raise.md`) and the loader honours
- `toplevel="true"`. Re-adding it here is a one-word change and would make the Esc menu come
- to the front over any other DIALOG-strata frame it overlaps; left off pending the
- director's call on the look, not on the mechanism.
+ (`script::object::toplevel`, wow-re `ui/scratch/toplevel-raise.md`), the loader honours
+ `toplevel="true"`, and the frame below carries it — so the Esc menu does come to the
+ front over any other DIALOG-strata frame it overlaps.
-->
-
+
@@ -275,15 +275,12 @@
-
-
-
+
+
-
-
-
- HideUIPanel(getglobal("BenillaScriptLogFrame"))
diff --git a/crates/benilla-app/assets/ui/benilla.toc b/crates/benilla-app/assets/ui/benilla.toc
index ff39d5b1..49863ce4 100644
--- a/crates/benilla-app/assets/ui/benilla.toc
+++ b/crates/benilla-app/assets/ui/benilla.toc
@@ -174,9 +174,10 @@ Interface\FrameXML\MoneyFrame.xml
# It is groundwork rather than a window, and the windows it is groundwork FOR are named so the
# next session does not have to re-derive it: stock `TradeFrame.xml` and `MailFrame.xml` both build
# their amount entry from this template and call `MoneyInputFrame_SetMode`/`_GetCopper`/
-# `_SetCopper`/`_ClearFocus`/`_SetTextColor`/`_SetOnvalueChangedFunc` — six of the names below —
-# and neither can be sourced until they exist. (Trade still needs four ENGINE verbs beyond this:
-# `AddTradeMoney`, `GetCursorMoney`, `GetTradePlayerItemLink`, `GetTradeTargetItemLink`.)
+# `_SetCopper`/`_ClearFocus`/`_SetTextColor`/`_SetOnvalueChangedFunc` — six of the names below.
+# Both windows are migrated now: `MailFrame.xml` at l.897 and `TradeFrame.xml` at l.906, the
+# latter once 1966 bound the four engine verbs it also needed (`AddTradeMoney`,
+# `GetCursorMoney`, `GetTradePlayerItemLink`, `GetTradeTargetItemLink`).
#
# **TWO entries, and the `.lua` was missing.** This `.xml` declares only the template and does not
# source its `.lua`; the reference's toc lists both (l.11-12). Listing the `.xml` alone brought the
@@ -489,8 +490,8 @@ Interface\FrameXML\MainMenuBarMicroButtons.xml
Interface\FrameXML\BattlefieldFrame.xml
# Minimap.xml + Minimap.lua: the cluster around the engine-rendered widget hole
# (`crate::minimap` fills it), the zone text, the zoom buttons, the tracking / mail / meeting
-# stone / battlefield icons, and `MiniMapPing` — a this engine draws no pixels for; the
-# app's ping sprite (`minimap/ping.rs`) follows that frame's own show/hide and alpha, so the
+# stone / battlefield icons, and `MiniMapPing` — a that renders its own MinimapPing.mdx
+# since 2013; `minimap/ping.rs` keeps the pin, the click seat and the wire half, so the
# 5 s lifetime is this file's, as the reference's is. After GameTooltip (the zone-text hover).
# 0203's transcription is gone.
Interface\FrameXML\Minimap.xml
@@ -579,8 +580,8 @@ Interface\FrameXML\ColorPickerFrame.xml
# s its own blip templates (WorldMapFrameTemplates.xml) before the frames that inherit
# them. Its player arrow is the Create/Position/Show/UpdateWorldMapArrowFrames family
# (`script/worldmap_arrow.rs`), an anonymous Model pane the app draws as the minimap's arrow
-# sprite; its WorldMapPing is a MinimapPing.mdx Model pane this engine holds and draws nothing
-# into (named gap, 1980).
+# sprite; its WorldMapPing is the same MinimapPing.mdx Model pane, which draws its own file on
+# the map sheet since 2013 (closing the gap 1980 named).
Interface\FrameXML\WorldMapFrame.xml
# ══ THE CAST BAR — the reference's own, off the player's chain (1751) ══
# `CastingBarFrame` + its Border/Flash/Spark/Text children, driven by the SPELLCAST_* events
@@ -964,7 +965,7 @@ Interface\FrameXML\BankFrame.xml
# a `CSimpleFrame` and nothing else, so it is `FrameKind::Frame` and the route lines stay what the
# reference makes them: plain `` children rotated by an 8-argument `SetTexCoord`.
#
-# Pulls only `TaxiFrame.lua`, and still needs only Fonts/UiPanels/GameTooltip (SetTooltipMoney),
+# Pulls only `TaxiFrame.lua`, and still needs only Fonts/UIParent/GameTooltip (SetTooltipMoney),
# all loaded above — so it keeps its seat in the "NPC session windows grouped" cluster.
Interface\FrameXML\TaxiFrame.xml
# The stable-master window (decision 1676): the hunter's three-slot pet stable over the stable
@@ -1186,8 +1187,8 @@ Interface\FrameXML\TutorialFrame.xml
# options family, the same chain `MainMenuBarMicroButtons` is deferred behind. All three columns
# read clean because the file LOADS clean; what it needs is a sibling window, not a verb.
#
-# Its CAMP/QUIT dialogs and their event driver HAVE moved out, to UiPanels.xml — the reference's
-# own homes (StaticPopup.lua l.564/586 for the dialogs, UIParent.lua l.304-315 for the three
-# events). The ESC menu never owned them; it was just where ours were first needed. That is one
-# less thing to move when the options family lands.
+# Its CAMP/QUIT dialogs and their event driver HAVE moved out — the dialogs to `StaticPopup.xml`,
+# the driver to `UIParent.xml`, the reference's own homes (StaticPopup.lua l.564/586 for the
+# dialogs, UIParent.lua l.304-315 for the three events), both stock since 1988. The ESC menu never
+# owned them; it was just where ours were first needed. That is one less thing to move when the options family lands.
GameMenuFrame.xml
diff --git a/crates/benilla-app/src/addon_harness/mod.rs b/crates/benilla-app/src/addon_harness/mod.rs
index b9339c3f..385d511c 100644
--- a/crates/benilla-app/src/addon_harness/mod.rs
+++ b/crates/benilla-app/src/addon_harness/mod.rs
@@ -1121,7 +1121,7 @@ fn load_dependencies(
///
/// **A string literal in the fourth argument, OR a local bound to one in the same file.** The
/// literal-only form was the honest under-report this doc used to name — and then a decision was
-/// made on the number it produced. `assets/ui/ItemButtonTemplate.xml` declined to build
+/// made on the number it produced. `Interface\FrameXML\ItemButtonTemplate.xml` declined to build
/// `ItemButtonTemplate` citing "the harness's template demand ranks it at zero on both axes"; the
/// zero was real, and pfUI wanted `ContainerFrameItemButtonTemplate` (which inherits it) the whole
/// time, through
@@ -3575,10 +3575,10 @@ mod dependency_tests {
/// **A template named through a local resolves; the shapes that still cannot are asserted too.**
///
/// The literal-only scan was an honest under-report — stated at `missing_templates` — and a
- /// decision was then made on the number it produced: `assets/ui/ItemButtonTemplate.xml`
- /// declined to build `ItemButtonTemplate` citing a demand of zero "on both axes". The zero was
- /// real and the demand was not: pfUI binds `local tpl = "ContainerFrameItemButtonTemplate"`
- /// and passes the variable, so the one addon that wanted it was invisible to the ranking.
+ /// decision was then made on the number it produced:
+ /// `Interface\FrameXML\ItemButtonTemplate.xml` declined to build `ItemButtonTemplate` citing a
+ /// demand of zero "on both axes". The zero was real and the demand was not: pfUI binds `local
+ /// tpl = "ContainerFrameItemButtonTemplate"` and passes the variable, so the one addon that wanted it was invisible to the ranking.
///
/// Both halves are asserted, because a scanner that quietly widened would be the worse fix:
/// the shape it now sees, AND the shapes it still does not, so the next decision quoting this
diff --git a/crates/benilla-app/src/capture/fixtures.rs b/crates/benilla-app/src/capture/fixtures.rs
index c47ff7d6..67efc141 100644
--- a/crates/benilla-app/src/capture/fixtures.rs
+++ b/crates/benilla-app/src/capture/fixtures.rs
@@ -252,8 +252,8 @@ pub(super) fn seed_ui_fixture(
gossip.quests = vec![(783, 0, 5, "Eagan Peltskinner".into())];
// One short option AND four that WRAP — the live shape both gossip bugs came in as
// (the director's screenshots), and a menu deliberately TALLER than the parchment so
- // the capture covers the whole chain: the per-row auto-height
- // (`BenillaGossipRow_Resize`), the scroll frame that contains the overflow, and the
+ // the capture covers the whole chain: the stock `GossipResize`'s per-row auto-height,
+ // the scroll frame that contains the overflow, and the
// scrollbar that appears with it. A fixture of one-line labels showed none of this —
// every row fit the template's 16 px and nothing ever overflowed.
let judgement = [
diff --git a/crates/benilla-app/src/cinematic.rs b/crates/benilla-app/src/cinematic.rs
index 6eece84e..4dadd52c 100644
--- a/crates/benilla-app/src/cinematic.rs
+++ b/crates/benilla-app/src/cinematic.rs
@@ -35,9 +35,9 @@
//! rather than being skipped (`0x48efe0`).
//! - **ESC is not an engine binding.** `StopCinematic` has zero native callers in the reference:
//! the only skip path is `CinematicFrame.xml`'s own `OnKeyDown`, which is why benilla's copy of
-//! that frame (`assets/ui/CinematicFrame.xml`) carries the same handler and why the Lua binding
-//! queues [`SessionRequest::StopCinematic`](benilla_ui::script::SessionRequest) rather than
-//! reaching in here.
+//! that frame (stock `Interface\FrameXML\CinematicFrame.xml`) carries the same handler and why
+//! the Lua binding queues [`SessionRequest::StopCinematic`](benilla_ui::script::SessionRequest)
+//! rather than reaching in here.
//! - **The ack ends the run, once.** `CMSG_COMPLETE_CINEMATIC` goes out on a natural end and on an
//! ESC skip alike (`0x48f080`). Decision 0196 is why it can never be dropped: unacked, vmangos
//! re-anchors object visibility to its own copy of the flying camera and everything around the
diff --git a/crates/benilla-app/src/minimap/ping.rs b/crates/benilla-app/src/minimap/ping.rs
index 228fd690..acc5afbf 100644
--- a/crates/benilla-app/src/minimap/ping.rs
+++ b/crates/benilla-app/src/minimap/ping.rs
@@ -37,7 +37,7 @@
//! `MiniMapPing` `` it shows on `MINIMAP_PING`, re-seats every frame from
//! `GetPingPosition()`, holds 5 s (`MINIMAPPING_TIMER`), "fades" 0.5 s through a `SetAlpha(255·t)`
//! that clamps to full until the last ~2 ms, and hides. Since 1751's swap that file runs here
-//! verbatim (1974), and since decision 2008 the `` it shows **renders its own file**
+//! verbatim (1974), and since decision 2013 the `` it shows **renders its own file**
//! (`Interface\MiniMap\Ping\MinimapPing.mdx`, through `crate::ui_models`): the spinner on its
//! global-sequence clock, the static centre, the ring on the looping Stand — the model's own
//! bones, weight tracks and additive quads, on the pane's private clock that runs only while the
diff --git a/crates/benilla-app/src/net/apply/chat.rs b/crates/benilla-app/src/net/apply/chat.rs
index 99a80e35..4d589326 100644
--- a/crates/benilla-app/src/net/apply/chat.rs
+++ b/crates/benilla-app/src/net/apply/chat.rs
@@ -186,8 +186,9 @@ pub(super) fn chat_wrong_faction(chat_log: &mut ChatLog) {
/// (wow-re `system/ui/ui.md` l.2459). Nothing on this path touches the chat composer.
///
/// **This used to push into the chat feed**, as a stand-in from before benilla had an errors
-/// frame. It has had a real one for a long time (`assets/ui/ErrorsFrame.xml`, the ref
-/// `UIErrorsFrame` as a genuine `MessageFrame`), and the stand-in outlived its reason: vmangos
+/// frame. It has had a real one for a long time — the ref `UIErrorsFrame`, a genuine
+/// `MessageFrame` (ours until 1751's fourteenth window, the chain's own
+/// `Interface\FrameXML\UIErrorsFrame.xml` since) — and the stand-in outlived its reason: vmangos
/// `Player::SetGameMaster` answers `.gm on|off` with **both** `SendSysMessage` and
/// `SendNotification` (`Objects/Player.cpp:2676-2677`/`2701-2702`), so a client that sinks the
/// notification into chat prints "GM mode is ON" **twice** where the reference prints it once.
@@ -382,8 +383,8 @@ mod tests {
/// handler `0x401800` is "read the cstring, `mov edx,1`, `call 0x4945b0`" — event `0xe0`
/// `UI_ERROR_MESSAGE`, the UIErrorsFrame toast — plus a console log, and it never reaches the
/// chat composer. Benilla used to park the notice in the chat feed for want of an errors
- /// frame; it has had one since `assets/ui/ErrorsFrame.xml`, and the stand-in was what printed
- /// "GM mode is ON" twice.
+ /// frame; it has had one since our own `ErrorsFrame.xml` (the chain's `UIErrorsFrame.xml`
+ /// since 1751), and the stand-in was what printed "GM mode is ON" twice.
///
/// The pair is the test: BOTH halves of one toggle, one chat line, one toast.
#[test]
diff --git a/crates/benilla-app/src/ui_cast.rs b/crates/benilla-app/src/ui_cast.rs
index c2e94c6e..1457f46e 100644
--- a/crates/benilla-app/src/ui_cast.rs
+++ b/crates/benilla-app/src/ui_cast.rs
@@ -3,7 +3,7 @@
//! The net bridge queues [`CastBarEdge`]s (self-casts only — the producers filter on the self
//! guid; the channel pair is self-only *on the wire*), and the drain fires the reference
//! client's FrameScript events into the script VM — `SPELLCAST_START` and family, the exact
-//! contract `assets/ui/CastingBar.xml` (the extracted 1.12 `CastingBarFrame`) registers for.
+//! contract stock `Interface\FrameXML\CastingBarFrame.xml` registers for.
//! The spell name rides the event (resolved here from the `Spell.dbc` catalog — the script VM
//! has no spell-catalog binding, deliberately: one lookup face, decision 0107).
diff --git a/crates/benilla-app/src/ui_mirror.rs b/crates/benilla-app/src/ui_mirror.rs
index 8a7a1ab5..591528f7 100644
--- a/crates/benilla-app/src/ui_mirror.rs
+++ b/crates/benilla-app/src/ui_mirror.rs
@@ -3,7 +3,7 @@
//!
//! The net bridge queues [`MirrorTimerEdge`]s and the drain fires the reference client's
//! FrameScript events into the script VM — `MIRROR_TIMER_START` / `_PAUSE` / `_STOP`, the exact
-//! contract `assets/ui/MirrorTimer.xml` (the transcribed 1.12 `MirrorTimer1/2/3`) registers for.
+//! contract stock `Interface\FrameXML\MirrorTimer.xml` (`MirrorTimer1/2/3`) registers for.
//! The bars themselves are the reference's: the frame stores the value and integrates
//! `value + scale * elapsed` every OnUpdate, so a packet every few seconds is enough to paint a
//! smooth countdown.
diff --git a/crates/benilla-app/src/ui_script/action_bar_tests.rs b/crates/benilla-app/src/ui_script/action_bar_tests.rs
index a00f0679..b165c3b1 100644
--- a/crates/benilla-app/src/ui_script/action_bar_tests.rs
+++ b/crates/benilla-app/src/ui_script/action_bar_tests.rs
@@ -6,7 +6,7 @@ fn action_ids(s: &mut UiScript) -> Vec {
s.take_action_uses().into_iter().map(|u| u.action).collect()
}
-/// Load the real `assets/ui/ActionBar.xml` (the shipped default bar) into a bare engine and
+/// Load the stock `Interface\FrameXML\ActionBarFrame.xml` into a bare engine and
/// drive it with a synthetic action snapshot — the slice-1 chain minus Bevy: template
/// expansion over 12 instances, the vanilla bonus-page formula, icon paint on events, empty
/// slots drawing no icon, and a physical click queuing the right UseAction id.
@@ -798,19 +798,20 @@ fn macro_name_line_follows_get_action_text_through_the_xml() {
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
}
-/// The shipped **bag BAR** — `assets/ui/BagFrame.xml` — materialized frame for frame, and then
-/// driven end to end: the bar's own backpack toggle opens the backpack window, the fed stack
-/// paints in its slot's well, the slot's clicks queue the right intents, and the toggle shuts it
-/// again. It lives in this file because the bar seats on `MainMenuBarArtFrame` (ActionBar.xml) —
-/// the toggle's anchor arithmetic below is the reason.
+/// The **bag BAR** — stock `Interface\FrameXML\MainMenuBarBagButtons.xml` — materialized frame
+/// for frame, and then driven end to end: the bar's own backpack toggle opens the backpack
+/// window, the fed stack paints in its slot's well, the slot's clicks queue the right intents,
+/// and the toggle shuts it again. It lives in this file because the bar seats on
+/// `MainMenuBarArtFrame` (`ActionBarFrame.xml`) — the toggle's anchor arithmetic below is the
+/// reason.
///
/// **What decision 1751 changed.** This asserted `report.frames == 259` over a breakdown that
/// counted five bag WINDOWS and a keyring window (37 + 4×42 + 42, plus the bar's own handful).
-/// Those windows are gone from this file: the live ones are the reference's `ContainerFrame1..12`,
-/// executed off the player's own patch chain, and `BagFrame.xml` is the BAR and nothing else —
-/// this client's stand-in for the reference's `MainMenuBarBagButtons.xml`. So the count is
-/// recounted from what the file declares today, and the drive reaches the reference's window
-/// through the bar's own button rather than showing one of ours by name.
+/// Those windows are gone: the live ones are the reference's `ContainerFrame1..12`, executed off
+/// the player's own patch chain, and the bar is the reference's own
+/// `MainMenuBarBagButtons.xml` (1783). So the count is recounted from what that file declares,
+/// and the drive reaches the reference's window through the bar's own button rather than showing
+/// one of ours by name.
#[test]
fn shipped_bag_frame_drives_end_to_end() {
let _data = benilla_formats::wow_data_or_skip!();
@@ -829,8 +830,7 @@ fn shipped_bag_frame_drives_end_to_end() {
// * StackSplit.xml and MerchantFrame.xml after the bags — the reference's
// `ContainerFrameItemButton_OnClick` reads `StackSplitFrame` on both arms and
// `MerchantFrame:IsShown()` on the right one, so a slot click raises without them. That
- // dependency is the reference's, not ours; MerchantFrame.xml is additionally the home of
- // the `BenillaMoney_*` coin rig this chain's windows call.
+ // dependency is the reference's, not ours.
let mut bar_frames = 0;
for file in BAG_UI {
let frames = load_ui(&s, file);
@@ -912,9 +912,9 @@ fn shipped_bag_frame_drives_end_to_end() {
// Click the toggle → the backpack window opens and slot 1 paints the jerky. The toggle seats
// on the bar's art frame BOTTOMRIGHT +(-6,2), 37×37: art frame BOTTOMRIGHT is the bar's
// (full-width, bottom-anchored) corner (1024,0) ⇒ toggle x[981,1018] y[2,39], center
- // (999.5,20.5). That arithmetic is THIS file's — the button is `BagFrame.xml`'s and its seat
- // is `ActionBar.xml`'s — so the click stays at literal coordinates rather than going through
- // `centre_of`: hitting them is part of what is being tested.
+ // (999.5,20.5). That arithmetic is THIS file's — the button is `MainMenuBarBagButtons.xml`'s
+ // and its seat is `ActionBarFrame.xml`'s — so the click stays at literal coordinates rather
+ // than going through `centre_of`: hitting them is part of what is being tested.
s.mouse_button(999.0, 20.0, "LeftButton", true);
s.mouse_button(999.0, 20.0, "LeftButton", false);
s.resolve();
diff --git a/crates/benilla-app/src/ui_script/bag_tests.rs b/crates/benilla-app/src/ui_script/bag_tests.rs
index 174379d5..80635e0d 100644
--- a/crates/benilla-app/src/ui_script/bag_tests.rs
+++ b/crates/benilla-app/src/ui_script/bag_tests.rs
@@ -937,7 +937,8 @@ fn a_second_bag_window_feeds_and_paints_via_the_bag_bar() {
);
assert!(!open(&s, 1), "hidden by default");
- // CharacterBag0Slot == bag id 1 (BenillaBagBarSlot_OnLoad(self, 1) in BagFrame.xml).
+ // CharacterBag0Slot == bag id 1: the stock bar's handlers carry no `bagId` field and
+ // recompute `this:GetID() - CharacterBag0Slot:GetID() + 1` (see `:2119` below).
s.run("CharacterBag0Slot:Click()").unwrap();
let _ = s.take_sounds();
assert!(open(&s, 1), "the bag-bar click opened bag 1's window");
diff --git a/crates/benilla-app/src/ui_script/bagnon_render_tests.rs b/crates/benilla-app/src/ui_script/bagnon_render_tests.rs
index 9c419353..3d477ea0 100644
--- a/crates/benilla-app/src/ui_script/bagnon_render_tests.rs
+++ b/crates/benilla-app/src/ui_script/bagnon_render_tests.rs
@@ -438,7 +438,7 @@ fn without_a_player_at_addon_load_bagnon_draws_an_empty_window() {
}
/// The **other** fault, pinned on its own so a later regression names itself: the reference's
-/// `SetItemButton*` family (`assets/ui/ItemButtonTemplate.xml`).
+/// `SetItemButton*` family (`Interface\FrameXML\ItemButtonTemplate.xml`).
///
/// Bagnon ends every slot update with `SetItemButtonDesaturated` / `SetItemButtonTexture` /
/// `SetItemButtonCount`. While those were nil the raise landed inside `BagnonFrame_AddBag`'s
@@ -1133,16 +1133,16 @@ fn a_texture_gradient_tints_the_art_it_sits_on() {
/// **The director's report: "when I first open the bags with bagnon the gold numbers are all
/// cramped up; if I close and open again it looks good."**
///
-/// Bagnon's money display is `SmallMoneyFrameTemplate` — OUR `MoneyFrame.xml`. Its `ShowCoin` used
-/// to size each coin with `label:GetStringWidth()`, which is served from the measure round-trip and
-/// therefore reads **0 in the tick that set the text**: every coin came out at exactly one icon
-/// width and the digits overlapped. The second open looked right because the first open's measure
-/// had landed in the cache by then — the reopen was reading the previous open's numbers.
+/// Bagnon's money display is `SmallMoneyFrameTemplate`, off the chain's own `MoneyFrame.xml`. Its
+/// `ShowCoin` used to size each coin with `label:GetStringWidth()`, which is served from the
+/// measure round-trip and therefore reads **0 in the tick that set the text**: every coin came out
+/// at exactly one icon width and the digits overlapped. The second open looked right because the
+/// first open's measure had landed in the cache by then — the reopen was reading the previous open's numbers.
///
-/// The fix sums `BENILLA_DIGIT_W`, the app's per-digit advance feed
-/// ([`benilla_ui::script::UiScript::set_digit_advances`]) — data pushed ahead, so the answer exists
-/// *in* the tick. That feed's own doc names this frame as what it was built for; only the merchant
-/// price had ever used it.
+/// The fix is the engine's font measurer answering inside the Lua call that asked
+/// (`benilla_ui`'s `script::measure`): `GetStringWidth` returns a real number in the tick that set
+/// the text. A digits-only stand-in — a per-digit advance feed pushed ahead from the app — shipped
+/// first and was retired by the general answer (decision 1285).
///
/// The assertion is the FIRST open, which is the half that was broken.
#[test]
diff --git a/crates/benilla-app/src/ui_script/basic_controls_tests.rs b/crates/benilla-app/src/ui_script/basic_controls_tests.rs
index 62bd6963..a427abdc 100644
--- a/crates/benilla-app/src/ui_script/basic_controls_tests.rs
+++ b/crates/benilla-app/src/ui_script/basic_controls_tests.rs
@@ -1,5 +1,5 @@
-//! The shipped `assets/ui/BasicControls.xml` — the reference's second file, driven the way an
-//! addon drives it.
+//! The stock `Interface\FrameXML\BasicControls.xml` — the reference's second file, driven the way
+//! an addon drives it.
//!
//! Nothing benilla ships calls `message`, `TEXT` or `_ERRORMESSAGE`; their only consumers are
//! third-party addons (26 call `TEXT`, ~10 genuinely call `message`, two replace `_ERRORMESSAGE`).
diff --git a/crates/benilla-app/src/ui_script/buff_tests.rs b/crates/benilla-app/src/ui_script/buff_tests.rs
index c67225f1..35f007d6 100644
--- a/crates/benilla-app/src/ui_script/buff_tests.rs
+++ b/crates/benilla-app/src/ui_script/buff_tests.rs
@@ -1,6 +1,6 @@
-//! The player buff bar (`assets/ui/BuffFrame.xml`, decisions 0255/0257) against its reference
-//! behaviour. The XML/Lua is the unit under test; the app-side feed (`crate::ui_aura`) is stubbed by
-//! pushing an [`AuraState`] list straight through [`UiScript::set_auras`] and firing
+//! The player buff bar (stock `Interface\FrameXML\BuffFrame.xml`, decisions 0255/0257) against its
+//! reference behaviour. The XML/Lua is the unit under test; the app-side feed (`crate::ui_aura`) is
+//! stubbed by pushing an [`AuraState`] list straight through [`UiScript::set_auras`] and firing
//! `PLAYER_AURAS_CHANGED`, so these exercise the *button* handlers — the row/filter wiring, the
//! dispel-tinted border, the stack count, the countdown, the warning flash, and the right-click
//! cancel — the way the reference's own `BuffButton_*` do.
diff --git a/crates/benilla-app/src/ui_script/chat_tests.rs b/crates/benilla-app/src/ui_script/chat_tests.rs
index 71006896..59227a62 100644
--- a/crates/benilla-app/src/ui_script/chat_tests.rs
+++ b/crates/benilla-app/src/ui_script/chat_tests.rs
@@ -1,9 +1,9 @@
//! Shipped end-to-end tests for the chat window + input (decision 0084, the chat arc): the real
-//! `assets/ui/ChatFrame.xml` loaded through the engine loader, driven exactly as the app drives it —
-//! `add_chat_message` → `resolve`/`extract` (lines render in the pinned colors), the wheel → the Lua
-//! `OnMouseWheel` handler → `ScrollUp` (which freezes the fade), and the input EditBox's ENTER →
-//! `OnEnterPressed` → `SubmitChatInput` → `take_chat_input` (the app then parses it — see
-//! `crate::ui_chat`'s `parse_line` tests for the `/say`//`/yell`//`/w` mapping).
+//! `Interface\FrameXML\ChatFrame.xml` loaded through the engine loader, driven exactly as the app
+//! drives it — `add_chat_message` → `resolve`/`extract` (lines render in the pinned colors), the
+//! wheel → the Lua `OnMouseWheel` handler → `ScrollUp` (which freezes the fade), and the input
+//! EditBox's ENTER → `OnEnterPressed` → `SubmitChatInput` → `take_chat_input` (the app then parses
+//! it — see `crate::ui_chat`'s `parse_line` tests for the `/say`//`/yell`//`/w` mapping).
use benilla_ui::script::{ExtractedQuad, QuadContent, UiScript};
@@ -378,11 +378,11 @@ fn chat_click_dismisses_a_stuck_spell_but_not_an_item() {
// ── ChatTypeInfo: the addon-facing color table ────────────────────────────────────────────────
-/// `ChatTypeInfo` carries the shipped default chat colors twice: once in `assets/ui/ChatFrame.xml`
-/// for addons to read, and once in [`crate::ui_chat::default_color`] for our own feed to render.
-/// Both are the same wow-re byte table (`chat-color-table.md`, the static registry at
-/// `.rdata 0x804710`) — so this is the gate that makes the duplication safe: every kind we model
-/// must agree to the byte, and the table's shape (`sticky`/`id`) must be the reference's.
+/// `ChatTypeInfo` carries the shipped default chat colors twice: once in
+/// `Interface\FrameXML\ChatFrame.xml` for addons to read, and once in
+/// [`crate::ui_chat::default_color`] for our own feed to render. Both are the same wow-re byte
+/// table (`chat-color-table.md`, the static registry at `.rdata 0x804710`) — so this is the gate
+/// that makes the duplication safe: every kind we model must agree to the byte, and the table's shape (`sticky`/`id`) must be the reference's.
#[test]
fn chat_type_info_matches_the_host_color_table() {
use crate::ui_chat::{default_color, ChatEventKind as K};
diff --git a/crates/benilla-app/src/ui_script/color_picker_tests.rs b/crates/benilla-app/src/ui_script/color_picker_tests.rs
index cd279a37..18bb3e89 100644
--- a/crates/benilla-app/src/ui_script/color_picker_tests.rs
+++ b/crates/benilla-app/src/ui_script/color_picker_tests.rs
@@ -1,5 +1,5 @@
-//! The shipped `assets/ui/ColorPickerFrame.xml` + the dropdown's colour-swatch row, driven the way
-//! the corpus drives them.
+//! The stock `Interface\FrameXML\ColorPickerFrame.xml` + the dropdown's colour-swatch row, driven
+//! the way the corpus drives them.
//!
//! Nothing benilla ships opens this window. Its consumers are third-party addons — 86 of the 218
//! reach `ColorPickerFrame`, and 64 of those files are copies of `Dewdrop-2.0.lua`, THE Ace2 menu
diff --git a/crates/benilla-app/src/ui_script/delete_item_tests.rs b/crates/benilla-app/src/ui_script/delete_item_tests.rs
index d44596f7..a9b4a7a3 100644
--- a/crates/benilla-app/src/ui_script/delete_item_tests.rs
+++ b/crates/benilla-app/src/ui_script/delete_item_tests.rs
@@ -85,8 +85,9 @@ fn bag_setup() -> UiScript {
for file in BAG_UI {
load_xml(&s, file);
}
- // `ContainerFrame_Update` reads `MerchantFrame:IsShown()` on any slot the tooltip owns, and
- // `BankFrame` (BAG_UI's last entry) fills its purse through `BenillaMoney_Set`.
+ // `ContainerFrame_Update` reads `MerchantFrame:IsShown()` on any slot the tooltip owns.
+ // `BankFrame`'s purse is an ordinary `SmallMoneyFrameTemplate` off the chain's own
+ // `MoneyFrame.xml` (1937/1962), so it is not a merchant dependency.
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
diff --git a/crates/benilla-app/src/ui_script/errors_tests.rs b/crates/benilla-app/src/ui_script/errors_tests.rs
index b979bd4e..295cc865 100644
--- a/crates/benilla-app/src/ui_script/errors_tests.rs
+++ b/crates/benilla-app/src/ui_script/errors_tests.rs
@@ -1,5 +1,5 @@
-//! The shipped errors/info frame (`assets/ui/ErrorsFrame.xml` — the ref UIErrorsFrame, a real
-//! ``) driven engine-only: the yellow `UI_INFO_MESSAGE` toast (the quest
+//! The errors/info frame — stock `Interface\FrameXML\UIErrorsFrame.xml`, a real
+//! `` — driven engine-only: the yellow `UI_INFO_MESSAGE` toast (the quest
//! objective-progress popup's surface), the red `UI_ERROR_MESSAGE` line, insertMode-TOP stacking,
//! and the hold+fade expiry.
//!
@@ -124,7 +124,7 @@ fn an_error_toast_draws_over_an_open_panel_window() {
load_xml(&s, "Interface\\FrameXML\\Cooldown.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
- load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // BenillaMoney_* — QuestLogDetail's reward money row
+ load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // QuestLogDetail's reward money row (1928)
// pane's UIPanelScrollFrameTemplate). A MISSING template is a loader *warning*, so an
// under-loaded list passes and then dies on the first FauxScrollFrame_Update.
load_xml(&s, "Interface\\FrameXML\\BasicControls.xml");
diff --git a/crates/benilla-app/src/ui_script/escape_tests.rs b/crates/benilla-app/src/ui_script/escape_tests.rs
index 43ae3c70..b5c10ddf 100644
--- a/crates/benilla-app/src/ui_script/escape_tests.rs
+++ b/crates/benilla-app/src/ui_script/escape_tests.rs
@@ -79,7 +79,9 @@ fn escape_closes_bag_and_panel_releases_loot_and_clears_cursor() {
load_xml(&s, "Interface\\FrameXML\\LootFrame.xml");
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon
load_xml(&s, "Interface\\FrameXML\\CharacterFrameTemplates.xml");
- load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // BenillaMoney_Set, BankFrame's purse helper
+ // The reference's own `ContainerFrameItemButton_OnClick` reads `MerchantFrame:IsShown()`
+ // on the bag-slot click below; the coin rig this line used to name is gone (1937/1962).
+ load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml");
s.set_money(0);
s.set_container(0, Some(one_item_backpack()));
diff --git a/crates/benilla-app/src/ui_script/frame_flag_gate.rs b/crates/benilla-app/src/ui_script/frame_flag_gate.rs
index 274169ba..8289b15d 100644
--- a/crates/benilla-app/src/ui_script/frame_flag_gate.rs
+++ b/crates/benilla-app/src/ui_script/frame_flag_gate.rs
@@ -23,10 +23,10 @@
//! answers the same whichever way it came.
//!
//! **Divergences are an explicit list with a reason each, never a pattern.** [`KNOWN`] carries
-//! them, in both directions; a new one cannot hide inside a tolerance. The list is where the
-//! seven frames the reference makes interactive through *handlers we do not carry* are recorded —
-//! those want the handler (and its tooltip), never a bare `enableMouse="true"` that would swallow
-//! the click and give nothing back.
+//! them, in both directions; a new one cannot hide inside a tolerance. **It is empty today** —
+//! 1751's window migrations, 1795, 1970 and 1980 each retired a group, and the in-body notes are
+//! the record of what each one was. The array stays because an empty list is the thing that
+//! notices a divergence arriving.
//!
//! ## Four flags, and only four
//!
@@ -68,8 +68,8 @@
//!
//! The reference side is **XML only**: a `SetID` or `EnableMouse` the reference makes from Lua at
//! `OnLoad` is invisible here and reads as absent. That blind spot only ever under-reports — it
-//! can hide a divergence, never invent one — so nothing it misses turns into a false failure; the
-//! handful of frames it does hide are in `KNOWN` with that reason.
+//! can hide a divergence, never invent one — so nothing it misses turns into a false failure. It
+//! would be a `KNOWN` entry's reason if any frame still needed one.
//!
//! The whole module skips cleanly with no install — `_extracted_framexml/` is a gitignored
//! Blizzard asset, like every other client-data test here.
@@ -157,16 +157,18 @@ impl std::fmt::Display for Flag {
}
}
-/// The accepted differences, in four groups: **seven frames the reference makes mouse-interactive
-/// through HANDLERS we do not carry**, the merchant rows whose mouse we take where it does not,
-/// the faux scroll panes we build from a different widget kind, and the ids the reference sets
-/// from Lua. Every entry is a judgement someone made; none of them is a tolerance.
+/// The accepted differences — **none, today**. The four groups this list once carried (the frames
+/// the reference made mouse-interactive through handlers we did not carry, the merchant rows, the
+/// faux scroll panes, the Lua-set ids) each retired with the window that owned them; the in-body
+/// notes below name the record for each. An empty array is not an oversight: it is what fails the
+/// gate the moment a new divergence appears, and every entry it ever holds is a judgement someone
+/// made, never a tolerance.
const KNOWN: &[Known] = &[
- // ── The reference has it, we do not: all seven are handler gaps, not flag gaps ─────────────
+ // ── The reference had it and we did not: seven handler gaps, not flag gaps (all retired) ───
//
- // In each of these the reference's mouse comes from an ``/`` pair whose body
- // we have not built, and the interaction the player would notice is the TOOLTIP those handlers
- // show — not the click-blocking the flag gives. Declaring `enableMouse="true"` here would make
+ // In each of these the reference's mouse came from an ``/`` pair whose body
+ // we had not built, and the interaction the player would notice was the TOOLTIP those handlers
+ // show — not the click-blocking the flag gives. Declaring `enableMouse="true"` would have made
// the frame swallow the click and hand back nothing, which is worse than the gap.
// `PetPaperDollFrameExpBar` RETIRED here (decision 1751's character-sheet window). It read
// "the reference bar inherits TextStatusBar, whose OnEnter/OnLeave show the value text; ours is
diff --git a/crates/benilla-app/src/ui_script/group_loot_tests.rs b/crates/benilla-app/src/ui_script/group_loot_tests.rs
index 4a1d9c64..f8826d27 100644
--- a/crates/benilla-app/src/ui_script/group_loot_tests.rs
+++ b/crates/benilla-app/src/ui_script/group_loot_tests.rs
@@ -1,5 +1,5 @@
-//! The group-loot roll popups (decision 0591, `assets/ui/GroupLootFrame.xml`): the four stacked
-//! `GroupLootFrame`s that answer `START_LOOT_ROLL`/`CANCEL_LOOT_ROLL` off a pushed
+//! The group-loot roll popups (decision 0591, stock `Interface\FrameXML\GroupLootFrame.xml`): the
+//! four stacked `GroupLootFrame`s that answer `START_LOOT_ROLL`/`CANCEL_LOOT_ROLL` off a pushed
//! [`LootRollsState`] snapshot (the `loot_roll.rs` seam's own harness idiom, mirrored here the way
//! `loot_tests.rs` mirrors it for `set_loot`/`LootState`).
diff --git a/crates/benilla-app/src/ui_script/inspect_tests.rs b/crates/benilla-app/src/ui_script/inspect_tests.rs
index 41d12594..3af72bb1 100644
--- a/crates/benilla-app/src/ui_script/inspect_tests.rs
+++ b/crates/benilla-app/src/ui_script/inspect_tests.rs
@@ -1,7 +1,7 @@
//! The shipped **inspect window** driven end-to-end, engine-only (no Bevy): the real
-//! `assets/ui/InspectFrame.xml` loaded behind `Fonts.xml`/`UiPanels.xml`/`GameTooltip.xml` and fed a
-//! synthetic target snapshot + a foreign equipment view (decision 0631). `character_tests.rs`'s
-//! harness, turned onto the other paper doll.
+//! The reference's own `Blizzard_InspectUI` addon loaded behind
+//! `Fonts.xml`/`UIParent.xml`/`GameTooltip.xml` and fed a synthetic target snapshot + a foreign
+//! equipment view (decision 0631). `character_tests.rs`'s harness, turned onto the other paper doll.
//!
//! What these are here to falsify, in order of how quietly it could have shipped broken:
//!
diff --git a/crates/benilla-app/src/ui_script/loot_tests.rs b/crates/benilla-app/src/ui_script/loot_tests.rs
index 898db63d..da8b4af8 100644
--- a/crates/benilla-app/src/ui_script/loot_tests.rs
+++ b/crates/benilla-app/src/ui_script/loot_tests.rs
@@ -595,11 +595,11 @@ fn the_loot_window_draws_over_the_party_frames() {
/// previews the row's item in the dressing room (decision 1060), SHIFT posts its link into an open
/// chat edit box (decision 1059) — and **neither loots**.
///
-/// That last clause is the whole point of the test, and it is ours to get right rather than the
-/// reference's: in the real client the loot itself is the C `LootButton` widget's click behaviour
-/// (l.94's `button:SetSlot(slot)`), so its Lua arms fall through harmlessly; ours owns the
-/// `LootSlot` call, so the arms had to grow a `return` the reference does not have. The unmodified
-/// click still loots — the regression that would otherwise ship silently.
+/// That last clause is the whole point of the test, and it is the WIDGET's to get right: the loot
+/// itself is the `LootButton` kind's click behaviour (`benilla-ui` `script/button.rs`, decision
+/// 1799 — `l.94`'s `button:SetSlot(slot)` is what arms it), gated on no shift/ctrl/alt, which is
+/// why the stock `LootFrameItem_OnClick` never calls a take itself and needs no `return`. The
+/// unmodified click still loots — the regression that would otherwise ship silently.
#[test]
fn ctrl_and_shift_on_a_loot_row_preview_and_post_without_looting() {
const WOOL_LINK: &str = "|cffffffff|Hitem:2589:0:0:0|h[Wool Cloth]|h|r";
diff --git a/crates/benilla-app/src/ui_script/macro_tests.rs b/crates/benilla-app/src/ui_script/macro_tests.rs
index 8eb5e3da..7117f220 100644
--- a/crates/benilla-app/src/ui_script/macro_tests.rs
+++ b/crates/benilla-app/src/ui_script/macro_tests.rs
@@ -1,4 +1,4 @@
-//! The shipped `assets/ui/MacroFrame.xml` — the macro editor + its name/icon popup (decision
+//! The reference's own `Blizzard_MacroUI` addon — the macro editor + its name/icon popup (decision
//! 0983), driven against the engine's own macro table.
//!
//! What these guard, end to end through the real file: the window loads clean in its real
diff --git a/crates/benilla-app/src/ui_script/merchant_tests.rs b/crates/benilla-app/src/ui_script/merchant_tests.rs
index a4f21a90..2b922736 100644
--- a/crates/benilla-app/src/ui_script/merchant_tests.rs
+++ b/crates/benilla-app/src/ui_script/merchant_tests.rs
@@ -1,6 +1,6 @@
-//! The shipped **merchant window** driven end-to-end, engine-only (no Bevy): the real
-//! `assets/ui/MerchantFrame.xml` (+ `GameTooltip.xml` for the hover chain) loaded behind
-//! `UiPanels.xml` and fed synthetic stock — the phase-4 vendor arc's machine checks (decision
+//! The **merchant window** driven end-to-end, engine-only (no Bevy): the stock
+//! `Interface\FrameXML\MerchantFrame.xml` (+ `GameTooltip.xml` for the hover chain) loaded behind
+//! `UIParent.xml` and fed synthetic stock — the phase-4 vendor arc's machine checks (decision
//! 0081/0084). Split from `panel_tests` (which keeps gossip + the slot manager itself) along the
//! folder's one-file-per-window convention.
@@ -40,7 +40,7 @@ fn frame_rect(quads: &[ExtractedQuad], w: f32, h: f32) -> benilla_ui::layout::Re
.unwrap_or_else(|| panic!("no bare-frame quad sized {w}x{h}"))
}
-/// Load the real `assets/ui/MerchantFrame.xml` (the shipped vendor window) behind `UiPanels.xml`
+/// Load the stock `Interface\FrameXML\MerchantFrame.xml` behind `UIParent.xml`
/// into a bare engine and drive it with a synthetic 2-item stock + a purse — the whole phase-4
/// chain minus Bevy (decision 0081), now over the UIPanel slot manager (decision 0084): the
/// hidden→shown lifecycle on MERCHANT_SHOW goes through ShowUIPanel (landing at the left slot),
@@ -1092,7 +1092,7 @@ fn trade_recipient_money_renders_the_digit_not_ellipsis() {
load_xml(&s, f);
}
load_xml(&s, "ScrollTemplates.xml"); // our scroll kit + the placeholder icon
- load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // the BenillaMoney_* helpers
+ load_xml(&s, "Interface\\FrameXML\\MerchantFrame.xml"); // MerchantFrame:IsShown(), read on the slot click
// TradeFrame's money entry is the chain's own since 1882 — its OnLoad calls MoneyInputFrame_*.
load_xml(&s, "Interface\\FrameXML\\MoneyInputFrame.lua");
load_xml(&s, "Interface\\FrameXML\\MoneyInputFrame.xml");
diff --git a/crates/benilla-app/src/ui_script/money_frame_tests.rs b/crates/benilla-app/src/ui_script/money_frame_tests.rs
index 31c77508..90f496bd 100644
--- a/crates/benilla-app/src/ui_script/money_frame_tests.rs
+++ b/crates/benilla-app/src/ui_script/money_frame_tests.rs
@@ -1,12 +1,11 @@
-//! The shipped `assets/ui/MoneyFrame.xml` — the reference's `MoneyFrameTemplate` /
+//! The stock `Interface\FrameXML\MoneyFrame.xml` — the reference's `MoneyFrameTemplate` /
//! `SmallMoneyFrameTemplate` kit and the `MoneyTypeInfo` table behind it (decision 1190: a name the
//! shipped 1.12 UI defines is a name we publish too — under our own implementation of it, 1260).
//!
-//! Nothing benilla ships consumes this file yet — our own eight coin displays run on
-//! MerchantFrame.xml's `BenillaMoney_*` slot kit, and MoneyFrame.xml's header is where the two are
-//! reconciled — so these tests ARE its only driver. That makes them the contract: they exercise it
-//! the way an addon does (declare a frame on the template, point it at a type, change the type,
-//! read the coins back), because that is who calls it.
+//! Eight shipped windows consume this file (1937 converged the coin cluster onto it; 1962 put the
+//! file itself on the chain). These tests exercise it the way an addon does — declare a frame on
+//! the template, point it at a type, change the type, read the coins back — because that is who
+//! calls it.
//!
//! What they guard: the type switch actually rewiring where the number comes from and whether the
//! coins take the mouse; the collapse rule per type (`collapse`, `showSmallerCoins`, `fixedWidth`);
@@ -203,8 +202,9 @@ fn update_paints_a_static_frame_by_name_and_resizes_it() {
//
// **The digits used to contribute 0 here and this test asserted the bare 13s that came of it.**
// That was the director's cramped gold on a first open: `ShowCoin` sized each coin from a text
- // measure that lands a frame later, so it read 0 every first time. It sums the engine's
- // `BenillaNumberWidth` feed now, which answers in the same tick.
+ // measure that lands a frame later, so it read 0 every first time. The engine's font
+ // measurer answers inside the Lua call that asked now (`script/measure.rs`), so the width
+ // is real on the first pass.
assert_eq!(
s.eval::("return TestPurseGoldButton:GetWidth()")
.unwrap(),
@@ -323,8 +323,8 @@ fn set_money_frame_color_recolours_the_digits_and_not_the_icons() {
}
/// `MoneyTypeInfo` is read directly by addons, so its shape is part of the contract — all seven
-/// reference types, each with an `UpdateFunc`, and the two we cannot source yet answering 0 rather
-/// than erroring (the header's `GetSendMailMoney`/`GetSendMailCOD` gap).
+/// reference types, each with an `UpdateFunc`, and the two send-mail rows reading the amounts
+/// their engine getters hold (`GetSendMailMoney`/`GetSendMailCOD`, built by 1962).
#[test]
fn the_money_type_table_carries_all_seven_reference_types() {
let s = harness(12_345);
@@ -345,7 +345,7 @@ fn the_money_type_table_carries_all_seven_reference_types() {
"MoneyTypeInfo[\"{t}\"] with an UpdateFunc"
);
}
- // The two whose engine getters we have not built answer 0 instead of nil-calling.
+ // The two send-mail rows: with no send-mail amount set, their getters answer 0.
for t in ["SEND_MAIL", "SEND_MAIL_COD"] {
s.run(&format!(
"this = TestPurse MoneyFrame_SetType(\"{t}\") this = nil"
@@ -359,7 +359,7 @@ fn the_money_type_table_carries_all_seven_reference_types() {
assert_eq!(
s.eval::("return TestPurse.staticMoney").unwrap(),
0,
- "{t} reads 0 while its engine getter is missing"
+ "{t} reads its engine getter, which is 0 with no send-mail amount set"
);
}
}
diff --git a/crates/benilla-app/src/ui_script/options_tests.rs b/crates/benilla-app/src/ui_script/options_tests.rs
index 3397aca6..b1c1e0ec 100644
--- a/crates/benilla-app/src/ui_script/options_tests.rs
+++ b/crates/benilla-app/src/ui_script/options_tests.rs
@@ -724,14 +724,15 @@ fn load_definers(s: &UiScript, files: &[&str]) {
/// The Interface page's harness (decision 1136), the same posture as `combat_harness` above: the
/// **real** definers ahead of the window, in the manifest's own order, so each row captures the
-/// same file-scope value it captures in the client. `SHOW_NEWBIE_TIPS` rides in on `GameTooltip.xml`
-/// which `harness_on` already loads; the two quest globals need their own windows —
-/// `MerchantFrame.xml` for the coin helpers both quest files reuse and `ScrollTemplates.xml` for
-/// the kit `QuestFrame.xml` inherits from (the same chain `quest_tests`/`questlog_tests` load).
-/// `SHOW_BUFF_DURATIONS` arrives with the bar it re-anchors (1139), behind the two files
-/// `buff_tests` loads ahead of it — `Cooldown.xml` (every button's child) and `ActionBar.xml`
-/// (`BENILLA_FALLBACK_ICON`), themselves behind `UIParent.xml`. `TextStatusBar.xml` rides in
-/// ahead of them for the Status Bar Text row's consumer — the XP bar's numerals (1140).
+/// same file-scope value it captures in the client. `SHOW_NEWBIE_TIPS` is set by our own
+/// `assets/ui/OptionsFrame.xml` (it lived in our `GameTooltip.xml` until the tooltip went stock,
+/// 1968; the reference keeps it in `UIOptionsFrame.lua`), which `harness_on` already loads; the two
+/// quest globals need their own windows — `MerchantFrame.xml` for the coin helpers both quest files
+/// reuse and `ScrollTemplates.xml` for the kit `QuestFrame.xml` inherits from (the same chain
+/// `quest_tests`/`questlog_tests` load). `SHOW_BUFF_DURATIONS` arrives with the bar it re-anchors
+/// (1139), behind the two files `buff_tests` loads ahead of it — `Cooldown.xml` (every button's
+/// child) and `ActionBar.xml` (`BENILLA_FALLBACK_ICON`), themselves behind `UIParent.xml`.
+/// `TextStatusBar.xml` rides in ahead of them for the Status Bar Text row's consumer — the XP bar's numerals (1140).
fn interface_harness() -> UiScript {
let mut s = audio_harness();
s.set_screen_size(1024.0, 768.0);
@@ -1847,8 +1848,9 @@ fn defaults_resets_the_controls_page_to_registered_defaults() {
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
}
-/// Drive the window a few frames so the frame-late fits (the scroll body, the tab widths)
-/// converge: rects resolve after Lua runs, so OptionsScroll_Fit answers one frame behind.
+/// Drive the window a few frames so the scroll body's frame-late fit converges: rects resolve
+/// after Lua runs, so `OptionsScroll_Fit` answers one frame behind. (The tab widths are not in
+/// that set — 2028 put them on a one-shot `OptionsTab_FitWidth`.)
fn settle(s: &mut UiScript) {
for _ in 0..4 {
s.resolve();
diff --git a/crates/benilla-app/src/ui_script/panel_template_tests.rs b/crates/benilla-app/src/ui_script/panel_template_tests.rs
index 85d80f43..c14ccd5e 100644
--- a/crates/benilla-app/src/ui_script/panel_template_tests.rs
+++ b/crates/benilla-app/src/ui_script/panel_template_tests.rs
@@ -1,5 +1,5 @@
-//! The shipped `assets/ui/UIPanelTemplates.xml` + `assets/ui/OptionsFrameTemplates.xml` — the
-//! reference's SHARED widget kit, driven the way an addon drives it.
+//! The stock `Interface\FrameXML\UIPanelTemplates.xml` + our `assets/ui/OptionsFrameTemplates.xml`
+//! — the reference's SHARED widget kit, driven the way an addon drives it.
//!
//! **These are not tests of a window.** Nothing benilla ships instantiates a single template in
//! either file: their only consumer is a third-party addon writing
@@ -238,7 +238,7 @@ fn a_panel_button_from_the_template_labels_and_paints() {
/// `UIPanelCloseButton` — 8 call sites across 4 corpus addons, and the one template here whose
/// whole point is its script: `HideUIPanel(this:GetParent())`, resolved at click time against
-/// `UiPanels.xml`.
+/// the chain's `UIParent.xml`.
#[test]
fn the_templated_close_button_hides_the_frame_it_sits_on() {
let _data = benilla_formats::wow_data_or_skip!();
@@ -438,7 +438,7 @@ fn the_options_check_button_resolves_its_whole_inheritance_chain() {
/// real 1.12.1 client has, read from `reference/1.12-globals.tsv`.
///
/// Scoped to these two files on purpose: the rest of `assets/ui` is full of deliberately
-/// benilla-shaped template names (`BenillaScrollBarTemplate`, `BenillaMacroPanelButtonTemplate`,
+/// benilla-shaped template names (`BenillaScrollBarTemplate`, `BenillaScriptLogRowTemplate`,
/// `OptionsRedButtonTemplate`), and a whole-tree sweep would be asserting something else. These
/// two files make the opposite claim — *these are the reference's own names, which is why an addon
/// can find them* — so that claim is the one worth gating. A template renamed to something
diff --git a/crates/benilla-app/src/ui_script/panel_tests.rs b/crates/benilla-app/src/ui_script/panel_tests.rs
index 3539c4f6..f6268065 100644
--- a/crates/benilla-app/src/ui_script/panel_tests.rs
+++ b/crates/benilla-app/src/ui_script/panel_tests.rs
@@ -4,9 +4,9 @@ use benilla_ui::script::{
};
/// Load one manifest entry into `s`, panicking on any loader error and returning the frame count
-/// it materialized — the panel tests all load `UiPanels.xml` (decision 0084 §2's slot manager)
-/// before the panel frame(s) under test, exactly as `benilla.toc`'s own order does, so
-/// `ShowUIPanel`/`HideUIPanel` already exist when a frame's OnLoad/OnEvent references them.
+/// it materialized — the panel tests all load `Interface\FrameXML\UIParent.xml` (decision 0084 §2's
+/// slot manager) before the panel frame(s) under test, exactly as `benilla.toc`'s own order does,
+/// so `ShowUIPanel`/`HideUIPanel` already exist when a frame's OnLoad/OnEvent references them.
///
/// This was a private disk-only reader until 1751's second window: `BankFrame.xml` is the
/// reference's own file off the player's chain now, and a reader that only knows `assets/ui`
@@ -30,7 +30,7 @@ fn frame_rect(quads: &[ExtractedQuad], w: f32, h: f32) -> benilla_ui::layout::Re
.unwrap_or_else(|| panic!("no bare-frame quad sized {w}x{h}"))
}
-/// Load the real `assets/ui/GossipFrame.xml` (the shipped gossip window) behind `UiPanels.xml`
+/// Load the stock `Interface\FrameXML\GossipFrame.xml` behind `UIParent.xml`
/// into a bare engine and drive it with a synthetic gossip menu — the whole phase-3 chain minus
/// Bevy (decision 0081), now over the UIPanel slot manager (decision 0084): the hidden→shown
/// lifecycle on GOSSIP_SHOW goes through ShowUIPanel (landing the window at the left slot,
@@ -738,7 +738,7 @@ fn displacing_an_npc_window_ends_the_displaced_session() {
}
/// Pin §4's pushable path: a higher-`pushable` occupant (loot's future pushable=7 row, already
-/// registered in `UiPanels.xml`) gets pushed to the center slot rather than replaced when a
+/// registered in `UIParent.xml`) gets pushed to the center slot rather than replaced when a
/// pushable=0 frame (merchant) wants the left spot (UIParent.lua l.734-741) — the synthetic
/// registrant the pin calls for, since no loot window ships yet. A bare `CreateFrame` with a
/// distinctive 50×50 size stands in for it: it has no visual layers, but `extract` still emits
diff --git a/crates/benilla-app/src/ui_script/perf_bar_tests.rs b/crates/benilla-app/src/ui_script/perf_bar_tests.rs
index 11956e8e..e399b270 100644
--- a/crates/benilla-app/src/ui_script/perf_bar_tests.rs
+++ b/crates/benilla-app/src/ui_script/perf_bar_tests.rs
@@ -1,5 +1,5 @@
-//! The shipped `assets/ui/ActionBar.xml`'s performance ("ping") meter — the tinted bar in the
-//! main bar's last empty recess — over the real files, never a stub.
+//! The stock `Interface\FrameXML\ActionBarFrame.xml`'s performance ("ping") meter — the tinted bar
+//! in the main bar's last empty recess — over the real files, never a stub.
//!
//! What these guard, in order: the ref geometry that puts the bar IN the recess (the whole point of
//! the slice); the LOW-strata draw order that makes it show *through* the bar art instead of over
diff --git a/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs b/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs
index b87e7e84..6c633ef8 100644
--- a/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs
+++ b/crates/benilla-app/src/ui_script/pet_paperdoll_tests.rs
@@ -398,8 +398,10 @@ fn the_level_line_names_the_family_and_is_untouched_without_one() {
// level line at all", because our deleted `assets/ui/PetPaperDollFrame.xml` declared
// `PetLevelText` with no `text=` and it started empty. The reference declares it
// `text="Level level race class"` (stock `PetPaperDollFrame.xml:70`) — a design-time
- // placeholder, and not a GlobalStrings key, so the loader's `text=` lookup falls through to the
- // literal and that literal is what a player sees in this state, un-replaced. Both spellings say
+ // placeholder, and not a GlobalStrings key. **A real 1.12 client draws that literal too**:
+ // `CSimpleFontString::LoadXML` substitutes the raw attribute when `FrameScript_GetText` comes
+ // back empty (`771029`-`771032 mov eax,esi`), exactly as `Button::LoadXML 0x778c31` does — so
+ // this is fidelity, not the loader divergence this comment used to call it. Both spellings say
// the same thing about the guard; this one says it about the file that ships.
let drawn = with_family(None);
assert!(
diff --git a/crates/benilla-app/src/ui_script/quest_tests.rs b/crates/benilla-app/src/ui_script/quest_tests.rs
index 89e6a210..e7427f64 100644
--- a/crates/benilla-app/src/ui_script/quest_tests.rs
+++ b/crates/benilla-app/src/ui_script/quest_tests.rs
@@ -1,7 +1,7 @@
//! The shipped **questgiver window** open/close sound, driven engine-only (no Bevy): the real
-//! `assets/ui/QuestFrame.xml` loaded behind `UiPanels.xml` and shown/hidden through the wire events.
-//! The window-sound convention's machine check for the quest arc (decision 0090), the sibling of the
-//! merchant/gossip/bag/loot sound tests.
+//! `Interface\FrameXML\QuestFrame.xml` loaded behind `UIParent.xml` and shown/hidden through the
+//! wire events. The window-sound convention's machine check for the quest arc (decision 0090), the
+//! sibling of the merchant/gossip/bag/loot sound tests.
use benilla_ui::script::{QuestPanel, QuestState, ScriptValue, SoundRequest, UiScript};
diff --git a/crates/benilla-app/src/ui_script/questlog_tests.rs b/crates/benilla-app/src/ui_script/questlog_tests.rs
index 64acfc2f..21b27198 100644
--- a/crates/benilla-app/src/ui_script/questlog_tests.rs
+++ b/crates/benilla-app/src/ui_script/questlog_tests.rs
@@ -1,7 +1,7 @@
//! The shipped **quest log window** driven end-to-end, engine-only (no Bevy): the real
-//! `assets/ui/QuestLogFrame.xml` loaded behind `UiPanels.xml`/`MerchantFrame.xml` (the money helpers
-//! its reward rows reuse) and fed a synthetic 8-entry log + a resolved detail — mirroring
-//! `quest_tests.rs`/`bag_tests.rs`'s engine-only harness for the quest-log slice (decision 0088 arc).
+//! `Interface\FrameXML\QuestLogFrame.xml` loaded behind `UIParent.xml`/`MerchantFrame.xml` (the
+//! money helpers its reward rows reuse) and fed a synthetic 8-entry log + a resolved detail —
+//! mirroring `quest_tests.rs`/`bag_tests.rs`'s engine-only harness for the quest-log slice (decision 0088 arc).
use benilla_ui::script::{
ExtractedQuad, PartyMemberInfo, PartyState, QuadContent, QuestItemView, QuestLogDetail,
@@ -843,15 +843,19 @@ fn empty_quest_log_hides_rows_and_disables_abandon() {
s.run("ToggleQuestLog()").unwrap();
assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
- // A bare FontString region has no Show/Hide/IsVisible in this engine (only Frames/Buttons do —
- // `region.rs`'s method table) — the empty-state message is a toggled SetText, read back here.
// The empty log says the reference's QUESTLOG_NO_QUESTS_TEXT (GlobalStrings.lua:3225) through
- // stock QuestLogNoQuestsText; "Your quest log is empty." was ours (1944).
+ // stock QuestLogNoQuestsText; "Your quest log is empty." was ours (1944). Regions carry the
+ // real `Show`/`Hide`/`IsShown`/`IsVisible` (0138), so the label's visibility is assertable
+ // too — and nothing ever hides this one: `QuestLogFrame.xml:427` is its only mention in the
+ // whole chain, so it stands behind the rows whether or not the log is empty.
assert_eq!(
s.eval::("return QuestLogNoQuestsText:GetText()")
.unwrap(),
"No Active Quests"
);
+ assert!(s
+ .eval::("return QuestLogNoQuestsText:IsVisible()")
+ .unwrap());
assert!(!s.eval::("return QuestLogTitle1:IsVisible()").unwrap());
assert!(!s
.eval::("return QuestLogFrameAbandonButton:IsEnabled() ~= 0")
@@ -968,14 +972,28 @@ fn reward_rows_follow_the_refs_two_per_row_layout() {
// With choices present, the receive text reads "...also..." (QuestFrame.lua:461-462) — it
// anchors under choice row 1 (the left/odd column: index=2 is even -> anchorIndex-1 -> 1, this
- // function's own logic). GetPoint() isn't wired for FontString regions in this engine (only
- // Frame/Button — `region.rs` has no GetPoint), so the anchor CHAIN itself is verified via the
- // mandatory capture-loop screenshot (this task's report), not introspected here.
+ // function's own logic). Regions carry `GetPoint` (1244), so the anchor CHAIN is introspected
+ // here rather than deferred to a screenshot: TOPLEFT of QuestLogItem1's BOTTOMLEFT, +3/-5.
assert_eq!(
s.eval::("return QuestLogItemReceiveText:GetText()")
.unwrap(),
"You will also receive:"
);
+ assert_eq!(
+ s.eval::(
+ "local p, rel, rp = QuestLogItemReceiveText:GetPoint() \
+ return p .. '|' .. rel:GetName() .. '|' .. rp"
+ )
+ .unwrap(),
+ "TOPLEFT|QuestLogItem1|BOTTOMLEFT"
+ );
+ assert_eq!(
+ s.eval::<(f64, f64)>(
+ "local _, _, _, x, y = QuestLogItemReceiveText:GetPoint() return x, y"
+ )
+ .unwrap(),
+ (3.0, -5.0)
+ );
// One fixed reward shows, chained under the receive text (its own SetPoint target).
assert!(s.eval::("return QuestLogItem3:IsShown()").unwrap());
diff --git a/crates/benilla-app/src/ui_script/reference_ui.rs b/crates/benilla-app/src/ui_script/reference_ui.rs
index a0cbc0f4..81098e0e 100644
--- a/crates/benilla-app/src/ui_script/reference_ui.rs
+++ b/crates/benilla-app/src/ui_script/reference_ui.rs
@@ -648,9 +648,10 @@ mod tests {
/// reasoning that widget methods are not in `_G`. True, and it meant the report could not see
/// a widget method we had *not built*. `MerchantFrame.xml` read `0 engine` and
/// [`chain_readiness_report`] read CLEAN while the stock row's `` called
- /// `ShoppingTooltip1:SetMerchantCompareItem(...)`, which this engine does not have — so the
- /// file loaded, every check passed, and hovering a vendor row would have raised in play. Both
- /// instruments were right about what they measure. Neither measured the window.
+ /// `ShoppingTooltip1:SetMerchantCompareItem(...)`, which this engine did not have then (1802
+ /// built it) — so the file loaded, every check passed, and hovering a vendor row would have
+ /// raised in play. Both instruments were right about what they measure. Neither measured the
+ /// window.
///
/// **A remaining `>` in the `fx=` column is usually a LoadOnDemand addon**, not something to
/// build. `ClassTrainerFrame_Show`, `CraftFrame_Show`, `MacroFrame_SaveMacro`,
@@ -1881,8 +1882,9 @@ mod tests {
/// read by the next session as if it were live.
///
/// That is not a tidiness problem. Our copies DIVERGE from the reference deliberately, and the
- /// divergence is what dies: `UiPanels.xml`'s `PanelTemplates_TabResize` carried a benilla-only
- /// `return tabWidth` that the tab settle reads, and the reference's returns nothing.
+ /// divergence is what dies: our retired `UiPanels.xml` carried a `PanelTemplates_TabResize`
+ /// with a benilla-only `return tabWidth` that our tab settle read, and the reference's
+ /// returns nothing (both are gone — 1988, 1993).
///
/// The reverse direction — ours seated BELOW the chain's, so we silently override the
/// reference — is a real category too, and a wider audit than this gate.
diff --git a/crates/benilla-app/src/ui_script/reputation_frame_tests.rs b/crates/benilla-app/src/ui_script/reputation_frame_tests.rs
index 035d2ce9..00b99092 100644
--- a/crates/benilla-app/src/ui_script/reputation_frame_tests.rs
+++ b/crates/benilla-app/src/ui_script/reputation_frame_tests.rs
@@ -1,6 +1,6 @@
-//! The shipped **Reputation tab** (`assets/ui/ReputationFrame.xml`) and the **reputation watch
-//! bar** (`assets/ui/ActionBar.xml`) driven end-to-end, engine-only (no Bevy) — the per-window test
-//! module the skills/spellbook/bank files already establish.
+//! The stock **Reputation tab** (`Interface\FrameXML\ReputationFrame.xml`) and the **reputation
+//! watch bar** (`Interface\FrameXML\ActionBarFrame.xml`) driven end-to-end, engine-only (no Bevy) —
+//! the per-window test module the skills/spellbook/bank files already establish.
//!
//! What it pins is the PAINT law, which is the half `benilla-ui`'s own
//! `script::reputation::tests` structurally cannot reach: that module drives the twelve globals and
diff --git a/crates/benilla-app/src/ui_script/skills_frame_tests.rs b/crates/benilla-app/src/ui_script/skills_frame_tests.rs
index 8b47cf32..0dc8a13a 100644
--- a/crates/benilla-app/src/ui_script/skills_frame_tests.rs
+++ b/crates/benilla-app/src/ui_script/skills_frame_tests.rs
@@ -376,10 +376,11 @@ fn the_pages_close_button_sits_where_the_reference_seats_it_and_closes_the_windo
// **"Close", not "CLOSE".** An XML `text=` attribute is a GlobalStrings LOOKUP, not a literal
// (`loader::Loader::resolve_text`, wow-re `rf28-typed-widget-loadxml.md` l.36 —
// `FrameScript_GetText 0x703bf0`), and `CLOSE = "Close"` (`GlobalStrings.lua:760`). This test
- // read "CLOSE" while the page's list carried no `GlobalStrings.lua`: it was asserting our
- // loader's miss-fallback (the LITERAL, a deliberate divergence for benilla-authored files),
- // not the label the reference client draws. [`super::test_ui::CHARACTER_UI`] loads the
- // player's own strings first, as the app does, so this is the real label now.
+ // read "CLOSE" while the page's list carried no `GlobalStrings.lua`: it was asserting the
+ // miss-fallback (the raw attribute), which is the REFERENCE's own arm too (`0x778c31` /
+ // `0x771032`), not the label a client with the strings loaded draws.
+ // [`super::test_ui::CHARACTER_UI`] loads the player's own strings first, as the app does, so
+ // this is the real label now.
let label = page_quads(&s)
.iter()
.find_map(|q| match &q.content {
diff --git a/crates/benilla-app/src/ui_script/spellbook_tests.rs b/crates/benilla-app/src/ui_script/spellbook_tests.rs
index 1997ad84..89cd23a4 100644
--- a/crates/benilla-app/src/ui_script/spellbook_tests.rs
+++ b/crates/benilla-app/src/ui_script/spellbook_tests.rs
@@ -1,7 +1,7 @@
//! The shipped **spellbook window** driven end-to-end, engine-only (no Bevy): the real
-//! `assets/ui/SpellBookFrame.xml` loaded behind `Fonts.xml`/`UiPanels.xml`/`GameTooltip.xml`
-//! (plus `ActionBar.xml` for the cross-window place test) and fed a small synthetic book —
-//! mirroring `character_tests.rs`'s/`action_bar_tests.rs`'s harness (decision 0216 §8, slice 5).
+//! `Interface\FrameXML\SpellBookFrame.xml` loaded behind
+//! `Fonts.xml`/`UIParent.xml`/`GameTooltip.xml` (plus `ActionBar.xml` for the cross-window place
+//! test) and fed a small synthetic book — mirroring `character_tests.rs`'s/`action_bar_tests.rs`'s harness (decision 0216 §8, slice 5).
use benilla_ui::script::{SpellBookState, SpellSlotView, SpellTabView, UiScript};
diff --git a/crates/benilla-app/src/ui_script/static_popup_tests.rs b/crates/benilla-app/src/ui_script/static_popup_tests.rs
index 08e8158b..a5eb61d3 100644
--- a/crates/benilla-app/src/ui_script/static_popup_tests.rs
+++ b/crates/benilla-app/src/ui_script/static_popup_tests.rs
@@ -1,7 +1,7 @@
//! The shared StaticPopup engine (decision 0308 §3 — the ref's registry + Show + OnUpdate
-//! machinery, transcribed in UiPanels.xml): the countdown/StartDelay/cancels/ESC laws the death
-//! arc's dialogs ride. Entries here are inline test dialogs — the real entries (DELETE_ITEM,
-//! ABANDON_QUEST, the death family) are covered by their features' own tests.
+//! machinery, stock `Interface\FrameXML\StaticPopup.xml` since 1988): the
+//! countdown/StartDelay/cancels/ESC laws the death arc's dialogs ride. Entries here are inline test
+//! dialogs — the real entries (DELETE_ITEM, ABANDON_QUEST, the death family) are covered by their features' own tests.
use benilla_ui::script::UiScript;
diff --git a/crates/benilla-app/src/ui_script/taxi_tests.rs b/crates/benilla-app/src/ui_script/taxi_tests.rs
index 9cbfc869..2a51daca 100644
--- a/crates/benilla-app/src/ui_script/taxi_tests.rs
+++ b/crates/benilla-app/src/ui_script/taxi_tests.rs
@@ -1,10 +1,10 @@
//! The shipped taxi-map window driven end-to-end, engine-only (no Bevy): the real
-//! `assets/ui/TaxiFrame.xml` fed a synthetic two-node snapshot (the [`crate::ui_taxi`] feed's exact
-//! output shape). Covers what only a runtime load exercises: the Lua parses and every referenced
-//! global resolves (including the static node-button pool and the runtime-created route-line
-//! textures — TaxiFrame.xml's own header note on both), `TAXIMAP_OPENED` shows the window with the
-//! flight master's name and paints the node buttons at their pushed positions, a click on a node
-//! drains through `TakeTaxiNode`, and `TAXIMAP_CLOSED` hides it.
+//! `Interface\FrameXML\TaxiFrame.xml` fed a synthetic two-node snapshot (the [`crate::ui_taxi`]
+//! feed's exact output shape). Covers what only a runtime load exercises: the Lua parses and every
+//! referenced global resolves (including the static node-button pool and the runtime-created
+//! route-line textures — TaxiFrame.xml's own header note on both), `TAXIMAP_OPENED` shows the
+//! window with the flight master's name and paints the node buttons at their pushed positions, a
+//! click on a node drains through `TakeTaxiNode`, and `TAXIMAP_CLOSED` hides it.
use benilla_ui::script::{ScriptValue, TaxiNodeType, TaxiUiNode, TaxiUiState, UiScript};
@@ -23,12 +23,12 @@ fn taxi_script() -> UiScript {
load_xml(&s, r"Interface\FrameXML\LocaleProperties.lua");
load_xml(&s, r"Interface\FrameXML\StaticPopup.xml");
load_xml(&s, "Interface\\FrameXML\\GameTooltip.xml"); // TaxiNodeOnButtonEnter's tooltip + SetTooltipMoney
- load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // BenillaErrorsFrame_AddMessage — DrawOneHopLines' refusal
+ load_xml(&s, "Interface\\FrameXML\\UIErrorsFrame.xml"); // `UIErrorsFrame:AddMessage` — DrawOneHopLines' refusal
// Three the reference's own TaxiFrame leans on that our transcription did not:
// · GlobalStrings — `ERR_TAXINOPATHS` is a GlobalString, and `AddMessage(nil)` draws an
// empty line rather than raising, so its absence is silent.
// · UIPanelTemplates (.lua then .xml) — `TaxiCloseButton` inherits `UIPanelCloseButton`,
- // which lives there and NOT in our UiPanels.xml. Without it the close button loads as a
+ // which the chain declares there. Without it the close button loads as a
// bare Button with no handler and a click does nothing at all.
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.lua");
load_xml(&s, "Interface\\FrameXML\\UIPanelTemplates.xml");
@@ -128,10 +128,9 @@ fn shipped_taxi_frame_drives_end_to_end() {
/// The "no single-hop destination" refusal (ref `DrawOneHopLines`, fired from `OnShow`): a map
/// with only the `Current` node (no `Reachable` neighbor at all) hits `numSingleHops == 0` and
-/// calls `BenillaErrorsFrame_AddMessage` (TaxiFrame.xml's deviation 3 from the reference's
-/// `UIErrorsFrame:AddMessage`) then hides the window — verified end-to-end since this is the one
-/// call this engine has no precedent for outside this window (`ErrorsFrame.xml`'s own Lua seam,
-/// not yet exercised from another shipped window's script).
+/// calls `UIErrorsFrame:AddMessage(ERR_TAXINOPATHS, …)` (stock `TaxiFrame.lua:161-162`) then
+/// hides the window — driven end-to-end because the message frame's Lua seam is what the
+/// refusal is visible through.
#[test]
fn no_single_hop_destination_posts_the_error_and_closes() {
let mut s = taxi_script();
diff --git a/crates/benilla-app/src/ui_script/test_ui.rs b/crates/benilla-app/src/ui_script/test_ui.rs
index 7aef340d..f2fbf756 100644
--- a/crates/benilla-app/src/ui_script/test_ui.rs
+++ b/crates/benilla-app/src/ui_script/test_ui.rs
@@ -665,7 +665,7 @@ pub(super) const BAG_UI: &[&str] = &[
// Our adapters over the reference's container files — the keyring tooltip wrapper and the
// three bag verbs 0561 shadows (`OpenBackpack`/`CloseBackpack`/`CloseAllBags`). It has to be
// AFTER `ContainerFrame.xml` and after the bar, which is why it is here and not up with
- // UiPanels.xml.
+ // `UIParent.xml`.
"ContainerFrameAdapters.xml",
// `updateContainerFrameAnchors` measures every open bag against `BankFrame:GetRight()`
// (ContainerFrame.lua l.505) on EVERY open and close, so the bank window is not optional
diff --git a/crates/benilla-app/src/ui_script/tooltip_template_tests.rs b/crates/benilla-app/src/ui_script/tooltip_template_tests.rs
index 40502958..6a097bae 100644
--- a/crates/benilla-app/src/ui_script/tooltip_template_tests.rs
+++ b/crates/benilla-app/src/ui_script/tooltip_template_tests.rs
@@ -1,5 +1,5 @@
-//! `GameTooltipTemplate` as an ADDON sees it — the shipped `assets/ui/GameTooltip.xml` driven the
-//! way the corpus drives it.
+//! `GameTooltipTemplate` as an ADDON sees it — the stock `Interface\FrameXML\GameTooltip.xml`
+//! driven the way the corpus drives it.
//!
//! **This is not a test of our tooltip window** (that is `tooltip_anchor_tests` /
//! `tooltip_compare_tests`, and they are the regression suite this refactor had to leave
diff --git a/crates/benilla-app/src/ui_script/trainer_tests.rs b/crates/benilla-app/src/ui_script/trainer_tests.rs
index 18ef3905..6eb17d64 100644
--- a/crates/benilla-app/src/ui_script/trainer_tests.rs
+++ b/crates/benilla-app/src/ui_script/trainer_tests.rs
@@ -1,12 +1,12 @@
//! The shipped **trainer window** driven end-to-end, engine-only (no Bevy): the real
-//! `assets/ui/TrainerFrame.xml` — a client-sorted, collapsible **skill-line tree** with a **dropdown**
-//! state filter and a draggable **scroll bar** (decisions 0247/0251) — loaded behind its deps
-//! (`UiPanels.xml` + `UIDropDownMenu.xml` + `ScrollTemplates.xml` + `MerchantFrame.xml` for the
-//! the stock money frames) and fed a synthetic service list. Covers what only a runtime load
-//! exercises: the Lua parses and every referenced global resolves, the tree renders interleaved
-//! header/service rows, a header click folds its group, the dropdown filter hides a state, the wheel
-//! scrolls the list, the NPC name rides `arg1` into the title, the byte-exact GlobalStrings render, the
-//! Train button gates on available-and-affordable, and the buy queues the row's spell id.
+//! The reference's own `Blizzard_TrainerUI` addon — a client-sorted, collapsible **skill-line
+//! tree** with a **dropdown** state filter and a draggable **scroll bar** (decisions 0247/0251) —
+//! loaded behind its deps (`UiPanels.xml` + `UIDropDownMenu.xml` + `ScrollTemplates.xml` +
+//! `MerchantFrame.xml` for the the stock money frames) and fed a synthetic service list. Covers
+//! what only a runtime load exercises: the Lua parses and every referenced global resolves, the
+//! tree renders interleaved header/service rows, a header click folds its group, the dropdown
+//! filter hides a state, the wheel scrolls the list, the NPC name rides `arg1` into the title, the
+//! byte-exact GlobalStrings render, the Train button gates on available-and-affordable, and the buy queues the row's spell id.
use benilla_ui::script::{
ExtractedQuad, QuadContent, ScriptValue, SoundRequest, TrainerAbilityReq, TrainerService,
diff --git a/crates/benilla-app/src/ui_script/uiparent_tests.rs b/crates/benilla-app/src/ui_script/uiparent_tests.rs
index 7f0a02e2..7eca8dc7 100644
--- a/crates/benilla-app/src/ui_script/uiparent_tests.rs
+++ b/crates/benilla-app/src/ui_script/uiparent_tests.rs
@@ -1,4 +1,4 @@
-//! `assets/ui/UIParent.xml`'s addon-facing helpers, driven from Lua the way an addon drives them.
+//! Stock `Interface\FrameXML\UIParent.xml`'s addon-facing helpers, driven from Lua the way an addon drives them.
//!
//! The panel/ESC machinery in that file is covered by `panel_tests` and `escape_tests`; this is for
//! the loose functions the reference's `UIParent.lua` also defines, which benilla itself may never
diff --git a/crates/benilla-app/src/ui_script/unit_frame_tests.rs b/crates/benilla-app/src/ui_script/unit_frame_tests.rs
index 08b49e1c..f3586270 100644
--- a/crates/benilla-app/src/ui_script/unit_frame_tests.rs
+++ b/crates/benilla-app/src/ui_script/unit_frame_tests.rs
@@ -603,13 +603,11 @@ fn raid_mark_clicks_through_the_nested_level() {
.unwrap();
s.mouse_button(sx as f32, sy as f32, "LeftButton", true);
s.mouse_button(sx as f32, sy as f32, "LeftButton", false);
- // RED while the `SetRaidTarget` engine binding is absent, and deliberately left that way.
// `UnitPopup.xml`'s row calls `SetRaidTargetIcon(menu.unit, mark)`; the definition of that
// used to be ours, and since the migration it is the reference's own — `TargetFrame.lua`
- // l.486-492 — whose whole body is `SetRaidTarget(unit, 0 or index)`. `SetRaidTarget` is an
- // engine verb this house does not have yet, so the click raises
- // "attempt to call global 'SetRaidTarget' (a nil value)" and no intent is queued. 1203: it
- // gets built, never stubbed.
+ // l.486-492 — whose whole body is `SetRaidTarget(unit, 0 or index)`. That is the ENGINE
+ // verb, built by 1820 (`benilla-ui` `script/party.rs`), never the wrapper's name on our
+ // body: this asserts the intent it queues, and `:638` asserts nothing raised.
assert_eq!(
s.take_party_requests(),
vec![benilla_ui::script::PartyRequest::SetRaidTarget {
@@ -1211,8 +1209,8 @@ fn the_party_art_paints_over_the_bars() {
let mut s = UiScript::new().unwrap();
s.set_screen_size(1024.0, 768.0);
// The loot test's prefix (`loot_tests.rs`): PartyFrame's inline