GRIP - Enhanced Macro Sequencer

A powerful macro sequencer for creating, managing, and executing multi-step spell rotations. Free. No paywalls.

File Details

v2.0.3

  • R
  • May 9, 2026
  • 1.35 MB
  • 175
  • 12.0.5+1
  • Retail

File Name

GRIP-EMS-v2.0.3.zip

Supported Versions

  • 12.0.5
  • 12.0.1

Changelog

Created: 2025 (pre-stamping; exact date unknown) Updated: 2026-05-09 WoW Patch at last update: 12.0.1+ Midnight (Retail LIVE)

All notable changes to GRIP - Enhanced Macro Sequencer will be documented in this file.

This changelog follows a variant of Keep a Changelog.

[v2.0.3] - 2026-05-09

Macro import, macro action type, picker UI. Imports of external sequences that reference auxiliary macros by bare name now recreate those macros so the steps fire correctly instead of typing the macro name into chat. The editor + Add menu offers a new Macro entry that opens a picker over your /macro list and EMS-stored macros, with drift detection and a Refresh button when the source macro changes after authoring. Also includes the early-cycle table-shaped-step hotfix that shipped at the start of this release window.

Added

  • Macro action type in the + Add menu. Opens a picker that lists your account-level WoW macros, per-character WoW macros, and EMS-stored macros (de-duped on name). Selecting a macro inlines its body into the step; the step still fires the inlined body at runtime, so deleting or renaming the source macro after authoring does not break the step.
  • Drift indicator on macro-reference steps. When the source /macro body changes, a yellow indicator appears in the detail pane with a Refresh button that re-pulls the live body. No auto-sync -- changes only land when you click Refresh.
  • Source-missing state on macro-reference steps. If you delete the source macro from /macro, the detail pane shows a hint and disables Refresh; the step continues to fire from the cached body.
  • Bundled macros from external-sequencer COLLECTION exports (paste-import + slash-import + in-game migrate). When an imported sequence references a macro by bare name and the export bundle includes the macro body, the macro is recreated in your /macro list so the step resolves correctly.
  • Per-character bucket migration from external-sequencer storage for the active character.
  • New macro storage: GRIP_EMS_DB.macros (account scope) and GRIP_EMS_CHAR.macros (per-character scope). Lazily initialized on first import.
  • Import warnings for missing dependencies. When an imported sequence's metadata declares a macro or sub-sequence dependency that is not present in the import bundle and not in your existing macros / sequences, the import summary names the missing dependency.
  • Slot-exhaustion warning on macro creation. When MAX_ACCOUNT or MAX_CHARACTER macro slots are full, the import surfaces a per-macro warning with the slot count instead of dropping the macro silently.
  • Reading of MetaData.HelpTxt, MetaData.Help, MetaData.Helplink, and MetaData.LastUpdated from imported sequences (clipboard paste path). Author description, author link, and original export timestamp are now preserved.
  • Recognition of MetaData.Normal as a fallback for MetaData.Default in imported sequences (newer external-sequencer alias).

Changed

  • Macro picker search has a 100ms debounce on text input. Typing a multi-character search no longer rebuilds the full row list on each keystroke.
  • Macro picker auto-focuses the search box when opened.

Fixed

  • Detail pane Del button on leaf step types. ACTION, Pause, and Embed steps now remove themselves when Del is clicked from the detail pane (previously the button only worked on container children, so leaf steps required closing the detail pane and using the outline Del). Loop and If container child-deletion behavior unchanged.
  • Keyboard Delete on action-tree nodes. The keyboard shortcut previously called the flat-mode delete path; now branches based on whether the editor is in flat or tree mode and uses the matching delete primitive.
  • BackdropTemplate on the macro-reference body preview frame. The first picker selection no longer raises a nil-call from UI:ApplyBackdrop.
  • Row-click on a macro-reference step in the outline opens the detail pane (the body is read-only, so the inline edit path is not useful for this step type).
  • Recursive AceGUI:Release in the macro picker close path. MacroPicker._finish now clears the frame reference before calling Release so the OnClose guard short-circuits.
  • Engine.lua:91 attempt-to-call-a-nil-value during multi-delete. Engine:SubstituteVariables now type-guards non-string input. SpellValidator:ValidateSequence and RepairAnalyzer:CheckPostSub coerce step values via SpellCache:StepToString before passing them to substitution. Reported by Pershizzle.
  • Nameless unclickable rows after /reload. Engine:RestoreSavedSequences drops sequences with non-string or empty keys instead of restoring them as ghost rows. SequenceList:InitRow stores _seqData immediately after setting the name so OnClick survives downstream validation errors. Existing corruption auto-cleans on the next /reload.
  • Defensive pcall wraps around SpellValidator:ValidateSequence and RepairAnalyzer:Analyze inside InitRow. A single bad sequence cannot break the visible row list anymore. Failures fall back to safe defaults (staleCount = 0, healthScore = 100) with a debug log entry.
  • Doubled "v" in version display. Core.lua strips a leading v or V from the packager-substituted tag value before assigning to GRIPEMS.version. MainFrame title bar, Minimap tooltip, and Remote Browser version labels now show the correct single-v prefix.
  • Type-guarded coercion across the bug class at every reachable string-method and concat call site. Sequences with table-shaped steps or keyPress / keyRelease values from older imports no longer raise during analysis, display, or compilation. Added guards in SubstituteVariables, CompileSteps, ResolveFitAndExpand, BuildStubBody, TranslateMacrotext, ResolveSpellIDsInText, ValidateStep, ExtractAllSpells, ExtractSpellsFromStep, RepairAnalyzer (CheckLimits / CheckVariables / CheckReadiness / CheckStateSync / CheckCrossSeq + their fix lambdas), StepListView (display + drag-ghost paths), and Defaults:NodeSummary.

Internal

  • New Engine/MacroManager.lua module (auxiliary-macro CRUD, drift detection, source enumeration).
  • New UI/MacroPicker.lua module (modal picker frame).
  • .gitignore: outputs/ added to the local-only folders block to keep dev scratch out of commits.

[v2.0.2] - 2026-05-05

BarIntegration taint hardening, Layer 1 condition helpers, and a Korean-clone locale fix. Replaces every BarIntegration write to a Blizzard action button child texture with a write to an addon-owned overlay texture, completing the private-table pattern started in v2.0.1's StaticPopupDialogs migration. Adds six pcall-wrapped boolean condition helpers for user variable expressions, a picker UI to insert them at the cursor, and a Function Body tooltip listing them. Regenerates zhCN.lua and zhTW.lua from English source after a copy-paste shipped Korean text to Chinese players in v2.0.1.

Added

  • Layer 1 boolean condition helpers for use in user variable expressions: GRIPEMS.HasBuff, GRIPEMS.HasDebuff, GRIPEMS.SpellReady, GRIPEMS.SpellOnCooldown, GRIPEMS.SpellEnabled, GRIPEMS.IsRestricted. Each helper pcall-wraps its underlying API and is safe to call in combat under 12.0 addon-action restrictions. Numeric variants (HealthBelow, PowerBelow, GetBuffStacks, SpellCooldownLeft, etc.) are architecturally blocked by the 12.0+ secret-value system on every reachable path tested -- see Research/Variable_Taint_Solution_2026-05-04.md v2.2 / v2.3 for the empirical sweep results. GRIPEMS.IsRestricted reads the existing GRIPEMS.restrictions table maintained by Engine/OOCQueue.lua's ADDON_RESTRICTION_STATE_CHANGED handler and registers no event handler of its own. Tracked under IC-VAR-01 Phase 3a.
  • Insert Helper button on the Variables Tab function-body editor: opens a picker with the eight Layer 1 condition helpers (HasBuff, HasDebuff, SpellReady, SpellOnCooldown, SpellEnabled, IsRestricted) and inserts the chosen helper at the cursor with the spellID placeholder pre-selected for type-over.

Changed

  • Function Body tooltip in the Variables tab now lists the six Layer 1 boolean helpers (HasBuff, HasDebuff, SpellReady, SpellOnCooldown, SpellEnabled, IsRestricted) and includes a Private aura note clarifying that 12.0+ Private auras are hidden from HasBuff and HasDebuff iteration. The locale-safety guidance is preserved. enUS authoritative; 10 mirror locales carry the new English value with REVALIDATE markers.

Fixed

  • BarIntegration ActionBar taint -- defensive guard. Engine/BarIntegration.lua rewritten so step icons land on addon-owned overlay textures only. 9 touch-points migrated; private overlays table plus 5 helpers (CreateOverlay, GetOrCreateOverlay, ApplyOverlayIcon, HideOverlayByName, HideAllOverlays); trackedButtons no longer caches originalTexture. Mirrors the StaticPopupDialogs private-table pattern from v2.0.1: addon state stays in addon-private storage, never written into Blizzard-owned tables. Closes the suspected root of ADDON_ACTION_BLOCKED on MultiBarBottomLeft:ShowBase() reported during talent swap and Guardian Druid form shift on Razer hardware autoclick. The previously disabled hooksecurefunc(ActionBarActionButtonMixin, "Update", ...) stays off; re-enabling it is now structurally safe and is tracked for v2.0.3 once telemetry confirms the defensive guard.
  • isInLongComment in the Variables tab function-body editor rewritten as a single-pass walker that tracks open level (count of = signs between brackets) and requires a matching close. Smart-concat now correctly suppresses inside --[==[ ... ]==] and other leveled long comments, not just plain --[[ ... ]]. Phase 3c.2-extra.
  • zhCN.lua and zhTW.lua were 98% Korean clones of koKR.lua from a prior copy-paste -- shipped in v2.0.1, exposing Chinese (Simplified and Traditional) players to Korean text across the Variables tab, settings, error messages, and every other locale-driven surface. Both files regenerated from enUS.lua source via machine translation, marked -- MT for future human-review pass. AceLocale registration headers preserved (zhCN, zhTW). Tracked under BUG-LOCALE-CHN-CLONE in the EMS Backlog. Phase 3c.1.5.

[v2.0.1] - 2026-05-03

Taint hardening + polish. Migrates 28 popups off the global StaticPopupDialogs table to a private GRIPEMS.Popup framework, eliminating CancelLogout ADDON_ACTION_BLOCKED and several recycled-slot taint paths. Drops a Blizzard ActionBar hooksecurefunc to mitigate BUG-BARINTEGRATION-ACTIONBAR-TAINT. Polishes the reload-required popup wording, the Reset-to-Defaults description, the Steps-tab max-depth feedback, and the Overview tab translations. Removes two dev-only diagnostic hooks that should not have shipped.

Fixed

  • Static popup taint. The 28 popups previously registered on _G.StaticPopupDialogs now live in a private GRIPEMS.Popup framework (Core/Popup.lua). CancelLogout no longer fires ADDON_ACTION_BLOCKED after EMS popups are recycled. Migrated under Phase StaticPopupTaint and Phase N-polish.
  • BarIntegration ActionBar taint. Dropped the Blizzard hooksecurefunc that was the suspected root of BUG-BARINTEGRATION-ACTIONBAR-TAINT. Tracked under Phase StaticPopupTaint-followup.
  • Stale StaticPopup_Show comment in Engine/Transmission.lua corrected (Phase 1-polish).

Changed

  • RELOAD_GATE_POPUP_BODY reworded from "ensure full visual effect" to "for changes to fully take effect" -- not every reload-required CVar is visual. 11 locales updated with native translations.
  • GEMS_CVAR_RESET_DEFAULTS_DESC and GEMS_CVAR_RESET_DEFAULTS_DONE extended to mention that auto-fix-on-login opt-ins are cleared by the reset, and voice-tightened. enUS authoritative; mirror locales carry the new English value with REVALIDATE markers for the future plain-language pass.
  • Overview tab labels (5 keys: name, version label, navigate hint, Discord button, author line) now ship with native translations across all 10 mirror locales -- no English fallback.
  • ActionCompiler max-nesting-depth gate now surfaces a throttled chat warning (max once per minute) naming the depth limit when reached. Replaces the previous Debug-only print that was invisible to users without /gems debug on. New locale key GEMS_COMPILE_DEPTH_EXCEEDED ships in all 11 locales.

Removed

  • Dev-only diagnostic hooks GEMS_BlizDbg_AccessibilityScroll and GEMS_BlizDbg_ScrollAudit removed from UI/SettingsPanel.lua. Both were left over from Phase 4 scroll-injection investigation.

[v2.0.0] - 2026-05-02

The Accessibility Release. v2.0.0 reframes EMS around the populations the addon was previously unusable for: blind and low-vision players using screen readers, players who play one-handed or with tremor, Deaf and hard-of-hearing players, players sensitive to flashing imagery, and players who need plain language and slower flow. The release adds spoken step announcements, a focus ring on every focusable widget, three palette presets plus an 8-type colorblind matrix, large-target mode at WCAG 2.5.5 AAA, and a one-click Accessibility preset that turns the lot on at once. CVar Health expands from a small panel into a 212-variable dashboard with auto-switching profiles, scoring, an onboarding modal, palette routing, and TAB / numbered-key / skip-to-issues navigation through the AceConfig focus shim. See ACCESSIBILITY.md for the full feature list, the compatibility matrix, and the structural-limit notes.

Accessibility (Phase 1-4 summary)

EMS aims to be usable for players who rely on screen readers, play one-handed, play with tremor, play with low vision, are Deaf or hard of hearing, or avoid motion in the UI. The full feature list, compatibility matrix, and structural-limit notes live in ACCESSIBILITY.md; this section names the v2.0.0 work groupings.

  • Spoken step announcements via Blizzard text-to-speech, a chat-frame emitter for external screen-reader bridges, and a peer visual-flash complement so Deaf and hard-of-hearing players see the same cues.
  • High-contrast focus ring on every focusable widget, with a per-element theming editor, a font switch via LibSharedMedia (Atkinson Hyperlegible bundled), and an editor scale slider 0.8x to 2.0x.
  • Three palette presets (Default, HighContrast, DeuteranopiaSafe) plus an 8-type colorblind matrix with a 0-100% strength slider; flicker-safe palette setting damps alpha-animation deltas below the WCAG 2.3.1 threshold.
  • Large-target density mode (WCAG 2.5.5 AAA) grows click areas to 44 by 44 pixels without changing visual size; sequence-editor tabs, row checkboxes, the help button, and the icon-picker close button all participate.
  • Keyboard-first navigation across every non-EditBox widget via FocusManager + AceConfigFocusShim, spell/item/macro/slash pickers (14 filter modes), a cursor enhancement overlay, and Simplified Mode for switch input, eye trackers, sip-and-puff, and head tracking.
  • Plain-language tooltips and validation messages, an opt-in first-run tutorial, help popovers on every editor section, and a sequence-metadata field for sequence authors to embed guidance that travels with the export.
  • One-click Accessibility preset toggles speech, reduce-motion, the High-Contrast palette, editor scale 1.25x, large-target density, the cursor overlay, and Simplified Mode together; toggling off restores prior state.
  • ACCESSIBILITY.md at the repo root with the feature list, compatibility matrix (BlindSlash, ConsolePort, DialogueUI, Leatrix Plus, ElvUI, WeakAuras, Atkinson Hyperlegible), theming-taxonomy notes, and structural-limit notes for capabilities the WoW addon API does not expose. README, CurseForge, Wago, and WoWInterface listings carry a pointer. The in-addon Accessibility subpanel gains an "Accessibility Guide" subgroup at the top.

CVar Health (Phase G summary)

  • 212 game variables across 13 sections with health scoring (good / warn / bad), per-section roll-up, and a top-level health badge.
  • 4 auto-switching profiles (Performance, Quality, Streaming, Custom) with What Changed login detection and per-CVar Pin so user-locked entries survive profile switches.
  • Onboarding modal on first cvarHealth open explains scoring, profiles, and the Pin model in plain language; tracked behind GEMS_CVAR_ONBOARDING_BODY.
  • ReloadGate cross-cuts every settings change that needs a /reload to fully apply: minimap pip + sidebar pip light up while changes are pending, single popup on settings-panel close offers Reload Now or Later, suppression resets per cycle.
  • Palette routing across the entire cvarHealth surface plus the ReloadGate pips: 13 new tokens to UI.Colors (scoreGood/Warn/Bad, cvarMatch, cvarMismatchCritical/Polish, cvarUnrecommended, cvarSqwManaged, cvarAdvisoryGood/Warn/Bad, reloadGateMinimap, reloadGateSidebar) plus the cvarChangesDetected micro-token; UI:ColorCode helper replaces every hard-coded chat-color literal.
  • Speech:Announce coverage across all activation paths (Fix, Set, Undo, Pin, Auto-fix), the onboarding popup, the reset-to-defaults popup, the export and import popups, and the toggle state-change handlers in the Accessibility subpanel; centralized cvarRowAnnounce helper coalesces ~1100 widget activations.
  • Numbered-key + skip-to-issues navigation in the cvarHealth subpanel via AceConfigFocusShim: keys 1-9 jump to section anchors, PageUp/PageDown cycle sections, Alt+N / Alt+Shift+N cycle the issue list.
  • ReloadGate sidebar pip wired into the active focus context: Focus:RegisterRegion at pip creation; pin on rising edge / unpin on falling edge; survives shim rewalks via R:_PinIntoFocusContext helper called from the cvarHealth onRewalk callback.

Editor + Engine

  • Editor auto-icon detection and import-preview fingerprint no longer crash on table-shaped sequence steps. Step-to-string coercion lifted into SC:StepToString and reused by SequenceList, SequenceEditor, and ImportPreview. Reported by Pershizzle.
  • SC:ParseSpellFromMacrotext now delegates input coercion to SC:StepToString, removing the duplicate string/table/array handling logic. Behavior unchanged for all input shapes.
  • Settings panel right-side detail pane no longer gets clipped on profile-list cascade: the cascade resize now runs on a deferred frame so AceConfigDialog gets its own width pass before the panel asks for the post-cascade dimensions.

Internal

  • AceConfigFocusShim landed: ~760-line bridge from AceConfigDialog subpanels into GRIPEMS.Focus so Blizzard SettingsCanvas pages get TAB cycle + ENTER activation. Opt-in per group via Shim:Enable. v2.0.0 surfaces enabled: accessibility (S19), cvarHealth (S20).
  • Locale framework: 22 new ACCESS_ANNOUNCE_* keys and 1 GEMS_CVAR_PROFILE_MANAGE_DESC key across 11 locales (242 string additions, English placeholder under REVALIDATE for non-enUS locales). enUS authoritative count moved 1777 -> 1778; mirror coverage stays at 85.8%.
  • Linter wiring stable: alllint pipeline runs luacheck, selene, markdownlint, jsonlint, and stylua --check in one pass; all shipped Lua / JSON code is at zero warnings; markdownlint baseline preserved in gitignored dev files.
  • Hard-link gate enforced on every commit via .pre-commit-config.yaml -> python Tools/cowork_util.py hardlinks; canonical Tools/ at Hub/GRIP/Tools/ with hard-links into each project's Tools/.
  • AVAV (post-Code verification) now mandates re-running alllint locally and comparing against Code's claims rather than trusting narrative numbers; tracked under TOOLING-AVAV-LINT-RERUN after a fabricated-numbers incident on 2026-05-02 G.8c.1.1.

[v1.9.10] - 2026-04-23

Hotfix for three BugSack errors reported against v1.9.9. Import and export paths only. No migration, no new settings.

Fixed

  • DebugWindow:AddMessage typo (4 sites). Four import and export paths called :Add instead of :AddMessage when writing advisory messages. The GRIP1 import preview hit this on every keystroke while a string was being pasted, producing a nil-method error per character typed. Fixed in Import/ImportPreview.lua, Import/GRIPExport.lua (two sites), and Data/VariableStore.lua.
  • ExportFrame combat taint. The first-time frame constructor called SetPropagateKeyboardInput(true) directly, before the OnKeyDown combat guard was attached. Opening the export frame during combat triggered ADDON_ACTION_BLOCKED. Wrapped the initial call in pcall to match the defensive pattern already used at lines 1181, 1185, 1189, 1192, and 1194 in the same file.

Thanks to Gabriel on Discord for the BugSack reports.

[v1.9.9] - 2026-04-19

Final stabilization pass before v2.0.0. Nine items, all backwards- compatible. The point is a clean baseline before the feature work resumes.

Fixed

  • OOCQueue: the "replaced setting for nil" debug spam is gone. The internal dedup key was being built from (opType, seqName) where seqName was silently nil for three call sites that queued global settings changes rather than per-sequence ones. The queue collapsed every subsequent generic queue into the same nil bucket and logged a replacement notice each time. Fix is two-part: (1) the three offending callers in Engine.lua and TempoAdvisor.lua now pass stable seqName strings ("macroResetModifiers", "msClickRate", "UseKeyHeldSpellErrorPollTime"); (2) OOCQueue:Add rejects a nil seqName for any non-OOC_OP_GENERIC op so the bug cannot re-emerge from a future caller forgetting the key.
  • TempoAdvisor: GRIP_EMS_CHAR.tempoOffGCD is now patch-stamped. When the saved-variables shape from an earlier patch loads on a different build, Initialize migrates each spec entry to the {_patch=..., spells={...}} shape and wipes the classification cache for any entry whose _patch does not match the current GetBuildInfo() string. Prevents the stale-off-GCD-classification issues that accumulate across patches and previously required /gems holdreset. A new /gems fs reset subcommand wipes _runtimeOverrides, GRIP_EMS_CHAR.tempoOffGCD, and the internal spell-class cache for users who want to force a fresh scan.
  • SequenceEditor: SetPropagateKeyboardInput(true) is now re-applied on both PLAYER_REGEN_ENABLED and panel OnShow. Prior builds only reset on combat-exit, so re-opening the editor after a /reload in a previously-tainted state left the editor in a key-swallowing mode until the next combat cycle. The dual reset path covers both the reload-then-open case and the reload-then-combat case.

Added

  • Interleave discoverability bundle (4-part). Interleave was previously a hidden feature that only surfaced if you selected a top-level Action node. The whole surface is now consistent:
    • Every nested Action child row in the detail pane renders an inline [checkbox] [interval editbox] steps widget. Toggling the checkbox flips node.interval between ACTION_INTERLEAVE_DEFAULT and nil; the editbox clamps to [ACTION_INTERLEAVE_MIN, ACTION_INTERLEAVE_MAX] and updates dirty state on enter.
    • The existing interleave checkbox in the detail settings bar now shows a tooltip (GEMS_INTERLEAVE_TOOLTIP_TITLE / GEMS_INTERLEAVE_TOOLTIP_DESC) explaining what interleave does and when to use it.
    • The add-step menu picks up a distinct "Action (Interleave)" entry after "Step" in both outline and detail-pane modes. The new node ships with node.interval = ACTION_INTERLEAVE_DEFAULT so the inline widget renders in its enabled state on first paint.
    • Defaults.NodeSummary grows an ACTION_TYPE_ACTION branch that emits the first macro line truncated to 40 chars with .. suffix when longer, and appends [IL:N] when interval is set. Top-level action badges in the outline now show the macro text and interval at a glance.
  • GRIP1 export checksum. GE.Export and GE.ExportCollection both compute S.ComputeTableChecksum over the sequence payload (or sequences map for collections) and stash the result in payload.checksum. The three import paths (LI._PreviewGRIP1COLLECTION + single, and GE.ImportNative used by TestSuite) recompute on decode and warn via GEMS_IMPORT_CHECKSUM_MISMATCHwhen the values diverge. Validation is non-blocking. The import still completes, and the only user-facing effect is a warning line in the import preview when a payload has been corrupted or tampered with in transit.

Changed

  • Removed UI/ActionRenderers.lua and the matching TOC line. The file was introduced during the S14 hierarchical-actions work but was superseded by StepListView renderers and never called from any remaining code path.
  • Removed three dead diagnostic blocks from Core.lua that referenced the deleted AR namespace (/gems perf AR frame-pool dump, an AR.RenderActionTree tracer hook, and a hooksecurefunc(AR, "Render") instrumentation block).
  • Removed the 60-line dead ACTION branch in StepListView:_renderDetailSettings. The branch was unreachable because detail settings for ACTION nodes have always routed through the interleave block. Its presence made the function harder to read.
  • SpellValidator.NodeHasInvalidSpells exposes a collectAll flag so badge calculations short-circuit on the first UNKNOWN while tooltip callers enumerate the full invalid list. The tooltip now shows every invalid spell inside a Loop/If/Embed subtree instead of just the first one.
  • The "new spell" tooltip built from the Spell Picker clamps to the screen edge via SetClampedToScreen(true) and flips anchor (ANCHOR_RIGHT -> ANCHOR_LEFT) when the owner sits in the right half of the viewport. Prevents overflow off the right edge on wide-tooltip content at high UI scale.
  • TempoAdvisor: flyout children (Call Pet 1-5, Hunter's Mark on [nopet], Warlock summon demon variants, Mage Teleport/Portal children) no longer get reclassified as OFF_GCD during combat. The previous guard referenced a non-existent SpellCachetable and silently passed every flyout child through to ReclassifyOffGCD, inflating complexity to INTENSE on any sequence that referenced one. Fix adds a spellID-keyed index to SpellCache and routes both the ScanPendingDurationZero and UNIT_SPELLCAST_SUCCEEDED guards through it. A one-shot scrub on the first SPELL_CACHE_REFRESHED after login drops poisoned entries from _runtimeOverrides and GRIP_EMS_CHAR.tempoOffGCDwithout requiring /gems holdreset. A write-side guard on ReclassifyOffGCD catches any future call-site before it can re-poison the tables.

Internal

  • Data/SpellCache.lua: new self.byID map, spellID -> entry. Built in Scan() after the byName pass. Zero extra cost on lookup-heavy TempoAdvisor paths that previously had no way to resolve spellID to entry metadata.
  • Four new locale keys across all eleven locale files: GEMS_INTERLEAVE_TOOLTIP_TITLE, GEMS_INTERLEAVE_TOOLTIP_DESC, GEMS_ADD_ACTION_INTERLEAVE, GEMS_IMPORT_CHECKSUM_MISMATCH. Non- English files carry the English text with a -- MT marker.

[v1.9.8] - 2026-04-18

Changed

  • TempoAdvisor confidence state now splits into two orthogonal SavedVariables fields: theoreticalConfidence (written by AnalyzeSequence when Tier 1 resolves spells) and empiricalConfidence (written by Tier 3 blending after enough CLEU samples accrue). A new TempoAdvisor:GetEffectiveConfidencegetter derives the display label: "Calibrated" wins when Tier 3 has converged AND the sequence has no unknown spells, otherwise the theoretical label shows. Fixes a 2-3 second oscillation where the two writers were clobbering a shared rec.confidence field and the tooltip/overlay flickered between "Estimated" and "Calibrated". Legacy rec.confidence values are mapped onto the best-fit new field on Initialize (Calibrated -> empiricalConfidence, anything else -> theoreticalConfidence) then cleared, so the UI shows a sensible label from the first /reload onwards rather than briefly showing "Unknown". Display strings unchanged.
  • SequenceList now desaturates the sequence-row icon whenever data.disabled is set, regardless of data.active. Previously the dim state only engaged when the OOC teardown flipped active to false, leaving a short window in combat where a just-disabled sequence still rendered at full colour.
  • SequenceList right-click menu: Enable/Disable entry now reads from L["GEMS_UI_ENABLE"] / L["GEMS_UI_DISABLE"] instead of a hardcoded English string. enUS keys already ship the short form ("Enable" / "Disable") to match adjacent Rename / Delete entries.

Added

  • SequenceEditor header: disabled-state badge plus a Disable/Enable toggle button in the button chain. The badge shows [Disabled] in muted text to the left of the button when the currently-loaded sequence has been disabled. The button calls Engine:ToggleSequenceDisabled and swaps its label between "Disable" and "Enable" based on current state. Combat-safe: the click delegates to the Engine function which queues the secure teardown or activation through OOCQueue, so flipping a sequence while in combat takes effect the moment combat ends. Tooltip swaps description copy to match the action about to be performed.
  • Five new locale keys for the disabled-state UX: GEMS_UI_ENABLE, GEMS_UI_DISABLE, GEMS_UI_ENABLE_BTN_DESC, GEMS_UI_DISABLE_BTN_DESC, GEMS_UI_DISABLED_BADGE. enUS only this pass; community translators pick them up on their own cadence.

Fixed

  • SequenceList: sequence row subtitle now dims when the row is disabled or not activated. Previously the subtitle text was unconditionally set to the active colour after the dim branch, so only the name and icon actually changed. Pre-existing bug, surfaced by v1.9.8's dim-trigger rework.

Internal

  • Tools/cowork_util.py wtdiff: Lua tail-pattern table now recognises AceLocale assignment lines (L["..."] = "...") so Locale files no longer trip the integrity gate. Narrow regex; will not mask truncation of regular Lua modules.

[v1.9.7] - 2026-04-18

Changed

  • Tooltip invalid-spell listing: tooltips now show ALL invalid spells in a node, not just the first encountered. Badge path still short-circuits on first UNKNOWN for performance.
  • Spell and item tooltips now flip to ANCHOR_LEFT when a row sits far enough right that an ANCHOR_RIGHT tooltip would overflow UIParent's right edge. SetClampedToScreen(true) re-asserted as a belt-and-braces guard.

Fixed

  • TempoAdvisor combat GCD verification now tracks numeric-string spell IDs (e.g. "34026") in _pendingVerification. Previously, sequences that referenced spells by ID-as-string never got the green "verified in combat" overlay checkmark.
  • SequenceEditor keyboard propagation now resets to true on PLAYER_REGEN_ENABLED. Fixes a stuck-false edge case where the last pre-combat editor shortcut left propagation disabled through the whole combat, blocking action-bar keybinds while the editor held focus.

Internal

  • OPP-17 verified (audit only): all StepListView OnUpdate scripts self-terminate. No leak.
  • OPP-11 verified (audit only): AceLocale-3.0 does not allocate memory for non-matching locale tables.

[v1.9.6] - 2026-04-18

Performance

  • Mount, companion, and toy caches no longer rebuild on PLAYER_ENTERING_WORLD for every boot. Built the first time the Spell Picker or Spell Cache Viewer actually asks for them; a deferred eager build 3s after PEW still populates diagnostics (perftest, compartment menus) without opening the picker. Cuts cold- boot scan time on characters that never open the picker UIs. Event-driven invalidation (NEW_MOUNT_ADDED, NEW_TOY_ADDED, PET_JOURNAL_LIST_UPDATE, UNIT_PET, PET_BAR_UPDATE) still re-dirties the lazy flag so the next picker read rebuilds.
  • UNIT_SPELLCAST_SUCCEEDED off-GCD reclassifier no longer wipes the entire TempoAdvisor debounce table and re-analyses every registered sequence. A name-keyed spellID-to-sequence index (TA._spellToSequences) drives a scoped reanalyse that touches only the sequences referencing the spells that were just flipped to off-GCD. For spells no active sequence uses -- the common case -- the scoped helper returns immediately. Rename is handled implicitly via the existing SequenceEditor DELETED+CREATED pair; no dedicated rename event or GUID infrastructure was added. The index rebuilds on SPELL_CACHE_REFRESHED so existing saved sequences are indexed correctly once SpellCache finishes its first scan at PLAYER_ENTERING_WORLD.
  • SpellCache dropped three pcall guards around C_Spell.GetSpellInfo in the hot scan path. The modern API returns nil cleanly for unknown IDs and does not raise; pcall was pure overhead across ~3k spellbook entries per scan. The three GetSpellBaseCooldown sites keep their pcall (older global, less stable).

[v1.9.5] - 2026-04-18

Performance

  • UNIT_SPELL_HASTE handlers in TempoAdvisor and SQWOptimizer now check the unit arg and skip anything that isn't the player. The event fires for nearby pets and party members too, so this cuts 40+ idle AnalyzeSequence passes per minute down to zero.
  • SpellCache keeps per-collection dirty flags (spells, items, toys, mounts, companions). A zone change that didn't mutate anything is now a scan no-op. Pure-reload boots still rebuild everything from scratch; per-event routing only touches the collection that changed.
  • ComparisonFrame scroll sync moved off OnUpdate polling onto the ScrollBox OnScroll callback. No more per-frame cost when the compare window is open.
  • Debug buffering skips string.format when nobody is watching. GRIPEMS:Debug now takes varargs; the formatter only runs when the debug setting is on or the DebugWindow is visible. Roughly 30 hot-path call sites in Engine, TempoAdvisor, Transmission, and SQWOptimizer switched over.

Fixed

  • TempoAdvisor recommendations stayed stuck after a /reload because StoreRecommendation was saving GetTime() into SavedVariables. GetTime() resets on every reload, so the freshness check read a huge negative delta and treated old cached data as permanently fresh. Freshness now lives on a module-local table that rebuilds each session; the timestamp field is gone from the SV payload.

Internal

  • New /gems perftest diagnostic with three sub- modes. events N wraps the top five OnEvent handlers for N seconds and prints fires/total/ peak ms per frame. scan forces every spell cache collection dirty and times each sub- builder. reanalyze re-runs OnSequenceActivated for every saved sequence. /gems memory now works as an alias for /gems memcheck.
  • Core.lua carries a SavedVariables schema comment block documenting which fields are session-local and must never hold GetTime() values. Prevents the same foot-gun landing again on the next module that touches SVs.

[v1.9.4] - 2026-04-18

Added

  • /gems record and /gems trace now work as slash commands. MacroRecorder and ExecutionTracer have been there for a while; the slash handlers are the missing piece that makes them usable without going through the UI.

Fixed

  • Imported and migrated sequences pick up their icon from the first spell in the sequence instead of staying on the red question mark stub icon. Sequences now look distinct in the macro list immediately after import.
  • Keybind capture shows a nudge in the red error area when you try to bind bare LeftClick or RightClick without a modifier. The v1.9.3 fix silently ignored those clicks, which made the capture dialog look broken.
  • /gems fs output that was still in English (hold, holdreset, holddiag branches) now uses locale strings.

Internal

  • /gems cvar row added to the README slash command table. The command has been wired since v1.9.1; only the doc row was missing.
  • F2 detail child rows pick up a pre-Midnight tooltip fallback that matches the step row code path. No behavior change on current LIVE; defensive parity for older TOC ranges.
  • ResolveIconName wraps C_Spell.GetSpellInfo in pcall to match the pattern used elsewhere in the codebase.
  • ImportNative now reads contextOverrides from the payload top level to match the export format. TestSuite-only path, no user-facing impact.
  • CHANGELOG v1.9.3 .luacheckrc bullet corrected to mention wow.toml (the selene side was shipped together).

[v1.9.3] - 2026-04-17

Added

  • Native in-game tooltips on step rows in the detail pane. Hover a step and you see the same tooltip the game shows on the action bar, with full description, cooldown, and range info. Both spells and items work (items via the item:ID syntax your macro already uses). Validation warnings, when present, appear below the native tooltip instead of replacing it.
  • Validation badges on every step and every node in the step list. A yellow "!" means you are referencing a real spell you do not have on this character. A red "!!" means the spell does not exist at all, usually a typo or a deprecated ID. Hover a flagged row for the full list. Structural nodes like Loops and If branches inherit badges from anything flagged inside them, so nothing hides behind a collapsed group.
  • Numeric spell IDs in macros now render as the localized spell name in the step list. /cast 34026 displays as Kill Command while your stored macro stays exactly as you wrote it. Works inside conditional brackets, /castsequence reset= clauses, and /castrandom.
  • Keybind capture accepts mouse buttons (Button4 up through Button31, covering standard and extended mice) along with mouse wheel up and down. Left-click and right-click without a modifier are blocked from capture so normal UI clicks do not accidentally become bindings.
  • Validation badges stay in sync with your spellbook. When you learn a spell, respec, or swap specs, the client re-scans, the validator re-runs, and the outline and detail pane refresh their badges on their own.

Fixed

  • Editor keyboard shortcuts no longer taint the UI during combat. Having the editor open when combat started could cascade ADDON_ACTION_BLOCKED errors to other frames; shortcuts are now suspended in combat and the game gets every keypress normally.
  • Plain left-click and right-click without a modifier could be captured as keybinds, and the resulting bindings fired on every UI click. Those two buttons now require at least one modifier (Alt, Ctrl, or Shift) during capture.
  • Legacy import no longer errors when the Settings module is not ready yet. The MS-to-click conversion falls back to the default click rate rather than crashing.

Internal

  • .luacheckrc and wow.toml: added GameTooltip_Hide to the WoW globals list for both luacheck and selene.
  • Stylua reformats in SequenceEditor (multi-line CR_BLOCK_HEIGHT calculation, crElements table literal).
  • GameTooltip_Hide single-liner replaces an explicit OnLeave closure on the Hold Mode checkbox.

[v1.9.2] - 2026-04-14

Fixed

  • FS_ADJUSTED chat spam: demoted notification to Debug channel with a 60-second cooldown keyed by spec and sequence name. Cooldown timestamps now live in memory instead of SavedVariables, so /reload does not block the gate. One-shot scrub removes the legacy _lastAdjustedNotify field from character data on load.
  • TempoAdvisor numeric spell-ID classification: spells referenced by numeric ID in macrotext (e.g. 34026 Kill Command) now resolve to the correct ON_GCD_INSTANT category instead of falling through to OFF_GCD.
  • GRIP1 single-sequence import: bundled variables were silently dropped on paste-frame single-sequence payloads. Variables now extract correctly, matching the collection branch.
  • SpellValidator numeric IDs: /cast 34026 and similar numeric references now resolve to spell names via C_Spell.GetSpellName before validation instead of being flagged UNKNOWN.
  • Action tree recompilation: imported sequences now clear action trees so the engine uses pre-compiled flat steps with correct interleave ordering.
  • Legacy import variable syntax: double-tilde variable references from older formats now convert to single-tilde on import.
  • ActionCompiler IF-node: strips /cast prefix from branch macros before conditional assembly, preventing doubled /cast output in conditional steps.

Added

  • GRIP1 v5 export format: sequences now bundle their variable definitions and context overrides. Imported payloads carry variables with name and function validation, duplicate detection, and fingerprint-based status badges (new, identical, different) in the import preview.

Internal

  • GRIP_FORMAT_VERSION bumped from 4 to 5.
  • 4 new ActionCompiler IF-node tests in TestSuite (true-only, true+false, complex multi-action, IF inside loop).
  • Import commit path tracks context override import counts for both collection and single-sequence formats.

[v1.9.1] - 2026-04-12

Added

Tempo Advisor (Faster/Slower)

  • TempoAdvisor engine (Engine/TempoAdvisor.lua): per-sequence click rate analysis with 3-tier model -- theoretical GCD timing, per-sequence stored recommendations, adaptive learning from ExecutionTracer play data
  • TempoOverlay HUD (UI/TempoOverlay.lua): movable dark-themed overlay showing Faster/Slower guidance, live CPS, recommended MS, off-GCD step count, confidence level (Estimated vs Calibrated), and sparkline history
  • Empirical calibration after 30 play samples (0.7 theory / 0.3 empirical blend with CLEU staleness detection)
  • Audio alerts on tempo mismatch (too fast / too slow, opt-in)
  • Settings panel: Faster/Slower section with mode selector, buffer slider, Hold Mode CVar toggle
  • /gems fs slash command (status/on/off/reset)

Interleave / Weave

  • Interval property on Action nodes -- interleave a spell every N steps at compile time
  • ActionCompiler two-phase weave (works inside Loop blocks)
  • StepListView detail pane: interleave checkbox + interval spinner (2-50 range) with inline [IL:N] row indicator
  • Legacy import preserves Interval from Repeat actions as node property (no more data loss on import)

Import Quality

  • Checksum validation on import (DJB2 hash, non-blocking warning on mismatch, nil checksums skipped)
  • Sequence disable toggle: disabled sequences import as dormant, show [Disabled] suffix and 0.3 alpha icon, right-click Enable/Disable in sequence list context menu
  • Pause field names corrected (MS/Clicks matching source format, GCD-string values default to 2 clicks)
  • Pet ability (/cast) and Toy (/use) sub-type import branches
  • MetaData (Author, SpecID, Icon) now read on clipboard import path

Other

  • Human-readable text export for forum/Discord sharing (metadata, numbered steps, KeyPress/KeyRelease, variables with event names)
  • /gems resetui: reset window position and size to defaults
  • Migration report distinguishes dormant vs active sequence counts

Fixed

  • /gems resetui persistence: empty table instead of nil so OnHide saves the reset position correctly (BUG-057)
  • CvarProfileManager IsCVarSecure: unpack GetCVarInfo positional returns instead of table indexing (was always returning false)
  • TempoAdvisor CPS source: use Engine:GetButtonPressRate() instead of CLEU spell timestamps (~0.3/sec vs actual ~2.8/sec)
  • StoreRecommendation: field-by-field merge instead of table replace (was wiping empirical blendedMs/totalSamples data)
  • Faster/Slower clickTimes threshold: 10 -> 3 (CLEU only yields 4-6 entries per 10s window, old threshold was unreachable)
  • Phantom eng.activeSequence: replaced with eng._lastClickedSequence in PrintStatus, LDB tooltip, and UpdateBroker
  • SetPropagateKeyboardInput taint: pcall wrapper in SequenceEditor OnKeyDown prevents ADDON_ACTION_BLOCKED in combat
  • Micro-stutter: UNIT_SPELL_HASTE player-only filter (was firing for all nearby units), reusable tables in AnalyzeSequence, OnUpdate replaced with C_Timer.NewTicker, incremental GC
  • blendedMs overwrite guard in StoreRecommendation merge loop
  • Hold to Cast CVar description: clarified native ActionButton scope

[v1.9.0] - 2026-04-07

Added

CVar Dashboard

  • CvarProfileManager (Data/CvarProfileManager.lua): 4 built-in profiles (Raid, M+, Solo, PvP) with context-aware auto-switching via ZONE_CHANGED_NEW_AREA, manual profile selection, per-CVar auto-fix opt-in, and "What Changed?" login detection comparing cvarSnapshot to current values
  • Defaults.lua: D.CVAR_SECTIONS data-driven architecture replacing D.RECOMMENDED_CVARS -- 212 unique CVars across 13 sections with per-CVar metadata (description, critical flag, recommended value, category). D.CvarMatch() float comparison helper for tolerance-aware CVar validation
  • SettingsPanel CVar Dashboard tab: full scrollable UI with per-section grouping, live current/recommended value display, individual Fix buttons, per-CVar auto-fix toggles, health score header, profile selector dropdown, and "What Changed?" notification banner
  • /gems cvar slash command for profile management from chat
  • /gems status now shows CVar health summary (OK/warn/critical counts) using new CVAR_SECTIONS format
  • Per-CVar auto-fix on login (replaces blanket auto-fix of all recommended CVars) -- only user-opted CVars are touched
  • Combat-safe CVar writes gated behind InCombatLockdown() check

Dynamic SQW Optimizer

  • SQWOptimizer engine (Engine/SQWOptimizer.lua): real-time SpellQueueWindow optimization using EWMA latency smoothing with outlier rejection, GCD-aware haste tracking, hysteresis to prevent flapping, click rate advisory, and automatic PLAYER_LOGOUT restore to user's original SQW value
  • SettingsPanel SQW dashboard: 4 header widgets (enable toggle, sensitivity slider, live SQW display, click rate advisory badge), per-CVar managed badge integration, Fix button guard, auto-fix skip for optimizer-managed CVar
  • /gems sqw slash command for optimizer status and manual control
  • /gems msadvisor now uses live optimizer data (EWMA latency, current GCD, applied SQW) when optimizer is active, falling back to raw GetNetStats/GetHaste when inactive

Repair Module Enhancements

  • Fix All button in single-sequence repair view with live fixable-issue counter, undo support (full sequence snapshot before batch fix), and automatic re-analysis after all fixes applied
  • UpdateFixAllState tracks remaining fixable issues and disables button when none remain

Localization

  • 448 GEMS_CVAR_* locale string stubs added to all 10 machine-translated locale files (deDE, esES, esMX, frFR, itIT, koKR, ptBR, ruRU, zhCN, zhTW) -- marked --MT for community reviewer tracking
  • enUS source strings for all CVar section headings, descriptions, SQW optimizer UI labels, and profile names

[v1.8.0] - 2026-04-07

Added

Repair Module

  • RepairAnalyzer backend (Data/RepairAnalyzer.lua): 13 diagnostic categories (spells, structure, limits, variables, keybinds, macros, engine, metadata, context, actions, locale, import, performance) with per-issue severity (critical/error/warning/info) and one-click fix closures
  • RepairFrame UI (UI/RepairFrame.lua): popup window for reviewing and fixing issues per-sequence or batch across all sequences, grouped by category with expandable rows and Fix / Fix All buttons
  • Health score overlay in sequence list -- color-coded numeric badge (green >= 80, yellow >= 50, red < 50) on each sequence icon
  • Context menu "Repair" option in sequence list right-click menu
  • /gems repair slash command -- analyze and open repair UI for a single sequence (falls back to selected sequence if no name given)
  • /gems repairall slash command -- analyze all sequences and open batch repair UI
  • Pre-export repair warning -- StaticPopup warns when selected sequences have critical or error issues before exporting
  • Pre-send repair warning -- StaticPopup warns before P2P sending sequences with critical or error issues
  • Post-import repair notification -- chat message with issue count after importing sequences with detected problems

Testing

  • TestSuite.lua wired into GRIP-EMS.toc and BigWigs .pkgmeta packaging
  • Expanded test coverage across multiple categories

Fixed

  • DebugWindow:Add corrected to AddMessage in OOCQueue restriction logging

[v1.7.3] - 2026-04-06

Added

Machine Translation (P9-A)

  • 10 locale files machine-translated from enUS (deDE, esES, esMX, frFR, itIT, koKR, ptBR, ruRU, zhCN, zhTW) -- 795 strings each, all marked -- MT for community reviewer tracking
  • Blizzard-official game terminology sourced from GlobalStrings database
  • Pre-commit hooks updated with UTF-8 encoding for CJK/Cyrillic support

Per-Sequence Reset Modifier Overrides

  • Sequences can now override global reset modifier settings with per-sequence toggles in the editor header
  • Engine reads per-sequence overrides at activation and live-update time, falling back to global settings for unset modifiers

Variable Locale Safety (Phase 2f)

  • Variables with spell-name values are now tagged with spell IDs and source locale on evaluation
  • HealLocaleVariables restores variable values when switching game language, mirroring step-level locale healing
  • Export picker shows locale risk warning when selected variables contain locale-dependent spell names

ConsolePort Integration

  • Keybind tab detects ConsolePort bindings and warns on conflicts
  • ConsolePort added to luacheck/selene globals

Restriction State Awareness

  • OOCQueue now tracks ADDON_RESTRICTION_STATE_CHANGED events into GRIPEMS.restrictions table with debug logging
  • TrackerHUD shows amber restriction label (M+, Encounter, PvP) when addon restrictions are active

Import Resilience

  • Serialization.Decode logs format detection failures to DebugWindow
  • Import statistics tracked in SavedVariables (importStats per format)
  • GRIP1 imports log source locale for cross-locale awareness

Testing

  • testlocale expanded with item, toy, apostrophe, colon, empty conditional, and multi-branch edge case tests
  • Test/TestSuite.lua added (automated test framework)

Changed

  • Pre-commit hooks use explicit UTF-8 encoding for all file operations
  • StepListView action-tree move operations corrected for node swap

[v1.7.2] - 2026-04-06

Fixed

Tree-Mode Editor (BUG-060)

  • Action bar buttons (Del, Dup, Up, Down) now correctly operate on the action tree in hierarchical sequences instead of silently targeting the flat step array
  • Node badge rows (If/Loop/Embed) can now be manipulated via action bar buttons, not just right-click context menus
  • Button enable/disable states are now tree-mode-aware, reflecting the selected node's position in the action tree
  • Outline selection is now mutually exclusive: clicking a step row clears node badge highlight and vice versa

Slash Command (BUG-061)

  • /gems now opens the main UI on first use without requiring a prior minimap or compartment button click

[v1.7.1] - 2026-04-06

Added

P2P Block List

  • Block and unblock players from sending you sequences via peer-to-peer transmission (/gems block, /gems unblock, /gems blocklist)
  • Blocked players are silently dropped on receive -- no error messages sent back to the sender
  • Settings panel section for managing blocked players with add/remove inputs and live display
  • Account-wide storage in SavedVariables (persists across characters)

Keybind Migration

  • /gems migrate now transfers per-spec override keybinds from your previous sequencer alongside sequences
  • Conflict detection: existing keybinds are preserved unless overwrite mode is active
  • Action bar override warning: counts source action-bar bindings that cannot be migrated (EMS uses keybind overrides instead) with guidance to rebind via /gems bind
  • Migration report includes keybind summary line (migrated/skipped/conflicts)

Export Enhancements

  • "Copy as Text" button in the export picker: generates a human-readable plain-text summary of selected sequences (step function, reset conditions, keybinds, steps, KeyPress/KeyRelease, variable dependencies)
  • Side-by-side comparison now shows a metadata strip above the diff panels (step function, reset conditions, icon, context versions) with change highlighting for quick difference spotting

Changed

  • Interface version updated to 120005 (WoW 12.0.5)
  • ComparisonFrame:Show() accepts optional metadata tables for left/right panels
  • SequenceList compare context menu passes metadata through to ComparisonFrame

[v1.7.0-Beta] - 2026-04-03

Added

Steps Tab Redesign (S30-FEAT-01)

  • Outline + Detail Pane pattern: left column shows flat steps and structural node badges, right column opens on node click with breadcrumb drill-down navigation

  • 5 structural node types: Action (spell step), Loop (cycle, blue), Pause (bars, yellow), If (conditional, purple), Embed (reference, green) with colored badge icons

  • Breadcrumb navigation with truncation at depth 5+ (first segment, ellipsis, last 2 segments)

  • Context-sensitive detail pane with child node list and toolbar

  • Add context menu shared between outline action bar and detail pane toolbar, supporting flat steps and all 4 structural node types

  • Flat-to-actions migration: one-click conversion of flat step sequences to the action tree model with full undo support

  • Drag-to-reorder for both outline rows and detail pane children with ghost frame and insertion indicator

  • Auto-focus name EditBox on structural node creation

Editor Enhancements

  • Syntax highlighting for macro commands in step edit boxes (UI/SyntaxHighlight.lua)
  • Spell autocomplete via Tab key with spellbook search dropdown (UI/SpellPicker.lua)
  • Undo/redo system (Ctrl+Z / Ctrl+Y) for step editing, drag operations, and structural changes (UI/UndoStack.lua)
  • Popup editor for quick sequence editing from the sequence list (UI/PopupEditor.lua)
  • Side-by-side sequence version comparison viewer (UI/ComparisonFrame.lua)
  • Action tree compiler for node-to-macrotext compilation (Engine/ActionCompiler.lua)
  • Compiled preview Copy button strips WoW color codes for clean clipboard text
  • 6 configurable editor colours in Settings > Editor Colours for macro commands, conditionals, variables, comments, reset, numbers
  • Multi-window popup editor system (frame pool max 4, independent dirty state, cascade offset, sequence sync via SEQUENCE_UPDATED)
  • Tab-autocomplete: sequence name fallback in step editor in addition to existing variable autocomplete
  • Dependency visualization in metadata panel (variable/sequence refs, found/missing status, reverse "Embedded by" lookup)
  • Per-editor undo stacks in PopupEditor (Ctrl+Z/Y undo/redo, Alt+Up/Down move steps, Up/Down step nav)
  • Ghost snap-back animation on drag cancel (lerp interpolation with alpha fade in StepListView)
  • Inline clipboard (hidden EditBox Ctrl+C flow, falls back to ExportFrame on failure)
  • Rich spell/item tooltips on step list rows (SetSpellByID, SetItemByID, keybind hint line)
  • Empty state illustration for sequence list (icon + label + hint when no sequences exist)
  • Macro stub body viewer (collapsible section showing BuildStubBody output)
  • Metadata description multi-line EditBox
  • Context Tab import origin indicator (imported vs user-created versions visually distinguished)
  • Scroll-during-drag in step list (auto-scroll near ScrollBox edges)
  • Mouse wheel scroll in KeyPress/KeyRelease EditBox fields

Engine Modules

  • Action bar icon override for Blizzard, ElvUI, and Bartender4 bars with per-step icon updates (Engine/BarIntegration.lua)
  • Vehicle, skyriding, and pet battle keybind auto-suspension extracted to dedicated modules (Engine/VehicleKeybinds.lua, Engine/PetBattleButtons.lua)
  • Execution tracing diagnostics (Engine/ExecutionTracer.lua)
  • Macro recorder module (Engine/MacroRecorder.lua)
  • Plugin registration API for third-party addon integration (Core/PluginAPI.lua)
  • Gear change variables with bag and equipment tracking (Data/GearVariables.lua)
  • MS click rate slider (global + per-character, Settings > General)
  • Configurable macro reset modifiers (15 individual modifier toggles)
  • CVar management panel (auto-fix + status display in Settings)
  • OOC queue priority + deduplication (replaces simple FIFO)
  • AddOnRestrictionType-aware OOC queue (checks beyond InCombatLockdown for addon-restricted states)
  • Configurable OOC timer delay (Settings > oocDelay, 1-60s, default 7)
  • Variable event dropdown (75 curated events, categorized submenu)
  • Function-type variable evaluation cache (compiled function caching in VariableStore for performance)
  • Hierarchical actions: If/Loop/Embed nesting (ActionCompiler flattens to linear steps, per-type UI renderers in UI/ActionRenderers.lua)
  • Spell picker dropdown with condition builder for step editing (UI/SpellPicker.lua, integrated into step editor)

Context Switching

  • 28 per-map context keys for arenas (15) and battlegrounds (13) via instanceMapID detection with rated-type priority
  • Battleground Blitz detection via C_PvP.IsSoloRBG() with fallback chain (BattlegroundBlitz > RatedBG > PVP)
  • 53 total context keys (up from ~20 in v1.1.6)
  • /gems mapinfo diagnostic command for live context detection
  • 9 new context keys (25 total): M+ tier detection (Low/Mid/High), PvP rated split (RatedArena/SoloShuffle/RatedBG), Delve tier detection (Low/High), Timewalking raid split
  • Select All/Clear All buttons per context group header
  • Visual fallback chain indicator (color-coded resolution path)
  • Configurable M+/Delve threshold sliders in Settings > Context

Import/Export

  • Raw text import path for plain macro paste (Import/RawImport.lua)
  • Tab-autocomplete for ~variable~ and sequence name insertion in step editor
  • /gems import now handles collection strings (multi-sequence + variables) via Preview path instead of failing (BUG-055)
  • CopyVersion() utility for safe per-version deep copy, replacing whitelist pattern that missed keyPress/keyRelease fields
  • Pause conversion (3-mode: Clicks/GCD/MS compiled to empty steps)
  • Action interval interleaving on import
  • Import conflict Compare option with visual diff
  • SequenceList "Compare with..." context submenu
  • Variable dependency auto-check on import (ResolveImportVariableDeps)
  • Export metadata editor stage (collection name, author, description, URL, talent string embedding with per-field toggles)
  • Icon suggestion utility (SuggestSequenceIcon auto-detects from spell content)
  • Freeform macro import warning (auto-detect raw /cast patterns, count display in import preview)

Quality of Life

  • Floating menu bar with movable shortcut icons (UI/FloatingMenu.lua)
  • Remote sequence browser for P2P shared sequences (UI/RemoteBrowser.lua)
  • Spell cache diagnostic viewer (UI/SpellCacheViewer.lua)
  • ContextTab group collapsed/expanded state persists across sessions
  • DebugWindow closes with ESC key (UISpecialFrames registration)
  • Clear Overrides confirmation dialog in SpellCacheViewer
  • SwitchVersion prompts Save/Discard/Cancel when switching versions with unsaved edits
  • MainFrame position restoration validates SavedVariables anchor strings with graceful fallback to CENTER
  • LibQTip-2.0 tooltip library added
  • P2P transmission: metadata-only sync, spell cache broadcast, chat links with clickable import, recipient autocomplete, cross-server
  • Corrupt sequence recovery (StaticPopup chain: Delete/Skip/Export Raw)
  • WagoAnalytics deep integration (sequence/import/export/feature events)
  • Support/About page in Settings (version, links, system info)
  • Developer utilities: /gems compress, /gems decompress
  • Click rate diagnostics (/gems status shows clickRate metrics)
  • Optimal MS advisor (/gems msadvisor, analyzes sequence timing)
  • Gamepad keybind capture (EnableGamePadButton + OnGamePadButtonDown, 32 button display names, ConsolePort addon detection)

Localization

  • 10 locale stub files added (deDE, esES, esMX, frFR, itIT, koKR, ptBR, ruRU, zhCN, zhTW) with framework for community translation
  • Spell replacement chain normalization: base spell names heal to active talent-replacement names (e.g. Steady Shot to Barbed Shot)
  • AceLocale-3.0 localization framework (11 locale files, 591 strings across 65 categories, community translation contribution path)
  • Locale risk detection: compile-time spell-name flagging with localeRiskFlags in VariableStore
  • Variables Tab locale warning banner (yellow icon for risky variables, suggests C_Spell.GetSpellName alternative)
  • Separate events-enabled toggle per variable (eventsEnabled field, independent of event string content)
  • 3 locale string wiring fixes (stub preview, empty hint, keybind hint)

Testing

  • 25 unit tests across 8 categories in Test/TestSuite.lua (stepfunc, compiler, reset, import, export, serialization, variables, engine)

Fixed

  • P2P metadata sync non-functional: SendSequenceMeta and CMD_META handler accessed fields on wrapper table instead of wrapper.data, always sending updatedAt=0 and help="" (NEW-HIGH-01)
  • UndoStack _suppressUndo permanently stuck true on callback error, disabling undo for the rest of the session (NEW-HIGH-02)
  • HandleDiag and HandleMSAdvisor used invalid setting keys, always returning 250ms default click rate (NEW-MED-01)
  • SpellCache spell-name overrides had no effect due to wrong AceDB path (read GRIPEMS.db instead of GRIPEMS.Settings.db) (NEW-MED-02)
  • SpellCacheViewer Clear Overrides also targeted wrong db path, making the button non-functional (HIGH-14)
  • SpellValidator load-time constant could crash if TOC load order ever changed (NEW-HIGH-03)
  • SettingsPanel early D binding could crash on TOC reorder (NEW-MED-03)
  • MacroManager DeleteStub substring match could delete wrong macro stub when one sequence name was a prefix of another (HIGH-03)
  • Cross-realm chat links fell through to remote request path due to missing Ambiguate normalization on player name (HIGH-01)
  • SwitchVersion silently discarded unsaved step edits (HIGH-04)
  • StepFunctions modulo-by-zero on empty sequences: Sequential returned NaN, Random errored (MED-38)
  • TrackerHUD GetActiveVersion nil crash on corrupt version data (MED-40)
  • TrackerHUD name truncation off-by-one: displayed 9 chars instead of max 8 (MED-24)
  • UndoStack Push accepted nil or non-function callbacks, causing delayed crash on Undo/Redo instead of immediate caller error (HIGH-11)
  • MainFrame RestorePosition crashed on corrupt SavedVariables anchor string (HIGH-05)
  • UpdateEditArea SH hook race: programmatic SetText triggered SyntaxHighlight colorization, corrupting step data (S29-BUG-05)
  • Autocomplete color code corruption from SyntaxHighlight focus hooks splicing colorized text into plain-text cursor positions (S30-BUG-01)
  • Flat sequences forced into tree mode after /reload due to unconditional auto-migration in Engine:LoadSequences (S30-BUG-02)
  • ShowRenameDialog whitelist missed keyPress/keyRelease fields on version deep-copy
  • Removed Test/TestSuite.lua from TOC load list (file excluded from packages via .pkgmeta, caused load warnings for installed users)

Changed

  • Branding: legacy import modules renamed to LegacyImport.lua and LegacyMigrate.lua. Module tables, aliases, functions, parameters, variables, and locale keys updated. Functional wire format references preserved
  • C_TooltipInfo API migration (GetItemByID/GetSpellByID with fallback)
  • MoveStep undo closures inlined (direct table swap)
  • Dead DRAG_SCROLL_SPEED constant replaced with DRAG_SCROLL_INCREMENT
  • OOCQueue now checks AddOnRestrictionType beyond InCombatLockdown
  • EDITOR_HEADER_HEIGHT reduced from 220 to 200 (dark EditBox contrast fix)
  • Preview icon strip edge fade textures on both sides (layout fix)
  • Deprecated split-pane UI code removed: RefreshTreeMode, stale Hide() calls, _ensureSplitPaneElements
  • ComparisonFrame OnUpdate skips when frame is hidden (NEW-MED-04)
  • PopupEditor callbacks unregistered on release instead of dispatching to idle instances (MED-37)
  • ReclaimFrame clears 12 scripts on recycle instead of 8, adding OnEnter, OnLeave, OnClick, and OnTextChanged (MED-20)
  • SequenceEditor callbacks skip refresh when editor panel is hidden (MED-14)
  • GearVariables event frame reused on /reload instead of orphaned (NEW-LOW-02)
  • MacrosTab overflow FontString uses create-once/reuse pattern instead of leaking a new FontString per refresh (NEW-LOW-03)
  • Export version prep deduplicated into shared PrepareExportVersions helper (NEW-MED-11)
  • SpellValidator validation counting deduplicated into AccumulateCounts helper (NEW-MED-06)
  • nameTooltipFrame dead overlay removed, tooltip moved directly to nameEditBox (NEW-LOW-01)
  • Duplicate locale key consolidated to GEMS_SEND_NO_SEQ (NEW-LOW-06)
  • KeyPress/KeyRelease tooltip descriptions clarified with per-step fit behavior explanation (MED-UX)
  • 5 tooltip strings standardized for tone and accuracy (S28-39)
  • README slash commands updated to 26 entries (S28-37)
  • .pkgmeta now excludes Test/, Prompts/, and internal dev folders from user packages (NEW-MED-07)

Internal

  • S28 Full Code Audit: 38 findings resolved across 4 tiers (see Backlog.md for itemized list with completion dates and evidence)
  • stylua reformat on 38 files (120 col, 4-space indent, Unix LF)
  • Selene pinned to v0.30.1 in lint.yml with fail-fast download (CI-MED)
  • .luacheckrc redefined warnings re-enabled with targeted 432/self suppression and 5 inline exceptions (NEW-MED-10)
  • wow.toml: 6 missing globals added (gsub, gmatch, getfenv, setfenv, rawlen, GetSpecializationInfoByID) (NEW-MED-08)
  • luacheck 0 warnings / 0 errors across 65 shipped files
  • Phantom method check: SLV 53 methods, SE 42 methods -- all clean
  • ActionRenderers.lua retained for future extraction (sole caller RefreshTreeMode deleted in S30 Phase 3)
  • New files: UI/ComparisonFrame.lua, UI/PopupEditor.lua, UI/SyntaxHighlight.lua, Core/PluginAPI.lua, Engine/MacroRecorder.lua, UI/RemoteBrowser.lua, Engine/ActionCompiler.lua, UI/ActionRenderers.lua, Engine/VehicleKeybinds.lua, Engine/PetBattleButtons.lua, Engine/BarIntegration.lua, UI/SpellPicker.lua, UI/FloatingMenu.lua, UI/SpellCacheViewer.lua, Import/RawImport.lua, Data/GearVariables.lua, Engine/ExecutionTracer.lua, Test/TestSuite.lua, UI/UndoStack.lua, 11 Locale/*.lua files
  • UndoStack module for per-instance undo/redo
  • BuildSeqDataFromGRIP1 shared helper eliminates import path drift
  • 28 sessions of parity work across 9 tiers (24 DONE, 4 PARTIAL, 0 DEFERRED)

[v1.1.6] - 2026-03-30

Added

  • Locale-safe SavedVariables: spell names in sequence steps are now backed by spell ID tags, enabling automatic recovery when the WoW client language changes. Existing sequences are migrated transparently on first load
  • Automatic locale healing: on login, if the client language differs from the language used when sequences were last saved, step text is automatically retranslated from spell IDs to the current language
  • Item and toy name translation: /equip, /equipslot, and /usetoy commands now participate in locale-safe tagging alongside /cast, /use, and /castsequence
  • Item cache built from bags and equipped gear, refreshed automatically on inventory or equipment changes
  • Toy cache built from the player toy collection (account-wide)
  • /gems testlocale command: runs a 9-spell round-trip tagging test plus a locale healing simulation to verify the translation pipeline
  • /gems revalidate command: force re-tags all sequences from current spell names (recovery tool for edge cases like spell renames between patches)

Internal

  • GRIP_FORMAT_VERSION bumped to 3 (adds taggedSteps, stepsLocale per version)
  • LOCALE_STORE_VERSION 1 for migration gating
  • SpellCache.lua expanded with item/toy caches, 3 tag formats (spell, item, toy), and unified TranslateSpellRef for bidirectional name-to-ID translation
  • Import path strips taggedSteps on export, captures on GRIP1 import
  • SPELL_CACHE_REFRESHED callback drives both migration and healing

[v1.1.5] - 2026-03-30

Added

  • Sequence metadata editor: collapsible section in the editor header with 4 editable fields (Author, Description, Help Text, Help Link) and 4 read-only fields (Class, Spec, Created, Updated). Wired to dirty-state save/discard and persisted through GRIP1 export/import
  • Drag-to-reorder steps in the editor: drag handle on each step row, ghost frame during drag, insertion indicator between rows
  • GRIP1 collection import: multi-sequence and variable payloads in a single export string
  • Import deep content comparison: fingerprint-based detection shows "identical" (grey) or "different" (yellow) badges when an imported sequence already exists, replacing the binary exists/new check
  • Legacy import mapping for Help and Helplink metadata fields

Fixed

  • GRIP1 variable export field name mismatch: description field now correctly reads from comments key with description fallback (BUG-056)
  • TrackerHUD nil guard: specID tooltip no longer errors when spec data is unavailable
  • CommitSelected metadata passthrough: both GRIP1 export paths now include full sequence metadata

Changed

  • Import frame restyled with native dark theme matching the export frame visual style

Removed

  • Dead SpellCache:IsValidSpell method (21 lines, zero callers)

Internal

  • Added tContains to selene wow.toml globals
  • Core.lua migration adds help/helplink defaults to existing sequences

[v1.1.4] - 2026-03-29

Added

  • Rotation preview: horizontal fade gradients on the icon strip edges indicating scrollable content when icons overflow

Fixed

  • Spell validation: /cast and /use lines with semicolon-delimited conditional branches now extract every spell instead of only the first token. Sequences using Secure Command Options (e.g. /cast [mod:alt] Spell A; Spell B) now validate all branches
  • Spell validation: issecretvalue() guard on C_Spell.DoesSpellExist prevents a potential Lua error if Blizzard adds taint annotations to the return value in a future patch

Changed

  • Import frame restyled with dark theme (native CreateFrame + BackdropTemplate) matching the export frame visual style
  • Context tab scroll area now resizes correctly when the editor window is resized

[v1.1.3] - 2026-03-29

Fixed

  • Import: /use inventory slot numbers no longer resolved as spell IDs, eliminating false "exceeds macrotext limit" warnings on sequences using trinket slots (BUG-046)
  • Spell validation: "null" placeholder in /castsequence recognized as valid no-op instead of flagged as unknown (BUG-047)
  • SpellCache: removed shouldHide filter that excluded castable spells from hidden skill lines (Hunter Pet Utility, Warlock summon, etc.) (BUG-048)
  • SpellCache: flyout children (Call Pet 1-5, summon spells) now cached using generic castable names instead of pet-specific display names (BUG-049)
  • Step editor: editBox byte limit corrected from 1023 to 255 to match the SAB macrotext limit (BUG-050)
  • Spell validation: /use with pure numeric arguments skipped as inventory slot references instead of validated as spell names (BUG-052)
  • Preview icons, TrackerHUD, and sequence list now show rotation spells instead of housekeeping spells. ParseSpellFromMacrotext rewritten with two-tier priority: unconditional or [combat] lines preferred over conditional housekeeping lines (BUG-053)
  • SpellCache: added UNIT_PET and PET_BAR_UPDATE event registration for prompt rescan on pet summon, dismiss, or death (BUG-054)
  • Export frame: ESC now closes only the export overlay instead of the entire addon window. Uses keyboard intercept instead of UISpecialFrames
  • Spell validation: "!" anti-toggle prefix (/cast !Moonkin Form) stripped in CleanSpellToken so toggled spells validate correctly
  • Spell warning banner tooltip anchors to mouse cursor instead of the banner frame for better readability
  • Cosmetic #showtooltip entries in spell warning tooltip now appear after the 10-entry truncation line instead of being silently cut
  • Debug log: gear-reset and spec-reset messages now include previous step number and equipment slot for diagnostics

Changed

  • CHANGELOG v1.0.1 BUG-009 entry corrected: SAB limit is 255 post-11.0.2, not 1023 (BUG-051)

[v1.1.2] - 2026-03-28

Added

  • Export Frame dark theme: native CreateFrame replacing AceGUI Frame, dark navy background, themed title bar and buttons, dark scrollBG on display stage editbox (A1)
  • Single-sequence export variable inclusion: right-click Export on a sequence with ~var~ references opens Export Multi picker with that sequence pre-selected and variable deps auto-checked with gold "auto" badge. Direct display (no picker) when no variables. /gems export slash command supports both paths (A2)
  • #showtooltip spell validation: ExtractAllSpells now parses #showtooltip and #show lines as cosmetic "tooltip_stale" category. Dimmed grey entries in spell warning banner tooltip. Does not inflate staleCount or trigger the yellow banner by itself. Bare #showtooltip (no args) ignored. "!" anti-toggle prefix stripped in CleanSpellToken (A3)
  • Copy Preview Text button: text-mode Rotation Preview shows a Copy button that routes through ExportFrame display stage for clipboard access. Hidden in icon-strip mode (B1)
  • SPELLS_CHANGED live revalidation: two-hop callback chain -- SpellCache fires SPELL_CACHE_REFRESHED after Scan(), SpellValidator throttles (1.0s debounce) and revalidates, fires SPELL_VALIDATION_UPDATED. SequenceEditor banner and SequenceList overlays update live on spec swap or talent change. Dual debounce (0.5s cache + 1.0s validation) prevents rapid-fire revalidation (B2)

Fixed

  • nameEditBox anchor chain: replaced hardcoded -280/-155 pixel offsets with right-to-left button chain from header TOPRIGHT (sendBtn -> exportBtn -> discardBtn -> saveBtn). nameEditBox RIGHT anchors to saveBtn (dirty) or exportBtn (clean). Eliminates magic numbers, scales with window resize (C1)
  • KeybindTab scroll panel: specContainer wrapped in UI:CreateScrollPanel(). Scroll activates only if class has more than 4 specs (future-proofing). Visually unchanged for current classes (C2)
  • Tooltip edge clamp: UI:ShowTooltip() now checks right edge of UIParent after GameTooltip:Show() and flips anchor to TOPRIGHT->TOPLEFT when tooltip would clip off-screen (C3)

Changed

  • Channel protection: new sequences default to /stopmacro [channeling] in keyPress template (B3, implemented in v1.1.1)

[v1.1.1] - 2026-03-28

Fixed

  • Locale key mismatch causing nil tooltip for Reverse Priority step function description (BugSack error at SequenceEditor tooltip builder)
  • Bare sort() replaced with table.sort() for Lua best practice consistency

Changed

  • Engine: extracted ResolveFitAndExpand helper, deduplicating resolve-fit-expand logic across Priority and ReversePriority paths in ActivateSequence and RecompileSequence (-33 lines)
  • Core: new D.NewSequenceFromTemplate() factory replacing 31-line manual field copy in HandleCreate
  • UI: centralized ResolveIcon, CreateScrollPanel, and ApplyBackdrop helpers in Util.lua, replacing duplicated patterns across 15 files (-100+ lines)
  • Removed dead OnChar callback in Core.lua (superseded by OnTextChanged)
  • Removed legacy GRIP_EMS_CHAR.config init from ADDON_LOADED (migrated to AceDB)

Internal

  • Full codebase audit: 69 findings resolved across 4 sessions, 26 prompts
  • Robustness: pcall-wrapped AceDB init, friend list iteration, and RestyleAceFrame; nil guards on locale fetch and spell validator module refs
  • Edge cases: field validation on raw tab apply, clamped defaultVersion, macro overflow indicator, type-safe icon handling in TrackerHUD, cross-version tooltip in ContextTab, scroll panel for 5+ spec keybind rows
  • Performance: dirty-flag sort cache, debounced step refresh, O(1) circular ring buffer for debug window, selective diff-based event registration in VariableStore, pre-computed strlower sort keys in SpellCache
  • Leak prevention: callback unregistration on disable, ticker reference storage, tContains guards for UISpecialFrames, known-user pruning in Transmission
  • UX polish: combat-unavailable save tooltip, keybind conflict detection with warning, ESC-cancels-capture hint, read-only indicator on raw tab, split unknown/known spell counts in import preview
  • Dead code removal: 57 unused locale keys, LMETA/RMETA modifier keys, click rate setting remnant in ADDON_LOADED
  • Module-level docstrings on all 36 shipped files
  • Luacheck: 0 warnings / 0 errors across all shipped files

[v1.1.0] - 2026-03-27

Added

  • Stale Spell Detector: validates /cast and /castsequence spells against your spellbook on import, editor open, and via /gems validate. Warning banner in editor header, icon overlay on sequence list entries, step-level status coloring (green/yellow/red), import preview warning count, and batch validation output in chat
  • Rotation Preview Panel: visual preview of your spell rotation below the step list. Dual-mode display (icon strip and text list) with toggle button. Spell icons resolve from spellbook, tooltips show full macrotext on hover, unknown spells show question-mark icon with red tint, variable steps show gray status, horizontal scroll for long sequences. Preview mode persists across sessions
  • Export: transitive variable dependencies auto-selected. If variable A references variable B, selecting a sequence that uses A auto-includes both A and B with "auto" badges in the export picker
  • Export: variable descriptions included in export payload with comments-field fallback for round-trip preservation on import
  • /gems validate slash command for batch spell validation across all sequences

Changed

  • Sort button labels and tooltips now use locale keys (L["GEMS_UI_SORT_*"]) instead of hardcoded English strings
  • ExportFrame: AceGUI close button hidden, replaced with custom styled Close button matching addon dark theme. ESC handler added. Button layout fixed to prevent overlap

Removed

  • Click rate setting removed from Settings panel, Defaults.lua, and locale strings. The Engine has ignored this setting since v1.0.4 (BUG-035 fix). No functional change

Internal

  • New file: Data/SpellValidator.lua (spell validation module)
  • 34 existing files modified across UI, Engine, Import, Data, Core, and Locale modules

[v1.0.9] - 2026-03-26

Fixed

  • Blizzard Settings dark theme: replaced unreliable C_Timer.After(0.5) with HookScript("OnShow") plus zero-delay C_Timer.After(0) deferral for reliable restyle timing. _gripRestyled guard prevents redundant restyle on re-opens
  • UI layout overflow at minimum window size: minimum frame bounds raised from 600x400 to 750x500, EDITOR_HEADER_HEIGHT updated for expanded reset row, button bar widths reduced to prevent sort/migrate overlap, MacrosTab list container switched from hardcoded 600px height to dual-point anchor
  • KeyPress/KeyRelease fields not resizing with window: replaced init-time fixed-width calculation with dual-point anchoring and OnSizeChanged handlers that propagate width to ScrollFrame children
  • Five layout constants in Defaults.lua had incorrect values causing RawTab and VariablesTab clipping at non-default window sizes (VAR_LIST_WIDTH, VAR_FUNC_EDIT_HEIGHT, RAW_STATUS_HEIGHT corrected; RAW_HEADER_HEIGHT and VAR_EDITOR_ROW_HEIGHT confirmed correct)

Added

  • Combined reset syntax: multi-condition resets (e.g. target/combat/5) via new ParseResetString and BuildResetString utilities with RESET_TOKEN_MAP lookup
  • Expanded reset UI: Gear Change and Spec Change checkboxes plus Timer EditBox in the sequence editor header, wired to per-version resetOnGear, resetOnSpec, and resetTimer fields
  • Import mapping: legacy Head field now maps to resetOnGear for gear-swap reset preservation during migration
  • Sort mode persistence: sequence list sort order (A-Z / Class / Recent) saved to AceDB profile and restored on login
  • SwitchVersion and LoadVersionIntoEditor: implementations added for multi-version navigation (previously orphan call sites)
  • TrackerHUD debug filter: early-return guard in OnSettingChanged prevents unnecessary rebuilds for non-tracker settings
  • 6 new locale keys for reset controls (timer label, gear change, spec change, timer placeholder, reset section header, combined reset tooltip)
  • BUG-020 test harness: /gems testspellid command with 7 test cases validating spell ID resolution for capital /Cast, /use alias, and multi-condition blocks

Changed

  • TrackerHUD Toggle() now cycles through all 4 visibility modes (Never to Always to In Combat to Has Target) instead of binary Always/Never flip
  • 9 nil-safety guards added across ExportFrame (3), ImportFrame (3), and StepListView (2) per LUALS-EMS-3 static analysis

Internal

  • Dead locale keys GEMS_TRACKER_ENABLED and GEMS_TRACKER_DISABLED removed (MAINT-17)

[v1.0.8] - 2026-03-26

Fixed

  • Macrotext 255-char limit: spells not firing in combat because keyPress/keyRelease prepended to each step exceeded 255-char SecureActionButton cap. Hybrid per-step fitting now includes keyPress when combined length fits, omits when it overflows (keybind path vs action-bar-click fallback) (BUG-045)
  • Truncation side-effect: "Unknown macro option: mo" caused by mid-token truncation at 255-char boundary (BUG-043, same root cause as BUG-045)
  • TrackerHUD infinite recursion: Rebuild/UpdateVisibility mutual call loop causing stack overflow. Separated concerns (UpdateVisibility now only Show/Hide) (BUG-044)

Added

  • TrackerHUD Phase 1: movable icon overlay for active sequences with 4-mode show dropdown (Always/In Combat/Has Target/Never), active-sequence highlight, scale slider, and per-character position persistence
  • WhatsNew popup: version-gated login popup showing release highlights with dark theme, scrollable content, ESC-closeable, and "Don't show again" checkbox
  • KeyPress/KeyRelease editor fields: dedicated edit boxes in the Steps tab with per-step fit status label and effective character count display
  • Per-step character counter: shows effective macrotext cost including fitted keyPress/keyRelease length per step

Changed

  • Double RefreshDataProvider removed from SequenceList (was causing redundant redraws)
  • Per-keybind rebuild debounce: _initialLoadComplete guard prevents bar-swap events during login from triggering SuspendKeybinds prematurely

Internal

  • lane_sync.json: cross-lane state tracking for Cowork/Code coordination
  • 6 new locale keys for BuildStubBody warnings and KeyPress fit status
  • 2 updated tooltip descriptions for KeyPress/KeyRelease editor fields
  • Diagnostic instrumentation removed (ClickDebugPre/Post, DiagDump, combat-start dump)

[v1.0.7] - 2026-03-25

Fixed

  • Event bus: CallbackHandler registry return was discarded since v1.0.0, leaving all Fire() calls dead. Captured registry and wired Fire method on addon object. 12 event types and 7 consumer modules now receive callbacks (BUG-040)
  • Variable changes now trigger recompilation of referencing sequences (BUG-041, fixed by BUG-040)
  • Import now refreshes SequenceList display (BUG-042, fixed by BUG-040)
  • /gems delete now correctly removes the named sequence (BUG-039)

Added

  • Channel protection: new sequences default to /stopmacro [channeling] in KeyPress template. HandleCreate copies KeyPress/KeyRelease to new versions (BUG-028)
  • KeybindManager fires KEYBIND_CHANGED after successful LoadKeybinds, ensuring UI consumers rebuild on login

Internal

  • TrackerHUD module (UI/TrackerHUD.lua): movable icon overlay for active sequences with step-advance animation, modifier display, and per-character position persistence. Disabled by default (trackerEnabled = false). Internal preview, not user-facing.

[v1.0.6] - 2026-03-25

Fixed

  • Keybind race condition: SetOverrideBindingClick now defers to pendingBinds when the engine button has not yet been created via OOCQueue, then applies in BindIfConfigured once the button exists (BUG-029)
  • Double step advance: changed RegisterForClicks from ("AnyUp", "AnyDown") to ("AnyDown") so WrapScript fires once per keypress instead of twice (BUG-036)
  • Raw tab edits reverted on Save: after ApplyChanges, force-syncs SequenceEditor working copy from newSeqData directly and clears dirty state (BUG-038)

Added

  • Settings panel dark theme: AceConfigDialog standalone window (/gems settings) now uses GRIP dark theme -- dark backdrop, styled tabs, green title text, hidden ornamental chrome, styled Close button (BUG-021)

Changed

  • Import: pet actions compile to /cast PetActionName, toy actions compile to /use ToyName (previously unsupported action types)
  • Import: if-block field resolution checks action.Spell before falling back to action.Actions

[v1.0.5] - 2026-03-25

Added

  • Import preview shows source sequencer version when available in export metadata (MAINT-15)
  • Import stores source format version and checksum as informational metadata on imported sequences (MAINT-15)

Fixed

  • Variable actions from legacy imports now resolve to substitution tokens instead of compiling as literal step text (BUG-024)

Changed

  • LibDBIcon-1.0 updated from v55 to v56 (MAINT-7)

Docs

  • README: fixed context types description to match the 15 actual CONTEXT_KEYS
  • README: removed false claim that keybinds transfer on import
  • README: replaced slash commands table (was 15 commands with errors, now 22 verified against Core.lua)
  • README: added Priority preview and source version display feature descriptions
  • Guide: replaced slash commands table (was 7 commands with errors including dangerously wrong /gems reset description, now 22 correct)
  • Guide: removed false Keybinds row from "What Transfers?" import table
  • Guide: expanded Import Preview section with two-stage UI details, badges, and conflict options
  • Guide: added Reverse Priority Step Function to shipped features roadmap
  • Guide: fixed keybind auto-suspend description (was "boss encounters, PvP arenas", now "vehicles, skyriding, and pet battles")

[v1.0.4] - 2026-03-21

Fixed

  • Click rate throttle freezing step counter during combat: removed insecure PostClick _shouldAdvance gate that could not SetAttribute during combat lockdown, causing Priority mode to stick on one step (BUG-035)

[v1.0.3] - 2026-03-21

Added

  • Locale Phase 1: tag translation at export/import boundaries for cross-locale sequence sharing (GRIP1 format v3)
  • FindSpellOverrideByID scan integration: SpellCache now resolves override spell IDs at scan time for correct name/ID consistency
  • SafeOverrideID bounds guard: pet spellbook actionIDs exceeding INT32_MAX no longer crash FindSpellOverrideByID (BUG-032)
  • /gems testlocale output routed to DebugWindow for easier copy-paste bug reporting

Fixed

  • Import preview showing 0 sequences when export uses Versions key instead of Macros (BUG-031, reported by GauPanda)
  • Semicolon spacing lost in TranslateMacrotext when inner-conditional refs had leading whitespace (BUG-033)
  • Missing locale key GEMS_STEPFUNC_REVERSEPRIORITY_DESC causing nil tooltip text (BUG-034)
  • GetBaseSpellID removed from locale translation path -- was walking full replacement chain and over-normalizing spec spell replacements (BUG-030)

[v1.0.2] - 2026-03-21

Added

  • Reverse Priority step function: inverts priority order so lower-numbered steps are weighted less (BUG-026b)
  • Priority preview in editor: shows numbered expanded step list with char counter for both Priority and Reverse Priority modes
  • Keybind debounce: spec-change events coalesced via ScheduleLoadKeybinds to prevent double-fire (BUG-027)
  • Diagnostic logging for keybind lifecycle: BindIfConfigured miss, LoadKeybinds spec=0 defer, binding counts per spec

Fixed

  • Combat lockup: button went dead after first cast in combat due to useOnKeyDown + 4-arg WrapScript postBody (BUG-026a, reported by Pershizzle)
  • Priority mode broken: multi-line /cast does not fall through on cooldown in WoW; replaced with pre-expansion where N steps become N*(N+1)/2 flat sequential entries (BUG-026b)
  • Variable substitution skipped on first Priority/ReversePriority activation (BUG-025)
  • Keybind lost after /reload: redundant 0.5s timer ClearOverrideBindings wiped bindings that BindIfConfigured already applied; replaced with synchronous LoadKeybinds after RestoreSavedSequences (BUG-027)
  • Keybind silently dropped during combat: BindIfConfigured now queues to OOCQueue instead of returning (BUG-027)
  • Bar-swap events during login could trigger SuspendKeybinds before initial load completed (BUG-027)

Changed

  • WrapScript: switched from 4-arg (preBody + postBody) to 3-arg (body only) for all step functions (BUG-026a)
  • Priority and Reverse Priority use Sequential round-robin cycling over pre-expanded step arrays instead of multi-line macrotext (BUG-026b)

[v1.0.1] - 2026-03-21

Added

  • Interactive HTML guide: rebuilt from scratch (2400+ lines) with 13 sections: welcome, getting started, core concepts, interactive UI tour with clickable mock-up and annotation hotspots, 5 step-by-step tutorials, editor reference, import and migration, slash commands and settings, advanced topics, sequence builder tool, roadmap, FAQ, and community links
  • FAQ section in guide covering 10 common questions
  • Interactive UI mock-up in guide: full clickable replica of the GRIP-EMS editor with 6 working tabs, annotation hotspots, and tooltip explanations for every element
  • Sequence Builder tool in guide: browser-based sequence creation with GRIP1 export for in-game import
  • Quick Start section in README for new users

Changed

  • README: full SEO-focused rewrite with competitor positioning, categorized features, Quick Start section, and migration framed as generic sequencer import (not addon-specific)
  • TOC Notes: replaced addon-specific reference with "context switching" in subtitle
  • 7 locale strings: user-facing import/migration text generalized to "export strings" and "another sequencer" instead of naming specific addons
  • ImportFrame header comment: generalized
  • In-game branding: GRIP green title/notes in addon list, Combat category, rich minimap/compartment tooltips with active sequence count and context display, colored settings panel name

Fixed

  • Imported "Priority List" step function mapped to concatenated Priority mode instead of Sequential cycling, causing rotation spells to not fire (BUG-013)
  • Sequence list empty after import due to scrollView vs scrollBox SetDataProvider mismatch (BUG-007)
  • Sequences not firing: SecureActionButton type="spell" silently blocked in restricted env, changed to type="macro" (BUG-008)
  • OOCQueue spam from icon updates during combat, added InCombatLockdown() guard (BUG-010)
  • Spell IDs not resolved in /cast and /castsequence lines (BUG-011)
  • Priority mode KeyPress/KeyRelease duplication killing rotation spells, now wraps KP/KR once for Priority (BUG-012)
  • AceComm-3.0 missing library files for local development (BUG-003)
  • Duplicate macro stubs on login from sanitized-name key mismatch (BUG-004)
  • Clean Orphans failing due to stale cached macro indices (BUG-005)
  • Editor header button overflow when Export+Send buttons present (BUG-006)
  • Version display showing raw @project-version@ token locally (dev fallback added)
  • Private repository URL removed from about links
  • ESC during key capture no longer closes the GRIP-EMS window (BUG-014)
  • Settings panel Profiles tab now visible via tabbed layout (BUG-015)
  • /gems migrate slash command now triggers migration (BUG-016)
  • Migration imports all sequences: .Versions field mismatch + array unwrap + fallback decode (BUG-017)
  • Macro slot limit corrected to 30 per-character using WoW global (BUG-018)
  • Settings Info shows correct macro slot count (BUG-019)
  • Lua 5.1 goto syntax error in import parser replaced with if/end guard (BUG-020a)
  • D:Debug() nil method crash in CompileMacroVersion replaced with GRIPEMS:Debug() (BUG-022)
  • ValidateSteps no longer blocks activation at 255 chars, downgraded to warning (BUG-023)
  • Char counter threshold and editBox max set to 255 (SAB macrotext limit post-11.0.2) (BUG-009)
  • Per-segment spell ID resolution in /cast and /use semicolon fallbacks (BUG-025)

[v0.9.1-beta] - 2026-03-21

Added

  • Multi-version sequences: N versions per sequence with version bar UI (add, duplicate, delete, set default) and MenuUtil dropdown selector
  • Context version selection: 15 context keys (Raid Normal/Heroic/Mythic, Dungeon Normal/Heroic/Mythic+, PvP Arena/Battleground/Rated BG, Scenario, Timewalking, Delves, Solo, Default) with automatic detection via GetInstanceInfo() and difficultyID
  • Context auto-switching: table-driven fallback chains (CONTEXT_FALLBACKS in Defaults.lua), Engine:GetActiveVersion() context resolution, ReloadContextSequences on zone/group changes
  • Context Tab: dedicated tab with collapsible groups (Raids/Dungeons/PvP/Other), per-version checkboxes, StaticPopup conflict warning dialog
  • Context migration: legacy context fields (Raid, Arena, PVP, Mythic, MythicPlus, Heroic, Dungeon, Timewalking, Party, Scenario) preserved during import and in-game migration
  • /gems guide upgrade: clickable chat hyperlink + copyable URL popup with online guide link (https://jesperlive.github.io/grip-ems-guide/)

Changed

  • SequenceEditor: removed inline contextBar grid, simplified anchor chain (versionBar -> tabBar) after Context Tab extraction
  • Import: all N versions now imported (previously only default version)

Fixed

  • Context reload: same-ref comparison bug causing missed reloads
  • SequenceEditor: 22px layout gap after contextBar removal
  • Context detection: missing Solo and Default fallback entries

[v0.9.0-beta] - 2026-03-20

Added

  • Core macro sequencer engine (SecureActionButton + WrapScript click body)
  • 3 step functions: Sequential, Priority, Random
  • SetOverrideBindingClick keybind system (per-spec, OOC-queued)
  • MacroManager for action-bar drag stubs with dynamic icon updates
  • Reset conditions: timer (idle timeout), combat, target change, gear swap, spec change
  • Click rate throttle (100-1000ms slider, restricted env enforcement)
  • Legacy format import (COLLECTION + simple array, double-decode, KeyPress/KeyRelease)
  • GRIP1 native export format (CBOR + Deflate + Base64)
  • In-game migration from other sequencers (detect installed addons, bulk import)
  • Variable migration (legacy variables mapped to GRIP-EMS VariableStore schema)
  • Structured migration report with limitation counts and per-sequence guidance
  • ExportFrame with auto-highlight and Ctrl+C auto-close
  • ImportFrame (AceGUI paste window, bypasses 255-char chat limit)
  • Full UI: MainFrame, SequenceList (native ScrollBox + DataProvider), SequenceEditor
  • 5-tab editor: Steps, Keybind, Macros, Variables, Raw
  • Editable step list with working-copy dirty-state pattern
  • Keybind tab with key capture (SetPropagateKeyboardInput, per-spec overview)
  • Macros tab with stub management and orphan cleanup
  • Variables tab (account-wide, pcall+loadstring validation, event-driven re-eval)
  • Raw macrotext editor with pcall+loadstring Lua validation
  • ~varname~ substitution in macrotext with Tab-press autocomplete
  • Spell cache (C_SpellBook scan, debounced) with Tab-press autocomplete
  • Icon picker with autoIcon auto-detect from step 1 macrotext
  • Dynamic macro stub icons via CallMethod in WrapScript
  • Settings panel (AceConfig + AceDBOptions profiles)
  • Blizzard Settings integration (ESC > Options > AddOns)
  • About/version info panel with dynamic status block
  • Debug window (ScrollingMessageFrame, 500-msg ring buffer, copy to clipboard)
  • Vehicle/skyriding/pet-battle keybind suspension (6 events, OOC-guarded)
  • Minimap button (LibDBIcon) + addon compartment registration
  • Luacheck CI (GitHub Actions)
  • BigWigsMods packager CI/CD (GitHub Actions)
  • WagoAnalytics tracking shim
  • Interactive HTML guide with 9 sections, tooltips, keyboard legends, and full sequence builder with export (Guide/GRIP-EMS_Guide.html)
  • /gems guide slash command to locate the guide file

Known Limitations

  • Multi-version sequences: only default version imported (fixed in v0.9.1-beta)
  • Context versions (Raid/PVP/Dungeon auto-switch): not yet implemented (added in v0.9.1-beta)
  • Embedded sequence resolution: logged as warning, not expanded
  • Pause blocks: skipped with warning (WoW API limitation for click-based execution)
  • Import collision UI: skip-if-exists only (no per-sequence pick list yet)
  • KeyPress/KeyRelease: imported and functional, not exposed as separate editor fields