# WarBoard Changelog

## 1.6.8

### Tracking & cargo fixes
- **Supply-runner tracking no longer freezes on the map.** A tracked runner's pin could get stuck at
  one spot while they kept moving — the hunter was ending the track whenever a carrier alert went stale,
  even though the live position pings were still arriving (and those alerts lag or miss cross-faction).
  Runners now report their carry state in every position ping, so a track only ends when the runner
  actually says they've stopped carrying. The pin follows them live.
- **A runner who already delivered can't be "robbed."** After a turn-in, a lost "ended" alert used to
  leave the runner flagged as a carrier indefinitely — so they kept showing as a runner and every later
  killing blow "stole" cargo they no longer had. Carrier flags now expire on a timer (and clear the
  instant a runner reports they've delivered), so a delivered runner drops off the map and yields
  nothing on a kill.

Client-side and wire-compatible; both fixes work hunter-side even against a runner on an older build.

## 1.6.7

### Kills no longer live in the activity ledger
- **World-PvP kill credit moved to its own lightweight tally.** Every kill still awards +1 War Credit
  and shows on the Leader Board and War Contribution bar exactly as before — but instead of writing a
  record into the shared ledger (the highest-volume event by far at population), kills now sync as one
  small evolving value per player per campaign. That's a big cut to the record churn, sync traffic,
  and repeated full-ledger scans behind the micro-stutter, especially with lots of people out killing.
- **It can't undercount.** The tally only ever merges *upward* (a stale or lost update leaves a peer
  briefly behind, never below the true count), it's kept out of the ledger so trimming can't touch it,
  and each campaign's kill credit is baked into the locked result at finalization — so past results
  can't change. Your personal total and rank still include every kill.
- Trade-off, stated plainly: this slice is now a trusted aggregate rather than a hash-verified record,
  so kill credit isn't tamper-proof the way gold/objectives/bounties still are. Being upward-only, the
  only possible abuse is a cheater inflating their *own* number — never harming anyone else's.

### Leaner ledger
- **Ledger cap lowered to 3,000 records** (from 10,000). With kills gone, a campaign's ledger footprint
  is small, so this holds many campaigns before it ever trims — while keeping the cap-trim spike tiny.
- **Old records auto-trim.** Records from campaigns that ended more than ~2 hours ago are dropped
  automatically (their results are long locked by then, so nothing changes); your own earnings are
  banked first so lifetime totals never move, and everyone trims the same set deterministically.
- **The sync fingerprint no longer spikes.** Hashing the ledger's sync digest used to process up to
  700 records in one synchronous burst (~18ms — a visible hitch on a busy ledger) and ran its first
  slice inline; it's now hashed in small slices fully spread across frames, so it never stalls a frame
  regardless of ledger size.

### Diagnostics
- **`/wb ledger`** — prints how many records currently live in your ledger, by type (a quick way to
  watch the churn drop).
- **`/wb perf` now reports ledger inflow** — records/min and which types dominate, so you can measure
  the record load directly during a busy session.

All client-side and wire-compatible: existing kill records already in ledgers still count and age out
normally, and older clients simply won't see the new kill-tally sync. Mixed versions still talk fine.

## 1.6.6

### Anti-cheat: a second port-out escape is now caught
- **Bench-porting out of a fight (Exit Lorewalking) is now flagged too.** The 1.6.5 anti-cheat only
  caught the quest-abandon teleport; leaving a Lorewalking bench mid-fight to escape now gets the
  exact same treatment — marked a DESERTER (stacking, no earnings while marked), publicly announced
  to both factions, and if you were bountied, the reward is handed to one random hunter who was
  tracking you.
- **It only triggers in PvP combat.** Exit Lorewalking is a normal, legitimate spell, so it's flagged
  only when cast while actually fighting a hostile player — using a bench normally is never touched.

### Performance — micro-stutter fixes
- **The objective tracker no longer relayouts on every kill/spawn.** Each objective update (every
  kill, every proximity in/out) was forcing a full relayout of Blizzard's *entire* tracker — so
  farming with mobs streaming in, or the start of a player fight, spiked. Those are now coalesced
  into a single relayout, which should smooth out the "lag when things load in" hitching.
- **Dropped a periodic guild-roster scan.** Peer selection was walking your whole guild roster every
  few seconds to dedupe sends — pointless work (the guild broadcast reaches everyone anyway). Removed;
  no more O(guild-size) hitch on big guilds.
- **Live tracking pings no longer decode twice.** A fast-path tracking packet and its reliability
  backstop were each being decompressed on arrival; the backstop is now skipped once the fast copy
  is handled.

### New: `/wb perf` — micro-stutter diagnostic
- **A built-in profiler to find what's causing a stutter.** Turn it on, reproduce the hitch, and it
  names the WarBoard function at fault (and flags garbage-collection pauses). Off by default with zero
  overhead; `/wb perf` for options. It's how the fixes above were pinned down.

All client-side and wire-compatible — mixed versions still talk fine.

## 1.6.5

### Anti-cheat: the port-out escape now has consequences
- **Fleeing a fight with the quest-abandon teleport ("port out") marks you a DESERTER — always.**
  It's detected on the escapee's own client, publicly announced to both factions, and stacks another
  hour per offense (capped at 10h). While marked you bank no gold or war credit.
- **If you were bountied when you ported, your bounty is handed to a hunter.** The reward goes to one
  random player who was *actively tracking* you (never one of the bounty's own posters), and a second
  announcement line names who received it. So porting out no longer wipes your bounty for free — it
  pays whoever was on your trail.

### New: micro-stutter / FPS-spike diagnostic — `/wb perf`
- **A built-in profiler that finds out whether WarBoard is behind a stutter, and which part.** Turn it
  on, reproduce the hitch, and it prints the culprit live (e.g. *"stutter WB.UI.RefreshLeaderboard
  took 22 ms"*) and in a ranked report. It also flags hitches that coincide with a garbage-collection
  pass, and can use the game's `scriptProfile` for exact whole-addon CPU. Off by default with zero
  overhead; see `/wb perf` for options. Honest by design — if nothing in WarBoard took measurable
  time during your stutter, it says so, and we look elsewhere.

### Smaller
- **Live tracking refreshes twice as often** — a tracked target's position now broadcasts every 5s
  instead of every 15s, so the map dot keeps up better.
- **Shorter chat tag.** WarBoard's chat lines are now just tagged `[WarBoard]` instead of
  `[WarBoard vX.X.X]`; the version is printed once at login.

Mixed versions still talk fine: the bounty hand-off is a normal claim record everyone already
understands, so hunters get paid regardless — but update to see the new public announcements.

## 1.6.4

### Tracking is near-instant now
- **Bounty and supply-runner tracking connect and follow immediately.** The ack + live-position
  pings were queued behind sync traffic; they now send at top priority AND take a raw fast path that
  skips the message-throttle queue entirely, with the normal path kept as a reliable backstop
  (whichever copy lands first wins). Map-following a target should feel instant.
- **"Supply Runner Spotted" alerts land faster** too (same fast-path treatment) — so do war-objective
  assault alerts.

### New
- **`/wb channel on|off`** — opt in/out of WarBoard's hidden realm sync channel. It never showed in
  your chat, but it does occupy a channel slot; turn it off if you'd rather WarBoard not join a
  channel (sync still works over guild, whispers, and peers). On by default.

All client-side; nothing changes on the wire, so mixed versions still talk fine.

## 1.6.3

Performance pass — all client-side, no wire/version impact. Follows the same idea as 1.6.2's board
gate: stop doing background work you can't see.

### Fewer background rebuilds
- **The Active Bounties and Alerts panels no longer rebuild while the board is closed.** Like the
  Leader Board fix in 1.6.2, these were quietly rebuilding on every event that touched them (each
  tracked target's position, the presence poll, every bounty post/accept/abandon, cargo theft, the
  alert ageing tick) — even with the board shut. They now rebuild only when it's actually open.
- **Bounty board rebuilds from sync are coalesced.** A burst of synced bounty events used to trigger
  a full O(ledger) rebuild per event; a burst now collapses into a single rebuild.

### Cached the heavy ledger scans
- Gold/War-Credit totals, the Leader Board, the War Contribution bar, and the Activity feed each
  re-scanned the whole ledger (up to 10k records) on every request — and some ran several times per
  refresh. They're now cached and only recomputed when the ledger actually changes (or the
  anti-cheat re-judges a record), turning repeated scans into instant lookups.

### Smoother objective farming
- **Killing objective NPCs no longer relayouts the game's objective tracker on every kill.** Rapid
  or AoE farming was forcing a full Blizzard objective-tracker relayout per kill; the intermediate
  progress ticks are now batched (a few times a second) while completions still show instantly.

## 1.6.2

### Stolen cargo
- **You can now turn stolen cargo in.** Your quartermaster (Tweedle / Apprentice Boulian) offered
  no delivery option once your *daily* run was already done — it only looked at the daily state and
  showed its "thank you" dialogue. It now recognizes stolen cargo (which has no daily limit) and
  offers the hand-in regardless.
- **"Stolen Cargo!" popup + objective.** Seizing an enemy's cargo now flashes a center-screen
  "Stolen Cargo!" banner and adds an objective-tracker step telling you to deliver it to your
  quartermaster (no War Effort card). It clears itself on turn-in / loss and survives a `/reload`.
- **The victim's map icon no longer lingers.** When a tracked runner dies, delivers, or loses their
  cargo, their icon is dropped immediately instead of sitting at the spot for up to ~2 minutes.
- **Tracking follows the cargo.** If you were tracking a runner and someone steals their cargo, your
  track now **auto-switches to the thief** — you follow the supplies instead of losing them at the
  corpse, no need to re-TRACK.
- **You're told when your cargo is stolen.** If a player seizes cargo you were carrying, you now get
  a chat line naming who took it (the thief already saw their own confirmation).
- **Completion jingle.** Completing a Supply Run and turning in stolen cargo now play the same
  "quest completed" sound as other objectives.

### Bounties
> **Everyone should update** for consistent scoreboards — an out-of-date client won't apply the fix.
- **Fixed two hunters both getting credit for one bounty.** A bounty can only be claimed once, but a
  near-simultaneous claim-race (e.g. a group killing the target) could let two hunters both score it.
  Claims are now de-duplicated on a strict "first claim wins" rule — corrected live as soon as both
  claims have synced, and enforced deterministically in the campaign audit so the final result is
  always right. (No wire change; a mixed-version network still stays in sync, it just won't correct
  the score until each client updates.)

### Anti-cheat
- Added an always-on guard that **ejects the player from the "Magical Snow Sled" and the Lorewalking
  "Bench"** the instant either is detected (as a vehicle or a pet). Runs the whole session, event-
  driven with a light backstop.

### Performance (micro-stutter)
- **Board panels no longer rebuild while the board is closed.** The Leader Board and Activity feed
  are O(ledger) rebuilds that were being triggered by *every* background peer-sync burst even with
  the board shut. They now only rebuild when the board is actually open (one catch-up rebuild on
  open). This was the biggest sync-time hitch.
- **World-map icons no longer rebuild every second.** Live bounty/carrier icons now redraw only when
  a position arrives and reposition themselves as you pan; a slow sweep just expires stale ones.
- **Duplicate messages are dropped before decoding.** The fanout delivers the same message over
  several channels at once; byte-identical copies are now skipped before the (costly) decompress +
  deserialize instead of being processed each time.

## 1.6.1

> **Everyone should update.** The bounty tracking fix works both when you track *and* when
> you're the one being tracked — an out-of-date client can still fail to answer a tracker.

### Fixes
- **Bounty TRACK no longer gets stuck on "Locating…".** The target's client was only recognizing
  a tracker's request by GUID, but a bounty's GUID is captured from the community roster when it's
  posted and can differ from the target's current character — so the target silently ignored the
  request and never shared its location. It now recognizes a track request by **GUID *or*
  name+realm** (the same way it already detects a bounty on itself), so tracking connects reliably.
  This is why supply-runner tracking worked while bounties didn't — a supply runner reports its own
  live identity, so it always matched.
- Hardened the track handshake generally: the request is now sent to every valid address for the
  target (stored + roster-resolved), and realm names are normalized so a display-form realm
  ("Area 52") can't silently break the whisper the request rides on.
- **Supply Run objective card now shows on the War Effort panel.** A load-order race meant the run
  wasn't resolved yet when the panel was first built, so the card was skipped.

### Added
- `/wb commdebug` — toggle a comm / tracking RX-TX trace for diagnosing tracking issues.

## 1.6.0

### New: Supply Run (daily World PvP delivery event)
A new daily event that turns a supply haul into open-world PvP bait. There's a separate Horde and
Alliance version — you only see and run your own faction's.

- **Horde** — talk to Overseer Gorthak at Warsong Lumber Camp, then haul the lumber on foot to
  Tweedle at Hellscream's Watch.
- **Alliance** — talk to Faldreas Goeth'Shael in Astranaar, then carry the ironwood beams on foot
  to Apprentice Boulian at Forest Song.
- Multi-page quartermaster dialogue (fake gossip), an objective card, a map pin at the pickup, and
  an objective-tracker step guide the run.
- **On foot only** — mounting, flying, druid Travel/Flight Form, taxis, and vehicles are all
  blocked while carrying the shipment (you're too heavily loaded).
- **Daily, per character** — once completed *or* failed, it's locked for that character until the
  next daily reset.
- **Fails** on death, logging out mid-run, taking a taxi, or crossing a loading screen.
- **Reward** — a completed run pays **300 gold + 150 war credit**.

### New: Supply Runner intel, opt-in tracking & cargo theft
Supply runners are visible to the enemy, and their cargo can be stolen.

- While you carry a shipment, a lightweight **alert** is broadcast to the enemy faction
  ("SUPPLY RUNNER SPOTTED"). No precise location is shared by default.
- Enemies can click **TRACK** on the alert to opt into live location tracking, drawing a flag
  icon on the world map (reuses the bounty location transport — only trackers who opt in ever see
  the position).
- **Cargo theft** — landing the killing blow on an enemy supply runner **steals their cargo**. You
  become a stolen-cargo carrier ("STOLEN SUPPLIES MOVING"), subject to the same on-foot rule, and
  can turn it in at your own quartermaster with **no daily cooldown**.
- Stolen cargo is **lost** on death (your killer steals it in turn), logout, loading screen, or
  taxi; it **survives a `/reload`**. You can carry multiple stolen shipments at once.
- **Reward** — each turned-in stolen shipment pays the same as a Supply Run: **300 gold + 150 war
  credit**.

### Rewards are now banked & synced
- Supply Run completions and stolen-cargo turn-ins now write a real, synced **`supply_run` ledger
  record** — they count toward your gold/war-credit totals, the leaderboard, and the war
  contribution bar, and are validated by the anti-cheat verifier like any other activity.
- Added a canonical `WB.SUPPLY_REWARD` (300 gold / 150 war credit) as the single source of truth
  shared by the run layer, the cargo layer, and the verifier.
- Rules version bumped to **6** for the new `supply_run` activity type, so out-of-date clients
  safely abstain on (and keep relaying) the new records until they update, rather than rejecting
  them.

### Fixes
- **Bounty TRACK now reliably locates online targets.** Pressing TRACK on a bounty whose target
  was clearly online could still fall through to "Failed to obtain." That's fixed — TRACK now
  correctly obtains their location. (Targets who don't have the addon, or have it disabled, still
  correctly can't be tracked, but no longer cause a false handshake.)
- **Supply runner map flag no longer lingers after a run ends.** When a tracked runner fails,
  delivers, or loses their cargo, the flag icon now disappears on the next location update: the
  tracker verifies they're still a carrier and, if not, stops tracking and tells them to stop
  broadcasting (unless they're also an active bounty).

### Removed
- `/wb testsupplyalert` and `/wb teststolenalert` (dev-only fake-alert previews).
- `/wb resetsupply` (dev-only Supply Run state reset).

### Performance
- Reduced micro-stuttering during peer sync: the ledger sync digest is now computed
  time-sliced across frames, online-peer lookups are cached briefly, and HELLO handling uses the
  async digest — so busy comm traffic no longer causes frame spikes.
