- GetObjectType and IsObjectType land from the binary's own carve, with the client's exact inheritance answers
- the survey seats money and a quest log — sixteen addons call GetMoney, five walk the quest log, and none of those paths had ever run
- `date("*t")` returns its table form; the missing shape was an infinite loop for any addon walking days backwards
- unit tokens fold case like the client's resolver, and a FontString template carries the font object it inherits through the whole chain
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- every ranked list now states what it dropped and `--deep` reads the whole tail — a silent top-16 over 1,946 rows had already produced one wrong "nothing left" conclusion
- the backpack and equipped gear take their seats beside the spellbook, and a rankless spell's rank comes back "" rather than nil
- a FontString answers the full Region method map as one set — a text region's GetParent works — and RaidWarningFrame and PanelTemplates_Tab_OnClick arrive for the addons that name them
- SetRaidTargetIconTexture lands: the half of a raid mark an addon draws with
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GetInventorySlotInfo folds case the way the client does, and gains the twelve bag-slot rows the shipped data really carries
- ChatTypeGroup exists for addons that register their own chat types at file scope — one missing table was taking five addons down
- GetChannelList answers in join order, shaped by the addons that consume it, and the harness's `--why` can now open any demand count
- the survey seats a spellbook, and the shapeshift bar's shelf art exists hidden, both exposing paths an empty fixture could never reach
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the main bar's page arrows page for real, with the reference's own rule that a page a shown multibar displays is not also reachable by paging
- `<Include file="X.lua">` executes the file the way the client does — dispatch on the extension — so an addon pulling its libraries through XML stops losing them
- UIParentLoadAddOn lands, the on-demand loader behind every "open the panel" path
- nine constants take the reference's names back (NUM_GROUP_LOOT_FRAMES and friends — an addon reads the real name, not our prefix), and UnitCreatureType answers through the client's own three-stage resolver
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the justify verbs had been written three times and drifted three ways; one implementation now serves the region, font-object and message-frame tables, and a cleared axis paints centre, as the client's draw path really does
- MessageFrame and ScrollingMessageFrame gain the ten-verb font block they were missing entirely, so font calls on message frames stop raising
- EnableKeyboard and IsKeyboardEnabled land as real Frame methods — eight addons were dying on their absence
- the harness's METHODS ranking states its own limits instead of reading as a build queue
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the corpus harness now seats a buff, a target and a ticking cooldown instead of an empty world, so "nothing to draw" and "failed to draw" stop sharing a row — and the richer seat immediately exposed two real gaps
- an addon button inheriting our action-button template now works even when it replaces the template's OnLoad: the handlers resolve their regions by name, the way the reference does on every access
- more of the reference's hidden-by-default frames exist by name — ReputationWatchBar, MiniMapBattlefieldFrame, MiniMapMeetingStoneFrame — for the addons that reposition them
- StartSizing lands beside its stop verb, and the sourced bag-anchor code runs against windows we actually build
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Lua 5.0's generic-for and nested long strings are restored in a forked VM — 60 corpus addons stopped dying on one deleted opcode
- a day of demand-driven carving takes the 218-addon corpus from 24 addons surviving a session start to 114, with 144 loading without a single error
- Bagnon draws a real bag and answers real gestures — hover tooltip, pickup, use, drag — because our frames wear the reference's names, and the reference's own ContainerFrame.lua runs off the player's install instead of being transcribed
- the physics broad phase leaves: nothing in the client reads a contact, and it was measured at up to 41% of main-thread samples in real sessions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- benilla loads real 1.12 addons from Interface/AddOns — TOC, XML and Lua through one loader, with per-addon saved variables, Bindings.xml and the lifecycle events addons expect
- both AddOns screens are in: the character-select list with per-addon enable state, and the ESC menu's in-game list
- the API surface is measured, not guessed — a corpus harness runs hundreds of real 1.12 addons and ranks exactly which globals, templates and verbs they demand
- the Lua dialect is the client's own, read off the binary — 5.0 semantics with the 1.12 additions, and UI source files are bytes, not UTF-8
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- minimap zoom and the camera's distance and pitch persist across sessions
- the trainer's point-filter is a saved variable now and survives a relog, resetting per packet like the reference
- the options window gains its Combat page, over rows that can write the UI's own saved globals
- the step-up is a rise, not a jump forward — and the descent cone's cap belongs to the body, on every leg
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the step-up and step-down budgets are the client's own verified numbers, and the step regime is chosen by the blocking edge
- walking off a kerb follows the surface down instead of diving past the edge; steep ground supports you only while you are descending onto it
- a ride on a moving platform survives the ground snap, and a vertical wall no longer depends on a float's sign
- trainer and craft rows sort with the real client's own comparators, one per window — Beast Training lists a skill's ranks in ascending order again
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the Great Forge's lava stays drawn from every angle, and the chasm catwalk reads as a connected grate again
- music decoding and shader-compile bursts stop crowding the audio's lane, and the output buffer follows the device's real deadline
- the audio path grows its instruments: a mix tap to WAV, a starvation meter, a hardware overload listener
- trainer detail icons carry the reference's own tooltip
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- clicking a book in the world opens it and turns its pages: letters and world books share one reader
- the cursor's object rules are the client's own 31-row strategy table now, so decorative objects stop pretending to be usable
- trainer and tradeskill windows draw each row's icon by the reference's own law, and the trainer's filter dropdown toggles again
- water color follows the zone's light blend, so lakes stop snapping between area tints
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the whole loop plays: the line arcs rod tip to bobber, the bite splashes with its own sound, and clicking the bobber reels in
- the verdicts read like 1.12: yellow "your fish got away" lines, the reel-in sound, the fishing loot window
- "You feel rested." prints on the transition, rest states come from the client's own Exhaustion table, and level 60 trades the XP strip for the max-level rail
- the Skills pane lists what the real client lists: the hidden rows, the sort, gray numberless single-rank lines
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the spellbook's pet tab lists what the pet knows, with autocast toggled right on the page
- pet ability cooldowns sweep on the pet bar, and the bar binds to 1.12's Secondary Action Button keys
- the options window scrolls its pages in a real trough with seated arrows, nothing overflows the frame anymore
- Esc un-queues a queued strike, and a hostile unit's frame stops showing buffs the real client hides
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- feign death plays dead for real: the body collapses and stays down, both bars read 0 and DEAD, the nameplate drops, the combat hum goes quiet
- melee and Auto Shot are exclusive now: starting one stops the other, even mid-swing
- another client's addon chatter no longer prints as party chat
- right-click presses look pressed, rage and happiness read on their real scale, and the login boxes blink their caret
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the pet gets its own unit frame beside yours, and an Attack order no longer latches as the standing command
- five rooms that always read bone dry hold their water now, the Deeprun Tram's flooded stretches among them
- macros fire through the client's own chat door, and the macro window fits its tabs and scrolls its icon chooser
- the options window grows a Nameplates page and its first dropdown, and the name-display switches apply live in the world
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- a hunter's or warlock's pet has its action bar now: attack, follow, stay, the pet's own spells with cooldowns and autocast sparkles
- the macro system lands: the macro window, the icon chooser, /cast and /macro, and macros dragged onto the action bar
- hunter shots look right at last: the bow draws and releases on the shot, and the arrow lays a spark trail its whole flight
- the options window re-dresses in 1.12's own art with the classic dialog look, and gets a working search box and clickable steppers
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- one era-style Options window: window chrome, category list, search box and its own ESC rung, with the game menu reshaped to match
- settings are real CVars now: GetCVar/SetCVar reach Lua, and your changes persist as a diff in benilla/config.toml
- all local state lives in one visible benilla/ folder beside your Data/ — nothing hides in platform config dirs
- UI text stays crisp at any scale and survives a mid-session resolution change: glyphs measure in the environment they raster in
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the mount transition re-seats the rider instead of rebuilding them: shield glows, weapon enchants and worn visuals stay lit through mount and dismount
- an enchanted item's tooltip carries its enchant line, coloured per slot, with a temporary enchant's countdown
- a server refusal with nothing to say now says nothing: the raw "Inventory error" debug line is gone, real refusals still print
- the mail icon clears when you close the mailbox, and translucent models classify against the water plane
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- follow a player and the screen names who you're following, the right-click menu grows its Follow row, and your own movement is what cancels it — creatures are refused like the real client
- a locked lockbox click asks the server instead of refusing silently, a quest-starter chest offers its quest before opening, and an item on cooldown hides its green "open" line
- a parried swing plays its clang like the real client keys it
- the README's What works / Not built yet caught up on a week of shipping
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- /target and /assist find units by name like the original, and /follow walks you behind your target
- right click opens clams and lockboxes, and the tooltip promises it
- the freeze thaws clean, poses release instead of sticking, and you drop to neutral standing before it grips
- unit frame art layers over the bars like the original
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The keyring is built. Your first key makes the keyring button appear by
the bags, opening the window the original keeps its dungeon keys in — the
server had been sending the keys all along; nothing had ever shown them.
- Keys open their doors now. The client used to cast the open as a bare
spell, which the server rightly refuses; it now sends the item-use the
original sends, carrying which key from which slot. The tooltip plays
along: "Locked" turns the soft green when something you carry opens it,
and a key stops inventing a "Use: Opening" line it never had.
- A building can own the sky: a WMO can name its own painted skybox, and
Stratholme's burning city now draws its near-black-to-red dome instead of
the zone's khaki gradient. The exact rule for when it applies settles in
the next snapshot.
- Signpost tooltips follow the cursor again — the tooltip anchor forks per
object class, corner for doors, cursor for signs — and the Blasted Lands
lightning stops striking the same spot for ever: a placed doodad re-rolls
its animation variation every play-window, like the original.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The UI stopped paying to discover that nothing changed. Layout used to hash
~1,900 frames' worth of inputs every frame just to decide "quiet"; it now
tracks a mutation epoch and answers with one integer compare, and a settled
frame reuses last frame's rendered quads instead of re-rasterizing every
glyph. ~0.9 ms off every idle frame — with a verify mode, forced on across
all 489 UI tests, that re-runs every skipped resolve in full and asserts it
would have produced identical results.
- Across this run of snapshots, the one number everything is graded by: CPU
work per frame at the crowded dungeon spot went from ~29 ms to ~16.5 ms.
- A lighting question got the full treatment and an honest answer. Units
briefly took a different day/night lighting law; it read wrong on screen the
same evening, and a build-by-build hunt a full week back confirmed the
world's look never regressed in the first place — the change is reverted,
nothing about the look changes in this snapshot, and the question stays
parked until the one remaining unknown in the reference client is pinned.
- The character pane's model booth grew a headless eye — a dump of exactly
what it draws, no live session needed — built for that hunt, kept for the
next one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Particles, ribbon trails, blob shadows, the selection ring, ground decals,
water foam and the weather all push their quads into one shared vertex
stream now — one buffer, batched draws, indices built per frame in draw
order. ~1,100 emitters at the crowded dungeon spot stopped being ~1,100 mesh
assets the engine reallocated every frame, no material asset is ever mutated
for an effect again, and adjacent draws merge like the original's own batches
(its measured shape: 793 quads in 23 draws). Vertices went camera-relative on
the way — the fix for streaks and flakes vanishing in far zones, where the
raw coordinates get big.
- Hovering an item in your bags cost +14 CPU ms for as long as the tooltip sat
open. The tooltip's refresh loop is faithful 1.12 behaviour (the bag button
re-runs its hover every frame, unthrottled, so a late-arriving item fills in
without a re-hover) — but each rebuild dropped the text measuring cache, so
every frame re-shaped every line. One line keeps the cache: +14 → +0.1 ms,
and the paperdoll, inspect and merchant tooltips stop paying the same tax as
spikes.
- "Which room is this creature in" walks one anchor per model instead of every
lit part — ~13,700 part visits a frame became ~1,700 anchor rows. The
frame-time win was honestly flat (the cost had already moved elsewhere); it
lands for the structure, and the old sweep's repair duties became
event-driven with it.
- The perf probe defends its own window now — always-on-top from the first
tick, occlusion counted on the measurement line — after two long overnight
runs were silently destroyed by the display going to sleep.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The social window: friends, ignore and `/who`, in the reference's own two-level
arrangement with its inner tabs and per-row right-click menus. The lists ride the
real wire — guid-keyed with no names, resolved through the name cache, and capped
at 50 friends / 25 ignores because those are the client's own caps — and the
ignore list does its actual job: an ignored speaker's chat is dropped silently, a
whisper additionally tells the sender, and a duel challenge is auto-declined.
Guild ships as a disabled tab, which is what a guildless character sees.
- The escape menu: ESC's last rung finally opens something. The game menu lands at
the reference's own size and ladder, and leaving works — logout and quit with the
server owning the clock (instant at an inn, refused in combat, or the 20-second
countdown), narrated by the real camp/quit dialogs. While the menu holds the
center nothing else opens, and the bag bar greys out under it.
- Items on the action bar act like items. An equipped trinket was a dead button;
the reference's use law is two stages — not equippable means use, equippable and
already worn means use in place — over its exact search order (equipment first,
then the bags, then the backpack, then the keyring; never the bank). What can go
on the bar is now the reference's own two filters, byte-read: an item with an
on-use spell or one you can equip, and no passive spells — and dropping a passive
there speaks the real client's own line, "You can't put a passive ability in the
action bar."
- A quest-starter item opens its quest instead of "The item was not found." The
question goes to the item's own guid, never through item-use — which the server
refuses for every one of the 215 quest-starter items — and refusing the quest
says what the client says, then closes the window.
- For the toolbox: a pixel pick that reports everything under the cursor all the
way back, a lens that says which render phase a draw landed in, and switches that
separate "discarded" from "lost depth" from "never drawn" — built while cornering
a flickering tent, whose fix ships in the next snapshot.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The main menu bar's two empty recesses fill. The micro menu — the eight arched
buttons: character, spellbook, talents, quest log, socials, world map, main menu,
help — sits in the dark panel between the page arrows and the bags, transcribed
from the reference's own layout: the character button wears your portrait, a button
holds itself down while its panel is up, and the talent button appears at level 10.
The latency meter fills the one slot the bar art leaves transparent for exactly it,
tinted green/yellow/red on the reference's 300/600 ms thresholds and drawn UNDER
the bar art, seen through its window, the way 1.12 actually does it. The socials
and main-menu buttons find their panels one snapshot later; help still waits.
- The UI explains itself on hover: 1.12 ships its detailed two-line tooltips ON — a
FrameXML default, not the opt-in extra it is often remembered as — so the micro
buttons, your own portrait, the XP bar, the five bag buttons and the ping meter
all answer a hover with the reference's own explanations.
- The PvP flag, end to end: crossed swords on the player, target and party frames,
driven by the two descriptor bits the wire actually carries, and `/pvp` speaks —
the yellow toast plus the system chat line, the OFF sentence being the one that
warns the flag lingers for five minutes. It really does linger: turning it off
waits out the server's timer, which looks like a bug and is the reference.
- Quest markers stopped freezing. The grey `!` over a questgiver above your level
goes gold the moment you ding, an NPC re-entering view is asked afresh instead of
wearing a session-old answer, and the marker drops when the questgiver bit goes
off — the re-ask triggers mirror the reference's own set, plus one named addition
(your own level changing).
- Water and heights: swimming downhill no longer bounces between swim and fall ten
times a second — the surface line is a two-sided constraint, so the swimmer
settles with the river instead of being left behind by it. And collision height
is per-unit now, read from the unit's own model: a gnome used to swim with a
third of a yard of water over her head because five depth lines were quoting a
human's number.
- A round of pixel honesty in text and chat: the newest chat line no longer wears a
wider drop shadow than every line above it (shadows move in whole pixels now),
keeps its descenders, and hover boxes stop painting over the chat body. The chat
input's history browse survives programmatic edits, a failed script chunk warns
instead of vanishing, and recall deepens to 64 lines. Idle animation got honest
too: a model's idle is Stand resolved through its own lookup table — never
file order, which had the duel flag bobbing on its spawn clip — and an armed idle
is culled on the box its animation authors, not the bind pose, so the flag stops
vanishing at most camera angles.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Other players walk the world. A watched player's motion between server updates now runs through
the same grounded movement resolve as your own character — same capsule, same colliders, same
step-up and ground election — so they follow terrain every frame instead of every packet, and
stop at a wall instead of walking into it and being snapped back. Their jumps are swept against
the world too, and a standstill jump steered mid-air reports that steer, the one mid-air press
the reference client broadcasts rather than defers.
- The move relay rebuilt: relayed moves ride a per-unit chain on real time, a due move never jumps
ahead of its unit's queue, and SMSG_COMPRESSED_MOVES — the batched carrier the server sends under
load — is decoded rather than skipped. Our own send path now matches the reference client's:
facing streams while moving, Nagle is off so each packet is one write, and the strafe axis nets so
left and right can never ride the same packet.
- NPC and quest text speaks the whole $-macro grammar, carved from the reference bytes — your name,
class and race, the gendered forms, and the server's live world states — and the same
substitution feeds gossip, quest text, the quest log and unit frames. Greetings are a weighted
draw, rolled per NPC per open, and a quest giver with no quest to give is no longer clickable,
where it used to open a dialog holding nothing but a placeholder greeting.
- Spell tooltips finish the reference's line law: cast time and cooldown behind the real passive
gate, the required tool or form, the reagents block, the chance-to-X line, a multi-bit
equipped-item requirement named properly instead of by raw bits, and a buff's dispel class.
- The UI layout engine got a dense, reusable anchor solver, and a change gate that skips the resolve
entirely on frames where no layout input moved — in practice, almost every idle frame. Pets are
named by their pet number rather than a creature-template entry, so the client asks the query the
server can actually answer. And the asset extractor grew a stray-geometry census for tracking
down geometry that renders where it should not.
This snapshot replaces the six dated `sync` commits that stood here before it, whose subjects said
nothing but the date. If you cloned before now: `git fetch && git reset --hard origin/main`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>