feat(net) Campaign CA CA2 #431: parse the inbound attribute/skill update family
The server's authoritative answers to a raise were dropped on the floor: only the vitals pair (0x02E7/0x02E9) had parsers, so after any RaiseAttribute/RaiseSkill/TrainSkill the client's stat model stayed frozen at login's PlayerDescription — the root cause of #431's stale derived skills and run speed. The GUI looked alive only because the panel applies optimistic local raises. New parsers with three-source-verified layouts (CA1 research doc §2.5/ §2.8): PrivateUpdateAttribute (0x02E3) and PrivateUpdateSkill (0x02DD — the wire's ushort ranks + hardcoded adjustPP=1 pair and f64 lastUsedTime preserved exactly). WorldSession dispatches both as typed events; LiveSessionEventRouter routes them into the J4 character owner's LocalPlayerState like every other private update. The vestigial PrivateUpdateSkillLevel (0x02DF) is deliberately unparsed — ACE has no producer (verified). OnAttributeUpdate now fans out to the derived-value observers, mirroring retail's live-at-inquiry model (CACQualities::InqSkill 0x00592660 — Set* writes raw, Inq* recomputes, notification carries no value): an Endurance write notifies the Health AND Stamina vital observers (ACE pushes only a Health record and its own comment says the client must refresh both), Self notifies Mana, and every attribute write notifies character-sheet consumers whose formula contributions just changed. OnSkillWireUpdate preserves the login FormulaBonus — the wire record carries no attribute contribution; CA3 replaces the cached field with the live computation. Also corrected while in the neighborhood: PropertyString.cs's comment claimed opcode 0x02DD for PrivateUpdatePropertyString; ACE's enum says 0x02D5/0x02D6 (doc-only — nothing dispatched on either). Conformance tests cover both layouts (including holtburger's golden skill fixture with adjustPP=1), truncation/wrong-opcode rejection, the Endurance/Self/Quickness fan-out contract, and FormulaBonus preservation. Full hermetic suite 15,333 passed / 0 failed (one load-sensitive transport flake observed on the first run, passed alone and on the clean re-run — filed as #439 rather than chased). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1fc64984c9
commit
65430d4c7c
9 changed files with 474 additions and 4 deletions
|
|
@ -24,6 +24,26 @@ What does NOT go here:
|
|||
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
|
||||
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
|
||||
|
||||
## #439 — Flake candidate: LossySession_FivePercentSeeded_ZeroMessageLoss_Headroom256 fails under full parallel suite load
|
||||
|
||||
**Status:** OPEN (observation filed; do NOT chase individually per docs/release-gate.md)
|
||||
**Severity:** LOW (test-infra)
|
||||
**Filed:** 2026-08-24 (one occurrence during Campaign CA CA2's full-suite run)
|
||||
**Component:** Core.Net.Tests / transport lossy decorator
|
||||
|
||||
**Symptom:** `LossyTransportDecoratorTests.LossySession_FivePercentSeeded_ZeroMessageLoss_Headroom256`
|
||||
failed once under the full parallel hermetic suite with `Headroom expected 256, actual 0`
|
||||
— i.e. the seeded loss-recovery simulation ended before the crypto search
|
||||
window recovered. Passed in isolation immediately after, and the full
|
||||
suite passed clean on re-run. The test drives a deadline loop over a
|
||||
seeded end-to-end loss simulation — the load-sensitive shape
|
||||
`Lane=Timing` exists for, but this test is not marked. Candidate fix:
|
||||
either mark it `Lane=Timing` or make its quiescence wait
|
||||
deadline-independent. Decide deliberately; do not just re-run until
|
||||
green.
|
||||
|
||||
---
|
||||
|
||||
## #438 — Launcher crash-report bundles (WER dump capture + local bundle, no upload)
|
||||
|
||||
**Status:** OPEN — designed, ready to pick up as a launcher slice
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue