promotional bannermobile promotional banner

Vigil Cooldown HUD

Customizable WeakAuras-style HUD that provides information Blizzard's CDM doesn't. Simple drag and drop interface. Works in all content.

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: ignore directive;
      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.