fix(chargen): Campaign CC CC5 re-review residuals R1-R5 + nits — REVIEW-CLOSED
The narrow re-review of fix commits 0c8e1e7d+2d4168f9 found every code fix
oracle-verified but returned NOT CLOSED on five test/doc residuals plus
three nits and a follow-up filing. All fixed:
- R1: the claimed "external-change->user-commit->SetName" regression test
for F1 (the deleted _suppressNextFieldEvent latch) never existed — the
Runtime-layer randomize test doesn't touch the page. Added
CharacterCreationUiControllerTests.SummaryNameField_RealCommitAfter
ExternalRefreshWhileUnfocused_StillReachesSetName: drives Refresh with a
revision bump + changed snapshot.Name while the field is unfocused (the
programmatic SetText path that used to arm the latch), THEN performs a
real user commit (field.SetText + field.Submit(), the actual event path),
asserting SetName receives the player's typed text.
- R2: RetailSkillFormula.CalculateChargenScore and ChargenSkillScoreResolver
had zero direct coverage (the F12(d) test substitutes skillId*10). Added
a Untrained/Trained(+5)/Specialized(+10) theory, the divisor-zero skip
path, and a six-way AttributeId theory (Str=1..Self=6) to
RetailSkillFormulaTests.cs.
- R3: RetailSkillFormula.cs's doc comment claimed "no retail-authored skill
sets MinLevel above Untrained=1" without ever reading the field — ACE's
own SkillBase.cs hedges the same field "// 1-2?". MEASURED (not assumed)
against the installed EoR dat's global SkillTable
(CharacterCreationLiveDatTests.SkillTable_MinLevelDistribution_
NeverExceedsTrained): 23 skills at MinLevel 1, 15 at MinLevel 2, zero
above 2, of 38 priced skills. ACE's hedge was right; the doc comment now
states the measured fact and leans on the structural argument (the gate
holds for Trained/Specialized under any MinLevel in {1,2}) as load-
bearing, not the unverified data claim.
- R4: filed AP-228 — the Summary/Skills skill-row KEY sources from
ItemAppraisalTextFormatter.SkillName's hardcoded English switch, where
retail's own key is DAT-sourced (SkillBase->_name via %hs,
0x0047b90f-0x0047b915) — same divergence class as AP-226 filed the same
round, reversed polarity, also present at CC4's Skills page. Softened
AP-224's "ported exactly, not simplified" claim: it only ever covered the
row's VALUE/template, never its KEY.
- R5: this commit corrects 0c8e1e7d's gate claim. "Release build zero
warnings" was false: a clean `dotnet build -c Release -t:Rebuild` shows
25 pre-existing warnings (18 in tests/AcDream.Core.Tests, 7 in
tests/AcDream.App.Tests — Composition/HostInputCameraCompositionTests.cs,
Composition/WorldRenderCompositionTests.cs,
UI/Layout/OptionsPanelLiveMountProbeTests.cs), none in any file this
campaign or its residual round touched. History is not amended; this is
the correction.
Nits: the ChargenPreviewController ctor doc now also cites
gmCGSummaryPage::Update @0x0047baa0 (the per-heritage re-derive site — 0xc
Olthoi/0xd OlthoiAcid/else — not just the one-shot InitializePage seed) as
the stronger justification for why Rebuild re-derives the zoomed-out eye
per heritage on every change. RuntimeCharacterCreationState's F2 comment
("Finish becoming a permanent no-op") reworded: the same unconditional
_verificationPending = false assignment ran pre-fix too, so Finish was
never blocked — only the response FEEDBACK vanished (no dialog, no created
character, nothing), not the request itself. Filed #404 for
ChargenSkillScoreResolver's own independent SkillTable read alongside
ChargenTableReader's (cleanup follow-up, out of this round's scope).
Ledger: CC5 flipped REVIEW-CLOSED in the campaign plan (dual-lens
architectural PASS-with-items / retail-fidelity FAIL -> F1-F14 fix round
0c8e1e7d -> narrow re-review: all code oracle-verified, residuals R1-R5
test/doc -> this commit; re-reviewer pre-authorized lead diff-check close).
This commit's own sha is recorded by a follow-up ledger-only commit,
matching 2d4168f9's own pattern.
Gates: Release build 0 errors (25 pre-existing warnings, unrelated to this
round — see R5 above); App suite 5257/3 skips (was 5242/3), 0 failed;
Runtime suite 1726/0 (unchanged); the three new/measured tests (R1, R2's
ten cases, R3) all pass individually.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
2d4168f926
commit
356545c530
9 changed files with 277 additions and 13 deletions
|
|
@ -24,6 +24,45 @@ 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.
|
||||
|
||||
## #404 — ChargenSkillScoreResolver duplicates ChargenTableReader's own SkillTable read
|
||||
|
||||
**Status:** OPEN (post-CC cleanup follow-up)
|
||||
**Severity:** LOW
|
||||
**Filed:** 2026-08-16 (Campaign CC CC5 re-review residual round, nit 3)
|
||||
**Component:** `src/AcDream.App/Composition/InteractionRetainedUiComposition.cs`
|
||||
(`ChargenSkillScoreResolver` construction, `:670-672`),
|
||||
`src/AcDream.Content/CharGen/ChargenTableReader.cs` (`:41`, `:61`)
|
||||
|
||||
`ChargenSkillScoreResolver`'s constructor takes its OWN independent read of
|
||||
the global SkillTable (portal.dat `0x0E000004`) at composition time
|
||||
(`InteractionRetainedUiComposition.cs:670-672`,
|
||||
`d.Dats.Get<SkillTable>(0x0E000004u)`), beside `ChargenTableReader`'s
|
||||
own already-established read of the SAME table
|
||||
(`ChargenTableReader.cs:41` names the id, `:61` reads it) — which discards
|
||||
the DAT's `SkillFormula` field entirely (`ChargenTableReader.Project` only
|
||||
projects `TrainedCost`/`SpecializedCost` per skill into
|
||||
`ChargenSkillCost`, never `SkillBase.Formula`). Two independent reads of
|
||||
the same DAT file are harmless today (both are read-only, one-shot, under
|
||||
the DAT lock) but are a duplicate-source-of-truth smell: if the two readers
|
||||
ever diverge (a caching change, a future write path), nothing enforces they
|
||||
stay in sync.
|
||||
|
||||
**Fix direction:** project `SkillFormula` (and `MinLevel`, needed by
|
||||
`RetailSkillFormula.CalculateChargenScore`'s gate) into `ChargenOptions`
|
||||
alongside the existing `GlobalSkillCostsBySkillId` — `ChargenTableReader`
|
||||
already walks every `SkillBase` in the table
|
||||
(`ChargenTableReader.Project`'s `globalSkillCosts` loop) so adding the
|
||||
formula/MinLevel costs no new DAT read, just a wider projection type. Then
|
||||
`ChargenSkillScoreResolver` becomes pure arithmetic over `ChargenOptions`
|
||||
it already receives from the caller, with no `SkillTable`/DAT dependency of
|
||||
its own, and its constructor-time DAT read goes away entirely.
|
||||
|
||||
**Acceptance:** one SkillTable read at composition time (through
|
||||
`ChargenTableReader`), not two; `ChargenSkillScoreResolver` (or its
|
||||
replacement) takes `ChargenOptions`/a projected formula table instead of a
|
||||
raw `SkillTable`; existing `RetailSkillFormulaTests`/`ChargenTableReaderInstalledDatTests`
|
||||
coverage still passes.
|
||||
|
||||
## #403 — Consolidate RetailAnimationCyclePlayback into LiveEntityAnimationPresenter's legacy branch
|
||||
|
||||
**Status:** OPEN (post-CC consolidation follow-up)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue