The Conditional Picker round-trip parser's multi-bracket detection moved out of the picker into the StepListView [v] button OnClick. The picker's earlier check used #clauses > 1 which was structurally dead (the parser produces exactly one clauses[1] regardless of bracket count). The correct signal is #clauses[1].conditions > 1 and now routes to the Conditional Builder modal instead of leaving the picker in a read-only state.
GRIP-EMS v2.1.0
Released May 12, 2026. 27 entries in the author's notes.
Every entry
The author's own words, complete. Long sections are sorted into areas by LazyGrip.
Added
16Resets and modifiers4
IF action node in the + Add menu. The node renders a Cond editbox plus separate True and False columns for child action lists. The compiler emits a bracketed /cast [<cond>] <body>; <else body> line per spec section 5 conventions. Child actions support every other step type already in the editor (Action, Loop, Pause, Embed, IF).
Original Author field on every sequence. The field locks after the first save and never updates again. A separate lastModifier field auto-stamps on every subsequent save. Sequences saved before v2.1.0 receive a Provenance unknown grey badge on first login under v2.1.0.
Verification badge palette in the SequenceList rows: green Verified, yellow Modified, red Tampered, blue Forked, grey Unknown, orange Damaged. Re-verify entry in the row context menu re-runs the check on demand. LibQTip2 tooltip on row hover shows the modifier chain and the last 5 chain entries.
Provenance UI in the ImportFrame paste-import pane. Each preview row shows the verification badge, an Original Author second-line label, and a LibQTip2 tooltip with the modifier chain. A Show all expander opens a scrollbox listing every chain entry. Tampered imports prompt a 3-button confirm dialog (Import anyway / Don't show again / Cancel).
Macros, export, import and sharing3
Conditional Picker popup, opened from the [v] button next to the Cond field. Three category tabs (Combat-relevant / General-purpose / UI-state) list the WoW macro conditional vocabulary as tickboxes with negation toggles and parameter inputs (modkey dropdown, integer ranges, pet family pickers, item-type dropdowns). Re-opening the picker on a non-empty Cond field hydrates the tickbox state from the existing input.
Privacy modes per sequence in the SequenceEditor metadata pane and a profile-level default in Settings -> Authorship Privacy. Public keeps full attribution. Pseudonymous swaps the display name for a configured pseudonym while keeping the identityHash so receivers can link sequences from the same author. Private swaps the name for Anonymous and generates a per-export random salt so two private exports are not linkable.
Native !EMS1! export format. Carries full provenance fidelity on the wire. The Import pane recognizes both !EMS1! (native v2.1.0+) and !GSE3! (legacy GSE3 export) prefixes. Export emits !EMS1! only; one-way GSE3 import compatibility stays in place.
Saving, naming and editing3
Spec scope dropdown in the Spell Picker's Spec filter. Choices are Current spec (default, matches v2.0.x behavior), All specs of this class, or a single off-spec by spec name. Off-spec spells reach the spell list via the existing C_SpellBook skill-line API, no new data files.
SHA-256 signatures on every sequence via embedded LibHash-1.0. The signature is computed over a canonical serialization of the sequence content and stamped on first save. Subsequent saves recompute a currentSignature field; mismatch detection drives the badge palette.
Fork mechanism. A Fork button on the SequenceEditor toolbar (visible only when the loaded sequence has a foreign Original Author) and a Fork entry in the SequenceList row context menu deep-copy the sequence, re-stamp the duplicating user as the new Original Author, and record the source's lineage in forkedFrom. Multi-hop fork chains (e.g. Gaupanda -> Daddysat -> John -> Paul) preserve every ancestor.
Combat and the Options pages2
Conditional Builder modal, opened automatically when the Cond field contains multi-bracket OR group syntax like [A,B][C,D], or from the single-clause picker's Convert to OR group button. Each OR clause is a self-contained sub-frame with its own 4-tab strip (Combat / General / UI-state / Targeting), independent tickbox state, and a Remove button. An Add OR clause button appends a new empty clause. Apply emits the joined bracket output back to the Cond field.
Combat-blocked command warnings on IF True / False child rows. A static lint pass scans each child action's leading slash command against the canonical Combat-Blocked Commands list. Matches surface a yellow ! badge with a tooltip that names the blocked command and suggests [nocombat] gating. Compiled Output preview adds a per-line annotation in yellow for the same matches.
Repair and spell warnings2
Custom tab in the Spell Picker (callback mode only, e.g. when opened from the IF picker's spellname row). Side-by-side Spell ID and Name fields. Typing a partial spell name renders a scrollable match-row list drawn from the active-spec spellbook unioned with the bundled cross-class catalog. Click a row to populate both fields, then Apply to insert.
All Classes tab in the Spell Picker, sourced from a bundled cross-class catalog of 2,637 spells across the 13 WoW classes. Class scope dropdown narrows the list to a single class. Each row appends the source class in muted brackets to disambiguate shared spell names.
Everything else2
Targeting tab in the builder. Per-clause radio for (none) / @focus / @cursor / @none / @unit (with a text input for arbitrary unit ids like raid1, party2, arena1) / target= (alternative syntax with the same text input). The targeting prefix emits first inside the bracket per WoW convention.
Cross-class spell catalog refresh workflow. GRIP_EMS_DB carries a D.SPELL_CATALOG_BUILD constant against the build the catalog was generated for. PLAYER_LOGIN prints a one-line drift notice when the running client build does not match the stamp. The catalog refreshes via Hub/GRIP/Hub/Tools/regen_spell_catalog.py (dev side; ships pre-generated to users).
Changed
2The Apply path in the Conditional Picker replaces the Cond field content wholesale rather than inserting at the cursor. Round-trip parsing on Open hydrates the picker from the existing field content so re-opening does not silently lose user input.
Fixed
5SpellID format crashes on Hero Talent SpellIDs that exceed 32-bit signed int max (e.g. 3,238,064,372). Every string.format call site that touches a SpellID now uses %s with tostring() instead of %d.
Custom tab SpellID truncation. The Spell ID EditBox previously held only 8 characters, which silently dropped 10+ digit Hero Talent SpellIDs on programmatic SetText. The field now holds 12 characters.
Catalog drift notice no longer prints on every login. The earlier extraction read position 4 of GetBuildInfo() (the integer interfaceVersion) and compared it to the composite "12.0.5.67403" stamp string; the inequality was always true. The fix reads positions 1 + 2 (buildVersion + buildNumber) and concatenates with . to match the stamp shape.
Conditional Builder Remove button no longer leaves an orphan sub-frame visible after click. The cleanup phase iterates scrollContent's actual child frames rather than the Lua-side clause table, which catches the just-removed clause whose state has already left the table.
Conditional Builder modal re-open after Apply no longer renders inert tickboxes layered over a fresh render. CB:Close now explicitly hides each per-clause sub-frame before wiping the state table; the explicit Hide persists across the next outer Show.
Internal
4New Engine/Identity.lua module covering identity resolution, canonical serialization, SHA-256 sign / verify, fork stamping, and the export payload scrub for privacy modes.
New Data/MacroLint.lua (combat-blocked command catalog), Data/CrossClassSpellCatalog.lua (the 2,637-spell bundle), UI/ConditionalPicker.lua (single-clause popup), UI/ConditionalBuilder.lua (multi-clause modal).
LibHash-1.0 vendored via .pkgmeta external and locally cached in Libs/LibHash-1.0/ for dev smoke testing. Packager refreshes from the upstream tag at build time.
New Hub/GRIP/Hub/Tools/regen_spell_catalog.py Cowork-side tool that walks SimulationCraft's per-class spell dumps, filters Passive+Hidden identity entries, deduplicates by SpellID, and emits the catalog file with header stamps.
Grab it
Release notes written by Sataana and reproduced here with his permission.