feat(chat): Campaign CH slice CH4 — command registry completion

Brings acdream's / and @ command parsing to parity with the complete
retail registry (130 registered verbs + 22 unregistered GetChannelID
fallback tags = 152 client-parsed verbs), per
docs/research/2026-08-09-chat-retail-command-registry.md.

Parser semantics (retail OnChatCommand/DoCommand):
- : and ; rewrite to "@emote <rest>" before dispatch.
- Verb trailing-comma trim ("@f, hi" == "@f hi") applied at every
  verb-lookup site in the catalog and the parser.
- @tell/aliases split the target on the FIRST COMMA, not the first
  whitespace token, so multi-word names work ("@tell Aunt Agatha, hi").
- The 22 unregistered GM/faction channel tags (admin, sentinel,
  celestialhand, ...) now broadcast for real via a new
  RetailChannelTagTable + SendRawChannelCmd bypass, reusing the existing
  BuildChatChannel wire builder.

Binding corrections:
- /g, /group, /party -> Fellowship (0x800), not General.
- /rp -> reply alias (retail's own help text confirms "@r or @rp"), not
  Roleplay; /role (an acdream invention) deleted.
- /allegiance, /all -> the allegiance management command
  (RetailClientCommandCatalog), not a channel verb.
- /house no longer swallows unrecognized subcommands with a local usage
  error; they now correctly fall through to ACE.
- @mr/@pr pinned as permanently non-executable (retail registers them
  with a null function pointer).

New verbs with real local execution: endurance, speaker, title (silent,
AP-182), chat, notell, join, leave, permit, hslist, index, clist, on,
off, alh/ah (+ "@allegiance hometown"/"ho"), "@allegiance info",
"@house abandon"; a missing-alias sweep across pkl/hou/message_types/
msgtypes/msg_types/rt/send/whisper/w/vassal/covassal/co-vassals/c/
fellows/group/party/guild/gu/cg/ct/clfg/crp/soc/o; the non-retail
inventions gen/cv/lookingforgroup/tr/role/h are deleted. New Core.Net
wire builders (IndexChannels, ListChannels, AddChannel, RemoveChannel,
RecallAllegianceHometown, AllegianceInfoRequest, ListAvailableHouses,
AddPlayerPermission, RemovePlayerPermission, AbandonHouse) are all
parameterless or single-field payloads cross-checked against ACE's
GameAction readers, not guessed.

Deferred (filed as #360/#361/#362, register rows TS-68/TS-69/TS-70):
the ~22 remaining allegiance/house subcommands + standalone @motd
(largest single item, needs its own slice per the doc), the three
still-inert pure-local commands (day/log/render), and the inbound
GameEvent responses for the new outbound requests. All correctly fall
through to ACE server-passthrough rather than being silently swallowed
or faking success.

RetailCommandRegistryConformanceTests pins the complete 152-verb
registry against production: every verb resolves through exactly one
production surface if Implemented, through none if HelpOnly/
ServerPassthrough, and two reverse-direction tests fail the build if
RetailClientCommandCatalog or ChatInputParser ever claims a verb
outside this registry again. Final tally: 138 Implemented / 5
ServerPassthrough / 9 HelpOnly = 152.

Release suite: 12,190 passed / 4 skipped / 0 failed (up from CH3's
11,964/4/0).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-09 21:10:17 +02:00
parent 9247d5d5b5
commit 090825e703
23 changed files with 2069 additions and 97 deletions

View file

@ -24,6 +24,55 @@ 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.
## #360@allegiance/@house management dispatchers only port their simple subcommands
**Status:** OPEN — filed 2026-08-09, Campaign CH slice CH4. 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
parameterless/single-string-field wire shapes — allegiance `info`,
`hometown`/`ho` (also the standalone `@alh`/`@ah`); house `recall`/`re`,
`mansion_recall`/`alleg_recall`/`ma` (already shipped pre-CH4), and
`abandon`. The remaining ~22 subcommands (allegiance boot/ban/officer/
title/name/lock/chat/broadcast/motd; house open/close/storage/remove/
boot_all/remove_all/guest/available/hooks/on/off) plus the standalone
`@motd` verb need real GameAction wire builders, most requiring
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.
## #361@day / @log / @render pure-local commands recognized in help only, not executed
**Status:** OPEN — filed 2026-08-09, Campaign CH slice CH4. Three
retail-registered pure-local verbs are not yet wired to real behavior:
`@day` (daylight override — needs a sky/time-of-day hook the renderer
doesn't expose), `@log` (chat-to-file logging — deferred to avoid an
unaudited file-handle lifecycle across session reconnects; see AP/TS-69
for the reasoning), and `@render` (retail's `SmartBox::HandleRenderOption`
— acdream has no equivalent render-option surface). All three are
recognized by `/help <verb>` (`RetailCommandHelpTable`) with retail's own
extracted help text, but fall through to server passthrough on execution.
Register row: TS-69.
## #362 — Four new CH4 outbound requests have no inbound response handler
**Status:** OPEN — filed 2026-08-09, Campaign CH slice CH4. `@index`,
`@clist`, `@hslist`, and `@allegiance info` send byte-correct retail
GameAction requests (`ClientCommandRequests.BuildIndexChannels`/
`BuildListChannel`/`BuildListAvailableHouses`/`BuildAllegianceInfoRequest`),
but their GameEvent responses (`ChannelIndex 0x0149`, `ChannelList
0x0148`, `AvailableHouses 0x0271`, `AllegianceInfoResponse 0x027C`) are
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.
## #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