promotional bannermobile promotional banner

FlipQueue

  FlipQueue is a workflow addon for cross-realm auction house flipping. It turns FlippingPal deals into a   step-by-step to-do list — telling you what to post, from where, on which character.

File Details

v0.11.0

  • R
  • Apr 21, 2026
  • 688.80 KB
  • 302
  • 12.0.5+1
  • Retail

File Name

flipqueue-v0.11.0.zip

Supported Versions

  • 12.0.5
  • 12.0.1

FlipQueue

v0.11.0 (2026-04-21)

Full Changelog Previous Releases

  • release: extend v0.11.0 notes with posting-price fixes; add TSM API request doc
    The v0.11.0 tag pointed at a commit that pre-dated the three posting-
    price fixes (MakePostDecision rewrite, self-match branch, postCap
    evaluation, audit-drift guard). Extend the "Fixes: posting and
    inventory" section to cover what shipped and note the drift guard. The
    tag itself is moved to this commit in a follow-up step.
    Also land docs/tsm-api-request.md — a drafted feature request for a
    GetAuctioningPostDecision entry point in TSM_API, so companion addons
    don't have to reimplement MakePostDecision and drift every release.
    Written for submission to the TSM upstream via GitHub issue or Discord.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix: posting follows TSM more faithfully (self-match, postCap eval, audit guard)
    Three follow-ups on top of the MakePostDecision rewrite:
    1. Match our own price when we're already the market's lowest. TSM's
      MakePostDecision has an isPlayer branch: if the lowest auction on the
      AH is us, TSM matches our price instead of undercutting. Without this
      guard, every FlipQueue repost drops the ceiling another step, and
      TSM's cancel scan immediately flags the fresh post as undercut or
      cancellable-for-repost-higher. Now GetOwnLowestBuyout walks
      GetOwnedAuctions for matching itemID entries; if our lowest is at or
      below DBMinBuyout (1s slack for silver rounding), ResolvePostPrice
      uses it directly with reason="match own (we're lowest)".
    2. Evaluate postCap via TSM's price evaluator, not tonumber. Operations
      with a literal postCap ("5", "1") parsed fine before; operations with
      an expression like "max(1, dbmarket/1g)" did not, and the caller fell
      through to "no cap" — so an op set to post in batches of 1 grabbed
      the whole stack instead. GetItemAuctioningOp now tries tonumber first
      for the common literal case, then TSM:EvaluateOpPrice, and caches the
      resolved number in pricing.postCap. When evaluation still fails but
      there's a TSM op, ScanBags falls back to postQty=1 (conservative)
      rather than "post everything" — a missing cap is never a license to
      dump a full stack of fee-bearing listings.
    3. Pass the real postQty to non-commodity PostItem. Old code hardcoded
      quantity=1, ignoring postCap for non-commodities (pet cages, gear,
      etc.) and forcing one click per auction regardless of the op's
      batch size. PostItem's quantity parameter is the number of separate
      auctions Blizzard will create by finding N matching items in bags;
      commodity PostCommodity quantity is the total fungible stack. Both
      now receive scanResult.postQty, capped during scan.
      Audit-drift scaffolding for future TSM updates:
    • TSM_AUDITED_VERSION constant documents which TSM version the decision
      tree was last validated against (currently v4.14.66).
    • TSM:GetAuditStatus compares the running version.
    • TSM:CheckAuditedVersion prints a one-time chat warning when TSM is
      newer than the audit (so drift is visible) and a structural warning
      when an Auctioning operation is missing a field we expect (TSM
      renamed or removed a setting).
    • Fires from GetItemAuctioningOp on first lookup per session.
      UI tooltip now shows "Your lowest: Xg" when we have a matching owned
      auction, so players can see when FlipQueue is matching their own price
      via the isPlayer branch vs. undercutting a competitor.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix: posting price now follows TSM's MakePostDecision algorithm
    Before: ResolvePostPrice just evaluated the Auctioning operation's
    normalPrice expression and posted at that value. normalPrice is a
    "no competition" baseline (typically ~2x DBMarket); using it when the
    AH actually has listings meant FlipQueue was posting way above market
    and auctions would sit unsold for the full 48h.
    After: faithful implementation of TSM's MakePostDecision tree from
    LibTSMSystem/Source/Operation/AuctioningOperation.lua. The operation's
    stored settings are the authority (minPrice, maxPrice, normalPrice,
    undercut, priceReset, aboveMax read directly from opsDB), and every
    price expression evaluates through TSM_API.GetCustomPriceValue (TSM's
    own evaluator). Branch tree:
    - No competition on AH: post at normalPrice
    - Lowest - undercut < minPrice: post at priceReset target, or skip
    if priceReset is "none"/"ignore"
    - Lowest - undercut > maxPrice: post at aboveMax target, or skip if
    aboveMax is "none"
    - Otherwise: post at lowest - undercut
    - Clamp final buyout >= minPrice
    TSM_API does not expose MakePostDecision or any "give me the post
    price" function — GetCustomPriceValue is the most we get. The decision
    logic itself is ours, but every input value (prices and expressions)
    comes from TSM's authoritative config.
    What's not covered: blacklist/whitelist seller matching, which needs
    live auction scan data (seller identity) we don't have. Players who
    configure those will still see TSM post slightly differently.
    UI changes:
    • ContextDrawer tooltip shows the actual post price (buyoutCopper),
      the AH lowest we undercut, and a "Reason: undercut/reset/aboveMax/
      no competition" line so players can see why TSM chose that price.
    • Row Post: label shows the post price instead of the normal baseline.
    • New "above_max" status rendered in orange for items TSM refuses
      because undercut would exceed maxPrice.
      TSM helpers:
    • TSM:GetItemAuctioningOp now returns undercut, priceReset, aboveMax,
      and bidPercent in addition to the existing min/max/normal/postCap.
    • TSM:EvaluateOpPrice evaluates a TSM price expression for a FQ item
      key, with the base-ID fallback that GetPrice uses.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • release: v0.11.0 — rewrite release notes as player-facing
    The previous notes were scoped to v0.11.0-alpha12..HEAD and written in
    technical language that made sense for commit bodies but not for players
    looking at what changed. The last full release was v0.9.8, so this
    rewrite covers everything since then — the 0.10 and 0.11 alpha cycles
    all the way through the posting regression fix — framed around what
    players can see and do rather than internal implementation.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • release: v0.11.0
    First stable release of the 0.11 line. Posting works again, active
    auction count stays aligned with the AH, sold-vs-expired ledger is
    cross-checked against TSM, goldBuffer is now a min-balance floor, and
    character deletion + restore ships. Compatible with both 12.0.1 and
    12.0.5 clients.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix: force QueryOwnedAuctions after post/cancel so TSM sees the change
    Blizzard fires AUCTION_HOUSE_AUCTION_CREATED / AUCTION_CANCELED after a
    successful post or cancel, but doesn't automatically push a fresh
    OWNED_AUCTIONS_UPDATED — their own Sell frame relies on the user tabbing
    to "Auctions" to trigger a requery. That means sibling addons (TSM's
    Auctioning view, Auctionator's owned auctions, our own context drawer)
    don't see the auction state change until the next organic refresh.
    Add RequestOwnedAuctionsRefresh, a 1-second debounced wrapper around
    C_AuctionHouse.QueryOwnedAuctions(). Call it from:
    - AUCTION_HOUSE_AUCTION_CREATED handler (after every successful post)
    - AuctionPost:CancelAuction (after CancelAuction returns)
    The 1s delay gives the server time to commit before we requery; the
    debounce collapses rapid sequential posts (multiple commodity stacks
    posted back-to-back) into one round-trip so we don't burn throttled
    query slots. Skips the requery entirely if the AH is closed.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • chore: list both 120001 and 120005 interfaces
    Tomorrow's 12.0.5 rollout hasn't happened yet on every client, and some
    users will still be on 12.0.1 when loading the alpha this evening. A
    comma-separated Interface list covers both versions so the addon isn't
    flagged out-of-date on either client.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix: PostItem must not pass bid==buyout (server returns ItemNotFound)
    Debug log on a live 12.0.x client shows every PostItem call failing with
    AUCTION_HOUSE_SHOW_ERROR code 10 (Enum.AuctionHouseError.ItemNotFound).
    Cancel also fails with code 10, but that's a downstream effect of phantom
    log entries from posts that never actually landed — the fix here is the
    post path.
    Root cause: commit fc0a7c7 changed PostItem's call to pass
    bid=buyout=unitPrice based on the incorrect claim that "bid=nil causes
    the server to silently reject the post." The Blizzard API docs list bid
    and buyout as optional; Blizzard's own AuctionHouseItemSellFrame
    CanPostItem() validator requires "buyout price must exceed bid price if
    both are set" (strict inequality). TSM follows this: bid = (buyout == 0
    or bid < buyout) and bid or nil. Auctionator too: passes nil bid when
    there's no starting bid. When we pass bid == buyout, the server-side
    validator treats the request as malformed and reports the item as not
    findable for an auction.
    Change: for non-commodity posts, pass bid=nil and buyout=unitPrice
    (buy-it-now only). Commodity path unchanged (uses PostCommodity, which
    takes unitPrice only).
    Also:
    • loggedQuantity now reflects what we actually posted (1 per click for
      non-commodity, stack size for commodity), so the ledger entry and chat
      "Posted N" message no longer lie about a 5-for-1 click.
    • AH_ERROR_NAMES table decodes AUCTION_HOUSE_SHOW_ERROR enum indices for
      readable debug output.
    • TestPost mirrors the real posting signature.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • docs: add feedback tracking workflow and update suite context
    • Add feedback/ scaffold (collection/, releases/, archive/) with README
      and _TEMPLATE.md; issue-ID prefix for this cog is FQ.
    • CLAUDE.md: document the feedback workflow and proactive-capture policy,
      refresh Cogworks suite status (Tally named, Syndicator migration now
      complete, not "upcoming"), drop the stale "no external libs" rule.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • ui: tool drawer thumb tracks mini height; unified animation
    When the mini is resized (e.g. grip resize), the tool drawer's thumb grip
    used to stay at CONTENT_HEIGHT and extend past the mini's bottom edge. The
    drawer now recaptures the mini's height on show/hide and on
    UpdateToolDrawerHeight, and clamps the collapsed thumb to that height.
    Also unified the animation into a single 0..1 progress value that drives
    clip width, clip height, and thumb height together — previously width and
    height animated on separate paths, which let transient states land with
    the thumb at a different size than the clip.
    MiniView now calls UpdateToolDrawerHeight on RefreshMini so height changes
    propagate without waiting for the next drawer show/hide.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • refactor: goldBuffer is a min-balance floor, not an additive buffer
    Previously the gold-management math treated goldBuffer as "extra to keep
    beyond AH fees", so the target balance was fees + 10% + buffer. In
    practice users configure buffer as "the minimum amount I want on my
    character" — they expect that when fees are small, the buffer is what
    dictates balance, not an addition on top.
    New formula on both withdraw and deposit paths:
    keepCopper = max(goldBuffer, ceil(fees * 1.1))
    keepCopper = ceil(keepCopper / 10000) * 10000 -- whole-gold target
    This also removes the "skip unless the char has tasks on this realm"
    short-circuit in AutoWithdrawGold: the buffer should apply regardless of
    whether there's work to do on the current realm, symmetric with
    AutoDepositGold which already enforced min-balance independent of tasks.
    UI label and description wording updated in SettingsFrame and
    SetupWizard so users see what the field actually does. ContextDrawer
    labels (withdraw/deposit buttons on the mini) use the same formula.
    Shortfall/excess calculations are now exact rather than rounded
    separately, since keepCopper is already whole-gold aligned.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • chore: bump interface to 120005 for patch 12.0.5
    WoW client 12.0.5 rolls out tomorrow; the 120001 TOC would otherwise be
    flagged out-of-date on load.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • feedback(FQ-001): append attempts entry — code committed as 6c62771
    Still uncommitted-at-tag (no alpha tag yet). In-game verification
    continues before the package pipeline runs.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix: reconcile active auction drift and upgrade sold outcomes via TSM
    Three interacting bugs caused the "N active auctions" badge to drift out of
    sync with the AH and the ledger to lose sold-vs-expired classification over
    time:
    • TrackerMail.lua pre-emptively flipped expired/cancelled entries to
      "collected" on MAIL_SHOW, 1s before ScanMailForSales ran. The scan's
      returned-item match set was built from status=="expired", so the pre-flip
      left nothing for it to match — postHistory / totalFeesSpent tracking never
      fired on the normal flow, and cancelled->collected transitions didn't set
      saleOutcome. Removed the pre-flip; ScanMailForSales now runs first and a
      cleanup pass finalizes unmatched expired/cancelled entries with the right
      saleOutcome. Cancelled entries are also included in the mail match set now
      (cancelled auctions return items via mail the same as expired).
    • TrackerAuctions.lua's CheckOwnedAuctions interleaved orphan recovery and
      stale-entry reconciliation, both keyed on stripped itemID, so stale log
      entries could "claim" newly posted auctions and produce off-by-one drift
      (badge reads 1 when AH has 0, 3 when AH has 2, etc.). Rewrote as three
      clean phases: todo match -> count-based per-itemID reconcile (oldest
      excess entries marked collected/cancelled) -> orphan recovery for any
      remaining unmatched owned auctions. Collapsed the #owned==0 special case
      into the general path.
    • No cross-check against TSM's sales data: any sale where the gold-mail
      scan failed (missed session, name mismatch) stayed expired/collected
      forever. New TrackerTSMReconcile.lua parses TSM's per-realm csvSales
      directly from TradeSkillMasterDB, indexes by (charKey, base-itemID) with
      whitespace-normalized charKeys, and upgrades eligible log entries to
      "sold" when TSM has a matching sale within postedAt - 1h .. postedAt +
      49h. Idempotent via _tsmReconciled flag, reset on PLAYER_LOGIN because
      TSM rewrites its CSV on logout. Fires on AH open (throttled to 1/hour)
      and via /fq reconcile. When TSM is loaded but no match is found and the
      auction window has closed, finalizes unresolved "collected" entries as
      saleOutcome=expired so they leave the limbo bucket.
      Mail cleanup pass also finalizes old collected-without-saleOutcome entries
      (> 49h postedAt) for users without TSM, so no entry stays uncounted.
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • feedback(FQ-001): update with fix details — three bugs, awaiting in-game verification
    Reframed from investigating → in-progress. Documents the three distinct
    bugs fixed (MAIL_SHOW ordering, CheckOwnedAuctions drift, no TSM cross-
    check), the files touched (TrackerMail, TrackerAuctions, new
    TrackerTSMReconcile, Tracker, toc, SlashCommands), and the known same-
    item-within-48h cross-match failure mode to probe during testing. Not yet
    committed as code; per project policy the versioned commit + alpha tag
    only happens after in-game verification.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • feedback(FQ-001): ingest from Discord thread
    Ledger figures not matching TSM sales records — reporter (gezmodean)
    flagged it in #flipqueue-feedback 2026-04-21. Doc lists clarifying
    questions to ask in-thread and suspect files (SalesIndex, TrackerMail,
    TrackerAuctions, RealmData, TSMRealms).
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • feat: character deletion with tombstones, cascade purge, and restore UI
    Adds a real "delete character" flow that survives TSM/Syndicator/sync
    re-detection, plus a restore path for mistaken deletes.
    • Schema v8: db.deletedCharacters tombstone table
    • DeleteCharacter cascades through db.characters, characterOrder,
      accounts.primary.characters, todoLists.active+upcoming tasks,
      pullTabs.bank, depositOverflow.char, guilds[*].members, and db.log
    • Optional Syndicator cache purge via opts.purgeSyndicator
    • Tombstones block re-adds in Scanner, TSM DetectCharacters, and Sync
      (MergeCharacters, ApplyDelta CHAR); new CDEL/CUND delta types
      propagate delete/restore across partners
    • Characters page: Delete button + custom dialog with Syndicator
      purge checkbox; Show Hidden / Show Deleted right-justified toggles
      on the Global Defaults bar; inline [Unhide] / [Restore] row actions
    • Settings page: Deleted Characters section lists tombstones with
      relative timestamps and Restore buttons; Clean Orphaned Data button
      sweeps for stranded task/log entries
    • Login guard: if current char is tombstoned, prompt Restore vs Keep
      Deleted; Scanner writes no-op for tombstoned keys either way
    • Retroactive cleanup in CleanupLegacyData for pre-cascade tombstones
      Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • fix: apply goldBuffer to withdraw path (symmetry with deposit)
    AutoWithdrawGold only targeted "fees * 1.1", ignoring the
    goldBuffer min-balance setting. With 832g on hand and a
    999g buffer, the withdraw path saw ~33g of fees, decided
    "player has enough", and pulled nothing — while the deposit
    path correctly used fees+buffer as the keep threshold.
    Mirrors AutoDepositGold's keepCopper formula in the withdraw
    estimator (TrackerBank.lua), the bank-popup preview
    (Tracker.lua), and the drawer label (ContextDrawer.lua) so
    all three paths target the same balance.
    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
  • v0.11.0-alpha12: posting fix, drawer fixes, phantom chars, find nearest
    AH Posting (critical fix):
    • Round prices to silver before PostItem/PostCommodity — WoW AH
      silently rejects prices with non-zero copper. This was the root
      cause of all posting failures.
    • Use PostCommodity for commodities, PostItem for non-commodities
      (was incorrectly using PostItem for everything).
    • Add AUCTION_HOUSE_AUCTION_CREATED / ADDON_ACTION_BLOCKED / error
      event listeners for post result diagnosis.
    • /fq testpost: minimal direct post for debugging.
      Context Drawer:
    • Fix crash: forward-declare HideAllContextContent (called from
      animation closure before its definition).
    • Fix thumb not visible: re-parent from contextContent to contextClip
      so it tracks the visible bottom edge regardless of content height.
    • Skip button now marks the to-do task as "skipped" (was only
      removing from the scan list without updating task status).
      Unknown Item Names:
    • ResolveUnknownNames on login: requests item data via
      C_Item.RequestLoadItemDataByID for tasks with name "Unknown".
    • GET_ITEM_INFO_RECEIVED listener updates task names when data
      arrives and refreshes the UI.
      Phantom Characters:
    • IsPhantomChar: detects characters with no class and no lastLogin
      (from Syndicator/TSM data for deleted or unowned characters).
    • Auto-hide on login: sets phantom characters to role=none with a
      chat message showing how many were hidden.
    • Guard all task assignment paths in TodoGenerator to skip phantoms.
      Find Nearest (tool drawer):
    • Location learning: records player position on MAIL_SHOW,
      BANKFRAME_OPENED, AUCTION_HOUSE_SHOW into SavedVariables.
    • Faction filtering on all static locations.
    • Expanded static locations: Dalaran, Boralus, Dazar'alor,
      Ironforge, Thunder Bluff. Warband Bank 2 → 10 locations.
    • World-coordinate cross-map distance via GetWorldPosFromMapPos.
    • Brutosaur variant: added Trader's Gilded Brutosaur (mount 2265).
    • Gold debug logging on all silent early returns.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • find nearest: location learning, faction filter, expanded locations
    Tool drawer FIND button overhaul:
    • Learned locations: records player position on MAIL_SHOW,
      BANKFRAME_OPENED, AUCTION_HOUSE_SHOW into SavedVariables.
      Deduplicates within 2% map distance, caps 15 per map/service.
      Suppresses recording for 120s after a summon click to avoid
      storing temporary player-spawned mailboxes/banks.
    • Faction filtering: Stormwind/Ironforge/Boralus Alliance-only,
      Orgrimmar/Thunder Bluff/Dazar'alor Horde-only.
    • Expanded static locations: added Dalaran, Boralus, Dazar'alor,
      Ironforge, Thunder Bluff. Warband Bank 2 → 10 locations.
    • World-coordinate cross-map distance via C_Map.GetWorldPosFromMapPos
      so nearest bank in a neighbouring TWW zone beats a far-away capital.
    • FindNearestService replaces PickNearestLocation: merges learned +
      static locations, ranks by same-map → world-distance → continent.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha11: fix brutosaur variant + gold debug logging
    Add Trader's Gilded Brutosaur (mount ID 2265) to AH and Mail
    services — players with the shop bruto but not the original BfA
    mount now see summon options in the tool drawer.
    Add PrintDebug to all silent early-return paths in AutoWithdrawGold
    and AutoDepositGold so users can diagnose why gold operations are
    skipped (no tasks on realm, setting disabled, already covered, etc).
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: pass unitPrice as both bid and buyout to PostItem
    WoW requires both bid and buyout parameters to be non-nil.
    bid=nil causes the server to silently reject the post.
    Setting bid=buyout=unitPrice matches TSM's behavior.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: remove pcall from PostItem — it strips hardware event context
    WoW's pcall breaks the hardware event propagation flag. When
    C_AuctionHouse.PostItem is called via pcall, the server silently
    rejects the post because it's no longer in a trusted execution path.
    Direct call preserves the hardware event from the button click.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: AH layout not updating after scan/post
    LayoutAH (dynamic positioning of Post Next, separator, owned rows)
    wasn't called after scanning or posting — only on initial build and
    OnShow. Now called from scan button handlers and post callback via
    ahContentFrame._layoutAH reference.
    Also: refresh path only grows drawer height (never shrinks to stale
    value), preventing cascading RefreshContextDrawer from overriding
    the scan button's height calculation.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: use PostItem for all items (PostCommodity is for buying)
    C_AuctionHouse.PostCommodity is the purchase API, not the sell API.
    All AH selling goes through PostItem(itemLoc, duration, qty, bid,
    buyout). For commodities, qty is the stack count to sell. For
    non-commodities, qty is always 1. bid=nil for buyout-only auctions.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: remove posted items from scan list + PostCommodity debug
    Scan list: posted items are now removed from currentScanResults
    after successful posting, so the list updates visually.
    PostCommodity: added detailed debug logging for the actual API call
    parameters to diagnose why commodity posts silently fail.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: commodity detection fallback + PostItem parameter fixes
    IsCommodity: when GetItemCommodityStatus returns Unknown (item data
    not cached), falls back to GetItemMaxStackSizeByID — stackable items
    (maxStack > 1) are commodities. Fixes enchant scrolls being misrouted
    to PostItem instead of PostCommodity.
    PostItem (non-commodity): quantity forced to 1 (non-commodities post
    individually), bid set to nil (buyout-only), buyout is per-unit price.
    PostCommodity: unchanged — quantity + unitPrice.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • ScanBags: skip soulbound items (can't be posted on AH)
    Items with info.isBound = true are now silently skipped during bag
    scanning, both for Scan To-Do and Scan All. Soulbound items can't
    be posted and shouldn't appear in the AH drawer.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: PostAll -> PostNext (one item per click, hardware event)
    C_AuctionHouse.PostItem is protected and requires hardware event
    context. Chaining posts via C_Timer broke TSM's hooks with
    ADDON_ACTION_BLOCKED. Replaced PostAll (auto-chain) with PostNext
    (posts one ready item per button click). Button shows remaining
    count: "Post Next (3)". Each click is a hardware event so the AH
    API and TSM hooks work correctly.
    Also added AuctionPost:CountReady() helper.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: throttle PostAll with BAG_UPDATE_DELAYED between posts
    Posting multiple items too fast causes "internal auction error" (same
    issue as warbank moves). PostAll now waits for BAG_UPDATE_DELAYED
    (confirming the server processed the post and the item left bags)
    before posting the next item. Falls back to a 2s timeout if the event
    doesn't fire. Adds a 0.3s settle delay after each confirmation.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: PostItem missing buyout parameter + duration tonumber
    C_AuctionHouse.PostItem takes 5 params: (itemLoc, duration, quantity,
    bid, buyout). We were only passing 4 — unitPrice went to bid, buyout
    was nil, creating a bid-only auction that modern WoW silently rejects.
    Now passes unitPrice as both bid and buyout.
    Also: tonumber on duration (TSM stores as string), debug logging for
    all PostItem calls showing item, price, qty, duration, slot.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: postCap string-vs-number comparison crash in ScanBags
    TSM operations store postCap as a string (e.g., "5"). ScanBags
    compared it directly with > and math.min, causing "attempt to compare
    number with string" error. Fixed both occurrences to use tonumber().
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: stop syncing content height during animation
    The animation was shrinking contextContent along with the clip,
    which meant scan rows had no room to render even though they were
    created. Now only the clip height animates — the content stays at
    full size and is clipped/revealed by the clip frame. Content frames
    are hidden explicitly when fully collapsed (instead of relying on
    zero-height content to hide them).
    Also: auto-scan now prints "N item(s) ready to post" to chat, and
    fetches owned auctions during context setup.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: scan buttons now directly resize drawer after populating results
    Scan button handlers now:
    1. Log the result count for diagnosis
    2. Call RefreshAHScanRows to populate rows
    3. Recalculate and set both content and clip height directly
      (instead of delegating to RefreshContextDrawer which could
      reset state or skip the update)
      This ensures the drawer grows to fit scan results immediately
      after scanning, without relying on the refresh cycle.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • debug: more detail in RefreshAHScanRows logging
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: bottom drawer thumb flush + clip overlaps mini border
    Thumb: removed 4px insets and 3px bottom offset — now flush with
    content edges (0,0) matching the tool drawer style.
    Clip: restored 3px overlap with mini's bottom border for seamless
    integration (was removed earlier when debugging the backdrop overlap,
    which is now fixed by the TOP anchor + height sync approach).
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: AH scan rows not visible — content hidden on drawer open
    Root cause: HideAllContextContent() on drawer close hid ahContentFrame.
    When the drawer re-opened, ShowContext wasn't called (same context),
    so ahContentFrame stayed hidden and scan rows were never shown.
    Fixes:
    • ShowContextDrawer forces ShowContext rebuild by clearing currentContext
    • RefreshContextDrawer "same context" branch always shows ahContentFrame
    • Added debug logging to RefreshAHScanRows
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: AH settings section added to reflow order
    The Auction House section was missing from sectionOrder, so
    ReflowSettings didn't position it, causing it to overlap with
    Bank & Warbank. Added "auctionhouse" to the ordered list between
    "bankops" and "notifications".
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • Auction House settings section + better price debug logging
    Settings: added "Auction House" collapsible section with the auto-scan
    checkbox (moved from Bank & Warbank section). This is independent of
    TSM so non-TSM users can find it.
    AuctionPost: debug logging now shows the exact normalPrice expression
    and its evaluation result (or error), so we can see when TSM returns
    nil for a valid operation.
    TSM fallback op dropdown: unchanged from prior commit.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • TSM fallback op: dropdown selector instead of text input
    Replaced the text input for the fallback Auctioning operation with a
    dropdown that lists all available TSM Auctioning operations from the
    active profile. First option is "(None — skip ungrouped)" which
    clears the setting. Dropdown auto-populates when the TSM page is
    shown/refreshed.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • TSM fallback auctioning operation for ungrouped items
    New setting on TSM Integration page: "Fallback Auctioning operation
    for ungrouped items" (tsmFallbackOp). When an item isn't in any TSM
    group, GetItemAuctioningOp now tries the named operation as a fallback.
    This gives ungrouped items proper duration, postCap, and pricing
    rules instead of just a raw price number.
    Leave blank to skip ungrouped items (previous behavior).
    Example: set to "Default" to use TSM's default auctioning operation.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • auto-scan on AH open + exhaustive price fallback chain
    New setting: "Auto-scan inventory when the Auction House opens"
    (ahAutoScanOnOpen). When enabled, the AH context drawer automatically
    runs a to-do scan when the AH opens, populating items immediately.
    Checkbox added to Settings under the gold section.
    AuctionPost price resolution now tries an exhaustive fallback chain:
    1. TSM Auctioning operation normalPrice (if item has a group/op)
    2. Player's tsmPriceSource setting (e.g., "70% DBRegionMarketAvg")
    3. DBMinBuyout
    4. DBMarket
    5. DBRegionMarketAvg
      Also resolves minPrice threshold from tsmMinPriceSource setting when
      no operation provides one, so below-threshold detection works for
      ungrouped items too.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • tool drawer: thumb on outside (left) edge
    Moved thumb from RIGHT edge (nearest mini) to LEFT edge (outside).
    Flipped inner frame anchor from TOPRIGHT to TOPLEFT so the thumb
    is visible when collapsed. Icons and header shifted right by
    THUMB_WIDTH to sit after the thumb.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: hide context content when drawer collapses
    With TOP anchor, collapsed drawer (12px) shows the top of content
    instead of just the thumb. Now HideAllContextContent() is called
    when the drawer closes (both immediately and when animation finishes),
    so only the thumb grip lines are visible when collapsed. Content is
    rebuilt via ShowContext when the drawer opens.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: context drawer overlap — TOP anchor + synced content height
    Root cause: with BOTTOM anchor, the content frame's backdrop extended
    above the clip rect. SetClipsChildren clips child frames but NOT a
    frame's own backdrop/border textures.
    Fix: switched content anchor from BOTTOM to TOP of clip frame. Content
    height now tracks clip height during animation (OnUpdate syncs both),
    preventing the backdrop from rendering outside the clip rect. When
    collapsed, content height is set to THUMB_HEIGHT so the thumb is at
    the visible top edge.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • AuctionPost: use tsmPriceSource setting for price fallback
    When no TSM Auctioning operation exists, uses the player's configured
    tsmPriceSource setting (default "70% DBRegionMarketAvg") instead of
    a hardcoded DBMinBuyout -> DBMarket chain.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • AuctionPost: fallback chain DBMinBuyout -> DBMarket -> DBRegionMarketAvg
    When no TSM Auctioning operation exists and DBMinBuyout is unavailable
    (item not currently on this realm's AH), tries DBMarket then
    DBRegionMarketAvg as fallback price sources. Adds debug logging for
    which fallback source was used or if all sources failed.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: drawer overlap + TSM price fallback to DBMinBuyout
    ContextDrawer: removed 3px overlap between mini and drawer clip frame.
    The drawer now sits flush below the mini, preventing the scan rows
    from rendering behind the mini's partner strip.
    AuctionPost: when no TSM Auctioning operation is assigned to an item,
    falls back to DBMinBuyout as the posting price reference (shown as
    op name "DBMinBuyout"). Items with TSM market data but no group
    assignment now show prices instead of "No TSM data".
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • AH drawer: multi-line scan rows, debug logging, price display
    Scan result rows redesigned as 34px two-line entries:
    • Line 1: [icon] item name, quantity, [Post] button
    • Line 2: Deal price (from todo), Post price (TSM normal), status text
    • Per-row backdrop with colored border based on status
    • Below-threshold: red border + "Below min price"
    • No TSM data: grey border + "No TSM data"
    • DNT: orange border + "Do Not Track"
      AuctionPost.lua:
    • Added debug logging to ResolvePostPrice (TSM availability, op lookup,
      price evaluation failures)
    • Added TSM_API type check before evaluating price expressions
      ContextDrawer:
    • Reduced max visible rows: scan 6 (was 8), owned 4 (was 6)
    • Height cap increased to 400px (was 280) for taller rows
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: pause toggle in default, AH scan module resolution, arrow icon
    ContextDrawer:
    • Fixed pause button not toggling in default context: defaultFrame
      variable was declared after RefreshPauseButton in file scope (Lua
      forward reference issue). Added _defaultPauseBtn bridge variable.
    • Fixed AH scan/post/cancel buttons: ns.AuctionPost was captured at
      BuildAHContent time (nil if module hadn't loaded yet). All closures
      now resolve ns.AuctionPost at click time.
    • Shows error message if AuctionPost module isn't loaded.
      ToolDrawer:
    • Changed Find arrow to MiniMap-QuestArrow (arrowhead icon).
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • pause toggle: 'Resume Automation' instead of 'Unpause'
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • bank popup: anchor below context drawer instead of mini + offset
    When the context drawer is visible, the bank operations popup now
    anchors its TOPRIGHT to the drawer clip's BOTTOMRIGHT directly,
    instead of anchoring to the mini with a calculated offset. This keeps
    the popup pinned to the bottom of the drawer as it opens/closes.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • tool drawer: waypoint arrow, white FIND text, dimmed background icons
    • Arrow changed from magnifying glass to QuestMap waypoint arrow
    • Find label: white text, all caps "FIND", 10pt OUTLINE
    • Background icon dimmed (desaturated, 30% opacity) in Find mode
      so the arrow and text have clear contrast
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • tool drawer: center Find text + arrow, increase font to 10pt
    Find label centered horizontally and vertically in the button (offset
    -8 from center). Waypoint arrow centered above it (+5 from center).
    Font increased from 9pt to 10pt OUTLINE for readability.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • AH drawer: item link tooltips, pricing detail, status indicators
    Scan result rows:
    • Mouseover shows item link tooltip (SetItemByID) + pricing breakdown
      (post/min/max price, TSM operation, post cap, deal price from todo)
    • Status text inline: "below min" (red), "no price" (grey), "DNT" (orange)
    • Post button disabled for non-ready items
    • Fixed data mapping: uses postQty/pricing.normalCopper (was qty/price)
      Owned auction rows:
    • Mouseover shows item link + your price, per-unit, market price,
      undercut amount, time remaining
    • "undercut" text replaces the old "!" indicator
    • Fixed field names: quantity, buyoutPerUnit (was qty, price)
    • Captured loop index for stable click handlers
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • tool drawer: show summon icon when owned, fallback icon only for Find
    When a summon is available (toy/mount/spell owned), the button shows
    that summon's actual icon (e.g., Stampwhistle, Inhibitor). The category
    fallback icon (envelope, coin, bag) only appears when no summon is
    available and the button acts as a Find/waypoint.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • tool drawer: larger icons (40px), wider frame (66px), bigger Find text
    Icons increased from 32px to 40px with more spacing (6px) and padding.
    Thumb widened to 14px. Total drawer width 66px (was 52px).
    Find label font increased from 7pt to 9pt outline, centered at bottom.
    Waypoint arrow moved to top-right corner, 14px (was 12px).
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: Lua 5.1 goto removal + tool drawer icons + pause label
    AuctionPost.lua: replaced goto/continue (not supported in WoW's
    Lua 5.1) with a todoMatched flag that gates the item processing block.
    ToolDrawer: service buttons now always show the service category icon
    (mail envelope, coin, bag, etc). When no summon is available, a
    waypoint arrow overlay + "Find" label appears and clicking sets a map
    waypoint to the nearest location. Removed separate Find buttons.
    ContextDrawer: pause button label changed from "Pause" to
    "Pause Automation" in all contexts (default, bank).
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • fix: restore Find buttons in tool drawer + allow default context drawer
    ToolDrawer: added Find/Locate Nearest buttons below each service icon
    (32x16px, same style as original ServiceDrawer). Increased content
    height to accommodate icon+Find blocks (50px per service).
    ContextDrawer: default context (no bank/AH open) now shows a pause
    button instead of collapsing to thumb-only. Drawer can be opened in
    any context. RefreshPauseButton updates both bank and default pause
    buttons.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha9: drawer reshape + AH posting engine
    Drawer architecture overhaul:
    • ToolDrawer (left): extends leftward from mini, vertical service icons
      (Mail, AH, Bank, Warbank), horizontal clip animation, grip on right
    • ContextDrawer (bottom): full-width, context-sensitive — bank tools
      when bank open, AH posting UI when AH open, pause-only when idle
    • Replaced ServiceDrawer.lua and ActionDrawer.lua
      AuctionPost.lua (new posting engine):
    • ScanBags: inventory scan with TSM price resolution, DNT filtering
    • PostItem/PostCommodity: native WoW AH posting via C_AuctionHouse
    • PostAll: sequential posting with 0.5s throttle
    • GetOwnedAuctions: owned auction query with undercut detection
    • CancelAuction: cancel with Tracker._pendingCancels coordination
    • ScanBankForSaleable: bank scan for items with TSM ops
      Bank context buttons: Pause, Pull, Deposit, Extras, Withdraw/Deposit
      Gold (with amounts), Pull Saleable (all/warbank/bank)
      AH context: Scan To-Do, Scan All, per-item Post/Skip, Post All,
      owned auctions with undercut indicators, Cancel/Cancel Undercuts
      Also: removed stale AH browse cache (was interfering with TSM posting)
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha8: drawer redesign + buy task detection + gold label fix
    Services drawer (right):
    • Redesigned as integrated drawer with grip-line thumb at bottom
    • Half-width, flush with mini bottom, slide animation via SetClipsChildren
    • Icons restored to 32px with Find buttons
    • Fixed toy detection: Katy's Stampwhistle ID (156833, was 141605)
    • Removed unreliable IsToyUsable check (false negatives)
    • Localized name resolution for toys/spells (German client fix)
      Action drawer (left, new):
    • Quick-action buttons: Pause, Pull, Deposit, Extras, Pull All
    • Gold ops: Pull Gold, Deposit Gold
    • Pause temporarily disables bank automation
    • Pull All scans entire to-do list with TSM postCap / defaultSellQty
      Buy task lifecycle fix:
    • Fuzzy name matching (strips non-alphanumeric) for bag detection
    • Backfills numeric itemID from bag scan onto name-only tasks
    • Bag scan now includes reagent bag (ALL_PLAYER_BAGS)
    • AdvanceStep clears blockedBy/depositFrom on sell task when buy completes
    • OnItemPurchased matches at both browse and buy steps
    • Fixed infinite recursion in GetAuctionInfoByID pre-hook
    • Debug logging throughout buy detection chain
      Gold withdrawal label fix:
    • BankPopup, chat messages, settings now say "fees + purchases" when
      buy costs are included (was always "posting fees")
    • CalculatePurchaseCosts logs skip reasons for diagnosis
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • sync perf + ESC-to-close + defensive log rendering
    Three user-reported issues:
    1. Sync "script ran too long" on Sync.lua:605/606 during a full sync.
      Root cause: Sync:Enqueue did a linear scan + table.insert shift on
      every send, so queueing the chunks of a large full-sync payload
      was O(N²). For a few thousand chunks this tripped WoW's watchdog
      and killed the send loop mid-flight.
      Fix: replace the single sorted array with per-priority buckets,
      each with head/tail indices. Enqueue and DrainQueue are now both
      O(1). sendQueues[priority] + sendQueueCount total.
    2. ESC does not close the main window. Added EnableKeyboard +
      SetPropagateKeyboardInput(true) + OnKeyDown on mainFrame in
      UI/MainFrame.lua, and the same on copyBlip in UI/ExportPopup.lua
      for the "no field focused yet" case. SetPropagateKeyboardInput
      flips to false only for the ESCAPE keypress so normal input
      (movement, ability bindings) still passes through. Mini view is
      deliberately excluded — it's a persistent HUD, not a modal.
    3. Blank rows in the sync log display. Defensive rendering: Sync:Log
      now coerces a nil/empty event name to "?" on write, and both the
      live sync log view (RefreshSyncLog) and the Copy Log button fall
      back to "?" when reading. The old renderer wrapped the event in
      color codes, so an empty-string event resulted in a visible-
      length row with nothing inside the color wrap — blank-looking.
  • click-to-copy: fix inconsistent dismiss (OnUpdate + click-eater)
    The alpha6 OnLeave-based dismiss was unreliable because OnLeave only
    fires after an OnEnter, and the popup opens BELOW the clicked row —
    so if the user's mouse never crosses into the popup before moving
    away, OnLeave never fires and the popup lingers.
    Replace with two complementary triggers:
    1. OnUpdate mouse-out poll: when IsMouseOver() is false, accumulate
      elapsed time; when it exceeds 2s outside, hide. Works regardless
      of whether the mouse ever entered the popup.
    2. Click-eater button at DIALOG strata covering UIParent, hidden
      unless the popup is shown. Since the popup lives at TOOLTIP
      strata (above DIALOG), clicks inside the popup hit the popup
      children first; clicks anywhere else route to the eater and
      dismiss. OnShow/OnHide handlers on the popup toggle the eater
      in lockstep so it doesn't leak onto the screen when the popup
      is gone.
      The popup is now effectively modal for its brief lifetime — the
      user either clicks an edit box to copy, clicks outside to dismiss,
      or waits 2s for auto-dismiss.
  • click-to-copy: settings toggle for realm vs character name
    Add a copyOnClickMode setting (default "realm") that controls which
    value the Next-steps click-to-copy blip exposes on a row click.
    Values: "realm" or "name". Default is realm because users primarily
    paste into the character-select realm filter, not a name search.
    • DB.lua: default copyOnClickMode = "realm" in InitDB
    • UI/ExportPopup.lua: BuildNextStepCopyEntries consults the setting
      and returns a single { label, text } entry (name or realm). Falls
      back to the other value if the preferred one is missing from the
      row (e.g. unassigned "Create char" entries only have a realm).
    • UI/SettingsFrame.lua: new "Click-to-copy" dropdown in the Mini
      section with Realm / Character name choices, wired into the
      existing RefreshSettings reload handler.
      The alpha6 dual-entry popup infrastructure stays in place —
      ShowCopyBlip still accepts a list of entries, the list just
      contains one entry now. Switching the setting at runtime takes
      effect on the next row click.
  • click-to-copy: dual-entry popup (name + realm side-by-side)
    The alpha6 compact popup copied just one value (name) and required
    the user to guess which click target gave what. Users asked for a
    dual-window popup that shows both the character name and the realm
    as separate clickable entries — pick whichever you need.
    ShowCopyBlip now takes a list of { label, text } entries instead of
    a single string, and pools one EditBox row per entry. Each row:
    • Labeled ("Character:" / "Realm:") and left-aligned
    • EditBox pre-populated, clickable anywhere in the row
    • Click or Tab focuses + highlights the text; Ctrl+C takes one keystroke
    • First row is auto-focused so the most-common path (copy name)
      stays one-keystroke from the row click
      Sized-to-content: width is max(label+text) + padding, clamped to
      [160, 480]. Height scales with row count. Anchored below the click
      source, TOOLTIP strata, auto-dismiss on mouse-leave with a 0.5s
      grace period.
      The legacy single-string signature still works (string is wrapped
      into a one-entry list) so incidental callers don't break.
      New UI:BuildNextStepCopyEntries turns a next-steps row data into
      the entry list — shared between main TodoPage and mini view so
      both surfaces have identical behavior.
  • v0.11.0-alpha6: compact click-to-copy for Next queue (mini + main)
    The alpha5 click-to-copy only worked in the main TodoPage and opened
    the full-size 500x350 ExportPopup with name+realm concatenated.
    Three things the user wanted fixed:
    • Mini view next-steps rows now have a click handler (previously
      explicitly nil'd via SetScript("OnMouseDown", nil) at row setup).
    • New UI:ShowCopyBlip helper in ExportPopup.lua creates a small
      sized-to-content popup (~120-400px wide, 48px tall) anchored below
      the clicked source. TOOLTIP strata so it floats over the mini or
      main frame. Auto-focus + HighlightText so Ctrl+C works in one
      keystroke. ESC or click-away dismisses.
    • Shared UI:GetNextStepCopyText extraction returns just the
      character name (for entries with _charKey) or the realm (for
      unassigned "Create char" entries). No more "Name\nRealm"
      concatenation — users get exactly what the character-select
      search accepts.
    • BuildNextStepsData now also sets _charKey on Check Mail /
      Expiring entries so they copy the char name, not the whole
      "Name-Realm" string.
      The full-size ExportPopup path via alpha5 is removed from the main
      TodoPage click handler (replaced with ShowCopyBlip), so both surfaces
      use the same compact dialog.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha5: click-to-copy char/realm in Next queue
    User request: clicking a row in the Next-steps queue should pop up a
    small copyable box with the character name (and realm on a second
    line) so the user can Ctrl+C and paste directly into WoW's
    character-select search on logout.
    Wires a RowClickHandler on UI.nextStepsTable at table-creation time
    in MainFrame.lua. Reuses the existing UI:ShowExportPopup dialog
    (same one used for the sync log Copy button) — it auto-focuses the
    edit box and highlights the text on open, so the click-to-Ctrl+C
    flow is a single keystroke after the popup appears.
    Priority:
    1. _charKey present → "Name\nRealm" with status "Character name + realm"
    2. _charKey absent, _tooltipText present → realm name alone for
      "Create char" entries, status "Realm — paste to find characters"
    3. Neither → no-op (shouldn't happen, but safe)
      Left-click only. Right-click preserved for future actions.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha4: Phase 2 Cogworks — delegate print helpers
    Route ns:Print and ns:PrintError through ns.cw:Print / ns.cw:PrintError
    when the Cogworks library is present, falling back to the legacy local
    print() path when it isn't (defensive — the library is a packager
    external and a bad install could leave it missing).
    Preserves the user-visible "FlipQueue:" yellow prefix by registering
    with prefix = "|cffffff00FlipQueue:|r " instead of the alpha2 default
    "FlipQueue" gold prefix. User-visible branding changes land in
    Phase 5 per PLAN.md, not here.
    ns:PrintDebug stays on the local path because the "[debug]" gray
    suffix and ring-buffer side effect are FlipQueue-specific and not
    part of the Cogworks print API.
    Known implication: chat addons that hook print() (e.g. Prat) will
    no longer catch branded FlipQueue messages — they now flow through
    DEFAULT_CHAT_FRAME:AddMessage via cw:Print. Debug prints still hit
    print() and remain hookable.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha3: fix silent gold deposit/withdraw failure
    A player on Doomflopper-Doomhammer hit a deposit failure where the bank
    popup's gold phase logged "fail=1, phase=Gold" with no diagnostic message
    and the deposit silently no-op'd. Root cause: Tracker:AutoDepositGold and
    Tracker:AutoWithdrawGold call C_Bank.DepositMoney/WithdrawMoney directly
    without ensuring BankFrame.BankPanel is on the warband bank type. When
    the user's last-active panel is the character bank, C_Bank.CanDepositMoney
    (Enum.BankType.Account) returns false even though the warbank is reachable,
    and the function early-returned with no debug print.
    Phase 6a uncovered this: the old Scanner.lua called
    C_Bank.FetchBankLockedReason(Enum.BankType.Account) on every BANKFRAME_OPENED
    which had the side effect of touching the warbank panel state. The new
    Syndicator-backed Scanner doesn't make that call, so users whose default
    view is the character bank now hit this case reliably.
    Fix:
    • Export BankQueue.SetBankPanelType so non-BankQueue callers can use it
    • Tracker:AutoDepositGold and Tracker:AutoWithdrawGold call it before
      the C_Bank API calls, ensuring the panel is on Account
    • Add diagnostic prints to every silent early-return path in both
      functions so future failures are traceable from the debug log
    • Add user-visible warning when CanDepositMoney/CanWithdrawMoney returns
      false instead of silently doing nothing
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha2 fixup: fetch Cogworks-1.0 via pkgmeta external
    Cogworks is now live on Wago and CurseForge as v0.1.0, so switch from
    the vendored local copy to a pinned git external pointing at the
    gezmodean-wow/cogworks repo at tag v0.1.0. The path: Cogworks-1.0
    directive copies only the library subdirectory so Libs/Cogworks-1.0/
    ends up containing just Cogworks-1.0.lua instead of the whole repo.
    • .pkgmeta: new externals section with the pinned-tag git external
    • .gitignore: ignore Libs/Cogworks-1.0/ so local dev copies don't get
      re-committed (the packager fetches a fresh copy at build time)
    • Remove the previously-vendored Libs/Cogworks-1.0/Cogworks-1.0.lua
      from git (the file stays on disk for local dev testing, it's just
      no longer tracked)
      Local dev note: running FlipQueue from a working-tree symlink requires
      either a gitignored copy of the library at Libs/Cogworks-1.0/ or a
      local packager run. The file is still present from the previous
      vendor step so existing local installs keep working.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha2: Cogworks embed + migration indicator + bulk-project alts
    Cogworks suite integration (Phase 1):
    • Vendor Cogworks-1.0 into Libs/ alongside the other libs, matching the
      existing vendor-locally strategy (no wowace externals)
    • Register FlipQueue with the Cogworks addon registry in Core.lua so
      sibling cogs can enumerate us
    • ns.cw cached namespace reference avoids repeated LibStub lookups
    • Fire cw.Events.InventoryChanged after each Syndicator projection
    • Fire cw.Events.GoldChanged on PLAYER_MONEY when the gold delta is real
    • Fire cw.Events.AuctionsChanged on OWNED_AUCTIONS_UPDATED
      Character migration indicator:
    • Scanner stamps charEntry.syndicatorBacked = true on every successful
      projection so the Characters tab can render a status badge
    • Badge shows Live / Ready / Pending / (remote) / (local):
      Live — projection has run, data is flowing from Syndicator
      Ready — Syndicator has the cache but we haven't projected yet
      Pending — neither FlipQueue nor Syndicator has data; log in once
    • Ready detection scans Syndicator.API.GetAllCharacters() by name match
      Realm alias map + alt bulk-projection:
    • ns.db.realmAliases[normalizedRealm] = displayRealm recorded on every
      current-character refresh (persistent; grows across sessions)
    • TranslateSyndicatorKey converts "Name-NormalizedRealm" back to
      "Name-DisplayRealm" for downstream reads that still use display realm
    • BulkProjectKnownAlts iterates Syndicator.API.GetAllCharacters() and
      projects any alt whose realm is in the alias map, skipping the current
      char (already refreshed) and anything outside alias coverage
    • Debounced to one run per 30s so bursts of BagCacheUpdate don't thrash
    • Fired after each current-char refresh so users who have Syndicator
      installed see their full stable populate on first login without
      having to visit each alt individually
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.11.0-alpha1: Syndicator hard dep + warbank scheduling + fixes
    Phase 6a — Syndicator migration:
    • Hard dependency on Syndicator (TOC)
    • New ItemLookup.lua: hyperlink → itemKey cache
    • Scanner.lua rewritten as a Syndicator projector; subscribes to
      BagCacheUpdate + WarbandBankCacheUpdate, writes into the same
      ns.db.characters[charKey].inventory.items and ns.db.warbank.items
      shapes downstream code already reads
    • Migration 7 wipes old inventory caches so Syndicator is the sole
      source of truth going forward; metadata (gold/class/guild/role/
      accountUUID) preserved
    • Guild bank scanner stays on the Blizzard API (unchanged)
      Warbank scheduling + constraint satisfaction:
    • TodoGenerator.GenerateTodoList tracks a live warbank budget seeded
      from scan data and credited by pending retrieves whose items are
      actually in warbank. Overflow deals held in preview.warbankFull.
    • BuildDisplayGroups now sorts retrieves before deposits within a
      group so execution naturally frees space before consuming it.
    • TodoPage: running-balance simulation flags at-risk tasks with a
      red [!] prefix; header readout shows "Warbank X/Y free, N↓ M↑".
    • Synthetic "Visit the warbank" task when no scan data exists.
    • BankQueue: deposit ops that can't find a slot defer (not abort)
      so stack-merge ops in the same batch still succeed.
    • AutoDepositExtraItems trims/skips when warbank would overflow.
      Session bug fixes:
    • RealmData: removed "Aggra (Portuguus)" typo duplicate
    • Todo gold estimates truncated (whole k instead of 1.5k)
    • FQ Mini default width bumped 280→340 for long realm names
    • ServiceDrawer: toy + mount detection paths, Brutosaur + Traveler's
      Anchorite + MOLL-E + Katy's Stampwhistle populated, Find Nearest
      now computes euclidean distance to player position
    • Linked Accounts widget refreshes across Settings/Mini/ServiceDrawer
      on peer sign-on via new Sync:NotifyPartnerStateChanged helper
    • Sync log "Copy Log" button routes through ExportPopup
    • Characters tab: simple (local)/(remote) tag replaces transport label
    • Warband Miser integration: FlipQueue defers auto-gold routines when
      WM is loaded; override checkbox in Bank settings
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • release: vendor libs, drop wowace SVN externals
    The previous two release builds (v0.10.2-alpha2 and v0.10.2-alpha3)
    failed because repos.wowace.com returned 502/503 when the BigWigs
    packager tried to fetch CallbackHandler-1.0, LibDataBroker-1.1, LibStub,
    and LibDBIcon-1.0 as externals. All four libs are already present in
    Libs/ committed to the repo, so removing the externals block lets the
    packager use the in-repo copies and eliminates the dependency on the
    flaky wowace SVN host.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.10.2-alpha3: Linked Accounts wizard + mini services drawer + warbank summon
    Multi-Account sync rework
    • New Link Account wizard with explicit BNet-friend vs Same-BNet-account
      mode selection (auto-dismisses when the pair lands)
    • Settings: replaced External Accounts panel with Linked Accounts manager
      (per-partner rows with Force Sync and Remove buttons)
    • Sync: UnlinkByUUID / ForceSyncByUUID for per-partner ops
    • RequestPair: no more auto-fallback; explicit transport is authoritative
      Mini overlay
    • Partner strip at the bottom of the mini with per-partner rows
      (blue = BNet, green = local) and status + force-sync button
    • Self row prepended for local pairs so both halves of the pair are
      visible; uses stored myCharName from pair time (not current char)
    • Services drawer popout (centered under mini) with gear toggle in the
      header. Mail / AH / Bank / Warband Bank columns, each with summon item
      or spell icon + Find button for nearest static location
    • Warband Bank Distance Inhibitor (spell 460905) wired as the warbank
      summon, with C_Spell.GetSpellCooldown for the swipe overlay
    • BankPopup: shifts down by drawer height when drawer is shown
      Incidental
    • DB defaults: tsmPriceSource and transformPriceSource now 70%/45% of
      DBRegionMarketAvg; transformDiscount default 100
    • Migration 6: tag existing partners as transport="bnet"
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.10.2-alpha2: warbank tab sort + Deal Finder fix + Deep Search + pet resolution
    BankQueue: stable sort for warbank tab selection — ties broken by
    original bag-list index so tabs fill 1→2→3→4→5 deterministically
    instead of Lua's non-deterministic sort order. Debug trace now
    reflects actual walked order.
    DealFinder: noCompetition no longer falsely flags realms with
    regional-only pricing (nil numAuctions ≠ no competition).
    Population mode sorts unknown-competition realms last (-1).
    TransformPage: "Warm Cache" renamed to "Deep Search" (user-facing).
    New nameless item detection for items with numeric ID but placeholder
    name. Deep Search now handles ID→name resolution (not just name→ID).
    TSM group items added to warming pool (selected profile). Retry pass
    after completion catches silently-loaded items. Debug dump lists
    remaining unresolved items. Pet name fallback via C_PetJournal
    stashes speciesID as metadata without converting to battle pet.
    Transformer: SplitPets promotes _petSpeciesID items to pets array
    for AAA output while preserving original itemID for PBS/TSM formats.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.10.2-alpha1: PBS import/export + pricing ilvl fix + Cogworks context
    New features
    • PBS (Point Blank Sniper) import/export. Paste a PBS export into
      Transform > Paste and the format auto-detects via a hybrid probe
      (fast-path on the ;;#;; tier-placeholder substring, structural
      fallback for the all-R3-crafted edge case). Each entry parses into
      the 14-field Auctionator advanced-search wire format from
      Auctionator.Search.ReconstituteAdvancedSearch, with every field
      preserved in a per-item _pbs metadata table so round-tripping via
      the new PBS output button is byte-identical. Output adapters for
      AAA JSON, FP CSV, TSM Group string, and Auctionator shopping list
      all work without modification since enrichment resolves names via
      the map lookup chain.
    • Name -> itemID resolution via TSM + PBS caches. Covers the "I have
      a PBS list from an expert" workflow: _G.TSMItemInfoDB is
      LongString-decoded (\002 separator, 1000-entry chunks per
      LibTSMUtil/BaseType/LongString.lua), and PBS's
      ItemKeyCache.State.orderedKeys + newKeys staging are walked for
      the user's own search history. Coverage on a representative
      foreign PBS file jumped from 6/100 to 64/100.
    • Warm Cache button. When the preview detects unresolved items AND
      TSM's realm data or Auctionator's price database is loaded, a
      "Warm Cache (N missing)" action button appears next to Preview.
      Clicking it collects every unique item ID from the union of
      TSMRealms.realmRaw and AUCTIONATOR_PRICE_DATABASE (parsing bare
      numeric, g:id:ilvl, gr:id:suffix formats per
      Auctionator/Source/Utilities/DBKeyFromLink.lua) and proactively
      forces them into WoW's client item cache via batched
      C_Item.RequestLoadItemDataByID (250 IDs / 0.05s). A
      GET_ITEM_INFO_RECEIVED listener matches incoming names against
      the unresolved PBS names and folds matches into the name map with
      source="cache". Re-runs the preview after a 1.5s settle window.
    • Per-source resolution breakdown in the preview status line.
      Shows where each resolved item came from (inv=2 pbs=4 tsm=58
      cache=30) plus an explicit "N unresolved" count. Previously
      unresolved items were silently dropped, making "paste 100, see
      64" mysterious.
    • AAA price mode toggle + recorded-price fallback. New TSM discount
      / Imported toggle on the AAA price row. In TSM mode, when TSM
      has no price for a resolved item, OutputAAAJSON now falls back
      to the recorded price (PBS _pbs.maxPrice first, then
      expectedPrice) with NO discount applied. The user explicitly set
      recorded prices as their target; discounting them would change
      the meaning.
      Bug fixes
    • Profession tools silently rejected from to-do generation as "TSM
      below min price". TodoGenerator.lua:891-894 had a dual-key
      fallback that fired whenever the first IsBelowThreshold returned
      false - which happens in two distinct cases the code couldn't
      tell apart: (a) variant price above threshold (correct) and (b)
      TSM has no data (undecided). The fallback then called
      IsBelowThreshold(deal.itemKey) on the FP import's base-item key
      (no bonus IDs), which for a high-ilvl variant resolved to the
      dramatically-lower base-item DBMinBuyout and returned true,
      overriding the correct "above threshold" result. Fixed by gating
      the fallback on not ahMin so it only fires when the poolItem
      check actually had no data. Full audit of all 5 IsBelowThreshold
      call sites confirms this was the only buggy one.
      Docs
    • CLAUDE.md gains a Cogworks suite context paragraph pointing at
      the sibling cogworks repo (docs/AGENT_BRIEF.md, PLAN.md,
      SYNDICATOR_INTEGRATION.md) for architectural guidance on the
      upcoming Phase 6a Syndicator migration.
      Known limitation
    • Very rare or discontinued items (TCG mounts, heritage rewards,
      items not currently on any tracked realm's AH) may not resolve
      if they aren't in any local data source. v0.10.2-alpha2 will
      add a vetted static mount/rare-item table to close this gap.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.10.1-alpha3: bank popup completion sync + reagent bag fix + popup diagnostics
    Three independent bugs causing the Bank Operations popup to show
    "Operations complete" rows but a partial/zero progress bar:
    1. Optimistic deposit progress reports — Tracker.lua's DoDeposits
      reported #depositOps and #extraOps (the requested counts) directly
      to BankOpProgress, never threading the actual successNames/errorCount
      from BankQueue:Process. Refactored to await AutoDepositToWarbank and
      AutoDepositExtraItems sequentially via callbacks that pass through
      the real counts. The two sub-phases now run in series instead of
      fire-and-forget, so progress reports always reflect what actually
      moved.
    2. AutoDepositExtraItems was fire-and-forget — no onComplete callback
      at all. The popup chain would proceed to BankPopupComplete while the
      extras' BankQueue:Process was still mid-batch, so the running tally
      could land anywhere between 0 and total depending on which timer
      raced first. Added an onComplete(successNames, errorCount) parameter
      that fires from every early-return path AND from the final Process
      callback after Scanner refresh settles, so the chain can actually
      wait for extras before declaring completion.
    3. Reagent bag silently dropped from AutoDepositToWarbank —
      Tracker:BuildDepositOps (the popup builder) iterates ALL_PLAYER_BAGS
      = {0..5} which includes the reagent bag, but
      Tracker:AutoDepositToWarbank was iterating INVENTORY_BAGS = {0..4}
      which excludes it. So a deposit task whose source item lived in slot
      5 would appear in the popup but get silently skipped during
      execution. Both call sites now iterate ALL_PLAYER_BAGS and stay in
      agreement.
      Defensive fix: ShowCompletionSummary now reconciles the running
      completed count up to totalOps - failed on transition to "Complete"
      (preserving the failed count so the orange/green color logic still
      reflects whether anything failed), and emits a [bank-popup] debug line
      whenever drift is detected so the underlying drift remains diagnosable
      even if a future regression introduces a new tally bug.
      Diagnostics: BeginBankExecution, BankOpProgress, ShowCompletionSummary,
      and BankPopupComplete now each emit a one-line [bank-popup] debug entry
      into the in-game debug ring buffer regardless of the debugMessages
      print setting. Records the operation, the running completed/failed/
      total, and any guard hits (popup not shown, execState nil). Use this
      to diagnose any future "popup state out of sync" reports — the entire
      execution timeline lives in the debug console after the bank visit.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.10.1-a2: deposit overflow + filter bypass + async-path throttle + picker debug log
    Three deposit-routing bugs reported by alpha testers, plus diagnostic
    logging to make future "wrong tab" reports debuggable in one round-trip.
    1. destType="any" overflow bypass — AutoDepositExtraItems builds
      non-soulbound deposits with destType="any" and both ProcessNextBatch
      and ProcessSync's Attempt handled "any" by merging warbank+bank
      into the picker's primary bag list, silently bypassing the
      overflowEnabled gate inside PickDepositSlot. A user with a full
      warbank, locked bank tabs, and overflow off still saw items leak
      into bank because the picker never consulted the overflow flag.
      Both call sites now treat "any" the same as "warbank": warbank as
      primary, bank as secondary, gated by overflowEnabled.
    2. Items leaking to bank even when warbank had open slots —
      ItemMatchesTabFlags only knows about Weapon/Armor/Consumable/
      Tradegoods/Recipe/Questitem/Junk classes. Items in any other class
      (Gem, ItemEnhancement, Glyph, Miscellaneous, Battlepet, Profession,
      …) get rejected by every tab with non-zero depositFlags, even when
      those tabs have empty space. The picker would declare warbank "full"
      and overflow into personal bank. PickDepositSlot now has a
      filter-bypass fallback path: if no filter-matching primary tab can
      take the item, walk every primary tab ignoring filters before
      falling back to overflow. Tab filters are now treated as a routing
      preference, not a hard wall. FindStackTarget and
      FindEmptyAcceptingSlot gained an ignoreFilters parameter.
    3. Warbank getting disabled after bulk deposits / between characters —
      ProcessNextBatch (the async path used by AutoDepositExtraItems)
      issued every op in a batch (pullBatchSize, default 5) inside a
      single tight Lua loop with no inter-move spacing — only
      INTER_BATCH_DELAY=0.3s between batches. Five container ops in a
      single frame is exactly what trips Blizzard's per-frame rate limit,
      and the resulting backoff manifests as the warbank being
      unresponsive on the next character. The async path now serializes
      ops the same way ProcessSync does — WaitForBagUpdate(0.1s, …)
      between every real container move, with skip-cases yielding via
      C_Timer.After(0, …) so big batches don't blow the Lua call stack.
      Diagnostics: every PickDepositSlot call emits one line into the debug
      ring buffer (visible in the in-game debug console regardless of the
      debugMessages print setting). Discloses the item, the picked
      destination, which branch picked it (stackTarget(primary),
      emptySlot(primary,filter-bypass), emptySlot(secondary,overflow), …),
      and the full candidate list with each tab's depositFlags, specificity,
      and accept/reject decision. Makes it obvious whether the picker chose
      tab N because of an existing partial stack, a higher-specificity
      Blizzard filter, or fall-through into the filter-bypass / overflow
      paths.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • release.yml: use literal alpha/beta in tag names for packager detection
    The BigWigsMods packager auto-detects release channel from the literal
    substrings "alpha"/"beta" in the tag name. The prior attempt to pass
    -a/-b CLI flags was wrong: -a in release.sh is wago-id (requires an
    argument), which broke v0.10.1-a1 with "Option -a requires an argument".
    Switch the tag convention to v<x.y.z>-alpha<N> / -beta<N> so the packager
    and the workflow's own channel detection both use the same rule.
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • v0.10.1-a1: deposit swap fix via allocation ledger + BAG_UPDATE wait
    CursorMove was targeting destination slots from the client container cache
    which can lag the server for unviewed warbank tabs. Two deposits in the
    same sweep would both pick the same "empty" slot, or a single deposit
    would hit a slot that was actually occupied server-side — either way, the
    server performed a swap and the delta verification (which only tracks the
    deposited itemID) declared success while an unrelated item was displaced
    out of the bank.
    Fix is modeled on Baganator's BankTransferManager:
    • Allocation ledger (allocatedSlots) scoped per sync attempt / async
      batch. Claim the slot before CursorMove runs; FindStackTarget and
      FindEmptyAcceptingSlot skip claimed slots. Two ops can never target
      the same slot regardless of what the cache says.
    • BAG_UPDATE_DELAYED wait between sync moves so the next move's picker
      sees a fresh cache. 100ms minimum still enforced for Blizzard's
      container-op rate limit; 600ms ceiling for rejected moves.
    • C_Item.DoesItemExist (ItemLocation-based) preferred for empty-slot
      detection in FindEmptyAcceptingSlot, which is more reliable than
      C_Container.GetContainerItemInfo for unviewed warbank tabs.
    • Source-item validation via op._expectedItemID — retries abort if the
      source slot no longer holds the item it did on first issue.
    • CursorMove destination guard rejects place attempts when the
      destination holds a different itemID than the cursor.
      Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • Discord: release notifications, server setup runbook, bot design
    Add Notify Discord step to release.yml that posts changelog embeds
    to a webhook on tag push. Add operator runbook for server/channel
    setup and GitHub→Discord issue webhook. Add architecture design doc
    for the Claude-backed interactive support bot (not yet implemented).
    Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
  • CHANGELOG: backfill v0.9.8, v0.10.0-a1, v0.10.0-a2, v0.10.0-a3
    The changelog had no entries past v0.9.7 even though four versions had
    shipped since (v0.9.8 stable + three v0.10.0 alphas). Backfilled all
    four with bug fixes / features / settings reorganization grouped per
    release, in the existing changelog format.
  • release.yml: detect -aN/-bN tags, pass -a/-b to packager
    The previous detection logic only matched the literal substring "alpha"
    in the tag name, so v0.10.0-a1 / -a2 / -a3 fell through to the "release"
    branch. That had two consequences:
    1. The local prerelease step set prerelease=false for the GitHub Release.
    2. The BigWigsMods/packager step never received any channel info — its
      own tag-name auto-detection only recognizes "-alpha" / "-beta" literal
      substrings, so it also classified -aN tags as stable. Both CurseForge
      and Wago therefore uploaded the last three alphas to their default
      stable channel where regular users would install them.
      Fix:
    • Detection regex now matches the literal "alpha"/"beta" words AND the
      shorthand "-a<N>" / "-b<N>" suffixes we actually use.
    • A new packager_flag output exposes "-a" or "-b" which is appended to
      the packager args, explicitly forcing the upload channel instead of
      relying on auto-detection.
      Next alpha tag (v0.10.0-a4 onward) will correctly land in CF Alpha /
      Wago Beta channels and become the latest release, superseding the
      mis-classified historical builds.