app: the press queue was switched off in play — a derived Default is the live config

`cvars.rs` announces a `CvarChanged` only when a value *moves*, and `config.toml`
holds only the rows that left their defaults ("CVar values that moved off their
defaults" — its own header). So a row the player never touched never reaches an
`on_cvar` observer, and the resource's own `Default` is what the client runs with
for the whole session.

`PressRules` and `SpellQueue` both derived `Default`. Every toggle was false, every
window 0 and every buffer 0, so the press-interception queue held nothing, the mount
refusal never fired, and `SpellQueue`'s zero window expired each explicit entry on
the frame it was queued — the day after all of it was committed. Fourteen of the
sixteen rows have a non-zero registered default.

grom's own `WoWCombatLog.txt` is what named it, with no live run to ask for: 147
`Sunder Armor: Not yet recovered` against 163 landed Sunders, in bursts 0.17-0.23 s
apart — every press refused, none held. Sunder Armor rank 1 on this realm is
`rec=0 cat=0 catrec=0 gcdcat=133 gcd=1500`, read off its own `Spell.dbc`: a global
cooldown and nothing else, which is precisely the case the queue must hold.

Both now hand-write `Default` with the registered values, which is the pattern
`cvars.rs::registered_defaults_mirror_the_code_truths` already welds for the engine
knobs; `np_press.rs::the_default_is_the_registry` welds these sixteen the same way.
The test-only `defaults_for_tests()` constructors are gone — they spelled out the
registered numbers for tests to read while the client could not reach them, which is
the whole shape of the bug. A sweep of the other nine CVar-cached resources (list
every `fn on_cvar`, take its `ResMut` types, check for a hand-written `Default`, look
up each CVar it names in `REGISTERED`) found no further victims.

Two things so the next session can speak for itself:

- `a_press_made_during_the_global_cooldown_is_held_and_sent_when_it_ends` — the
  end-to-end cycle with the GCD as the only guard, which is what a class with no cast
  bar presses into all day. The existing end-to-end test arms `PendingCast` by hand
  and so never starts a GCD at all; this one presses through the real ladder, so the
  commit arms it the way a cast does.
- one `info!` a minute from the drain, and only when something moved: held, sent,
  dropped, retried, fell-through, channels cut — plus the live windows and buffers.
  Every other line this half writes is `debug!` and the default filter is INFO, so a
  67-minute session could not say one word about the queue. A line of zeroed knobs
  now diagnoses this class of fault by itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-25 09:46:50 -06:00
co-authored by Claude Opus 5
parent fcdf14c0dc
commit 5a824f1625
5 changed files with 502 additions and 83 deletions
+15
View File
@@ -976,6 +976,21 @@ were the plain cast, which was the honest mapping at the time and is no longer t
same slot an explicit `QueueSpellByName` would use, and the drain sends it the moment the guard
clears. No packet, no global cooldown, no error line while it waits.
**It shipped doing nothing, and the reason is worth writing down here rather than only in the
code.** `cvars.rs` announces a `CvarChanged` only when a value *moves*, and `config.toml` holds only
the rows that left their defaults — so a row the player never touched never reaches an `on_cvar`
observer, and the resource's own `Default` is the live configuration for the whole session. Both
`PressRules` and `SpellQueue` derived `Default`, which meant every toggle false, every window 0 and
every buffer 0 on the day this landed: the queue held nothing, and `SpellQueue`'s zero window
expired each explicit entry on the frame it was queued. Fourteen of the sixteen rows have a
non-zero registered default. Both now hand-write `Default` with the registered values, welded by
`np_press.rs::the_default_is_the_registry`, and a sweep of the other nine CVar-cached resources
found no further victims. What caught it was the player's own `WoWCombatLog.txt` — 147
`Sunder Armor: Not yet recovered` against 163 landed Sunders, in bursts a fifth of a second apart —
because every line this module writes is `debug!` and the default filter is INFO. So the drain now
prints one `info!` a minute when something moved, carrying held/sent/dropped/retried/fell-through
**and the live windows and buffers**: a line of zeroes diagnoses this class of fault by itself.
**Where the rung sits, and the one deviation that comes of it.** Five rungs stay above it — the
profession opener, the auto-repeat re-press, the dead caster, the targeting cursor's clear and the
on-swing re-press — because each is what the press *means* whatever is in flight, and holding them