promotional bannermobile promotional banner

TOG Profession Master

TOG Profession Master should help you and your guild to know faster which player has which profession and who can craft which item or who has learned which enchantment.
Back to Files

TOGProfessionMaster-v1.0.3

File nameTOGProfessionMaster-TOGProfessionMaster-v1.0.3.zip
Uploader
PmptastyPmptasty
Uploaded
Jul 15, 2026
Downloads
264
Size
938.6 KB
Flavors
ClassicMoP ClassicClassic TBC
File ID
8438044
Type
R
Release
Supported game versions
  • 5.5.3
  • 4.4.2
  • 3.4.5
  • 2.5.6
  • 1.15.8

What's new

TOG Profession Master Changelog

[v1.0.3] (2026-07-15) - Cooldown-sync repair, switched-profession cleanup & cross-guild data-leak fixes

Bug Fixes

  • Guild cooldown sync has been broken since v1.0.0 — now fixed. The v1.0.0 "cooldown-sync overhaul" wrapped cooldown serving in a timestamp gate: a client would only hand over a cooldown when its own copy was strictly newer than the requester's. That comparison can't hold across a guild — it trusts each client's updatedAt, but the migration off the old relative-remaining format left every client stamping updatedAt at its local receive time (≈now), so an owner's real copy was never "newer" than anyone's stamp and nobody ever served a cooldown to anybody. Guild cooldown data silently froze at v1.0.0 and withered as cooldowns expired with nothing replacing them — most people saw only their own. TOGPM now serves cooldowns like every other leaf (prefer-newer, but it never stays silent), and the request advertises what you actually hold — real data, not a leftover hash — so a first fetch always resolves and orphaned hashes can't block it. The absolute-timestamp format that stops sync churn is kept; only the broken serve gate is gone. Cooldowns propagate again the moment two updated clients share a guild. Location: Scanner.lua, Modules/HashManager.lua, TOGProfessionMaster.lua, GUI/Settings.lua.
  • Synced guild cooldowns no longer vanish because your character lacks the profession. A cooldown that had genuinely synced (e.g. a guildmate's Salt Shaker) could be filtered out on your end if your copy of their profession snapshot hadn't caught up — so a bank alt or a fresh login saw an empty Cooldowns tab even though the data was sitting in the database. The dropped-profession hide now applies only to your own characters, where the profession read is authoritative and current; guild sync always displays what it received. The owner decides what to broadcast — a viewer shows everything it got. Location: TOGProfessionMaster.lua.
  • Fixed a Lua error when hovering the Cooldowns tab's "Ready Only" button. The button's new tooltip referenced a locale key (ReadyOnlyTooltip) that didn't exist, and AceLocale raises its "Missing entry" error on the access itself — before the code's own fallback string could run. Added the string and hardened the lookup (rawget) so it can never throw regardless of client locale. Location: GUI/CooldownsTab.lua, Locale/enUS.lua.
  • Alt-group sync (accountchars) no longer churns forever. The alt-group leaf still ran the original v0.7.0 model: a relay union-added incoming entries and then recomputed the hash on receipt, so every client hashed its own accumulated view instead of the owner's canonical one. The leaf therefore perpetually differed between clients and peers re-requested it every sync cycle — a constant background of accountchars:* re-sends and repeated full-list subhash broadcasts. It's now owner-authoritative like cooldowns and professions: the alt group is minted only by its own account and adopted verbatim everywhere else — no union, no recompute — so all clients converge on one hash. Two bonuses fall out of the verbatim replace (vs. the grow-only union): a dropped alt now propagates guild-wide (the old union could never remove one), and a peer can no longer union stray entries into your own alt list. The character purge was also completing this loop wrong — it dropped the alt-group hash but left the data, so the next cache rebuild re-minted the hash and a purged (left-the-guild) character reappeared; the purge now removes the data too, so a purge sticks. Same release-gated convergence as cooldowns — it settles fully once peers are on the new code. Location: Scanner.lua, Modules/HashManager.lua, TOGProfessionMaster.lua.
  • Guildmates who drop or switch a profession no longer linger in the old profession's data. When someone unlearned a profession, TOGPM kept listing them as a crafter of its recipes, kept counting them on the Guild tab, and kept showing their profession cooldowns — forever. A dropped profession has no trade-skill window to re-scan, and guild sync could only ever add data, never remove it, so the stale entries never cleared. TOGPM now keeps an owner-authoritative snapshot of each character's current professions and syncs it on a new professions: channel: on login your client reads the professions you actually have right now (window-less — it doesn't need you to open anything) and broadcasts the complete set, so a profession you dropped is removed for everyone. Your recipes disappear from the Professions browser, your headcount drops off the Guild tab, the recipes you no longer cover reappear in Missing Recipes, and (below) your profession cooldowns drop off the Cooldowns tab. Heavily guarded against false removals: it only acts on a confident, complete read (never a partial early-login scan — a profession must be absent from two consecutive reads before it's removed), so a profession you still have but simply haven't opened is never touched. Location: Scanner.lua, Modules/HashManager.lua, GUI/GuildTab.lua, GUI/MissingRecipesTab.lua, TOGProfessionMaster.lua.
  • Dropping a profession now also clears its cooldowns. Unlearn Alchemy and its transmute drops off the Cooldowns tab; the same applies to every profession cooldown — Tailoring's Mooncloth / specialty cloths / Dreamcloth, Enchanting spheres, JC prisms and daily cuts, Inscription research, Blacksmithing ingots, Leatherworking Magnificence, and the Salt Shaker (whose Use effect requires Leatherworking 250, so losing LW means you can't use it). Each cooldown is matched to its profession. For your own characters the row is hidden immediately (checked against your live, authoritative profession read); a guildmate's dropped cooldown clears once their client rescans and re-broadcasts without it — the viewer-side hide is deliberately limited to your own toons so a guildmate's genuinely-synced cooldown is never hidden just because your copy of their profession snapshot lagged. Location: Data/CooldownIds.lua, GUI/CooldownsTab.lua, TOGProfessionMaster.lua.
  • On accounts with characters in more than one guild, each toon showed profession/cooldown data from the OTHER guild. The "guild only" filter on the Professions tab (and the Cooldowns, Guild, and Missing Recipes tabs, plus item tooltips) failed to filter out data belonging to a different guild. Root cause: the database is a single account-wide table (all your toons write into it), and the display-time guild gate IsVisibleCrafter short-circuited with "own alts are always visible, regardless of guild." So when you were logged into a Guild A character, your Guild B alts — and any recipe or cooldown only they knew — leaked into Guild A's view. The Cooldowns "guild" view was worse still: it carries no guild tag and returned the entire account-wide cooldown table with no scoping at all, so even other-guild members' cooldowns (synced while you were on a Guild B toon) rendered under Guild A. Fixed with a single roster-truth scope test, addon:IsInCurrentGuildScope — a character counts only when LibGuildRoster confirms it's in your current guild (or a configured sister guild), your own alts included. It's applied to every guild-scoped view: the Professions guild/missing views (the Mine view still shows all your alts across every guild), item tooltips, the Cooldowns guild view, the Guild-tab profession headcounts, and the Missing Recipes "known by the guild" test. The check is read-only — a hidden cross-guild alt is never purged, so its data survives for when you log into that guild — and cold-start-safe (before the roster finishes its first build nothing is hidden; the tabs re-scope once it's ready). Note: because cooldowns/skills carry no guild tag, an own bank alt that is guildless (not in the guild) is also scoped out of the guild views — it remains in the Mine view. Location: TOGProfessionMaster.lua, GUI/BrowserTab.lua, GUI/CooldownsTab.lua, GUI/GuildTab.lua, GUI/MissingRecipesTab.lua, Tooltip.lua.

Improvements

  • Fixed a 1–2 second freeze the first time you open the Professions tab. The background cache-warmer builds one profession at a time, and after each one it forced a full tab teardown-and-rebuild (ReleaseChildren + redraw of every dropdown, the toolbar, and the scroll pool). With the tab open while the warm ran, that was ~one full rebuild per profession back-to-back — a dozen complete UI rebuilds in a row, which is the hitch (the list build itself is effectively instant). The warm now refreshes only when the profession it just built is the exact view you're looking at, collapsing that storm to a single redraw; the other professions still warm silently into the cache and appear instantly when you switch to them. Location: GUI/BrowserTab.lua.
  • Recipe-browser build does fewer redundant roster lookups. Each crafter's visibility/guild-scope checks (IsMyCharacter, IsVisibleCrafter, IsInCurrentGuildScope) are now memoized per character within a build, so a crafter known across many recipes is evaluated once instead of once per recipe. Location: GUI/BrowserTab.lua.
  • Serve-side coalescing cuts redundant guild broadcasts. Serving a leaf (or a roll-up's subhash list) is a guild-wide broadcast, but it's request-driven per peer — so when many clients ask for the same thing at once (common in a mixed-version guild, where the one client actually holding real cooldown data gets asked by everyone), it was re-broadcast to the whole guild once per requester. TOGPM now suppresses a repeat of the same leaf or roll-up subhash list within a short window — everyone already got the first copy — collapsing those request bursts to a single send. It targets burst amplification (e.g. a login storm); the steady per-cycle re-requests from un-converged old clients still settle only on release. Location: Scanner.lua.
  • The new profession snapshot is owner-authoritative and fully backward-compatible. Each character's profession set is minted only by that character's own client and adopted verbatim by everyone else — hashes are never recomputed on receipt, the same convergence-safe model the cooldown sync uses (recompute-on-receive is what caused past drift/redraw churn). It rides a separate professions: sync leaf, so un-updated guildmates are completely undisturbed — their existing sync is byte-identical to before and there's no cross-version churn. Un-updated clients simply don't get the switched-profession cleanup until they update. Location: Scanner.lua, Modules/HashManager.lua.

[v1.0.2] (2026-07-09) - Fix: Auctionator error when opening Enchanting with crafting takeover on

Bug Fixes

  • Opening Enchanting with crafting takeover enabled threw an Auctionator error (attempt to index global 'CraftReagent1'). On Vanilla/TBC the Enchanting "Craft" window's frames (CraftReagent1..N) are created by the load-on-demand Blizzard_CraftUI addon, and the only thing that lazy-loads it is UIParent's built-in CRAFT_SHOW handler. When crafting takeover is on, TOGPM unregisters that handler so Blizzard's window doesn't pop over its own tab — which also removed the loader, so any other addon that hooks CRAFT_SHOW (Auctionator's CraftShown) ran while those globals were still nil and errored. TOGPM now assumes UIParent's load responsibility: it loads Blizzard_CraftUI itself so the frames exist for co-installed listeners, then unregisters CraftFrame's own CRAFT_SHOW so it still won't auto-pop a second window. Gated on Vanilla/TBC (HAS_CRAFT_WINDOW) and the takeover path only, so default hands-off users and Wrath+ clients are unaffected; the escape-to-Blizzard button still works (it summons the window via UIParent_OnEvent, which doesn't depend on that registration). Location: Modules/Crafting/CraftingEngine.lua.

[v1.0.1] (2026-07-05) - Specialization detection fixes, full guild coverage & crafter search

New Features

  • Search the Professions tab by crafter name. Typing a guild member's name into the recipe search box now lists every recipe that player can make — crafter names are folded into the same cached, per-keystroke filter, so there's no added cost, and it honours the current view/visibility. Set the Profession dropdown to All and type a name to audit "what can this character craft?" across every profession at once. Location: GUI/BrowserTab.lua, Locale/enUS.lua.

Bug Fixes

  • Alchemy specializations were detected with the wrong spell IDs. The spec scan checked 28682 / 28683 — which are actually "Combustion" and "Leap", not alchemy specs — so Transmutation and Potion Masters were never detected and fell to Unspecialized (only Elixir Master, 28677, happened to be correct). Corrected to the DBC-verified 28672 / 28675 / 28677 (Transmutation / Potion / Elixir Master) in the spec scan, the Guild tab's canonical spec list, and the transmute-proc cooldown table (which was keying the every-transmute proc on "Leap"). Location: Scanner.lua, GUI/GuildTab.lua, Data/CooldownIds.lua.
  • Mooncloth Tailoring could never be detected. The Tailoring spec list used 26802"Detect Amore", a Love-is-in-the-Air holiday spell — where Mooncloth's real id 26798 belongs, so Mooncloth tailors were never categorised, and anyone who owned the holiday spell risked a bogus tag. Fixed to 26797 / 26798 / 26801 (Spellfire / Mooncloth / Shadoweave) in the spec scan, the Guild tab list, the recipe-tagging pipeline, and the cloth-cooldown table. Location: Scanner.lua, GUI/GuildTab.lua, Data/CooldownIds.lua, tools/build_authoritative_data.py.
  • Cloth-cooldown "guaranteed 2×" bonus was mapped to the wrong specs. Primal Mooncloth's bonus was keyed to Spellfire's spec id and Spellcloth's to the holiday spell, so Mooncloth tailors got no bonus indicator and Spellfire's never lit up. Each cloth cooldown now maps to its own spec — Mooncloth → Primal Mooncloth, Spellfire → Spellcloth, Shadoweave → Shadowcloth. Location: Data/CooldownIds.lua.
  • Archaeology didn't appear on the Guild tab. The skill-name → profession map was missing Archaeology (794), so the gathering scan never recorded it on Cata/MoP clients. Added. Location: Scanner.lua.
  • Skill levels rendered an impossible cap like "375/300". A missing or stale skillMax defaulted to the hard-coded Vanilla cap of 300, which then synced guild-wide and displayed below the actual rank on TBC/Wrath. The stored fallback is now the rank (a cap can't be below the current skill), and the Guild tab shows every skill against this expansion's real cap (addon.SKILL_CAP: 300/375/450/525/600 for Vanilla…MoP) instead of the per-character value. Location: Scanner.lua, Compat.lua, GUI/GuildTab.lua.
  • Gathering skills were missed when a skill header was collapsed. GetSkillLineInfo hides a collapsed header's children, so a character with "Professions" or "Secondary Skills" collapsed dropped Skinning / Herbalism / Fishing / Archaeology from the scan. It now expands all headers first (ExpandSkillHeader), guarded against the re-entrant SKILL_LINES_CHANGED that expansion fires. Location: Scanner.lua.

Improvements

  • The Guild tab now lists EVERY profession, even at 0. Previously only the gathering professions were force-shown; now every profession available on this client appears with a headcount (0 when nobody has it), so the guild-wide "who has what" view surfaces crafting-profession coverage gaps too. Location: GUI/GuildTab.lua.
  • TBC/Wrath specialization recipes now attribute their crafters (requires ProfessionDB v1.2.2). The recipe data only tagged Vanilla-era spec plans; TBC and Wrath moved the spec gate onto the crafted item, so ~65 TBC and ~72 Wrath spec recipes — Lionheart weapons, Dragonscale/Elemental/Tribal leatherworking, Gnomish/Goblin engineering, Mooncloth tailoring — shipped untagged and their crafters showed as Unspecialized. The ProfessionDB generator now reads the crafted item's requirement as well. Update to ProfessionDB v1.2.2 to pick this up. Location: tools/build_authoritative_data.py (ProfessionDB).

[v1.0.0] (2026-07-01) - First full release: Guild professions tab, skill-tier filter & Cooldowns reagent overhaul

TOG Profession Master reaches 1.0 — its first full release. A milestone worth marking, and still growing. A new Guild tab drills from a profession headcount down to each specialization and the individual crafters — with their skill levels — and now tracks the gathering professions (Herbalism, Skinning, Fishing) that have no window to open; a skill-tier filter declutters the Professions browser; the Cooldowns tab gets a batch of reagent improvements — every reagent shown for multi-reagent crafts (Brilliant Glass, the specialty cloths), an at-a-glance "you already have this" highlight, a tidier reagent popup, and a fix for the supply-mail button that looked up the wrong item; and under the hood, profession-cooldown sync was overhauled to kill a convergence bug that churned CPU and redraws on busy guilds.

New Features

  • New Guild tab — the guild's crafting capacity, from headcount down to the people. Tallies how many guild characters have each profession, then lets you drill in: click a profession to expand its specializations, then a specialization to list the characters in it. Every specialization is shown even at 0, so coverage gaps are obvious ("nobody's an Axesmith"). Names are coloured exactly like the Professions tab — white online, grey offline, brand-colour You — with an online alt surfacing its offline main, and each name carries that character's skill level (You (300/300)). A character's spec comes from their recorded specialization or is inferred from the spec-only recipes they're known to craft, so even guildmates who don't run the addon get categorised. Counts are the union of synced skills and known recipe crafters, the tracked-character total sits in the status bar, column headers and a dedicated help (i) tooltip explain the view, and it's localized. Location: GUI/GuildTab.lua, Scanner.lua, GUI/MainWindow.lua.
  • Gathering professions are now tracked — see who herbs, skins, and fishes. Herbalism, Skinning, Fishing (and Archaeology on Cata/MoP) have no trade-skill window to open, so the recipe scan never saw them. They're now read from the character's skill lines (GetSkillLineInfoGetProfessions is a no-op on Classic Era) and shown on the Guild tab, always listed even at 0 so the gap is visible. The skill levels sync guild-wide through a new owner-authoritative skills: leaf that mirrors the cooldown / alt-group leaves — you record your own, it's relayed by anyone — so once a guildmate offers theirs up, everyone sees it. Mining stays on its existing Smelting path. Location: Scanner.lua, Modules/HashManager.lua, GUI/GuildTab.lua.
  • Missing Recipes now has Personal / Guild sub-tabs. The Missing Recipes tab gained a sub-tab switch: My Character (the existing per-character "what am I missing?" view) and Guild — a guild-wide list of recipes nobody in the guild knows, filterable by profession (or All Professions, which tags each row with its profession) and searchable, so officers can spot coverage gaps at a glance. The Guild view drops the character dropdown and the "Can learn now" filter (both are per-character) and computes "missing" as any recipe in the shipped universe with zero crafters across the whole guild. Your sub-tab choice persists across sessions. Location: GUI/MissingRecipesTab.lua.
  • Missing Recipes hides recipes your specialization can never learn. A Tribal leatherworker no longer sees Elemental or Dragonscale patterns; an Armorsmith no longer sees Weaponsmith plans, etc. Recipe scrolls carry their required spec in the game data (ItemSparse.RequiredAbility), which the ProfessionDB pipeline now ships as a requiredSpec field; the My Character view compares it against your recorded spec and hides mismatches (guild view and "Show All" keep everything). Understands the Blacksmithing sub-spec hierarchy — a Swordsmith still sees general Weaponsmith recipes. Covers Leatherworking, Blacksmithing, Engineering, and Tailoring across Vanilla/TBC/Wrath (specializations were removed in Cata). Requires the updated ProfessionDB (regenerated data + LibProfessionDB load of the new field). Location: GUI/MissingRecipesTab.lua, Scanner.lua, tools/build_authoritative_data.py (ProfessionDB).
  • Filter the Professions browser by skill tier. A new multi-select Skill tier dropdown in the Professions toolbar shows only recipes in the trainer ranks you tick (Apprentice / Journeyman / Expert / Artisan, plus Master / Grand Master / Illustrious / Zen Master on later clients) — untick the lower tiers to hide their recipes and cut the clutter. Tick multiple tiers (the menu stays open), with Select All / Clear All at the bottom; only tiers your client can reach are offered, your selection persists across sessions, and recipes with no known skill level always stay visible. Localized in all shipped languages. Location: GUI/BrowserTab.lua.
  • Cooldowns tab now shows every reagent for multi-reagent crafts. Brilliant Glass (six gems) and Primal Mooncloth / Spellcloth / Shadowcloth (three reagents each) previously showed only one reagent — or none — and no mail button. They now render as click-to-expand [+] rows whose popup lists every reagent with its own [AH] / [Bank] / mail controls, matching how transmutes already work. Prismatic Sphere and Void Sphere, which showed no reagent at all, now display theirs. Location: Data/CooldownIds.lua, GUI/CooldownsTab.lua.
  • Reagents you already have are highlighted. In the Cooldowns reagent popup, a reagent name turns white (from grey) when you're holding enough of it in your bags to fill the supply mail — so you can see at a glance which reagents you can send. Location: GUI/CooldownsTab.lua.

Bug Fixes

  • Profession-cooldown sync no longer churns the client (or redraws the UI) every second. On active guilds, cooldown sync never converged: cooldowns are stored as absolute expiry timestamps but were transmitted as a countdown and rebuilt against each receiver's clock, so every relay hop added the transmission latency, the value ratcheted upward, its hash changed, and the peer-to-peer negotiation re-fired forever — pegging CPU and tearing down / rebuilding the open tab about once a second. Cooldowns are now owner-authoritative: the owner ships the absolute expiry plus its own hash, and receivers adopt both verbatim instead of reconstructing them, so the hash converges in one exchange and stays quiet. Legacy-format cooldowns from un-updated peers are dropped rather than merged. Location: Scanner.lua, Modules/HashManager.lua.
  • Your own cooldown starting/finishing now refreshes the Cooldowns tab. Using a transmute or Salt Shaker committed the cooldown to the database but raised no UI signal — the constant sync churn used to redraw the tab anyway, so it went unnoticed; with that churn fixed, the tab stopped updating until the next guild event. A local cooldown scan that actually changes a value now fires a cooldowns-scoped refresh, plus a short follow-up re-check for a cooldown the client reports a beat late. Location: Scanner.lua.
  • Salt Shaker cooldown detected on more Classic builds. The scan called only C_Container.GetItemCooldown; where that's absent or returns nothing it fell through to showing "Ready". It now falls back on the result to the global GetItemCooldown. Location: Scanner.lua.
  • Search fields keep focus while guild data streams in — fixed for every tab. The earlier fix relied on GetCurrentKeyBoardFocus, which isn't available on all Classic flavors, so it silently no-op'd (the Professions search still went "unbound"). The focus-aware refresh deferral now lives in the shared StyleSearchBox helper that every search box already uses, keys off the reliable EditBox:HasFocus(), and resets the deferral counter on each keystroke so continuous typing is never interrupted. Covers Professions, Missing Recipes, Crafting, and Profit Planner. Location: GUI/SharedWidgets.lua, GUI/MainWindow.lua.
  • Missing Recipes recipe names now colour by the crafted item's quality. Names were tinted by the recipe-scroll item's own quality, so e.g. "Pattern: Molten Helm" (a common/white scroll that produces an epic helm) showed white instead of purple, and uncached scrolls showed white inconsistently. They now use the produced item's quality — matching the crafting window — falling back to the scroll's quality for recipes with no crafted item (enchants). Location: GUI/MissingRecipesTab.lua.
  • Missing Recipes no longer lists recipes you (or the guild) already know. Recipes whose spell ID is above 25000 — e.g. several patch-added Vanilla cooking recipes like Smoked Sagefish (spell 25704) — were wrongly appearing in the missing list even when known. Root cause: the Classic-Era "untagged post-Vanilla" existence gate (spellId > 25000) sat inside the same elseif chain as the "already known" filter; when a recipe passed that gate (the recipe genuinely exists), the chain short-circuited and the known-filter was never evaluated. The known-filter is now an additive guard that always runs for recipes that survive the version gates — the same fix pattern the "Can learn now" filter already used. Location: GUI/MissingRecipesTab.lua.
  • Search fields no longer lose focus mid-typing during guild sync. On a busy guild, incoming sync fired a window refresh that rebuilt the active tab's toolbar — including its search box — dropping keyboard focus so further keystrokes fell through to keybinds ("unbound"). The refresh now defers while a search field in the window is focused (the same way it already defers while a dropdown pullout is open), so typing isn't interrupted. Location: GUI/MainWindow.lua.
  • Fixed the cooldown reagent-mail button reporting "You have no item:1 in your bags." The mail button inside the reagent-breakdown popup called the mail helper with a missing argument, which shifted the reagent's item ID out of position — so it looked up item "1" (which nobody has) instead of the real reagent. It now passes the full argument set and attaches the correct reagent. This is distinct from the v0.10.10 C_Container bag-scan fix — different button, different cause. Location: GUI/CooldownsTab.lua.
  • Missing Recipes stops re-rendering several times a second (and the scroll no longer creeps to the bottom). The list rendered item names and quality colours through WoW's asynchronous GetItemInfo, which returns nothing until the client caches each item — so every row stayed "pending", every cache-fill event (from any addon) fired another full re-render several times a second, and that churn slowly walked the scroll position down to the bottom while colours flickered white. Names and quality colours now come from the synchronous, offline LibItemDB (the ItemDB dependency) on the first paint, with GetItemInfo only as a fallback for items LibItemDB doesn't carry — so a drawn list is stable immediately, doesn't refresh on unrelated item loads, holds its scroll position, and shows the correct quality colour right away. Location: GUI/MissingRecipesTab.lua.
  • Basic Campfire no longer appears as a Cooking "recipe." It's the learned campfire ability (it produces no item), not a craftable, so it never belonged in the recipe list. It's now excluded from the shipped data in every game version, and LibProfessionDB was hardened so a recipe present only in a locale name file (but not the structural _core set) is no longer resurrected as a dataless phantom — which is why it kept showing with a blank skill even after the data drop. Requires the updated ProfessionDB. Location: tools/build_authoritative_data.py, LibProfessionDB-1.0.lua (ProfessionDB).
  • Crystal Infused Bandage no longer shows on Classic Era. This is a TBC First Aid recipe (skill 300→360, Netherweave-based); the Anniversary Classic client ships its data even though it isn't learnable in Vanilla, so it leaked into the Classic missing list. It's now excluded from the Vanilla data only — TBC and later clients still get it. Requires the updated ProfessionDB. Location: tools/build_authoritative_data.py (ProfessionDB).

Improvements

  • Redraws are scoped to what actually changed. GUILD_DATA_UPDATED now carries a change-scope (cooldowns / recipes / skills / alt-groups), and each tab skips refreshes it doesn't render — so a cooldown sync no longer tears down and rebuilds the thousands-of-rows recipe Browser, and a skills sync only touches the Guild tab. Tab switches still always redraw from live data, so nothing goes stale. Location: GUI/MainWindow.lua, GUI/BrowserTab.lua, Scanner.lua.
  • Cooldown sync send-storm curbed. Un-updated peers were pulling every cooldown leaf each round (and being served all of them). The request and serve paths now gate cooldown leaves on a delivered timestamp, so a converged client neither pulls stale copies nor re-serves them, and old clients that can't parse the new format are no longer fed a stream of leaves. Location: Scanner.lua.
  • Sync Log gets a Pause button. Settings → General → Sync Log. Freezes the live view so a text selection survives long enough to copy; entries keep accumulating while paused and the view catches up on unpause, with a "(paused — N buffered)" note in the title. Location: GUI/Settings.lua.
  • Spec breakdowns fill in for the whole guild, not just addon users. The Guild tab now infers a crafter's specialization from the spec-only recipes they're known to craft (the requiredSpec the Missing tab already uses), so a Tribal leatherworker who's never run the addon still lands under Tribal instead of Unspecialized. Location: GUI/GuildTab.lua.
  • Tidier reagent popup on the Cooldowns tab. Removed the redundant per-reagent status column (readiness is already shown on the main cooldown row) and widened the reagent column so long names like "Bolt of Imbued Netherweave" sit on one line instead of wrapping — all within the existing popup width. Location: GUI/CooldownsTab.lua.
  • Profession-spec detection now covers Leatherworking & Blacksmithing. The spec scan learned the Vanilla LW specs (Dragonscale / Elemental / Tribal) and BS specs (Armorsmith / Weaponsmith → Swordsmith / Hammersmith / Axesmith) that feed the new Guild tab's breakdown. Harmless on Cata+, where these specializations were removed (the scan simply finds none). Location: Scanner.lua.
  • Cooldown group rows keep their proper icon. Reworked the cooldown-row icon resolution so multi-reagent cloth cooldowns rendered as [+] group rows still show the produced-bolt icon override instead of Blizzard's generic net/cloth spell icon. Location: GUI/CooldownsTab.lua.
  • Migrated to DeltaSync's multi-host API (requires DeltaSync v4.0.0+). DeltaSync v4.0.0 (LibStub MINOR 15) made the library multi-host: each addon now creates its own isolated sync host instead of sharing one singleton, so TOGPM no longer clobbers — or gets clobbered by — another DeltaSync-using addon in the same client (previously whichever addon initialized last owned the shared namespace). TOGPM now creates its host via NewHost and routes everything through it. This requires the standalone DeltaSync addon at v4.0.0 or newer — on an older DeltaSync, TOGPM's guild sync stays disabled (it will not silently fall back to the clobbering singleton path) until you update the dependency. The wire format is unchanged, so a v15 host still syncs with peers exactly as before. A new /togpm dsstatus command reports the host's namespace, the DeltaSync MINOR, the comm prefixes and P2P state, so you can confirm the multi-host setup at a glance (and prove isolation by running it next to another DeltaSync addon's status). Location: Scanner.lua.

[v0.10.10] (2026-06-30) - Live-refresh fixes, leaner recipe sync & a live Sync Log

Follow-up to v0.10.9's guild-mode work. With sync finally flowing on private servers, testing surfaced that incoming guild data was being ingested into the database but the Professions tab didn't show it until a /reload — switching tabs didn't help either. The data was live in memory the whole time; the bugs were all in the Browser's recipe-list cache (a performance snapshot the Professions tab renders from, separate from the live data the Cooldowns/Missing Recipes tabs read directly). Sync itself was never the problem. This release also makes recipe sync much leaner with an optional per-player drill-down, turns the Sync Log into a live, copyable diagnostic, and adds pickers for the crafter-alert sound and on-screen visual.

New Features

  • Sync Log is live, persistent, and copyable. Settings → General → Sync Log. The window now updates in real time as sync events happen — no more clicking to refresh — remembers its position and size across /reload, and its contents are selectable and copyable (read-only) for pasting into bug reports. Entries are also far more informative: sends now show what actually went out — a crafter transfer names its profession (crafters:165 (Leatherworking)) instead of a bare id, and a per-player transfer names the exact player — instead of a meaningless "0 B"; the hash-offer and sub-hash sends are logged for the first time; and a dedicated size column reports the real byte size of every message — sends included (which previously reported nothing) — beside the payload type, all under a column-header row (Time / Event / Size / Peer / Detail) above the live box. The send-size figures specifically require DeltaSync v3.2.1+ (which now returns the serialized size to the host) — that dependency is only for those send numbers in the Sync Log; on an older DeltaSync they show "—" and everything else in the addon behaves identically. Location: Modules/SyncLog.lua, GUI/Settings.lua, Scanner.lua.

  • Choose your crafter-alert sound and visual. Settings → Alerts. Two new dropdowns let you pick which sound (Chime, Ready Check, Raid Warning, Auction Bell, Whisper, Map Ping) and which on-screen visual (full-screen flash in gold / red / blue, a raid-warning banner, top-center error text, or a taskbar flash for when you're alt-tabbed) fire when a guild crafter comes online. Selecting an option previews it, and each dropdown greys out while its matching suppress toggle is on. The old "Suppress screen flash" toggle is renamed "Suppress alert visual" to match. Localized. Location: GUI/Settings.lua, TOGProfessionMaster.lua.

  • Jump from the Profit Planner straight to the Crafting tab. Clicking a row in the Profit Planner now opens that recipe directly in the Crafting tab, ready to craft (shift-click still links the item in chat — the tooltip spells out both). If you've hidden the Crafting tab (Settings → Crafting), it tells you how to bring it back instead of silently doing nothing. Location: GUI/AHProfitTab.lua, GUI/CraftingTab.lua.

Bug Fixes

  • Professions tab now updates live as guild data arrives. Two root causes, both fixed: (1) the background cache rewarm rebuilt the recipe list but never re-rendered the open tab, so freshly-synced recipes sat in the cache unseen; the rewarm now redraws the visible tab the instant the viewed profession's list is rebuilt — and does so without losing your scroll position. (2) The rewarm's debounce timer was starved on actively-syncing realms: every data update reset a 10s timer, so when updates arrived faster than that (a busy guild, or a private server catching up), the rebuild never fired at all — which is why even switching tabs showed nothing and only a /reload worked. The debounce is now capped so a rebuild always lands within ~10s, even under continuous traffic. Location: GUI/BrowserTab.lua.
  • Purge buttons now clear the Professions display immediately. "Purge all guild data" and "Purge my character data" did clear the database (Cooldowns and Missing Recipes emptied instantly), but the Professions tab re-rendered stale rows because its recipe cache isn't keyed on the database and wasn't being invalidated. The cache is now wiped on purge before the refresh, so the tab reflects the empty state at once. Location: GUI/BrowserTab.lua, GUI/Settings.lua.
  • "All Professions" view now reflects your own freshly-scanned professions. Scanning a profession locally (opening its window) committed the recipes to the database but raised no UI-refresh signal — only received sync did — so the cached "All Professions" list stayed stale. Most visible right after a purge: the All Professions filter showed "no data yet" while selecting a specific profession showed the recipes (that filter rebuilt fresh on a cache miss). Now a local scan that actually changes your recipe set refreshes the UI on the same path a peer update uses, gated on a real change so crafting's repeated scan events don't churn the open tab. Location: Scanner.lua.
  • Professions tab now reflects members going online and offline. Each crafter's online status is baked into the recipe-list cache when it's built, so a roster change alone didn't update the tab — someone logging off kept showing as online until the next data change or /reload. Roster online/offline transitions now invalidate and refresh the tab (debounced, and only while it's on screen so login/logout bursts don't thrash the pre-warm), so status reflects within ~2s. Location: GUI/BrowserTab.lua.
  • Cooldown supply-mail now finds your reagents on older TBC / Classic clients. On builds without C_Container (older TBC and some private servers), the legacy GetContainerItemInfo returns only 7 values — no item ID — so the mail helper's bag scan matched nothing and reported "you have no <reagent> in your bags" even when you had it. (The reagent count shown on the row uses GetItemCount and was correct all along, which is why it looked contradictory.) The compat shim now derives the item ID from the item link when the API omits it, so .itemID is always populated — fixing the mail scan on every supported client (and any other bag lookup that keys on item ID). Location: Compat.lua. Thanks to Bzum for the report.

Improvements

  • Leaner recipe sync — per-player drill-down. Previously, when anyone in the guild changed a recipe, peers re-fetched that entire profession's crafter set — on a large guild a single transfer of ~90 KB. Recipe sync now negotiates a per-player hash list under each profession and pulls only the players whose recipes actually differ, newest-scanned first and each as its own small message — so a one-person, one-recipe change ships just that player's recipes instead of the whole profession, the data populates incrementally, and traffic interleaves far better on congested or slow servers. It's fully additive and backward-compatible: feature-detected, so it engages only between updated clients and falls back to the existing whole-profession path for anyone else — no coordinated guild-wide update required, no wire-format break, no namespace bump. Location: Scanner.lua, Modules/HashManager.lua.
  • Consistent TSM setting labels. The two TradeSkillMaster pricing toggles now both read "TSM" — "Use TSM pricing" and "Use TSM App Helper pricing" — instead of one spelling out "TradeSkillMaster" and the other abbreviating. Location: GUI/Settings.lua.
  • Crafter column fills the available width. The Professions tab's crafter summary used to show a fixed "2 names + N more"; it now fits as many crafter names as the column's current width allows, with a greyed "+N" for the rest, and re-fits live when you drag the window wider or narrower. Location: GUI/BrowserTab.lua.

[v0.10.9] (2026-06-29) - Guild-only sync mode for private servers

Resolves the "nothing syncs on Whitemane" investigation. Diagnostics confirmed that Whitemane (and similar emulated Cataclysm servers) deliver addon messages over GUILD fine but silently drop them over WHISPER — and TOGPM's sync is hash-then-fetch, where the fetch request rides WHISPER. Hash offers went out on guild chat and arrived, but the follow-up data request never landed, so members kept broadcasting while nothing ever came back. This release adds an opt-in toggle that reroutes the whisper-based sync traffic onto the guild channel.

New Features

  • Guild-only sync modeSettings → General → Sync. For private/emulated servers that don't deliver addon whispers (e.g. Whitemane "Maelstrom"). When enabled, DeltaSync's directed channels (QUERY / RESPONSE / DELTA / OFFER / HANDSHAKE) are rerouted from WHISPER to GUILD, with each message stamped for its intended recipient so other members ignore it — directed delivery over a broadcast transport. Opt-in and OFF by default, so nothing changes on retail/Classic Era or any server where whispers work. The setting is realm-scoped (enable it once, all your alts on that realm inherit it) and feature-detected — the toggle is hidden unless the installed DeltaSync supports guild-mode (requires DeltaSync v3.2.0+). Cross-guild sharing auto-disables while it's on (it can't work on a whisper-dead server anyway). Coordinate per guild: on an affected realm, everyone should enable it — directed traffic only reaches members who also have it on. Localized in all shipped languages. Location: Scanner.lua, GUI/Settings.lua, TOGProfessionMaster.lua.

Notes

  • Diagnosing this used /togpm commtest (from v0.10.7/0.10.8) plus raw two-player tests, which is how we isolated WHISPER-drop-but-GUILD-works. If guild sync ever looks dead on a server, that command remains the fastest way to see which addon-message channels the server actually relays.

[v0.10.8] (2026-06-28) - Fix: commtest missing from per-flavor TOCs

Follow-up to v0.10.7. The new diagnostic shipped in only one of the addon's five TOC files, so it never loaded on the very clients it was built for. This release wires it into all of them.

Bug Fixes

  • /togpm commtest now loads on TBC / Wrath / Cata / MoP clients. v0.10.7 added Modules/CommTest.lua to only the base TOGProfessionMaster.toc. WoW loads the flavor-specific TOC when one exists, so on TBC/Wrath/Cata/Mists clients — including privately-hosted Cataclysm servers like Whitemane "Maelstrom" — the file was never in the load list, RunCommTest stayed undefined, and /togpm commtest silently fell through to the help menu (the command's help line still showed because that lives in the always-loaded main file, which is what made it look present). Added the line to all four flavor TOCs (_TBC, _Wrath, _Cata, _Mists) so the diagnostic is available on every supported version. Location: TOGProfessionMaster_TBC.toc, TOGProfessionMaster_Wrath.toc, TOGProfessionMaster_Cata.toc, TOGProfessionMaster_Mists.toc.

Notes

  • Whitemane runs a modern Classic-engine client, not the original 4.3.4 client. Diagnostics surfaced that its addon-message API is C_ChatInfo.SendAddonMessage (the bare global SendAddonMessage is nil), and C_ChatInfo.SendAddonMessage returns a SendAddonMessageResult code. The commtest probe already handles this via its C_ChatInfo shim; this corrects the v0.10.7 note that assumed the original 4.3.4 client.

[v0.10.7] (2026-06-27) - Private-server addon-comm diagnostics

Groundwork for running TOGPM on privately-hosted Cataclysm 4.3.4 (build 15595) servers such as Whitemane "Maelstrom", where some emulation cores leave the Cataclysm per-channel addon opcodes (CMSG_MESSAGECHAT_ADDON_GUILD, …) unhandled and silently drop guild addon traffic — which makes the sync stack look dead even though the addon loads fine. This release adds a diagnostic to pinpoint exactly which addon-message channels a given server relays. No change to existing behavior — it's a new, opt-in command; nothing in the live sync path was touched.

New Features

  • /togpm commtest [name] — addon-channel diagnostic probe. Fires a tagged addon message on every distribution (GUILD, WHISPER→self, a temporary CHANNEL, and PARTY/RAID when grouped), listens briefly for which ones echo back, then prints a copy-pasteable verdict including the client build number. The GUILD self-echo is the decisive test and works solo — on a healthy core you receive your own guild addon message; if the server drops guild addon traffic you get nothing. It probes both the raw SendAddonMessage path and your actual AceComm + AceCommQueue send path, so a server-side drop is distinguishable from a wrapper/chunking issue. Pass a player name to add a real two-player WHISPER probe. Run it on your home realm (control) and on the private server (test); the diff identifies the broken channel and which fallback (WHISPER/CHANNEL) is viable. Cross-version safe — uses C_ChatInfo where present, bare globals on 4.3.4, registers prefixes only where that API exists, and deliberately uses an OnUpdate timer instead of C_Timer (which the original 4.3.4 client lacks). Location: Modules/CommTest.lua.

[v0.10.6] (2026-06-12) - Cross-guild profession sharing & crafting hands-off

First stable release of cross-guild profession sharing (matured across the v0.10.x beta line) plus new crafting-window controls. Fully backward-compatible — single-guild use is unchanged, and cross-guild sharing stays completely dormant until you configure an allied guild. Cross-guild requires DeltaSync v3.1.0+ and GuildRoster v6+ (both install/update automatically).

New Features

  • Cross-guild profession sharing. Share recipe and crafter data between two socially-linked guilds that can't reach each other over the normal guild addon channel. An officer or the guild leader sets the allied guild under Settings → Cross-Guild (the list is guild-wide and members see it read-only); once both guilds list each other (it's bilateral — a one-sided config does nothing, and a guild you don't list can't pull or inject anything), their crafters become visible to each other. The allied-guild list propagates across your guild automatically, allied rosters are shared so every member sees the crafters (not just whoever pulled them), and a live Diagnostics panel plus /togpm xgdiag show exactly what's synced. With no allied guild configured, the addon does nothing cross-guild — purely local. Location: Scanner.lua, TOGProfessionMaster.lua, GUI/Settings.lua.
  • Crafting hands-off modeSettings → Crafting, on by default. TOGPM no longer opens or forces a crafting window when you open a profession; Blizzard's window (or another addon such as TSM / Skillet) owns it, so no second window appears beside it. The TOGPM toggle button still rides on the Blizzard window when it's shown, and the Crafting tab stays available from the main window. If you previously enabled "Open the TOGPM Crafting tab automatically," untick this to keep that behavior. Requires /reload. Location: Modules/Crafting/CraftingEngine.lua.
  • Hide the Crafting tabSettings → Crafting. Removes the Crafting tab from the main window entirely, for those who craft with another addon. Requires /reload. Location: GUI/MainWindow.lua.

Bug Fixes

  • Browser performance overhaul — instant tab open and instant search. The recipe list (the expensive part: DB lookups, the per-crafter visibility gate, item tooltip text) is now built once and cached, and pre-warmed in the background after login — sliced across frames so it's invisible — so opening the Professions tab and switching professions are instant instead of taking a second or more. Searching just filters the cache (no rebuild, no per-keystroke freeze). This removes the multi-second tab-load and search stutter that had grown as cross-guild sharing enlarged the crafter sets. Location: GUI/BrowserTab.lua, TOGProfessionMaster.lua.

Improvements

  • Settings window is tabbed (General / Cross-Guild) and remembers its position, size, and selected tab across /reload.
  • Roster engine runs on the standalone LibGuildRoster-1.0 (GuildRoster addon), an auto-installed dependency — the foundation for cross-guild support.

[v0.10.5-beta] (2026-06-09) - Roster propagation & Browser search fix (beta)

Beta build. Completes the cross-guild "anyone is a transfer point" model. Backward-compatible; single-guild operation is unchanged. Requires DeltaSync v3.1.0+ and GuildRoster v6+.

New Features

  • Sister-roster propagation (Part B). The visibility gate keeps an allied crafter only if their character is in a sister roster you hold — so a member who configured an allied guild but never pulled its roster would purge every relayed crafter. Now a member who holds a sister roster broadcasts it on the guild channel and everyone applies it, so the whole guild sees allied crafters, not just the puller. A "recently-seen by hash" suppression keeps it to ~one broadcaster per interval (duty rotates if that member logs off), fresh pulls propagate within ~10s, and receipt is gated by the allied-guild list (an unlisted guild's roster is never accepted). This is the piece that makes federated members churn-free without each pulling. Location: TOGProfessionMaster.lua, Scanner.lua.

Bug Fixes

  • Browser (recipe) search no longer freezes on each keystroke. Two causes: the search box rebuilt the whole list synchronously on every character (no debounce — the fix that was already in Missing Recipes had never been applied here), and the per-recipe crafter list was built before the search filter ran, so every keystroke walked every recipe's crafter set — which grew heavier as cross-guild sharing added crafters. The search now debounces (~200ms) and applies the cheap client-version + name/effect filters before the expensive crafter-list build, so excluded recipes are skipped. Location: GUI/BrowserTab.lua.

[v0.10.4-beta] (2026-06-09) - Cross-guild bilateral federation gate (beta)

Beta build. Security model for cross-guild sharing. Backward-compatible; single-guild operation is unchanged. Requires DeltaSync v3.1.0+ and GuildRoster v6+.

New Features

  • Bilateral federation — both guilds must list each other. Cross-guild data now only flows when both sides have configured each other as allied guilds. A one-sided config does nothing; a stranger, an accidental config, or a malicious puller from a guild you don't list gets nothing. Enforced by gating every direction:
    • Serve gate: we hand over our data only if we list the requester's guild and the request proves they list us (it carries their guild key + sister-guild set). Plus an anti-spoof check — once we hold the requester's guild roster, the requester must actually be a member of it.
    • Accept gate: we ingest cross-guild data only from a guild on our list.
    • Merge gate: every crafter is kept only if its guild tag is our home, our own alts, or a listed sister — so data for an unlisted guild is dropped even when it arrives relayed inside a home-guild broadcast, and is never re-relayed.
    • Roster gate: we persist/re-feed a sister roster only for a guild we list; a de-configured guild can't be resurrected on login.
    • De-configure cleanup: removing a guild from the list (or receiving a federated removal) tears down its roster and stops its data from displaying.
  • No allied guilds configured → purely local operation. With an empty list the permitted-tag set collapses to home + your own alts, so the addon does nothing cross-guild at all. Location: Scanner.lua, TOGProfessionMaster.lua.

[v0.10.3-beta] (2026-06-09) - Cross-guild config propagation & churn fix (beta)

Beta build. Continues the cross-guild work. Backward-compatible and dormant until an allied guild is configured. Requires DeltaSync v3.1.0+ and GuildRoster v6+. For the relay/anti-churn behavior, all participating beta players need this build — a peer on an older build re-broadcasts relayed crafters with the guild tag stripped.

New Features

  • Allied-guild config now propagates across your guild. The allied-guild list you set under Settings → Cross-Guild is broadcast to the rest of your guild (on change, every ~12 minutes, and via a new Sync now button), so every member participates — essential once editing becomes officer-only. Conflict resolution is last-writer-wins by the timestamp captured when the list was set; members re-broadcast what they hold without clobbering a newer edit. A member holding no config never broadcasts. Location: TOGProfessionMaster.lua, GUI/Settings.lua.

Bug Fixes

  • Relayed cross-guild crafters no longer churn under mixed addon versions. Because guild sync is gossip, a single guildmate on an older build (no per-crafter tags) re-broadcasts relayed sister crafters with the tag stripped; the receiver then re-stamped them as the home guild, the visibility gate purged them (not in the home roster), the relay re-added them, and the cycle repeated — counts visibly oscillating with no membership change. The merge now treats an explicit shipped tag as authoritative and never lets a tagless (older-build) broadcast overwrite an attribution it already holds, so a known cross-guild crafter stops flipping. The roster gate still decides visibility, so genuine leavers are still purged. Location: Scanner.lua (MergeCraftersIntoGdb).

Improvements

  • Diagnostics: orphan breakdown. The Cross-Guild diagnostics now show, per allied guild, how many crafters match the roster vs. are orphaned (with a few example keys), making it easy to tell roster-matching issues from genuine non-members. Location: GUI/Settings.lua.

[v0.10.2-beta] (2026-06-09) - Cross-guild relay attribution & diagnostics (beta)

Beta build. Continues the cross-guild work from v0.10.1-beta. Backward-compatible and dormant until an allied guild is configured. Requires DeltaSync v3.1.0+ and GuildRoster v6+ (both install/update automatically). For cross-guild relay to work, all participating players need this build.

New Features

  • Cross-guild diagnostics panel. A live, read-only status section on Settings → Cross-Guild showing dependency status (DeltaSync/RosterSync, LibGuildRoster/multi-roster), known rosters (home + each sister) with member counts, configured allied guilds, crafter counts per guild, and persisted allied rosters with feed timestamps. Plus a "Pull from player" field to trigger a pull without the slash command. Location: GUI/Settings.lua.
  • /togpm xgdiag command. Dumps the same cross-guild diagnostics to chat as plain lines for easy copy-paste when troubleshooting. Location: GUI/Settings.lua, TOGProfessionMaster.lua.

Bug Fixes

  • Cross-guild attribution now survives relays. The crafters sync leaf previously shipped bare character keys with no guild tag, on the assumption that every crafter in a payload belonged to the receiver's guild. In a confederation that assumption breaks: when a member who holds sister-guild data rebroadcasts it into their home guild, those sister crafters were re-stamped as the home guild and then hidden/purged by the visibility gate (not in the home roster). The leaf now ships each crafter's origin guild tag (already stored locally), so a relaying "bridge" member can propagate allied-guild crafters into their home guild with attribution intact. The leaf hash is unchanged (it already normalized values before hashing), so old and new clients stay in sync — but both ends of a relay must run this build for tags to be preserved. Location: Scanner.lua (BuildLeafPayload, MergeCraftersIntoGdb).

[v0.10.1-beta] (2026-06-09) - Cross-guild profession sharing (beta)

Beta build. This is the first testable cut of cross-guild sharing. It is fully backward-compatible — single-guild users are unaffected and the feature stays dormant until an allied guild is configured — but the cross-guild round-trip has not yet been validated with live players. Please report issues. Requires DeltaSync v3.1.0+ and GuildRoster v6+ (both install/update automatically).

New Features

  • Cross-guild profession sharing (beta). TOGPM can now share recipe/crafter data between two socially-linked guilds that can't reach each other over the normal guild addon channel. Configure an allied guild under Settings → Cross-Guild, and your crafters become discoverable to them (and theirs to you). Built on directed peer-to-peer whispers — no extra chat channel required. Location: GUI/Settings.lua, Scanner.lua, TOGProfessionMaster.lua.
  • Sister-guild roster tracking. Allied-guild rosters are pulled, persisted across /reload, and kept live via LibGuildRoster-1.0's multi-roster store, so allied crafters survive a session restart and stay correctly attributed to their own guild. Location: Scanner.lua (PersistSisterRoster, RefeedSisterRosters, OnSisterRosterUpdated).
  • /togpm pullroster <player> command. Manually pull an online allied-guild member's roster and crafter data on demand — the testing/bootstrap path before automatic discovery lands. Location: TOGProfessionMaster.lua.

Improvements

  • Settings window is now tabbed. Options are organized into General and Cross-Guild tabs (with room for officer/GM-only settings as features grow). Location: GUI/Settings.lua.
  • Each guild stays authoritative for its own membership. Cross-guild data exchange shares only a guild's own crafters and is opt-in (nothing is served until you configure an allied guild), so attribution can never bleed between guilds in a multi-guild confederation. Location: Scanner.lua (BuildFullGuildPayload).

Bug Fixes

  • Settings window position, size, and selected tab now persist across /reload. The standalone options window kept its geometry in a runtime-only table; it's now backed by SavedVariables (.char.frames.settings), matching the main window. Location: GUI/Settings.lua.

Known Limitations (beta)

  • Allied-guild crafters currently display as offline — live presence arrives with automatic /who discovery in a later beta.
  • Cooldown sharing is not yet cross-guild (crafter data only this build).
  • Allied data must be bootstrapped with /togpm pullroster <name>; automatic discovery is not in this build.

[v0.10.0] (2026-06-05) - Roster engine migration (LibGuildRoster-1.0)

Improvements

  • Roster engine migrated to LibGuildRoster-1.0. Guild-roster data (membership, online state, and the join/leave/online callbacks) now comes from the standalone LibGuildRoster-1.0 library (the GuildRoster addon) instead of the retired GuildCache-1.0. This is the foundation for upcoming cross-guild support. GuildRoster is now a dependency and installs automatically. Location: Scanner.lua, TOGProfessionMaster.lua, Tooltip.lua, GUI/BrowserTab.lua, GUI/CooldownsTab.lua.

Bug Fixes

  • Pending-purge sweep now re-validates before deleting. The timed sweep that removes departed members' data re-checks each flagged character against the live roster, deletes only confirmed non-members, and bails entirely if the roster isn't ready — closing any path where a legitimate guildmate's crafter data could be removed by a stale or early-login purge flag. Location: TOGProfessionMaster.lua (RunPendingPurge).
  • Visibility gate hardened against an unbuilt roster. A tag-matching crafter is shown (not flagged for purge) while the roster library is absent or still loading, restoring the pre-migration leniency and preventing early-login false-flags. Location: TOGProfessionMaster.lua (IsVisibleCrafter).

[v0.9.1] (2026-06-02) - Profit Planner UX, addon-wide sortable headers, search icons & persistence fixes

New Features

  • Profit Planner profession filter now supports multi-select. The Professions dropdown in the Profit tab is a native AceGUI multi-select dropdown (matching the Crafters/Sources dropdowns) that stays open while you tick multiple professions, with Select All / Clear All rows at the top. It defaults to all professions except Enchanting on first load (locale-safe addon.PROF_NAMES[333] lookup); once you clear the selection it stays cleared. Location: GUI/AHProfitTab.lua.

  • Missing Recipes columns are now sortable. Click the Recipe, Skill, or Sources headers to sort the list (click again to reverse); it defaults to skill ascending. Location: GUI/MissingRecipesTab.lua.

  • Tab selection now persists across /reload and addon reopen. The main window remembers which tab you were viewing (Browser, Cooldowns, Missing Recipes, Crafting, Profit Planner, Shopping List) in lastMainTab and restores it when you reopen the addon or reload the UI. Profit Planner's subtab (Live AH Profit vs Historical Profit) also persists independently in profitSubTab. Location: GUI/MainWindow.lua, GUI/AHProfitTab.lua, TOGProfessionMaster.lua.

Improvements

  • Profit Planner money columns sized to fit the window. Craft Cost, Sell Price, and Profit columns widened from 72px to 112px for readability while still fitting inside the minimized window (the right edge and scrollbar stay on-screen). Location: GUI/AHProfitTab.lua.

  • Sortable column headers now share one consistent style across the addon. On the Profit Planner, Cooldowns, Crafting, and Missing Recipes tabs, headers are centered over their columns with the up/down sort arrow placed beside the header text (measured via GetStringWidth) rather than at the column's far edge, plus a brand-colored glow that fades in on hover to signal "click to sort". Built as shared helpers (ConfigureCenteredHeaderIcon, MakeHeaderHoverGlow) so any future sortable header matches automatically. Location: GUI/SharedWidgets.lua, GUI/AHProfitTab.lua, GUI/CooldownsTab.lua, GUI/CraftingTab.lua, GUI/MissingRecipesTab.lua.

  • Profit Planner row count moved to the window status bar. "Rows: N" now follows the version string in the bottom status bar (e.g. v0.9.1 Rows: 300) instead of a mid-panel label, and reverts to just the version on other tabs. Location: GUI/AHProfitTab.lua, GUI/MainWindow.lua.

  • Profit Planner recipe tooltips now show full game item tooltips with profit details. Row hover anchors the game's native item tooltip (via GameTooltip:SetHyperlink) and appends a profit breakdown (source, craft cost, sell price, profit) below the standard item data, matching the enriched tooltip pattern from the Browser/Cooldowns tabs. Location: GUI/AHProfitTab.lua.

  • AH data source toggle changes now prompt for /reload in settings. Added a yellow warning label above the AH data source checkboxes (Auctionator, TSM, etc.) reminding users that toggling pricing integrations on/off requires a /reload to fully take effect, since external addon APIs are cached at load time. Location: GUI/Settings.lua.

  • Search boxes now use a magnifying-glass icon instead of a text label. The Profit Planner, Browser, Crafting, and Missing Recipes search fields show WoW's universal search icon inside the box (TSM-style) rather than a "Search recipes" label, via a shared StyleSearchBox helper. The Profit Planner "+ Profit only" checkbox also sits on the same center line as the dropdown controls. Location: GUI/SharedWidgets.lua, GUI/AHProfitTab.lua, GUI/BrowserTab.lua, GUI/CraftingTab.lua, GUI/MissingRecipesTab.lua.

Bug Fixes

  • Profit Planner empty profession filter now shows no rows. Previously, unchecking every profession (or using Clear All) displayed all rows and re-checked everything on the next redraw. An empty selection now matches no rows, and the all-except-Enchanting default applies only on first build. Location: GUI/AHProfitTab.lua.

  • Sort arrow no longer vanishes after the first sort/filter. The arrow texture was detached (SetParent(nil)) when its column went unsorted and never re-attached when shown again, so it disappeared once the sort column changed. ConfigureHeaderIcon now re-parents the texture before showing it, and sortable headers register OnRelease callbacks that clean up widget._sortIcon textures (Hide, SetParent(nil), ClearAllPoints, nil) so they don't bleed across pooled AceGUI widgets. Location: GUI/SharedWidgets.lua, GUI/AHProfitTab.lua, GUI/CooldownsTab.lua, GUI/CraftingTab.lua.

  • Missing Recipes skill sort no longer buries default recipes. Sorting by Skill now falls back to a recipe's orange difficulty tier when it has no explicit required-skill value (e.g. Basic Campfire), so low-skill recipes sort to the top instead of being treated as unknown and pushed to the bottom. Only recipes with neither value remain last. Location: GUI/MissingRecipesTab.lua.

  • Fixed memory leak: GameTooltip now hides when switching tabs. If the tooltip was showing for a Profit tab element when you switched tabs, it remained visible and anchored to the wrong position. DetachPool now calls GameTooltip:Hide() on tab detach. Location: GUI/AHProfitTab.lua.


[v0.9.0] (2026-06-01) - Shared global headers/sort across tabs

New Features

  • Added a dedicated Profit Planner tab. TOGPM now has a full AH profit-planning view for recipes known by your own characters, with separate Live AH Profit and Historical Profit subtabs so you can compare current listings against longer-horizon pricing without leaving the addon. The tab is wired into the main window as a first-class screen rather than a Crafting detail add-on, giving profit sorting/planning its own workspace. Location: GUI/AHProfitTab.lua, GUI/MainWindow.lua, Locale/enUS.lua.

Improvements

  • One shared global sortable-header path now drives all sortable tabs. Added shared helpers in addon.GUI.Sort for header-icon rendering and click-state transitions, then switched the Profit Planner, Cooldowns, and Crafting tab headers to use those globals instead of per-tab copies. Sort arrows now come from one reusable function (ConfigureHeaderIcon) with the same FGI-style texture behavior everywhere, and click transitions now use one shared state function (Next / NextOrNone) so tab behavior stays consistent as future columns are added. Location: GUI/SharedWidgets.lua, GUI/AHProfitTab.lua, GUI/CooldownsTab.lua, GUI/CraftingTab.lua.

  • Column-header styling is further centralized through shared helpers. Updated remaining table headers that were still hand-styled to use the shared brand/header factory, reducing drift between tabs and keeping color/style changes globally managed. Location: GUI/ShoppingListTab.lua, GUI/BrowserTab.lua.

  • Labeled dropdowns and edit boxes now share one global label offset. The old per-tab one-off nudges were replaced with a shared input-label helper that shifts labeled Dropdown/EditBox headers by the same 4px everywhere they appear, and restores the original anchors on release so pooled AceGUI widgets do not leak the tweak into other owners. Location: GUI/SharedWidgets.lua, GUI/BrowserTab.lua, GUI/CooldownsTab.lua, GUI/MissingRecipesTab.lua, GUI/ShoppingListTab.lua.

  • Zebra striping is now global across tab row lists. The shared addon.GUI.ApplyRowStripe helper now drives row banding throughout the addon table UIs (not just Profit Planner), so stripe appearance is centralized and consistent across Browser, Missing Recipes, Crafting, Cooldowns, and Shopping List views. Location: GUI/SharedWidgets.lua, GUI/BrowserTab.lua, GUI/MissingRecipesTab.lua, GUI/CraftingTab.lua, GUI/CooldownsTab.lua, GUI/ShoppingListTab.lua.

  • Cooldowns rows now render with the same raw frame/fontstring model as Missing Recipes, while still using the shared GUI helpers. The tab no longer relies on AceGUI row-cell widgets for the list body; each row now uses raw frame hit zones, textures, and fontstrings like the working Missing Recipes/Professions lists. The reworked rows now also detach their raw child frames through the shared addon.GUI.DetachPool release path when AceGUI recycles a row widget, so the pooled Cooldowns rows don't bleed into later widget reuses. Headers remain on the shared column factory and row hovers stay on the addon-wide tooltip-owner path. Location: GUI/CooldownsTab.lua, GUI/SharedWidgets.lua.

  • Profit Planner now has Missing-Recipes-style subtab filters plus recipe search. Each Profit subtab now renders its own toolbar with dynamic Profession and Crafter dropdowns populated only from rows currently present in that subtab, a + Profit only toggle, a recipe search box, and a multi-select source filter that defaults to all sources currently enabled by settings for that mode. Filtering runs before sort/render and keeps per-subtab state. Location: GUI/AHProfitTab.lua.

  • Profit Planner now shows all known craftable recipes, not only fully-priced rows. Row construction no longer drops recipes just because the crafted item has no current sale source or because one or more reagents lack price data; those rows are now retained with clear "No price" source text and empty cost/profit values until pricing is available. Source filtering now applies only when a row actually has source data, so default views do not hide unpriced recipes. Location: GUI/AHProfitTab.lua.

  • TSM App Helper pricing is now wired into material-cost lookups used by Profit/Crafting cost math. The generic item-price resolver (Price.Get) now includes TSM live/history fallbacks (before TOGPM scan/vendor tiers), so reagent costing can consume TSM coverage instead of appearing unpriced when Auctionator/TOGPM scan data is absent. Also removed a hidden gate that required the separate "Use TSM" toggle for App Helper reads, so App Helper can function when its own toggle is enabled. Location: Modules/Price.lua.

  • Crafting reagent source tags no longer truncate in the detail panel cost column. The per-reagent cost field was width-limited to coin text only, which clipped trailing source suffixes (e.g. [TOGPM]/[TSM]) on longer values; the column now has enough width to extend left and render full cost+source text. Location: GUI/CraftingTab.lua.

  • TSM sell-price lookup now falls back across the full TSM source stack to avoid nil sell prices when TSM has data. The TSM bridge now tries both item string forms (i:itemId and item:itemId) and a broader ordered source chain (DBMinBuyout/DBRecent/DBMarket/DBHistorical plus DBRegionMarketAvg and DBRegionSaleAvg fallbacks), so items missing realm-live values can still resolve from TSM historical/region datasets in Profit views. Location: Modules/Price.lua.

  • Profit Planner now resolves sell-price item IDs and source filters more defensively to avoid false No price rows. Sell lookup now probes multiple candidate output IDs per recipe (scanned crafted-item link first, then LibProfessionDB crafted item, then fallback item field), using the first one that resolves a price. Historical/live views now also allow cross-mode fallback when one side is missing, and the Profit-tab enabled-source defaults were aligned with the shared Price module's TSM toggle logic so valid TSM rows are not filtered out accidentally. Location: GUI/AHProfitTab.lua.

  • Per-tab scroll position now persists to SavedVariables and restores after tab switches/reopen. The shared PersistentScroll helper now stores each tab's scroll status in TOGPM_Settings.char.frames.scrollTabs and restores from that table on redraw, so Browser/Cooldowns/Missing/Crafting/Profit return to the same place after refreshes, tab hops, and window reopen/reload. Profit keeps separate saved scroll for Live vs Historical subtabs. Location: GUI/SharedWidgets.lua, GUI/BrowserTab.lua, GUI/CooldownsTab.lua, GUI/MissingRecipesTab.lua, GUI/CraftingTab.lua, GUI/AHProfitTab.lua.

  • BoP reagents no longer create false profit/cost gaps. Craft-cost completeness now excludes Bind-on-Pickup reagents from the priced == count gate, so recipes like Gordok Ogre Suit are still costed/profited from their priceable materials even when BoP components (for example Ogre Tannin) have no AH/vendor market price. Non-BoP unpriced reagents still correctly mark totals as lower-bound. Location: Modules/Price.lua.

  • Profit search box no longer drops keyboard focus after the first character. The Profit tab search handler previously triggered a full table redraw on every OnTextChanged, which recreated the edit box and swallowed the caret. Search now refreshes rows in place (filter/sort/row repaint only) so typing remains continuous. Location: GUI/AHProfitTab.lua.

  • TSM source labels now distinguish live quotes from AppHelper-backed data. TSM prices are now classified by the exact TSM expression that resolved: DBMinBuyout/DBRecent remain TSM Live, while DBMarket/DBHistorical/region values are labeled as non-live (TSM App) so Profit/Crafting columns no longer show everything as live. Profit source filters were updated so both TSM categories stay visible by default in each subtab. Location: Modules/Price.lua, TOGProfessionMaster.lua, GUI/AHProfitTab.lua, GUI/MainWindow.lua.

  • Auctioneer pricing is now integrated as an optional non-live source. Added a new Use Auctioneer pricing toggle and wired AucAdvanced.API.GetMarketValue into sale/cost lookups as Auctioneer App (non-live), with source labels/colors, Profit source-filter support, Crafting source tags, and TOC/pkgmeta optional dependency declarations. This allows using Auctioneer-backed values when TSM is disabled, without mislabeling them as live quotes. Location: Modules/Price.lua, GUI/Settings.lua, TOGProfessionMaster.lua, GUI/AHProfitTab.lua, GUI/CraftingTab.lua, GUI/MainWindow.lua, .toc files, .pkgmeta.

  • Auctioneer source naming now resolves more reliably on sell-price rows. Auctioneer market-value lookup now tries canonical item string forms (including full 8-field item: form) before falling back, which avoids false No price rows where Auctioneer has data but couldn't parse a compact link form. Resulting rows now correctly show the Auctioneer App source label. Location: Modules/Price.lua.

  • Auctioneer source naming now falls back to stat-engine values when market-value returns nil. When Auctioneer's combined market-value PDF path has insufficient data for an item, TOGPM now probes common Auctioneer stat engines (stat_simple, stat_histogram, stat_stddev, stat_iLevel) before giving up, reducing remaining false No price rows and preserving Auctioneer App source labels where Auctioneer has usable pricing. Location: Modules/Price.lua.

  • Auctioneer now has a separate cached-fallback toggle, mirroring live-then-helper behavior. Settings now include a second checkbox directly under Use Auctioneer pricing: Use Auctioneer cached pricing fallback. Resolver flow now tries Auctioneer primary market value first, then only uses Auctioneer cached stat-engine values when primary returns nil and the cached toggle is enabled, matching the intended two-stage fallback model used by other pricing integrations. Location: GUI/Settings.lua, Locale/enUS.lua, Modules/Price.lua, TOGProfessionMaster.lua.

  • Auctionator now has a separate historical/cached fallback toggle, matching the Auctioneer two-stage model. Added Use Auctionator cached historical fallback directly under Use Auctionator pricing; resolver flow now tries Auctionator live first, then only uses Auctionator cached historical pricing when live is unavailable and the second toggle is enabled. Profit source defaults were aligned so Auctionator History is enabled only when this toggle is on. Location: GUI/Settings.lua, Locale/enUS.lua, Modules/Price.lua, GUI/AHProfitTab.lua, TOGProfessionMaster.lua.

  • Auctioneer source labels are now split in UI to clearly show live vs cached origin. Resolver output now distinguishes Auctioneer primary market values (Auctioneer Live) from stat-engine fallback values (Auctioneer Cached) instead of reporting both as one Auctioneer App bucket, aligning with the same live-vs-cached clarity used for TSM labels. Profit source filters, main help legend, and Crafting source tags now surface the split explicitly, with a back-compat migration path for existing saved Profit source selections. Location: Modules/Price.lua, TOGProfessionMaster.lua, GUI/AHProfitTab.lua, GUI/MainWindow.lua, GUI/CraftingTab.lua.

  • Legacy Auctioneer alias text now resolves to Auctioneer Cached for consistency. The old compatibility key (auctioneer-app) is still accepted for saved-state/back-compat paths, but its UI label/color now map to cached semantics so users never see contradictory Auctioneer App wording after the live/cached split. Location: TOGProfessionMaster.lua, GUI/CraftingTab.lua.

  • Missing Recipes column-header sorting is now wired into the shared global sort path. The header row now uses clickable shared column headers with global sort indicators and state transitions (same addon.GUI.Sort pipeline as other sortable tabs), and the tab now applies sort to Recipe, Skill, and Source before virtual-row render. This fixes the broken/no-op header clicks in Missing Recipes. Location: GUI/MissingRecipesTab.lua.

  • Auctioneer live/cached probes are now more tolerant across API variants, and a new price diagnostic slash command was added. The resolver now probes multiple Auctioneer call signatures and alternate stat-engine identifiers for cached values instead of relying on one strict signature, reducing false nils when Auctioneer builds/plugins expose slightly different APIs. Added /togpm dumpprice <itemId|itemLink> to print Get/GetSaleLive/GetSaleHistorical and Auctioneer live-vs-cached diagnostics for one item (for example Savory Deviate Delight 6657) directly in chat. Location: Modules/Price.lua, TOGProfessionMaster.lua.

  • Auctioneer cached pricing now falls back to Stat modules directly when algorithm APIs yield nil. Some Auctioneer installations expose cached prices through loaded Stat-* modules even when GetAlgorithmValue is unavailable or non-productive; TOGPM now probes AucAdvanced.GetAllModules(nil, "Stat") + each module's GetPriceArray and picks the best seen-backed cached value before giving up. dumpprice output now also reports whether the Auctioneer module registry is available for this fallback path. Location: Modules/Price.lua, TOGProfessionMaster.lua.

  • Global multi-select dropdown handler added, and Profit tab dropdown filters now all use it. Added a shared addon.GUI.MakeMultiSelectDropdown factory (summary row + checkmark rows + no-empty fallback) and migrated Profit Profession, Crafters, and Sources filters to it so they now share one look/behavior and all support multi-select. Back-compat migration from older single-select profession/crafter state is handled automatically. Location: GUI/SharedWidgets.lua, GUI/AHProfitTab.lua.

  • TOGPM scanned-AH source now has an explicit on/off gate (no bleed when disabled). Added a dedicated Use TOGPM scanned AH pricing setting and wired the central resolver to honor it for both reagent costs and live sell-price paths; when turned off, TOGPM's cached AH values are excluded so external-only testing (for example Auctioneer-only) is accurate. Profit source defaults now also respect this toggle. Location: Modules/Price.lua, GUI/Settings.lua, GUI/AHProfitTab.lua, TOGProfessionMaster.lua.

  • Blizzard Auction House now gets a native TOGPM Scan button. Mirroring the profession-window TOGPM toggle pattern, the addon now injects a manual branded scan button directly onto the Blizzard AH frame (legacy and modern frame names), wired to TOGPM's full-scan path so users can trigger a TOGPM price refresh from the AH UI itself without opening any TOGPM tab first. Button state auto-disables while scans run and re-enables on completion/cancel/close. Location: Modules/AHScanner.lua.

  • Profit-tab recipe icons now use Crafting-style fallbacks for reliable rendering. Profit rows now resolve icons using crafted-item texture first and fall back to recipe spell texture when item-icon cache data is unavailable, fixing intermittent ?/missing icons on entries like Savory Deviate Delight while preserving normal item-icon rendering when available. Location: GUI/AHProfitTab.lua.

  • Profit now rejects recipe-scroll IDs when crafted output IDs exist. For recipes that provide both IDs (for example Savory Deviate Delight: crafted 6657, recipe scroll 6661), Profit sell/icon candidate selection now anchors to crafted output and ignores scroll-item IDs, preventing recipe-scroll icon/source leakage in Profit rows. Location: GUI/AHProfitTab.lua.

  • Browser and Cooldowns profession filters now use the shared global multi-select dropdown handler. Both tabs now use addon.GUI.MakeMultiSelectDropdown for profession filtering so the selector look/behavior matches Profit (same summary row/checkmark UX) and supports selecting multiple professions at once. Cooldowns keeps its specific cooldown sub-filter visible only when exactly one profession is selected, preserving the existing two-level workflow without inconsistent dropdown styles. Location: GUI/BrowserTab.lua, GUI/CooldownsTab.lua, GUI/SharedWidgets.lua.

  • Era recipe gating is now stricter in Missing Recipes and Browser to stop SoD/non-valid bleed-through. Client-validity filtering no longer skips required-skill/high-ID sanity checks just because recipe metadata is lib-backed, and unknown-client suppression now checks crafted-item IDs as well as recipe-scroll IDs before showing rows. This keeps legitimate late-Vanilla recipes while filtering non-Era bleed from shared 1.15-era datasets. Location: GUI/MissingRecipesTab.lua, GUI/BrowserTab.lua.

  • Global multi-select dropdown UX now supports true multi-pick sessions. The redundant selected-row check indicator was removed by moving the selected-count summary into the collapsed control text, and multi-select menus now stay open while you toggle items so you can select/deselect several entries before clicking away. Profit filter updates now refresh rows in place (not full redraw) so the open pullout is preserved while selecting. Location: GUI/SharedWidgets.lua, GUI/AHProfitTab.lua.

  • Fixed Missing Recipes invalid order function for sorting Lua error. Header-sort logic now precomputes stable sort keys before table.sort instead of calling live item/spell lookup APIs inside the comparator, preventing comparator instability while cache lookups change during sort passes. Location: GUI/MissingRecipesTab.lua.

  • Fixed blank captions on global multi-select dropdowns. The collapsed selected-count text now persists correctly after list refreshes; dropdowns no longer render as empty dark boxes after the keep-open multi-select UX change. Location: GUI/SharedWidgets.lua.

  • Fixed first-click multi-select behavior in profession filters. The dropdown now clears AceGUI's internal selected row marker (so only per-item checkmarks are shown) and uses a short delayed reopen tick so the pullout reliably stays open while you pick multiple entries in one session. Location: GUI/SharedWidgets.lua.

  • Fixed multi-select reopen race that could still close after each pick. The shared dropdown now waits for the pullout to finish closing, then reopens once (with short retry ticks) instead of blindly toggling immediately, so multi-select sessions stay open consistently on first and subsequent clicks. Location: GUI/SharedWidgets.lua.

  • Multi-select action rows now include both Select all and Clear all. The old Reset to all action is now named Select all, and a new Clear all action clears every selected entry in one click for profession/crafter/source filters using the shared helper. Location: GUI/SharedWidgets.lua, GUI/BrowserTab.lua, GUI/AHProfitTab.lua.

  • Fixed Missing Recipes tab crash (attempt to index local 'kb' (a nil value)) during sort. Sort-key precompute now uses defensive fallback key generation inside the comparator so sparse/edge-case lists cannot crash when a compared row lacks a cached key. Location: GUI/MissingRecipesTab.lua.

  • Fixed multi-select toggles that appeared to do nothing on some dropdowns. The shared dropdown function now maps UI tokens back to canonical key types before mutating selection state, preventing numeric/string key mismatches from turning select/unselect clicks into no-ops. Location: GUI/SharedWidgets.lua.

  • Multi-select dropdowns now use AceGUI's built-in multiselect flow directly. The shared helper now calls Dropdown:SetMultiselect(true) and synchronizes selection via SetItemValue(...), removing custom keep-open/reopen hacks and aligning behavior with AceGUI's native toggle handling while keeping shared Select all / Clear all actions. Location: GUI/SharedWidgets.lua.

  • Fixed open multi-select pullouts going visually empty after a click. The shared helper no longer rebuilds SetList(...) on every toggle while the pullout is open; it builds once and then only syncs check-state/text, matching AceGUI's open-time item rendering lifecycle. Location: GUI/SharedWidgets.lua.

  • Fixed Missing Recipes sparse-list sort crash (table index is nil). The comparator now guards nil operands before key lookup and never indexes the key cache with nil, preventing edge-case tab-open crashes when a sparse row list reaches table.sort. Location: GUI/MissingRecipesTab.lua.


[v0.8.4] (2026-06-01) — Enchanting shows a single "Enchant" button

Improvements

  • Enchanting now presents one clean "Enchant" button. Because an enchant is applied to a single item, the Crafting tab's controls for Enchanting are simplified to just an Enchant button (the secure /cast from v0.8.3) — the quantity stepper, Craft Max, and Queue are hidden (none apply to one-at-a-time enchanting), the button moves to the top of the controls column, and the detail panel sizes down to suit. Every other profession keeps the full Craft / Craft Max / Queue stack with the quantity controls. Also hardened: the now-secure Craft button's enable / position / attribute changes are guarded against combat lockdown (they can't be changed mid-combat). Location: GUI/CraftingTab.lua.

[v0.8.3] (2026-06-01) — Enchanting can be cast from the Crafting tab (protected-function fix)

The DoCraft error is gone for certain (we no longer call it); the secure-cast enchant path is pushed for community testing — there's no enchanter on the test account to verify it in-game.

Bug Fixes

  • The DoCraft error is gone, and Enchanting should now craft from the Crafting tab. Root cause of the long-running "can't enchant" bug: DoCraft — the Vanilla/TBC Craft API used for Enchanting — is a protected function, so an addon calling it from Lua trips ADDON_ACTION_FORBIDDEN and the craft is blocked. (That's why only Enchanting failed; DoTradeSkill, used by every other profession, isn't protected.) Fix — the same technique TradeSkillMaster uses: the Craft button is now a secure action button that, for an enchant, runs a /cast <recipe> macro. A /cast inside a secure macro is allowed, so the enchant casts and you click the target item to apply it — just like Blizzard's own Create button. Trade-skill professions keep the normal Lua craft (with batch quantity) via the button's PreClick. Craft Max / queued enchants still open Blizzard's Create button. Location: GUI/CraftingTab.lua, Modules/Crafting/CraftingEngine.lua, Locale/enUS.lua.

[v0.8.2] (2026-06-01) — Opt-in AH scan & crafting takeover, SoD recipe filtering, enchant-button fix, consumable buffs

Heads-up: this release adds LibItemDB as a required dependency (for consumable buff data). Like LibProfessionDB it must be published on CurseForge before this ships, or installs break on the missing dependency.

New Features

  • Crafted-item stats & consumable buffs from LibItemDB. Recipes now carry their product's stats, read at runtime from the new LibItemDB library via DB:GetStats (which merges equip stats + use-effects) — so it covers crafted gear (Blacksmithing / Tailoring / Leatherworking: +5 Strength, +12 Stamina, +400 Armor) and consumables (food / elixir / flask / potion: +12 Spirit, +12 Stamina) in one path. The Crafting / Professions / Missing Recipes searches now find recipes by stat — strength, 12 stam, spirit — and the recipe tooltip shows the stat line, the same effect field enchants already use. LibItemDB is authoritative; ProfessionDB's effect text is the fallback only for true enchants, which LibItemDB doesn't cover. It's a required dependency (auto-installed by CurseForge; read via LibStub, never embedded), and its data is per-game-version. GetStats exposes the GetItemStats vocabulary (+stats, resistances/armor, crit/health/mana), so an item whose only effect is a non-stat one (a flat damage absorb like Fire Protection Potion) has no line to show. A new /togpm itemgaps [profId] command lists crafted items LibItemDB returns no stats for, to surface coverage gaps for filling. Location: TOGProfessionMaster.lua (GetCraftedItemStatText / GetRecipeEffect / ReportItemDBGaps), GUI/CraftingTab.lua, GUI/BrowserTab.lua, GUI/MissingRecipesTab.lua, TOCs + .pkgmeta.

  • Craft Max & Craft All — fewer clicks to batch-craft. A new Craft Max button in the detail panel (between Craft and Queue) queues the most of the selected recipe you can make right now and starts crafting it in one click — Skillet's "Create All"; fan across several recipes (Craft Max each) to stack them all up fast. And a new Craft All button in the queue panel (between Craft Next and Clear All, all three on one row at the same total width) works down the whole queue, crafting each eligible recipe in turn — it chains to the next as each batch finishes, stopping on an interrupt or when nothing's left (Enchanting still pauses for you to click each target). Location: GUI/CraftingTab.lua, Modules/Crafting/CraftQueue.lua.

  • Profit / loss on the Crafting tab. The Crafting Cost row now also shows — when the crafted item has an Auction House price (from Auctionator or TOGPM's own AH scan; never the vendor table) — the item's lowest AH buyout and the profit: AH price − crafting cost, green if you'd come out ahead, red if you'd lose coin (cost 5g / sells 8g → +3g; cost 5g / sells 3g → -2g). The row reads cost / AH / profit. Profit only shows when the craft cost is fully priced and there's a real AH sale price for the product. (First cut: assumes one item per craft and ignores the AH cut.) Location: GUI/CraftingTab.lua.

Changes

  • The automatic Auction House full-scan is now opt-in (off by default). v0.8.0 auto-ran a full getAll scan every time you opened the Auction House. That scan draws on a shared, client-wide budget the server limits to roughly once every 15 minutes — so on a client also running a dedicated AH addon (Auctionator, TradeSkillMaster, etc.) it consumed the budget that addon needs for its own scan and blocked it. A new Settings → Auction House → "Auto-scan the Auction House on open" toggle, off by default, now gates it, with a tooltip that spells out the once-per-15-min, shared-across-addons trade-off. With it off, TOGPM never fires a getAll on open (your other AH addon keeps its budget); cost-to-craft falls back to the built-in vendor prices, Auctionator (if you enable that), and the per-tab [Scan AH] buttons — which do small targeted per-item lookups, not getAll, and are unaffected. Turn the toggle on to restore the v0.8.0 auto-scan behaviour. Location: Modules/AHScanner.lua, GUI/Settings.lua.

  • The TOGPM Crafting tab no longer replaces the Blizzard profession window by default. Opening a profession at a station now opens Blizzard's own crafting window, with the TOGPM button on it to switch to the Crafting tab whenever you like — so TOGPM no longer takes over every profession open. Two new Settings → Crafting toggles, both off by default: "Open the TOGPM Crafting tab automatically" restores the old takeover (opens straight into the TOGPM tab), and "Remember the last crafting UI used" reopens whichever UI — Blizzard window or TOGPM tab — you last used, overriding the first toggle (saved per character). The takeover setting moved from per-character to account-wide (profile); /togpm craft on|off still flips it. Conversely, navigating to the TOGPM Crafting tab itself now auto-opens your selected profession straight into TOGPM (no Open <profession> button click needed) — going to that tab is an explicit choice to craft there, so it overrides the default-to-Blizzard rule. Location: Modules/Crafting/CraftingEngine.lua, GUI/CraftingTab.lua, GUI/Settings.lua.

Bug Fixes

  • Missing Recipes (and the Professions browser) no longer list Season of Discovery recipes on Era / Hardcore / Anniversary. SoD runs on the same 1.15 client as Era, so its recipes live in the shared client tables — and therefore in LibProfessionDB's Vanilla set — even though they can't be learned on a non-SoD realm (e.g. Enchant Weapon - Grand Crusader, Sigil of Innovation, Blackfathom Mana Oil, Scroll of Spatial Mending). v0.8.0 had dropped TOGPM's client-side recipe gates (trusting the version-scoped lib data), which let them through. SoD content sits in a distinct spell-ID range (400,000+) far above any real Vanilla recipe (under ~30,000), so a Vanilla client that isn't running Season of Discovery now hides IDs ≥ 200,000. SoD itself is detected via the rune-engraving system (C_Engraving), so actual SoD players keep their recipes. Location: Compat.lua, GUI/MissingRecipesTab.lua, GUI/BrowserTab.lua.

  • Enchanting's Craft button enable now covers both crafting APIs. v0.8.1 made the Craft button derive its craftable count from reagents for the Vanilla/TBC Craft window (since GetCraftInfo's numAvailable reads 0 for enchants, which produce no item). That repair now also applies to the trade-skill API as a fallback (GetTradeSkillInfo numAvailable == 0 → mats-based count), so Enchanting's Craft button enables when you hold the materials regardless of which API the client routes Enchanting through. A disabled button was why clicking did nothing / never put up the apply-to-item cursor; once enabled, DoCraft/DoTradeSkill raises that cursor — the same call TradeSkillMaster makes from its own UI. (Still pending community confirmation — no enchanter on the test account.) Location: Modules/Crafting/CraftingEngine.lua.

  • The "TOGPM" button now appears on Blizzard's profession window whenever it's open — not only when you switch to it from TOGPM. It's hooked to the frame's OnShow, so it rides along even when a coexisting addon (TSM, Skillet) or the auto-open-into-TOGPM flow is what put the Blizzard window up, and even if that addon shows the frame after our handler runs (immediate-show-if-visible covers the event-order race). That guarantees there's always a way back into TOGPM after you close its window. Previously the button was only injected on our own ShowDefaultUI path, so it was missing in those cases. Location: Modules/Crafting/CraftingEngine.lua.

  • Recipe tooltips no longer stretch across the screen. The Professions tab builds a recipe's hover tooltip by scraping the crafted item's tooltip lines; long ones (e.g. a flask's verbose Use: text, or a six-school resistance line) were added unwrapped and blew the tooltip out to full screen width. They're now word-wrapped, so the tooltip sizes to its header/stat lines. Location: GUI/BrowserTab.lua.

Improvements

  • Window scale slider. A new Settings → Display → "Window scale" control (50%–150%) scales the entire TOG Profession Master window. It lets the Crafting tab — and every tab — take far less screen space than the resize floor (820×540) allows: scaling shrinks the text, recipe columns and queue panel together instead of squeezing the layout, so nothing overlaps. Independent of size, so the window still resizes and remembers its dimensions; the on-screen footprint is size × scale. Stacks with corner-dragging for full control. Location: GUI/MainWindow.lua, GUI/Settings.lua.

  • Recipe search now matches the crafted item's full tooltip text. Beyond the recipe name and stat line, the Crafting and Professions searches fold in the whole crafted-item tooltip — use/proc text, durations, requirements, flavor — so any word matches (e.g. hour finds a 1-hour elixir, chance on hit finds a proc weapon, requires level 40 works). LibItemDB stores stat values, not the prose, so this text is scraped from the live client item tooltip and cached per item; an item the client hasn't loaded yet becomes searchable once its data arrives. Location: TOGProfessionMaster.lua (GetItemTooltipSearchText), GUI/CraftingTab.lua, GUI/BrowserTab.lua.

  • Clearer reagent counts in the Crafting detail panel. v0.8.1's bank / bags / needed triple was easy to misread — the "needed" figure looked like part of an inventory count. The needed quantity is now a prefix on the reagent name ("12x Greater Eternal Essence"), and the count column is just your inventory, in bags / bank order. Same green/red colouring (green when bags + bank covers the need). The needed prefix carries no tooltip. Location: GUI/CraftingTab.lua.


[v0.8.1] (2026-05-31) — Crafting tab: Enchanting craft, queue completion, resizable window, bank counts & smarter search

Reported from Classic Era Hardcore play-testing. The Enchanting / craft-queue fixes could not be verified locally (no enchanter on the test account) — pushed for community testing.

New Features

  • Crafting tab reagents now show bank / bags / needed. The Missing Materials column previously showed only bags-on-hand against the needed amount; each reagent now reads bank / bags / needed. bank is the count from your last visit to your personal bank — a cached snapshot persisted between sessions (it reuses the existing Reagent Watch bank scan taken on BANKFRAME_CLOSED), so it can be slightly stale until your next bank visit; bags is live. A reagent you've stashed in the bank no longer reads as missing — the row turns red only when bank + bags together fall short of what's needed. Location: GUI/CraftingTab.lua, Modules/ReagentWatch.lua.

  • Optional: clear the craft queue when switching professions. The queue is intentionally kept across profession switches (so you can bounce between professions toward a single goal without rebuilding it). A new Settings → Crafting toggle — "Clear craft queue when switching professions", off by default — empties the queue each time you change the Crafting tab's profession dropdown, for players who prefer a clean slate per profession. Location: GUI/Settings.lua, GUI/CraftingTab.lua.

Bug Fixes

  • Enchanting (and any Vanilla/TBC Craft-window profession) couldn't be crafted from the Crafting tab — the Craft button stayed greyed out, the Have-Materials filter hid every enchant, and the craftable-count column read blank. Root cause: the tab gated craftability on GetCraftInfo's numAvailable, which is unreliable on the classic Craft API — it returns 0 for enchants even with reagents in hand (item-making professions like Alchemy were fine, which is why the bug looked Enchanting-specific). Confirmed against TradeSkillMaster, which ignores numAvailable entirely and derives the craftable count from materials. Fix: CraftingEngine:GetRecipeList now computes num for Craft-window recipes from reagents (min(floor(have/need)), matching TSM's GetNumCraftable), so the Craft button enables when you hold the mats, the Have-Materials filter keeps those enchants, and the count column is correct — all from one corrected number. The enchanting rod is a spell-focus (not a reagent), so it never skews the count. Trade-skill professions keep their reliable numAvailable and are unchanged. Location: Modules/Crafting/CraftingEngine.lua.

  • Switching professions via the Crafting-tab dropdown closed the TOGPM window when another profession addon (e.g. Skillet) was loaded. Root cause: two addons both hijack the trade/craft window, so a profession switch fires a window CLOSE immediately followed by a SHOW, and we tore down synchronously on the CLOSE — collapsing our window in that gap before the SHOW reopened it (disabling Skillet made it stop). Fix: the teardown is now debounced (CraftingEngine:ScheduleClose) — on a CLOSE we wait 0.2s and only fold the window up if both the trade-skill and craft sessions are still closed, so a profession-switch handoff (or a rival addon's event churn) can no longer close us. Location: Modules/Crafting/CraftingEngine.lua.

  • Finished crafts didn't always drop off the craft queue. Two gaps: (1) completion tracking only ran for the queue's Craft Next button — crafting a queued recipe with the detail-panel Craft button left the made item stuck in the queue, because that path never told the queue a craft had started; (2) on the Vanilla/TBC Craft window (Enchanting), the queue expected one UNIT_SPELLCAST_SUCCEEDED per item in the batch even though DoCraft makes exactly one item per call, so an enchant entry never counted down to zero. Fix: both craft buttons now route completion tracking through the single CraftingEngine:Craft chokepoint (new CraftQueue:TrackCraft), and the Craft window registers a single expected success — so a queued recipe decrements as it's made no matter which button started it. Location: Modules/Crafting/CraftQueue.lua, Modules/Crafting/CraftingEngine.lua.

Improvements

  • The Crafting tab is now resizable. It previously opened at a fixed 820×600 with the resize grip removed entirely. It now has a draggable grip (minimum 820×540, no maximum) and the layout reflows to fit: the recipe list grows in both directions while the detail panel stays pinned full-width along the bottom and the queue panel stays pinned to the right. The chosen size is remembered (shared with the Browser tab's resizable size). Reported in-game. Location: GUI/CraftingTab.lua, GUI/MainWindow.lua.

  • Crafting and Professions search now matches each term independently across name + effect. Effect text ships stat-first (e.g. Agility +5, Weapon Damage +5), so the old single-substring match couldn't find natural queries like 5 agi or 5 agility"5 agi" simply isn't a substring of "agility +5", which is why an Enchanting search for 5 agi came back empty even though the effect-search feature was working. Search now splits the query on spaces and requires every term to appear somewhere in the recipe's name + effect, in any order, so 5 agi, agi 5, 5 agility, and weapon damage all match regardless of how the effect text is worded. Reported in-game. Location: GUI/CraftingTab.lua, GUI/BrowserTab.lua.


[v0.8.0] (2026-05-30) — Crafting tab, cost-to-craft, and the LibProfessionDB data library

Heads-up: this release moves the recipe database into the new standalone LibProfessionDB library and depends on it. It cannot load until LibProfessionDB is installed (it's a required dependency in the TOC / .pkgmeta), so it must not ship before that library is published.

New Features

  • Crafting tab. A full fourth tab modeled on TradeSkillMaster's crafting screen but in TOGPM's own style (AceGUI widgets, brand colour, shared tooltip handler). It replaces the native profession window when you open a profession — with a toggle button to drop back to the Blizzard UI — pre-populates a dropdown from your known professions, and lists every recipe with a difficulty-coloured name and an orange→yellow→green→grey skill-tier column. Local single-character crafting; a virtual-scroll raw-frame row pool keeps it instant on large recipe sets. Location: GUI/CraftingTab.lua, Modules/Crafting/CraftingEngine.lua.

  • Craft queue. Queue recipes and craft them top-down, with click-drag to reorder so you can stack-rank what gets made first. Completion-tracked (watches UNIT_SPELLCAST_SUCCEEDED) and persisted as a proper per-character table. Location: Modules/Crafting/CraftQueue.lua.

  • Cost-to-craft. A per-recipe Crafting Cost total (on the recipe-name row, above the Missing Materials label) plus a per-reagent Cost column, summed by a unified price provider. Sources, in priority order: the Auction House (TOGPM's own scan, or Auctionator when you opt in) then a shipped vendor-price table. Markers: * = a reagent has no price yet (total is a lower bound), ~ = a contributing price is stale, = nothing priced. Location: Modules/Price.lua, GUI/CraftingTab.lua.

  • Built-in Auction House scan — no Auctionator required. Opening the Auction House auto-fires a one-pass full scan (legacy getAll on Era/TBC/Wrath, C_AuctionHouse.ReplicateItems on Cata/MoP) that builds TOGPM's own price DB — no button to click. Modeled on Auctionator's FullScan: a dedicated scan frame silences every other AUCTION_ITEM_LIST_UPDATE listener during the getAll so the Blizzard AH UI can't corrupt the result set; lowest per-unit buyout per item, batched across frames. Honours the server's ~once/15-min getAll throttle, and the scan is cached for the whole session so re-opening the AH inside the cooldown reuses it. Location: Modules/AHScanner.lua.

  • Auto-populated [AH] buttons. Because the full scan knows every listed item, the per-row [AH] buttons across the Professions / Crafting / Missing / Cooldowns / Shopping List tabs now light up straight from it — no per-recipe "Scan AH" click. Location: Modules/AHScanner.lua GetListingsFor.

  • Optional Auctionator integration (off by default). A "Use Auctionator pricing" toggle under Settings → Auction House. Off by default so the addon uses its own scanned + vendor prices first; tick it to prefer Auctionator's price database when installed. Auctionator is an OptionalDeps, never required. Location: GUI/Settings.lua, Modules/Price.lua.

  • Shipped vendor-price table. A generated Data/VendorPrices.lua gives thread, dyes, vials, flux and other vendor-bought reagents a cost out of the box — gated to genuinely vendor-sold items (emulator npc_vendor, unlimited-stock + gold-only, so drop/farmed mats are never mis-priced) and priced from wago ItemSparse.

Changes

  • Recipe data now comes from the standalone LibProfessionDB-1.0 library. TOGPM no longer bundles its own all-version-merged Data/Recipes/*.lua; those are removed and replaced by a small bridge (Data/RecipeDB.lua) that points addon.recipeDB at the library's point-in-time recipe set for the running game version + locale. Because the library data is already version-scoped, the per-client expansion gates in BrowserTab / MissingRecipesTab (minExpansion, the spellId > 25000 heuristic, the skill cap) now step aside for it — which also fixes the class of bug where legitimate high-ID Classic recipes were wrongly hidden. ProfessionDB is declared in ## Dependencies and .pkgmeta required-dependencies.

  • Enriched, searchable effect text. Enchanting recipes carry their effect (+5 Weapon Damage, +1 All Stats, …). The Crafting and Professions tab searches now match recipe name OR effect (so 5 damage, agility, mining all find recipes), and both tabs' tooltips show the effect. Search boxes lost the non-functional AceGUI "okay" button and got clearer tooltips. Location: GUI/CraftingTab.lua, GUI/BrowserTab.lua.

Localization

  • Crafting tab is fully localized. Every crafting-tab string is a locale key (no hardcoded text), defined in Locale/enUS.lua and present in all 15 shipped locale files so translators can localize in place — English fallback until then. The per-reagent Cost column also right-aligns cleanly (coin strings no longer wrap to a second line). Location: Locale/, GUI/CraftingTab.lua.

  • Dutch (nlNL) native-speaker review. Reviewed by a Dutch speaker: game-mechanic terms (profession / reagent / Auction House / cooldown names, etc.) kept in English, "watch" → "in de gaten houden", "characters" → "personages". Location: Locale/nlNL.lua.


Older releases (v0.7.6 and earlier) are archived in CHANGELOG_ARCHIVE.md.

This mod has no additional files