fix(chat): CH4 review fixes — allegiance ownership guard, house-abandon confirmation

Blocker 1: an unrecognized "@allegiance <sub>" subcommand escaped
TryMatchAllegiance (which only claimed "info"/"hometown") and fell through
the unregistered-tag channel fallback, broadcasting the raw subcommand
text to the Allegiance chat channel (0x02000000). Retail's own
DoAllegiance never reaches DoChannelCommand for an unrecognized
subcommand — it claims the whole verb and prints its own client-local
refusal. TryMatchAllegiance now claims "allegiance"/"all" unconditionally
and shows retail's "Please see @help Allegiance..." text; ChatCommandRouter
also gained a blanket RetailClientCommandCatalog.KnownVerbs ownership
guard in TryDispatchChannelFallback as defense in depth.

Blocker 2: "@house abandon" sent 0x021F immediately with no confirmation.
Retail runs a real two-stage dialog before Event_AbandonHouse(); ported
both verbatim strings and chained two ShowConfirmation calls.

Should-fixes: a bare unregistered tag with no text now passes through
silently instead of showing a refusal that belongs to a different retail
function; @join/@leave update RuntimeCharacterOptionsState locally (new
SetOptionBit) before the wire push so the Turbine membership gate stops
refusing a just-joined room; @permit accepts multi-word names; @clist/
@on/@off validate shape only and raise WeenieError 0x422 for an unknown
tag; @mr/@pr help text is now the verbatim retail strings; corrected
issue #360, register row TS-68, the campaign doc's B.7 note, and a stale
RetailChannelTagTable comment; filed issue #363 + register row AP-183 for
the deferred error-typing debt.

Nits: fixed TryMatchHouse's stale doc comment, the AP-182/@title "stores
the value" comments (the binding is a no-op), IsUnregisteredFallbackTag's
olthoi false-positive, added /g and /rp binding-level conformance pins,
made @index ignore extra arguments, and noted the six removed invented
verbs in ISSUES.md.

Suite: 12,216 passed / 4 skipped / 0 failed (Release), up from CH4's
12,190/4/0 — net +26 tests, no removals.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-09 21:59:35 +02:00
parent 090825e703
commit 724ef2d389
17 changed files with 853 additions and 85 deletions

View file

@ -26,7 +26,8 @@ What does NOT go here:
## #360@allegiance/@house management dispatchers only port their simple subcommands
**Status:** OPEN — filed 2026-08-09, Campaign CH slice CH4. Retail's
**Status:** OPEN — filed 2026-08-09, Campaign CH slice CH4; corrected
2026-08-09 at the CH4 REJECT-review (Blocker 1). Retail's
`@allegiance`/`@all` and `@house`/`@hou` are 12- and 15-subcommand local
command dispatchers (`ClientCommunicationSystem::DoAllegiance @
0x0057D5A0` / `DoHouse @ 0x00580860`). CH4 ports the subset with simple
@ -40,13 +41,23 @@ boot_all/remove_all/guest/available/hooks/on/off) plus the standalone
target-name/guid resolution, confirmation dialogs, or multi-field payloads
this session did not attempt to build without byte-level verification
against both the retail decomp and ACE's reader — see the doc's own
framing ("largest single item; deserves its own slice"). Today these
subcommands correctly fall through to ACE as server-passthrough text
(`RetailClientCommandCatalog.TryMatchHouse`/`TryMatchAllegiance`) rather
than being swallowed locally, which was the Tier-1 correctness fix this
slice DID land — but they don't yet execute. Register row: TS-68.
Registry doc: `docs/research/2026-08-09-chat-retail-command-registry.md`
§2.5/§2.5b.
framing ("largest single item; deserves its own slice"). For `@house`,
these subcommands correctly fall through to ACE as server-passthrough
text (`RetailClientCommandCatalog.TryMatchHouse`) rather than being
swallowed locally, which was the Tier-1 correctness fix CH4 landed — but
they don't yet execute. **For `@allegiance`/`@all`, the original filing's
"falls through to ACE" claim was wrong**: retail's own `DoAllegiance`
never reaches server passthrough for an unrecognized subcommand — it
prints "Please see @help Allegiance for more information on how to use
this command." locally and stays entirely client-side
(`ClientCommunicationSystem::DoAllegiance`, label at 0x0057DA4B). The
CH4 REJECT-review found acdream had instead been broadcasting the
unmatched subcommand text to the Allegiance chat channel — a real
chat-visible bug, now fixed (`TryMatchAllegiance` claims ownership
unconditionally and shows retail's own refusal text). The 22 subcommands
themselves still don't execute; only the fallback behavior changed.
Register row: TS-68. Registry doc:
`docs/research/2026-08-09-chat-retail-command-registry.md` §2.5/§2.5b.
## #361@day / @log / @render pure-local commands recognized in help only, not executed
@ -73,6 +84,42 @@ registered in `GameEventType` with no `GameEventWiring` handler — ACE's
reply is silently dropped. The request itself is correct and verifiable
on the wire; only the response rendering is missing. Register row: TS-70.
## #363 — Chat refusal/usage call sites are typed ClientLocal 0x00 where retail types several 0x1A
**Status:** OPEN — filed 2026-08-09, CH4 REJECT-review, SHOULD-FIX 9.
`ChatVM.ShowSystemMessage`'s single-typed sink (`LogTextType 0x00`,
informational) is correct for most of `ClientCommandController`'s output,
but Campaign CH slice CH4 added roughly 10 new refusal/usage call sites
that retail types `0x1A` (bright red / ClientLocal), not `0x00`:
`DoStupidChannelHack` (the "You must specify the text you wish to say!"
family, registered channel verbs only), `DoChannelList`/`DoChannelOn`/
`DoChannelOff` ("Please specify the channel name."), `DoAllegiance` (the
"Please see @help Allegiance..." refusal this session's Blocker 1 fix
added), `DoHouseAvailableList`, and `DoReply` ("Someone must @tell you
first!"). Three CH4 sites are ALREADY correct because retail itself types
them informational `0x00`: `DoSpeaker`, `DoEndurance`, `DoTitle`.
Separately, retail's own bad-args fallback
(`ClientCommunicationSystem::DoCommand @0x0057E46D`) answers a registered
handler that returns 0 with `HandleFailureEvent(0x26)`, not a local
"Usage: <usage>" line — `ChatCommandRouter.Submit` shows a synthesized
`"Usage: {clientCommand.Usage}"` string instead whenever a catalog
command's `InvalidArgumentsText` is null. Register row: AP-183.
Deliberately NOT fixed this session — re-plumbing every call site to a
typed sink (and porting `HandleFailureEvent(0x26)`'s real text) is larger
than a REJECT-review fix batch; CH5-or-later.
## Note — six invented chat verbs removed for registry parity (2026-08-09)
Campaign CH slice CH4 deleted `/gen`, `/cv`, `/lookingforgroup`, `/tr`,
`/role`, `/h` from `ChatInputParser`/`ChatCommandRouter` — none are
retail-registered verbs; the retail command registry doc
(`docs/research/2026-08-09-chat-retail-command-registry.md` §4,
"candidates for removal") confirmed none exist in the real client. Not a
bug, no issue number — recorded here so they aren't reintroduced later as
"missing aliases." `RetailCommandRegistryConformanceTests`'s two
reverse-direction ownership tests now fail the build if any of the six
(or any other invented verb) resurfaces.
## #356 — Alt-tab during login crashed the client: focus loss faulted on an unpublished movement controller
**Status:** CLOSED 2026-08-08 — `972c7ab3`. Window focus loss runs