0.0.7-forever
What's new
Wayscribe
0.0.7 (2026-10-17)
Full Changelog Previous Releases
- Merge pull request #37 from ollidiemaus/1.0-launch
Launch trackers: cheaper looks on bursty events - Build a gold best-day candidate only for money earned
Spent counts no longer make a throwaway table in the month rollup. Adds the
missing tie spec: the earlier day stays best, in a month and across months.
Closes #36 - Hear PLAYER_GUILD_UPDATE only for the player
Guild registers the event as a guarded unit event for the player, so the
client no longer wakes the tracker for nearby players' guild changes.
The fake API now filters unit events by their registered units and
counts deliveries, so specs can prove it.
Closes #35 - Save nothing on a reputation look that finds nothing changed
A look first compares the standings with the saved snapshot in place and
ends unchanged without copying or saving it; only a changed reaction or a
new faction copies, writes and saves. Closes #34. - End an equipment change for a known item at once
The per-slot path reads the saved gear snapshot instead of a deep copy, so
a set swap of known items no longer copies every item ever worn: 16 slots
made 23 KB at 20 items and 643 KB at 800, now 0.3 KB at both. A new item
goes into the saved snapshot directly, a notable one only once its entry
is written; the read-only check comes first. The look at every slot keeps
its copy.
Adds T.garbage to testlib, a cost spec for the swap and a read-only spec.
Closes #33 - Arm one timer per burst in the core debounce
Module:Debounce arms a timer only when none armed for the key fires by
the request's due time. A timer that fires early arms one more for the
rest, and the work runs once a timer finds its due time reached. The
callback is built once per key. Twenty UPDATE_FACTION events now arm one
timer instead of twenty; AskForLook, TakeAsked and every trace line are
unchanged, and Guild's retry still waits its own delay.
Switching a module off now drops its pending work even if it is switched
on again before it was due, as the debounce's contract always said.
The module spec gets debounce specs, the Reputation spec the burst,
spread, time jump and switch-off cases, and the fake C_Timer counts the
timers armed. §3.3 says a debounce arms one timer per burst.
Closes #32 - Sweep every event with secret arguments, and list all a tracker needs
tests/secrets_spec.lua fires every event any module registers with
secret arguments, once posing as numbers and once as strings, and fails
on any error the boundaries log. It catches the unchecked slot that
6cefdac fixed in Gear.
Stubs.LoadAddon takesonly, a tracker id, and switches every other
tracker off, so a tracker's trace test no longer lists the others and a
new tracker no longer edits every launch tracker's spec.
DEVELOPMENT.md's "Adding a tracker" now names every place a tracker
commit touches: Compat and §5, .luacheckrc, the stubs, §6, §9, §11, the
README and the in-game checks. - Merge pull request #17 from ollidiemaus/1.0-launch
1.0 Launch: plan the launch trackers and probe their APIs - Say how a restored journal keeps its firsts, and record the launch decisions
The 6.11 rule now matches the trackers: snapshots are Store state the
backup carries, and the firsts rebuilt from the entries keep a first from
repeating. Decisions gets the firsts from before a tracker, whose Legacy
Challenge it is, mounts-only Collections, and heirlooms and tokens left
out of notable gear. - Count hover-only explored areas as explored
The beta ruled hover-only textures out as the cause of the phantom zones,
and an area the map shows under the mouse is explored all the same, so
Compat.GetExploredZones counts every zone that returns a texture. The
probe still lists each zone's textures and hover-only ones. - Record only listed challenges from ACHIEVEMENT_EARNED
Compat.GetLegacyChallenges says third whether every category and row was
read. When it was, an earned ID missing from the list isn't a Legacy
Challenge (a guild achievement, say) and makes no entry; an earned
challenge whose row can't be read is still recorded by its ID. - Take the gear and mount firsts worn or owned at the first look
A rare or an epic worn at the gear tracker's first look, and a mount owned
at the collections tracker's first look, was the character's first. The
snapshot keeps hadRare, hadEpic and hadMount, and later epics and mounts
carry notFirst so a rebuild of the firsts doesn't mark them either. A
journal restored without the gear state takes its epics as had. - Tidy what the launch-tracker review found
- Compat.GetGlobalStringForPlayer(key) reads a client string in its
female form for a female character; Reputation's standing names and
Compat.GetPvPRankTitle both read it there instead of each by hand. - Compat.LEGACY_TRACK_FACTION (2802) joins Compat.PVP_RANK_FACTION, and
Reputation and the probe name the two progress tracks by them. - The probe listed PLAYER_CONTROL_GAINED twice.
- Flight paths' list of nodes to write is toWrite, not record, which is
the journal's word for an entry.
- Compat.GetGlobalStringForPlayer(key) reads a client string in its
- Copy snapshots through the Store and steer looks by results
Five launch trackers copied their snapshot four different ways before
changing it, so a look that stops at a failed write leaves the saved one
as it was. Store:CopyState(key) gives that copy once.
Gear, Legacy Challenges and Home decided what to do next by matching
their own trace labels ("^not written", "read-only", "first epic"), so
rewording a label would have changed behaviour. Gear's consider now
says whether it wrote the entry, Legacy's compare whether the look was
saved, and Home's compare whether this session has read the home; the
labels only go to the trace. Gear asks to read an item again when its
quality wasn't loaded, rather than when the label says so. - Keep raw values for the trace through one Compat helper
Eight Compat readers hand-wrote the same type check, pcall and Safe so
the launch trace could show the value the way the game gave it.
Compat.CallWithRaw(fn, expectedType, ...) does it once: the safe value,
the raw value, and whether the call ran (an empty equipment slot and an
error read differently). GetMoney, GetFactionStandings,
GetLegacyChallenges, GetEquippedItem, GetGuild, GetBindLocation,
GetMounts and GetPvPRank use it and return what they did before. - Share the look batching between the launch trackers
Nine launch trackers each carried the same AskForLook and drained
self.asked by hand before tracing. Trackers now get both from
Core/Trackers.lua: AskForLook(event, seconds) debounces the look by the
tracker's lookDelay (one second unless ns.Trackers:New says otherwise,
as First visits and Flight paths do), TakeAsked() gives the events
joined by "+" for the trace line, and switching a tracker off drops
what it had asked for. - Read the equipment slot through Compat.Safe
PLAYER_EQUIPMENT_CHANGED's slot was compared with the slot range as it
came. A secret number passes the type check and then raises an error on
the comparison (docs/ARCHITECTURE.md §1), so the slot now goes through
Compat.Safe first, as Legacy Challenges does with its achievement ID. - Launch Collections with mounts only; pets and toys wait
The beta probe read 0 of 0 pets and toys on characters that own none,
which can't tell a broken journal from an empty one, and no pet or toy
was learned to settle it. Closes #28, closes #29. - Track each new highest PvP rank in a season
An entry for each new highest PvP rank the character reaches in a
season, "Reached PvP rank 3: Sergeant", in PvP. The rank is the renown
of the PvP rank faction (2800) and the season the current arena season.
PLAYER_PVP_RANK_CHANGED, MAJOR_FACTION_RENOWN_LEVEL_CHANGED (for 2800
only), login and loading screens ask for a look, compared with the
snapshot state.pvpRank, so a missed event is caught at the next look
and a rank found at login is recorded on the login day.
The title is the client's PVP_RANK_<Rank_1 + rank - 1>_<0|1> for the
player's faction, its _FEMALE form for a female character, as Blizzard's
PVPRankFrame builds it; without one the entry names the rank by number.
The first look, losing a rank and a new season make no entry.
Your Year gets a PvP rank card after Duels: the highest rank, its title
and when it was reached. Each look is traced in developer mode.
Closes #30 - Track each new mount the character collects
An entry for each new mount, "New mount: Brown Horse", in Progress.
Login, loading screens, NEW_MOUNT_ADDED and COMPANION_LEARNED ask for a
look at the mount journal's collected flag, which is compared with the
snapshot state.collections, so a missed event is caught at the next look
and a mount found at login is recorded on the login day.
The first look takes the owned mounts silently. The firsts key MOUNT
marks only the first mount; the snapshot says which were recorded, and a
journal back without it gets a silent first look. A mount whose
collected flag isn't loaded yet is left out, so it can't read as new
later.
Your Year gets a Mounts card after Legacy Challenges: how many were
collected and the first mount. Each look is traced in developer mode.
Pets and toys join this tracker in their own ticket.
Closes #27 - Track each new inn the hearthstone is bound to
An entry when the character binds its hearthstone at a new inn during
play, "Hearthstone bound to Thunder Bluff", in Travel. HEARTHSTONE_BOUND,
CONFIRM_BINDER, PLAYER_ENTERING_WORLD and the login ask for a look
(Compat.GetBindLocation), which compares the inn's place with the saved
snapshot, so a missed bind event is caught at the next look during play.
The place is read in the client's language, so the first look of each
session takes it silently: a switched client language, or a bind made
while Wayscribe was off, is no move. Switching the tracker off and on
during play keeps the session's look, so a bind made meanwhile is found.
No Your Year card. Each look is traced in developer mode.
Closes #26 - Track joining and leaving a guild
An entry when the character joins a guild, with its name, and when it
leaves, in Adventure. PLAYER_GUILD_UPDATE and the login ask for a look
(Compat.GetGuild: IsInGuild and GetGuildInfo), which compares the guild
with the saved snapshot, so a change made while Wayscribe was off is
recorded at login on the login day. A switch writes both entries.
Only "not in a guild" means the character left: in a guild with the
name still missing, the look changes nothing and looks again 5 seconds
later, at most three times. Rank changes make no entry, and the first
look is silent. No Your Year card. Each look is traced in developer
mode.
Closes #25 - Track each new flight master the character learns
An entry for each newly known flight path, once per node (firsts key
FLIGHT:<node>), in Travel, with the node's name. TAXIMAP_OPENED asks
for a look at the known nodes: Forever's flight map (GetTaxiMapID,
C_TaxiMap.GetAllTaxiNodes, states current and reachable) or else the
old taxi frame. The "New flight path discovered!" chat line only asks
for another look.
A look compares the known nodes with the saved snapshot, so a path
learned without a look is recorded at the next flight master. The first
map on each continent is silent, except when the only known node is the
one the player stands at, which keeps a fresh character's first flight
path.
The Footsteps card in Your Year gets a line with how many flight paths
were learned. Each look is traced in developer mode.
Closes #24 - Track each Legacy Challenge the character completes
An entry for each Legacy Challenge, once per challenge (firsts key
LEGACY:<id>), in Progress. Login, loading screens and
ACHIEVEMENT_EARNED ask for a look at every challenge through the
achievement API, so a missed event is caught at the next look.
Forever's wasEarnedByMe is true for the account's challenges too, so a
challenge named by ACHIEVEMENT_EARNED is this character's, while at a
look an account-wide challenge (ACHIEVEMENT_FLAGS_ACCOUNT) or one not
earned by it is taken silently. The first look back-fills the rest on
the game's date, without a time; a level 1 character's first look takes
everything silently, so the beta challenge makes no entry.
Your Year gets a Legacy Challenges card after Reputation: how many were
completed and the latest. Each look is traced in developer mode.
Closes #23 - Track the first rare and every epic item equipped
An entry for the first rare item the character equips and for every
epic or better item, once per item, with the first rare and the first
epic marked as firsts. On PLAYER_EQUIPMENT_CHANGED the changed slot's
item and quality are read; login and loading screens look at every
slot, so a missed event is caught there. Every item seen worn is kept,
so re-equipping an item or a second copy repeats nothing, and what is
worn at the first look is taken silently. An item whose quality isn't
loaded yet is read again a second later. A restored journal gives its
epics and the GEAR:RARE first back as seen. Heirlooms are left out.
Your Year gets a Notable gear card after Bosses: the epics worn and the
dates of the first rare and the first epic. Each look is traced in
developer mode.
Closes #22 - Track new standings with a faction
An entry the first time the character reaches Friendly, Honored, Revered
or Exalted with a faction, and the first time it falls to Hostile or
Hated. Each look reads every standing through C_Reputation, the list by
index and the known factions by ID, so a collapsed header hides none,
and compares them with a snapshot of each faction's last, highest and
lowest reaction. A missed event writes every standing it passed, falling
back and climbing again repeats nothing, meeting a faction is no entry
and the first look is silent. The firsts key REP:<faction>:<standing>
keeps a restored journal from repeating one. PvP Rank Points and the
Legacy Track are left out.
The faction's name is kept with the entry; the standing reads as the
client names it, in the female form for a female character. Your Year
gets a Reputation card after Quests: the factions at Exalted, Revered
and Honored, and the faction climbed most. Each look is traced in
developer mode.
Closes #21 - Track gold earned and spent each day
A per-day gold counter { earned, spent } in copper. On PLAYER_MONEY the
current money is compared with the saved amount, so every source counts
and a missed event is caught at the next one. The look when the tracker
is switched on, and the first loading screen after it, take the amount
silently, so money changed between sessions never lands on a day.
The day page shows one Progress line in the game's coin format. Your
Year gets a Gold card before Time played: earned, spent, the best day
and the most held at once. The best day comes from the counters through
a new counter rollup/merge hook; the most held is kept per year in the
tracker's state. Each look is traced in developer mode.
Closes #20 - Take no explored zones on a level 1 character's first look
A probe on a brand-new level 1 Tauren in Camp Narache (build 70374)
shows Alterac Mountains, Elwynn Forest and Moonglade explored right
after it enters the world, as on the level 3 character, though it has
been nowhere. First visits' first look kept them in state.visits, so
their first visits would never be recorded, and every character at
launch is new. A level 1 character's first look now records the zone
it stands in and takes nothing else; above level 1 the explored zones
are still taken.
The probe notes, §12 row 16, §6.12 and §13 say so. The same probe
shows a Legacy Challenge completed and "earned by me" six days before
the character existed, so §6.16 notes that wasEarnedByMe doesn't tell
the account's challenges from the character's.
Refs #28 - Record that hover-only textures don't explain the phantom zones
The 15:07 and 15:08 beta runs with 962ac39 show Alterac Mountains,
Elwynn Forest and Moonglade with one explored texture each, none of
them hover-only, so the cause is still unknown. Pets and toys read
0 of 0 because the journals list only what the character owns and it
owns none. Away from a flight master GetTaxiMapID gives -1 or nil.
Row 16, §6.12 and the GetExploredZones comment say so.
Refs #28 - Leave hover-only map textures out of the explored zones
On the beta (build 70374) the world map called Alterac Mountains,
Elwynn Forest and Moonglade explored on a level 3 Tauren who had only
been to Mulgore, Thunder Bluff and the Barrens, so First visits' silent
first look kept them as visited. Forever's own map hides textures with
isShownByMouseOver until the mouse is over them. Compat.GetExploredZones
now counts a zone only when one of its textures is shown without a
hover, read through Compat.Safe; Compat.GetExploredTextureCounts gives
the per-zone counts.
/ws probe's firstVisit.explored lists each zone with textures and how
many are hover-only, so the next beta run confirms the cause. The
collections lines add C_ToyBoxInfo.HasAnyToy and the
onlyShowCollectedItemsInJournal CVar, to tell a "0 of 0" that means
nothing owned from one that means the API doesn't answer.
Refs #28 - Record the launch probe from the beta
Three /ws probe runs on build 70374 (after login, at the Thunder Bluff
flight master, in Camp Taurajo) and the launch trace go into
forever-probe.md; §12 row 16 says what each launch tracker showed.
Nothing reads missing, error or secret. Still open: the world map calls
three unvisited zones explored, and pets and toys read 0 of 0.
Refs #28 - Keep a launch trace of what each launch tracker saw
In developer mode every look by a launch tracker adds one line through
ns.Trace:Add (Data/Trace.lua): when, which tracker, the events that
asked for the look, the values it read and how it ended. A nil value
reads "missing", a secret one "secret", a table its keys; the trace
never raises, so it can't count against the tracker. The newest 500
lines are kept account-wide in WayscribeDB.trace. /ws trace prints the
last 20 and /ws trace clear starts over; /ws duellog shares the printing.
First visits traces every look, also those that write nothing (on a
taxi, in an instance, no zone, known, recorded before), and a debounced
burst names each event that asked. The first look adds the level and
the explored zones it read. §6.11, DEVELOPMENT.md and the glossary
describe the trace.
Closes #19 - Track first visits to zones and cities
A FIRST_VISIT entry the first time the character is in each zone. The
best map is walked up to its zone, so a cave counts as its zone and a
city as its own. Instances and zones flown over on a taxi don't count;
the landing looks again. The journal's firsts (VISIT:<map>) keep a zone
from being recorded twice, also after a restore.
The first look is silent for the current zone and for every zone the
world map shows explored (C_MapExplorationInfo), kept in state.visits.
A level 1 character's starting zone is recorded instead. The Footsteps
card gets a line, and /ws probe reports the zone and the explored zones. - Probe the launch trackers' APIs
/ws probe now also reads what the 1.0 trackers rely on: the zone chain,
money, reputation rows and standings, worn item qualities, Legacy
Challenges (with wasEarnedByMe), the taxi map's nodes, guild, home,
mounts, pets, toys and the PvP rank track. Each value tells missing,
error and secret apart, so one run on the beta answers which trackers
can work. - Plan 1.0 Launch: glossary, tracker spec, roadmap and beta checklist
Ten trackers for Forever's launch on Nov 4, in build order: first visits,
gold, reputation, notable gear, Legacy Challenges, flight paths, guild,
home, collections, PvP rank (stretch). A tracker ships when it is probed,
unit-tested and fails silent; one beta session on a fresh character
covers what a level 1 character can reach, the rest waits until after
launch. GLOSSARY.md starts with the terms settled while planning. - Merge pull request #16 from ollidiemaus/agent-skills
Configure the agent skills: GitHub Issues tracker and domain docs - Configure the agent skills: GitHub Issues tracker and domain docs
docs/agents/ tells to-spec, to-tickets and the other skills where issues
live (GitHub Issues via gh) and where the glossary and ADRs go. GLOSSARY.md
joins the .pkgmeta ignore list so it stays out of the release. - changed addon categories
This mod has no additional files

