docs: FA2 fix-round -- ledger update, D2 correction, seam-map addenda
Plan (docs/plans/2026-08-11-fellowship-allegiance-campaign.md): - D2 gets the D9-style dated strike/addendum recording the corrected allegiance reset semantics (clears at every generation reset; the HasServerSeed latch only gates pre-seed rendering WITHIN a session) with the three-way evidence citation: the retail OnEndCharacterSession hook, the RuntimeCharacterOptionsState precedent's actual clear-and-relatch behavior, and the no-character-selector connect path (SessionPlayerComposition.cs:1127). - The architecture blurb and FA2's slice-map contract row get matching strike/addendum corrections so the "fellowship session-scoped, allegiance survives reconnect" claim does not survive uncorrected anywhere in the plan. - FA2's ledger row: fix-round commit SHAs, corrected delegate-hole/ wrapper counts (blast SHOULD-FIX 3: 10 not 15, 11 not 12), the allegiance register-row re-evaluation conclusion (blast SHOULD-FIX 6 -- no row needed, MF-1's fix retires the deviation entirely), and the reconciled fix-round test totals (13,201/4/0 -> 13,215/4/0, +14, arithmetic exact per file). Seam map (docs/research/2026-08-11-fa-acdream-seams.md), per the FA1 fix-round's established in-place-correction convention: - SS1.3 and SS9's dispatcher-replaces-not-chains correction is now dated and cites the actual GameEventDispatcher.Dispatch behavior, matching the code comment already landed in GameEventWiring.cs. - SS2.3 gets the 0x01C9/0x01CA disposition it was missing (correctly left unregistered -- dead COMDAT-fold no-ops per FA1) so FA3 does not have to re-derive it or "fix" the gap. - The SS8 seam-map table's Allegiance-owner row and the executive-summary ownership bullet both get the "survives reconnect" claim struck with a dated correction to "session-scoped, clears at every generation reset". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
ded23067aa
commit
ed8b3ec96d
2 changed files with 117 additions and 11 deletions
|
|
@ -146,6 +146,25 @@ Rationale and precedent:
|
|||
(same class as `RuntimeCharacterOptionsState`'s `HasServerSeed` latch,
|
||||
`project_settings_options_digest.md` DO-NOT-RETRY row "Applying a
|
||||
pre-seed Reset/local snapshot over server truth").
|
||||
**[FA2 fix-round addendum, 2026-08-12
|
||||
(docs/research/2026-08-12-fa2-review-mechanism.md MUST-FIX 1): this
|
||||
citation was INVERTED. `RuntimeCharacterOptionsState`'s `HasServerSeed`
|
||||
latch does NOT survive a reset — `ResetSession`
|
||||
(`RuntimeCharacterState.cs:1007-1017`) explicitly zeroes the options AND
|
||||
clears `_hasServerSeed`, with its own doc comment naming the exact hazard
|
||||
this row then walked into: "a stale seed surviving a session boundary
|
||||
could let a flush ship the PRIOR character's words over the new one's."
|
||||
Retail itself clears allegiance at the same per-character-session
|
||||
boundary Fellowship already clears at
|
||||
(`ClientAllegianceSystem::OnEndCharacterSession @0x00569FA0` tail-calls
|
||||
`AllegianceProfile::Clear`, mirroring
|
||||
`ClientFellowshipSystem::OnEndCharacterSession @0x005690A0`). Corrected:
|
||||
allegiance is now ALSO a reset stage
|
||||
(`RuntimeGenerationResetStage.Allegiance`) with the identical
|
||||
clear-and-relatch shape as the cited precedent. The two owners remain
|
||||
separate classes because fellowship and allegiance are independent
|
||||
retail systems with independent wire families, not because their
|
||||
lifetimes differ — they no longer do.]**
|
||||
- **Borrow, never copy, the entity table.** Fellowship member rows must
|
||||
read live names/vitals from `RuntimeEntityObjectLifetime`'s canonical
|
||||
`ClientObjectTable` the way `RuntimeInventoryState` does
|
||||
|
|
@ -264,6 +283,37 @@ existing lambda or add a second `registrar.Register` for the same type
|
|||
`OwnedGameEventRegistrar.Register`, `:929-940`) and accept that both fire.
|
||||
Decide this in the plan, explicitly.
|
||||
|
||||
**[FA2 fix-round addendum, 2026-08-12
|
||||
(docs/research/2026-08-12-fa2-review-blast.md SHOULD-FIX 1): the
|
||||
parenthetical above is WRONG and was disproved during FA2 implementation.
|
||||
`GameEventDispatcher.Dispatch`
|
||||
(`src/AcDream.Core.Net/Messages/GameEventDispatcher.cs:95-117`) does a
|
||||
single `_handlers.TryGetValue(...)` and invokes the ONE stored
|
||||
`RegistrationNode`; `OwnedGameEventRegistrar.Register` REPLACES the prior
|
||||
registration for that `GameEventType`, it does not add a second co-owned
|
||||
handler. A second `registrar.Register(GameEventType.AllegianceInfoResponse,
|
||||
...)` call would have silently killed the already-live `@allegiance info`
|
||||
chat-text output the instant a caller supplied an allegiance-owner
|
||||
callback. FA2 folded both behaviors into the ONE existing registration
|
||||
instead (`GameEventWiring.cs`'s `AllegianceInfoResponse` handler) — see
|
||||
that method's own code comment for the corrected claim. This was also the
|
||||
right call independent of the correction: FA2's fix round (MUST-FIX 2)
|
||||
subsequently found that `0x027C` should not feed a Runtime callback at
|
||||
all, since retail's own handler for it is print-only over a stack-local
|
||||
profile — so the "second handler" question this section poses is now moot
|
||||
either way.]**
|
||||
|
||||
`0x01C9 FellowshipFellowUpdateDone` and `0x01CA FellowshipFellowStatsDone`
|
||||
from the table above are **[FA2 fix-round addendum, 2026-08-12
|
||||
(docs/research/2026-08-12-fa2-review-blast.md SHOULD-FIX 2): correctly
|
||||
left unregistered by FA2.** FA1 established that both COMDAT-fold onto the
|
||||
identical no-op body in the Sept-2013 client and are parse-and-ignore only
|
||||
(`src/AcDream.Core.Net/Messages/GameEvents.cs:779-803`) — there is nothing
|
||||
for a Runtime owner to consume. This is the disposition for the two rows
|
||||
this section's own title ("The 11 events FA must register") implied FA
|
||||
owed a registration for; FA2 registered the other 9 plus the `0x027C`
|
||||
fold, 10 total.]**
|
||||
|
||||
### 2.4 Bindings-record plumbing (both hosts)
|
||||
|
||||
`LiveSessionEventRouter`'s five binding records are the host-facing
|
||||
|
|
@ -808,7 +858,7 @@ A/B should confirm this against retail rather than inferring it from ACE.
|
|||
| Subsystem | Where new code goes | Pattern to follow | Precedent citation |
|
||||
|---|---|---|---|
|
||||
| Fellowship state owner | `src/AcDream.Runtime/Gameplay/RuntimeFellowshipState.cs` (new) | J4 owner: `IDisposable` + `ResetSession()` + `CaptureOwnership()`; borrow entity table | `RuntimeInventoryState` ctor `GameRuntime.cs:192-193`; snapshot shape `RuntimeCharacterState.cs:9-51` |
|
||||
| Allegiance state owner | `src/AcDream.Runtime/Gameplay/RuntimeAllegianceState.cs` (new), ~~wrapping existing `AcDream.Core.Allegiance.AllegianceTree`~~ **[FA1 fix-round addendum, 2026-08-12: `AllegianceTree` was DELETED by Campaign FA slice FA1 (`4281750b`) — there is nothing left to wrap. Wrap `ClientCommandResponses.AllegianceProfileLookups` (the flat `AllegianceMemberRecord` list + `GetData`/`GetPatron`/`FindVassals` walk that replaced it) instead. FA2 is the very next slice — this is its seam-map row.]** | Same; **survives reconnect** — use a `HasServerSeed`-style latch | `RuntimeCharacterOptionsState` seed latch; ~~`AllegianceTree.cs:56-162`~~ **[FA1 fix-round addendum: see `ClientCommandResponses.cs:250-295` (`AllegianceProfileLookups`) instead]** |
|
||||
| Allegiance state owner | `src/AcDream.Runtime/Gameplay/RuntimeAllegianceState.cs` (new), ~~wrapping existing `AcDream.Core.Allegiance.AllegianceTree`~~ **[FA1 fix-round addendum, 2026-08-12: `AllegianceTree` was DELETED by Campaign FA slice FA1 (`4281750b`) — there is nothing left to wrap. Wrap `ClientCommandResponses.AllegianceProfileLookups` (the flat `AllegianceMemberRecord` list + `GetData`/`GetPatron`/`FindVassals` walk that replaced it) instead. FA2 is the very next slice — this is its seam-map row.]** | Same; ~~**survives reconnect** — use a `HasServerSeed`-style latch~~ **[FA2 fix-round addendum, 2026-08-12 (docs/research/2026-08-12-fa2-review-mechanism.md MUST-FIX 1): WRONG — retail clears the allegiance profile at `OnEndCharacterSession`, the very same boundary Fellowship clears at. Allegiance is now a `RuntimeGenerationReset` stage exactly like Fellowship; the `HasServerSeed` latch clears AND re-arms every generation (matching the `RuntimeCharacterOptionsState` precedent's actual clear-and-relatch behavior, not the persist behavior this row previously (mis)cited it for).]** | `RuntimeCharacterOptionsState` seed latch; ~~`AllegianceTree.cs:56-162`~~ **[FA1 fix-round addendum: see `ClientCommandResponses.cs:250-295` (`AllegianceProfileLookups`) instead]** |
|
||||
| Owner registration | `GameRuntime.cs` | ctor + `construction.Own` + fault point + `*Owner` prop + view prop + `CaptureOwnership` + shutdown step | `GameRuntime.cs:200-214`, `:419-429`, `:463-470`, `:545-567`, `:703-752` |
|
||||
| Session reset | `RuntimeGenerationReset.cs` | new `RuntimeGenerationResetStage` ordinal + `Drain` case; **fellowship clears, allegiance re-seeds** | `:21-44`, `:236-349`; shared-stage example `:248-261` |
|
||||
| Ownership rollup | `RuntimeGameplayOwnership.cs` | add to record + `Capture(...)` signature + `IsConverged` | `:8-21`, `:23-44` |
|
||||
|
|
@ -850,8 +900,16 @@ A/B should confirm this against retail rather than inferring it from ACE.
|
|||
3. **`0x027C AllegianceInfoResponse` already has a handler**
|
||||
(`GameEventWiring.cs:192-198`, chat output for `@allegiance info`).
|
||||
Does FA extend that lambda, register a second handler, or leave the
|
||||
panel to use a different event? The dispatcher permits multiple owned
|
||||
handlers per type — but two handlers writing to two different owners is
|
||||
panel to use a different event? ~~The dispatcher permits multiple owned
|
||||
handlers per type~~ **[FA2 fix-round addendum, 2026-08-12
|
||||
(docs/research/2026-08-12-fa2-review-blast.md SHOULD-FIX 1): wrong —
|
||||
`GameEventDispatcher.Dispatch` invokes only the single
|
||||
most-recently-registered handler per type; a second `Register` call
|
||||
REPLACES, it does not co-own. See §2.3's addendum for the full
|
||||
correction. Answered: extend the existing lambda (done), and FA2's own
|
||||
fix round then found the extension itself should not exist — retail's
|
||||
0x027C handler is print-only, so no owner ever gets fed from it.]** —
|
||||
but two handlers writing to two different owners is
|
||||
the "two writable copies" smell.
|
||||
4. **Which of the 6 dimmed rows actually gain consumers in FA v1?** Each
|
||||
un-dim requires three coordinated edits (§4.2). Under-claiming is safe;
|
||||
|
|
@ -908,8 +966,12 @@ A/B should confirm this against retail rather than inferring it from ACE.
|
|||
parsers**, **no inbound registrations**, and **no F3/F4 handler**.
|
||||
2. **Ownership: two new sibling J-owners under `GameRuntime`**
|
||||
(`RuntimeFellowshipState`, `RuntimeAllegianceState`), NOT children of
|
||||
`RuntimeCommunicationState` — the lifetimes differ (fellowship is
|
||||
session-scoped, allegiance survives reconnect) and J4's own precedent is
|
||||
`RuntimeCommunicationState` — ~~the lifetimes differ (fellowship is
|
||||
session-scoped, allegiance survives reconnect)~~ **[FA2 fix-round
|
||||
addendum, 2026-08-12: both are now session-scoped, cleared at every
|
||||
generation reset — see §1.3's addendum. They remain separate owners
|
||||
because they are independent retail systems, not because their
|
||||
lifetimes differ]** and J4's own precedent is
|
||||
one owner per coupled graph. Each costs eight mechanical edits, listed
|
||||
with line-cited templates in §1.1.
|
||||
3. **Inbound has exactly one registration site**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue