File Details
v2.15.0
- R
- Apr 16, 2026
- 478.73 KB
- 22
- 12.0.1
- Retail
File Name
Vigil-v2.15.0.zip
Supported Versions
- 12.0.1
Vigil
v2.15.0 (2026-04-16)
Full Changelog Previous Releases
- Audit fixes: crashes, perf, pipeline hardening, CDM taint (#33)
- Audit fixes: crashes, perf, CI, pipeline hardening
Core fixes:
- Options.lua forward-reference for movePopup/ShowMovePopup (right-click on
placed sidebar row no longer calls nil) - Preserve standalone /vigil test on edit-mode exit instead of clobbering
- Wrap elem.Update in pcall inside UNIT_AURA dispatch (match SafeUpdate pattern)
- Stack badge falls back to C_UnitAuras.GetAuraApplicationDisplayCount when
aura.applications is secret - ScanAura: use AuraUtil.ForEachAura when available, drop unnecessary pcall,
name the 40-slot constant
Pipeline hardening: - Emit now throws if it wrote fewer than Object.keys(SPEC_FILENAMES).length
spec files (catches silent upstream failure shipping stale specs) - Parallel fetch with 8 concurrent workers + fetch retry + 30s timeout
(replaces sequential loop with 100ms sleeps) - Atomic writes: all cache and emit writes stage to .tmp + rename
- parse-apls logs skipped files so healer-vs-format-change is distinguishable
- link.mjs duration regex handles decimal _s notation
- luaValue escapes control bytes (\n/\r/\t/etc) for safer spec emission
- Moved hardcoded token Sets to shared.mjs (INTERRUPT_TOKENS, DEFENSIVE_TOKENS,
CC_TOKENS, MOVEMENT_TOKENS, RACIAL_EXCLUDE, SKIP_RACIALS, TOP_LEVEL_BASES,
DEFENSIVE_SUBTYPES)
Perf: - Cache GetTime in OnUpdate hot paths (Elements bar + icon)
- Cache UIParent:GetEffectiveScale in chrome-bar drag OnUpdate
- Debounce sidebar search filter (150ms) so keystroke bursts coalesce
- Pool help-overlay callouts instead of orphan + recreate per toggle
- Drop redundant elementMap nil guards (always initialized in CreateGroup)
Tooling: - .luacheckrc with WoW Lua 5.1 std and Vigil globals allowlist
- .github/workflows/lint.yml runs luacheck + packager dry-run on PR
Style compliance: - Em-dash sweep: 47 sites across 12 files replaced with hyphens
- Removed numbered-step comments in EnterEditChrome
- Rewrote "Fix:" and "Note:" narrative comments as invariants
- Deleted vestigial "-- (silent)" markers
- Collapsed GRID_SNAP/GRID_VISUAL aliases to one name
Deferred (followup PRs): - Full sidebar row pool (debounce captures the keystroke-burst case;
full shell-vs-bind refactor needs its own PR with edit-mode regression) - Remaining popup rebuild pools (profile, element picker, move, group menu,
element menu, toolbar dropdown) - Engine.lua module split
- Healer classification rewrite in classify.mjs
- Simplify: fixes from review of audit-fixes commit
Blockers fixed:
- Edit-mode exit was clobbering per-element test state via unconditional
elem.SetTestMode(false). Pass addon.testMode so preserved test mode keeps
the per-element rendering aligned. - forEachAuraMatch ran the manual 40-slot fallback even when AuraUtil's
search completed with no match - doubling scan cost on every Update miss.
Now returns immediately after AuraUtil. - .luacheckrc Specs/*.lua exclusion masked the per-file enable overrides.
Generated spec files now emit an inline-- luacheck: ignoredirective;
all hand-authored files under Specs/ get linted automatically.
Should-fix: - _preEditModeTestMode moved to a file-local (not addon namespace).
- classify.mjs INTERRUPT_TOKENS re-export dropped; resolve.mjs imports
directly from shared.mjs. - Emit spec-coverage check moved before file writes so upstream failures
don't leave partial updates on disk. - Sidebar search debounce guards against exiting edit mode before the
timer fires. - fetchWithRetry retries on 429/500/502/503/504 in addition to thrown
errors. - Pipeline consistency: update-interface.mjs, validate-wago.mjs,
fetch.mjs now use the shared writeAtomic helper.
Minor: - Trimmed over-narrating comments (shared.mjs token-set intro, Options.lua
pool clear, emit spec-count assertion). - validate-vdh.mjs em-dashes swept.
- Remove dead sidebar right-click move popup code
Sidebar rows are always created with sourceGroup=nil (single call site at
CreateSidebarRow passes nil). The RightButton branch in HandleClick guarded
on sourceGroup, so the whole branch was unreachable - and ShowMovePopup's
only caller was in that dead branch. The real right-click flow for placed
elements lives on the per-group element overlays via ShowElementContextMenu.
Deletes the entire ShowMovePopup function (~160 lines), the movePopupRows
table, the forward-decls, the hide-on-exit reference, and simplifies
CreateSidebarRow's OnClick to just handle the drag-threshold path. - Fix: taint propagation from CDMBridge + font scale consistency
Taint:
Wrap CDM frame modifications in securecallfunction so Blizzard's taint
tracker attributes them to a clean context instead of Vigil. Previously,
every time CDMBridge repositioned a CooldownManager frame (at load, on
hook firing, on Blizzard layout passes) the frame accumulated taint that
propagated through the UI hierarchy. The talent frame's first-load path
then blocked with ADDON_ACTION_BLOCKED because a shared button was tainted.
Covers: SinkEssentialFrame, InstallEssentialSetPointGuard hook,
InstallFrameHooks SetPoint callback, ReanchorPool overlay positioning,
reskin callbacks (ApplyBarSkin, ReskinIconFrame, ReskinBarFrame),
StyleCooldownFont, and anchor release on element detach.
Falls back to a plain call when securecallfunction isn't present
(classic era / pre-10.x clients).
Font consistency:
Native Vigil bar label/duration/stack font strings now also
SetIgnoreParentScale(true), matching CDMBridge. Previously CDM-wrapped
bars (e.g. Fiery Brand buff, which has a CooldownManager entry) rendered
at raw 10pt while target debuffs (no CDM entry, native bar) honored
parent scale, producing a visible size mismatch whenever the master
frame's scale was < 1.0. - Pre-load Blizzard_UIPanelTemplates + Blizzard_PlayerSpells at Vigil init
The ADDON_ACTION_BLOCKED error on talent frame open in combat was firing
from inside the LoadAddOn() call that bootstraps Blizzard_UIPanelTemplates.
That load runs SpellButtonMixin:OnLoad, which calls button:ClearAllPoints;
if the LoadAddOn itself happens inside a tainted execution context (which
it does, because by the time combat is ending or the user pressed talent
mid-fight Vigil has been hooking CooldownManager for a while), the taint
gets attributed to Vigil.
Pre-loading both packages at Vigil's own init runs the LoadAddOn before
any Vigil hook can taint anything. The later toggle finds the packages
already loaded and LoadAddOn is a no-op.
securecallfunction wrappers (previous commit) stay - they defend against
runtime propagation paths. This commit closes the load-time one. - Remove lint.yml to be added via GitHub web UI
Requires workflow scope which the push token doesn't have. Add back via
the GitHub UI after merge - content is in commit cf9bf25.
- Audit fixes: crashes, perf, CI, pipeline hardening

