docs: FA1 review round -- register repoint, seams corrections, plan reconciliation

Applies the documentation-only MUST-FIX items from the blast review
(docs/research/2026-08-12-fa1-review-blast.md), plus mechanism SF-4:

Blast MF-1 / mechanism SF-4: register row AP-90
(retail-divergence-register.md) cited the deleted AllegianceTree class as
its evidence. Re-pointed to ClientCommandResponses.AllegianceProfileLookups
and the fellowship parsers FA1 added -- the deviation itself (radar
relationship state undelivered at runtime) is unchanged and NOT retired,
since FA2 hasn't wired a live owner yet.

Blast MF-2: corrected four falsified statements in the lane D research doc
(fa-acdream-seams.md), each marked with a dated, clearly-struck FA1
fix-round addendum rather than silently rewritten (it is a committed
research record):
  - :791 "wrapping existing AllegianceTree" -- class deleted; re-pointed to
    AllegianceProfileLookups.
  - :666/:672 `commands.Fellowship.SetOpen -> BuildFellowshipUpdate` -- that
    builder no longer exists; its renamed successor is panel visibility,
    not openness, and using it here would re-introduce the exact semantic
    bug FA1 fixed. Re-pointed to BuildFellowshipChangeOpenness (0x0291).
  - :429/:668 `BuildFellowshipCreate(seq, name, openness, shareXp)` -- the
    builder is now 3-arg; there is no wire openness field.
  - :854 open question 8 (trailing-pad rule) -- ANSWERED by FA1 (VC-3),
    closed with the answer instead of left open for re-derivation.

Blast MF-3: plan decision D9 and the FA1 slice-map row both asserted "the 8
missing fellowship WeenieError strings are added in FA1" -- FA1 shipped the
opposite, verified finding (no retail display text exists for any of the
8 ids). Both struck and annotated with the actual outcome.

Blast MF-4: reconciled the ledger's internally-inconsistent test-total row.
Direct measurement at the pre-fix-round tip (bc693728, stashed/restored
during this session to isolate it) confirms 13,149 passed / 4 skipped / 0
failed (13,153 total) -- the ledger's own prior number was actually
correct; the "baseline 13,103" and "net +50" framing next to it did not
reconcile with each other or with the diff-verified delta (+58 added / -9
deleted = net +49, one test of drift attributed to a different baseline
commit, not a further miscount). Also records this session's own +9 tests
and the blast SF-1 live-surface note (FA1 changed observable @allegiance
info output, not a purely-unwired slice).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-12 00:47:09 +02:00
parent ed30808720
commit 511ba6e5d4
3 changed files with 45 additions and 12 deletions

View file

@ -426,8 +426,14 @@ The plan must decide per-row, but the code evidence says:
- `FellowshipShareXP` / `FellowshipShareLoot` — these are **server-side**
policy (ACE decides the split). They un-dim only if FA reads them to
drive the create-fellowship dialog's initial checkbox state
(`BuildFellowshipCreate(seq, name, openness, shareXp)`,
`SocialActions.cs:123-138`, takes `shareXp` as a parameter — that IS a
(~~`BuildFellowshipCreate(seq, name, openness, shareXp)`,
`SocialActions.cs:123-138`~~ **[FA1 fix-round addendum, 2026-08-12: FA1
repaired this builder — there is no "openness" field on
`FellowshipCreateOpcode`'s wire (the prior 4-arg builder invented one and
silently sent it as the low byte of shareXP, which ACE would read as an
INVERTED shareXP value). The current signature is
`BuildFellowshipCreate(seq, fellowshipName, shareXp)`,
`SocialActions.cs:144-155`.]**, takes `shareXp` as a parameter — that IS a
client-side read). `FellowshipShareXP` is additionally tagged Group D
(deferred) in the derivation table (`:137`).
- `IgnoreAllegianceRequests` — un-dims if FA gates the incoming-swear
@ -659,11 +665,11 @@ idempotence — is exactly reusable for FA.
| Command | Underlying builder |
|---|---|
| `commands.Fellowship.Create(gen, name, open, shareXp)` | `SocialActions.BuildFellowshipCreate` |
| `commands.Fellowship.Create(gen, name, open, shareXp)` | `SocialActions.BuildFellowshipCreate` **[FA1 fix-round addendum, 2026-08-12: the builder is now 3-arg — `BuildFellowshipCreate(seq, fellowshipName, shareXp)` (`SocialActions.cs:144-155`). There is no wire "openness" field; drop `open` from this command's own signature too.]** |
| `commands.Fellowship.Recruit(gen, targetGuid)` | `BuildFellowshipRecruit` |
| `commands.Fellowship.Quit(gen, disband)` | `BuildFellowshipQuit` |
| `commands.Fellowship.Dismiss(gen, targetGuid)` | `BuildFellowshipDismiss` |
| `commands.Fellowship.SetOpen(gen, open)` | `BuildFellowshipUpdate` |
| `commands.Fellowship.SetOpen(gen, open)` | ~~`BuildFellowshipUpdate`~~ **[FA1 fix-round addendum, 2026-08-12: `BuildFellowshipUpdate` no longer exists. Its renamed successor `BuildFellowshipUpdateRequest` (`0x00A6`) is PANEL VISIBILITY, not openness — wiring `SetOpen` to it would re-introduce the exact semantic bug FA1 fixed. The real openness action is `BuildFellowshipChangeOpenness` (`0x0291`, `SocialActions.cs:222-230`).]** |
| `commands.Allegiance.Swear(gen, patronGuid)` | `AllegianceRequests.BuildSwear` |
| `commands.Allegiance.Break(gen, targetGuid)` | `BuildBreak` |
@ -788,7 +794,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` | Same; **survives reconnect** — use a `HasServerSeed`-style latch | `RuntimeCharacterOptionsState` seed latch; `AllegianceTree.cs:56-162` |
| 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]** |
| 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` |
@ -845,9 +851,21 @@ A/B should confirm this against retail rather than inferring it from ACE.
7. **`ID_Fellowship_*` / `ID_Allegiance_*` string-table id.** Assume
nothing — dat-verify. The options family is `0x23000003`, but chat
filters live in `0x2300000D` and keyboard refusal in `0x23000004`.
8. **`BuildFellowshipCreate` trailing-pad rule** is currently pinned only
8. ~~**`BuildFellowshipCreate` trailing-pad rule** is currently pinned only
by a self-consistent test (`SocialActionsTests.cs:53-68`), not against a
retail/ACE reference. Lane A/B should confirm before FA sends it live.
retail/ACE reference. Lane A/B should confirm before FA sends it live.~~
**[FA1 fix-round addendum, 2026-08-12: ANSWERED by FA1, close this
question rather than re-deriving it. `PackString16L`
(`SocialActions.cs:389-403`) pads the string record to a 4-byte multiple
INCLUDING its own u16 length, so `12 + name.Length` is already
4-aligned before the trailing `u32 shareXP` is appended — the pad the
old (now-deleted) builder added after its two invented bools was never
the string's own pad. ACE reads exactly `ReadString16L()` then
`ReadUInt32()` (`GameActionFellowshipCreate.cs`), and `ACE.Common`'s
`ReadString16L` skips the identical `CalculatePadMultiple(2 + length,
4)` pad. The golden vector at `SocialActionsTests.cs:65-83` ("Team",
len 4, 2 pad bytes) is hand-derived against that ACE reader, not merely
self-consistent. No further confirmation owed.]**
9. **`DisplayAllegianceLogonNotifications` semantics**: receive-side
display filter (swallow locally) or membership-style suppression? Unlike
`Hear*Chat` this is almost certainly display-only — but it must be