Applies the seven NITs from the CH2 re-review (verdict APPROVE-WITH-FIXES,
following the REJECT->rework at e0e78883):
1. SpewBoxController's centered Left was captured once via
AnchorEdges.Top and replayed forever on resize (UiElement.ApplyAnchor's
Left/Right-both-false branch pins a fixed margin). Anchors is now
AnchorEdges.None and Tick recomputes Left every frame against the
current root width.
2. OneLine=false was defaulting to UiText's bottom-pinned transcript flow
(VerticalJustify honored only via ConfigureDatState, which this
synthesized element never calls). Added UiText.HonorVerticalJustification
so a non-DAT controller can opt the scrollable path into
VerticalJustify without a full LayoutDesc binding; SpewBoxController
sets VerticalJustify=Top so lines flow from the top of the 450x72 box,
matching newest-at-top insert semantics. Noted as invented-pending-
measurement in AP-178's row (no new row).
3. Documented the deliberate inversion of UiText.LinesProvider's
oldest-first contract in SpewBoxController.Tick (SpewBoxVM.Lines feeds
newest-first, which is correct specifically because the box is now
top-aligned) and added a test pinning the rendered order (newer message
is the topmost line), driving root.Tick.
4. Fixed the stale "retail's code default, 1" comment in
SpewBoxControllerTests — MaxConcurrentItems is the shipped LayoutDesc's
AUTHORED value, 4.
5. Added the matching unmapped-id diagnostics line to
LiveSessionRuntimeFactory's ShowWeenieError sink, matching the pattern
GameEventWiring's WeenieError/WeenieErrorWithString handlers already
use.
6. Corrected the "EXHAUSTIVE Portal sweep found ZERO" overclaim in
SpewBoxLayoutDumpDiagnostic: the loop's id source was DatCollection's
top-level aggregate GetAllIdsOfType<LayoutDesc>(), not dats.Portal's
own (which reports a count of ZERO for this type), so querying those
ids against dats.Portal.TryGet established nothing about Portal either
way. Corrected the same overclaim echoed in SpewBoxState's
MaxConcurrentItems doc comment and in AP-178's register text (both the
table row and the section-header history line). What's actually
established: dats.Local hosts the SpewBox layout at 0x21000011; whether
Portal also carries a copy remains unestablished.
7. Added a test exercising the full ShowWeenieError -> AddText -> SpewBox
path for id 0x0561 (the 50-friends-cap refusal) in
LiveSessionCommandRouterTests, mirroring LiveSessionRuntimeFactory's
ShowWeenieError closure exactly since every other LiveSessionRuntimeFactory
test in this tree is a source-text conformance grep, not an
instantiation.
Ledger: CH2 ledger row's review column now reads REJECT -> reworked
e0e78883 -> re-review APPROVE-WITH-FIXES -> nits (this commit); Status
header flips CH2 to code-complete/closed pending the user gate, CH3 next.
Build green; touched-project tests green (19/19 new/changed,
4351/3354 App.Tests unaffected pass); full Release suite 11,916 passed /
4 skipped / 0 failed (baseline 11,914/4/0 plus the two new tests this
commit adds).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>