- Scope: retail WoW addon stability, taint safety, scalability, and performance.
- Ticket order is execution priority (
P0first). - Definition of done for each ticket:
- All acceptance criteria pass.
- Taint test cases pass in a clean UI and in a realistic addon stack.
- No Lua errors in
/console scriptErrors 1sessions.
- Priority:
P0 - Goal:
- Eliminate direct replacement of Blizzard mixin/instance functions and move to hook/wrapper patterns that survive patch churn.
- Files:
core/main.luamodules/frames/unitframe_blizzard.lua
- Key changes:
- Replace direct assignments like
EncounterWarningsTextElementMixin.Init = ...with safe guarded interception strategy. - Isolate expansion-specific compatibility logic behind version-gated adapters.
- Add hard fail-safe: if target API shape changes, skip patch and log debug message instead of overriding unknown behavior.
- Replace direct assignments like
- Acceptance criteria:
- No direct reassignment of Blizzard frame/mixin methods remains in these files.
- Addon loads without Lua errors on login/reload/zone change.
- Edit Mode entry/exit works with boss frames and encounter warnings enabled.
- Taint test cases:
- Enter/exit Edit Mode repeatedly in city and in instance.
- Open EncounterWarnings-producing content, then toggle Edit Mode.
- Run with common UI packs and verify no
ADDON_ACTION_BLOCKEDfrom QUI.
- Priority:
P0 - Goal:
- Prevent namespace collisions by converting unscoped
Foo = function()helpers tolocal function Foo()unless intentionally exported.
- Prevent namespace collisions by converting unscoped
- Files:
modules/frames/raidbuffs.luamodules/character/character.luamodules/qol/consumablecheck.luamodules/qol/reticle.luaskinning/notifications/loot.luamodules/utility/anchoring.lua- plus any remaining matches from
rg "^[A-Za-z_][A-Za-z0-9_]*\\s*=\\s*function\\("
- Key changes:
- Convert helper assignments to local functions.
- Keep only explicit public APIs on
_G.QUI_*orns.*. - Add a lightweight lint/check script to detect new accidental globals.
- Acceptance criteria:
- No unintentional globals in addon codebase.
- Public API surface is documented in one section in this file or a dedicated API file.
- Taint test cases:
- Load with 20+ addons; ensure no behavior changes from symbol collisions.
- Validate
/reload, options panel open/close, and key features still work.
- Priority:
P0 - Goal:
- Remove split state between
QUI_DBandQUIDB; keep one canonical DB.
- Remove split state between
- Files:
QUI.tocinit.luacore/main.luacore/compatibility.lua(if migration helpers are placed there)
- Key changes:
- Choose canonical DB (
QUIDBrecommended for continuity with core usage). - Implement one-time migration from legacy DB key.
- Stop writing to legacy key after migration and remove dead-path reads.
- Choose canonical DB (
- Acceptance criteria:
- Single SavedVariables key in TOC.
- Existing users keep settings after upgrade.
- New installs create only canonical DB.
- Taint test cases:
- Upgrade path test with old SV file.
- Fresh install test.
- Profile switch/import/export still works after migration.
- Priority:
P0 - Goal:
- Avoid overriding Blizzard/global reload command behavior.
- Files:
core/main.luainit.lua(slash command handling)
- Key changes:
- Remove
SlashCmdList["RELOAD"]reassignment. - Keep safe reload on addon-specific command(s), e.g.
/qui rl.
- Remove
- Acceptance criteria:
/reloadremains Blizzard/default behavior.- QUI safe reload still available and combat-safe.
- Taint test cases:
- Execute
/reloadand/qui rlin and out of combat. - Ensure queued reload popup still works after combat.
- Execute
- Priority:
P1 - Goal:
- Reduce baseline CPU use by replacing frame
OnUpdatepolling where events are sufficient.
- Reduce baseline CPU use by replacing frame
- Files:
modules/frames/buffbar.luamodules/frames/unitframes.luacore/main.luacore/viewer_skinning.lua
- Key changes:
- Document where polling is truly required (API gap only).
- Drop polling frequency and auto-disable pollers when hidden/inactive.
- Use debounced event triggers for layout refresh.
- Acceptance criteria:
- Measured reduced CPU in idle and combat compared to baseline.
- Feature parity preserved for buff/cooldown updates.
- Taint test cases:
- Raid combat pull with many auras.
- Target swapping stress test.
- Enter/leave combat rapidly.
- Priority:
P1 - Goal:
- Reduce GC churn from repeated temporary table creation.
- Files:
core/viewer_skinning.luacore/main.lua- any other hot paths using
{ frame:GetChildren() }repeatedly
- Key changes:
- Replace temporary child arrays with reusable scratch buffers or direct iteration utilities.
- Avoid repeated creation of small tables in per-frame/per-second paths.
- Acceptance criteria:
- Lower GC spikes in
/fstack+ profiler sessions. - No layout regressions in CDM and unit frame updates.
- Lower GC spikes in
- Taint test cases:
- Prolonged 10+ minute dungeon run with combat logging.
- Rapid UI toggles and options edits while in city and instance.
- Priority:
P1 - Goal:
- Replace many independent
C_Timer.Afterchains with one orchestrated refresh queue.
- Replace many independent
- Files:
core/main.luacore/utils.lua(new scheduler helper)- modules using profile-change delayed refresh hooks
- Key changes:
- Add scheduler API:
QueueRefresh("unitframes"),QueueRefresh("ncdm"), etc. - Coalesce duplicate refresh requests in one short window.
- Run refresh sequence deterministically.
- Add scheduler API:
- Acceptance criteria:
- Profile changes produce one stable refresh transaction.
- No race-driven visual glitches or stale frame positions.
- Taint test cases:
- Rapid profile switching.
- Import profile followed by immediate Edit Mode toggle.
- Zone transition during queued refresh.
- Priority:
P1 - Goal:
- Ensure all secure frame mutations (attributes/position/state drivers) are combat-safe and consistently deferred.
- Files:
modules/frames/unitframes.luamodules/qol/quicksalvage.luamodules/qol/consumablecheck.luacore/utils.lua(new deferral helper)
- Key changes:
- Introduce shared helper:
RunOrDeferSecure(key, fn)onPLAYER_REGEN_ENABLED. - Replace scattered ad-hoc checks with centralized deferral and logging.
- Introduce shared helper:
- Acceptance criteria:
- No protected-action errors from QUI during combat-heavy scenarios.
- Deferred actions execute once and clear correctly.
- Taint test cases:
- Start combat while opening options/changing settings.
- Trigger quicksalvage/consumable picker interactions during combat transitions.
- Priority:
P2 - Goal:
- Make optional libs behavior explicit and deterministic.
- Files:
core/main.lualibs/libs.xmlREADME.md
- Key changes:
- Either vendor required optional libs or clearly gate feature with user-facing status.
- Add startup diagnostics line in debug mode showing optional feature availability.
- Acceptance criteria:
- No silent feature failure.
- Minimap button behavior predictable on clean install.
- Taint test cases:
- Run without any other addons (clean dependency environment).
- Run with other addons that embed different lib versions.
- Priority:
P2 - Goal:
- Reduce coupling and improve patch agility by decomposing the large core file.
- Files:
core/main.lua(split)- new files:
core/lifecycle.lua,core/profile_events.lua,core/editmode_manager.lua,core/compat_patches.lua(names can vary) core/core.xml(load order update)
- Key changes:
- Move lifecycle hooks, profile handling, edit mode, and compatibility patches into isolated modules.
- Keep one thin
main.luaentrypoint.
- Acceptance criteria:
- No behavior regressions after split.
- Improved readability and smaller diff surface for future fixes.
- Taint test cases:
- Full smoke run of login, reload, profile switch, edit mode, dungeon entry.
- Environments:
- Clean UI (
WTF/Interfaceminimal) - Real addon stack (common raider setup)
- High-combat (M+, raid)
- Clean UI (
- Core scenarios:
- Login, reload, zone change, dungeon start/end
- Profile switch/import/export/reset
- Edit Mode enter/exit while frames are visible
- Combat lockdown transitions during UI updates
- Pass criteria:
- No new Lua errors
- No
ADDON_ACTION_BLOCKEDattributable to QUI - No major FPS regression at idle or in combat
- Sprint 1:
P0-1toP0-4 - Sprint 2:
P1-1andP1-2 - Sprint 3:
P1-3andP1-4 - Sprint 4:
P2-1andP2-2