acdream/tests/AcDream.UI.Abstractions.Tests/Panels/Chat
Erik 44fb74f8a6 feat(chat): CT-A3 — a chat line keeps the identity of who said it
Campaign CT slice A3. Still nothing visible; this removes the blocker.

ChatEntry carried Sender and SenderGuid the whole way through ChatLog, and
RecentLinesDetailed dropped both one step before the transcript. That is why a
speaker's name could never be coloured or clicked apart from the sentence
around it — by the time anything could draw it, there was no name left, only
prose.

FormattedLine now carries a Spans sidecar: the line split into stretches, one
of which may hold a retail text tag. Text remains the VISIBLE line with markup
consumed, so wrapping, selection, hit-testing and the caret are untouched, and
Spans is null for the ordinary single-colour line, which is most of them.

FormatEntryTagged shares its format strings with FormatEntry through a sender
decorator rather than duplicating retail's wording. Two copies would be two
things to keep in step, and these two renderings MUST show the same characters:
the transcript selects against the flat text, so any drift would mean clicking
one character and selecting another.

Tagging is gated on AC1's player id range (0x50000001..0x6FFFFFFF), read off
the guard in Handle_Communication__HearSpeech @0x005712A0 — so monsters and
NPCs never become clickable, which a "has a name" test would get wrong.

One real bug came out of a defensive test rather than a report. A sender name
containing '<' re-parsed as a marker and SWALLOWED characters from the visible
line ("Od<d says" rendered as "Od says"). The markup has no escape mechanism,
and retail's has none either because AC name validation makes the case
unreachable there — but sender names are server data. Such a name is now simply
not tagged, so the line renders plain like any other untaggable sender instead
of rendering corrupted.

Solution builds clean; full hermetic gate green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 07:27:14 +02:00
..
ChatCommandRouterTests.cs fix(chat): consolidated-review fixes — retail /help Detail extraction, seam wiring test 2026-08-10 16:22:36 +02:00
ChatInputParserAtPrefixTests.cs feat(chat): Campaign CH slice CH4 — command registry completion 2026-08-09 21:10:17 +02:00
ChatInputParserTests.cs fix(chat): #363 — retail 0x1A typing for command refusals via the interface-text seam 2026-08-10 15:21:30 +02:00
ChatPanelFocusTests.cs feat(runtime): share chat commands and run login sequence 2026-08-14 20:27:45 +02:00
ChatPanelInputTests.cs feat(runtime): share chat commands and run login sequence 2026-08-14 20:27:45 +02:00
ChatPanelLayoutTests.cs fix(chat): CH1 review fixes — sbb-idiom channel catch-all, command-output typing 2026-08-09 16:03:13 +02:00
ChatVMCombatTests.cs fix(chat): CH1 review fixes — sbb-idiom channel catch-all, command-output typing 2026-08-09 16:03:13 +02:00
ChatVMLastTellSenderTests.cs fix(chat): CH1 review fixes — sbb-idiom channel catch-all, command-output typing 2026-08-09 16:03:13 +02:00
ChatVMRetellAndProvidersTests.cs fix(chat): #363 — retail 0x1A typing for command refusals via the interface-text seam 2026-08-10 15:21:30 +02:00
ChatVmTaggedSenderTests.cs feat(chat): CT-A3 — a chat line keeps the identity of who said it 2026-08-21 07:27:14 +02:00
RetailChatColorTableTests.cs feat(chat): Campaign CH slice CH1 — retail LogTextType color table 2026-08-09 15:24:09 +02:00
RetailClientCommandCatalogTests.cs fix(chat): CH4 review fixes — allegiance ownership guard, house-abandon confirmation 2026-08-09 21:59:35 +02:00
RetailCommandHelpTableTests.cs fix(chat): round 4 — no user-visible meta text, real /help groups, indicator buttons toggle 2026-08-10 18:46:34 +02:00
RetailCommandRegistryConformanceTests.cs fix(chat): CH4 review fixes — allegiance ownership guard, house-abandon confirmation 2026-08-09 21:59:35 +02:00