tinymux/tests/comsys_handoff
Stephen Dennis 687ca87309 fix(comsys): the module honours all five MOGRIFY hooks and CHATFORMAT (#1572)
The module implemented BLOCK and NOBUFFER.  MESSAGE, OVERRIDE and FORMAT
were silently ignored, and per-player CHATFORMAT was not present at all,
so a channel configured with any of them behaved differently depending on
which implementation happened to be live.  Silence rather than an error,
which is why 31 comsys cases in the corpus passed identically against
both.

Two of the issue's claims were stale and are corrected here: BLOCK already
evaluated through the evaluator interface rather than comparing raw
attribute text, and NOBUFFER had landed.  The gap was three hooks and
CHATFORMAT, not four hooks and a semantics bug.

Order and precedence follow comsys.cpp:1705-1822 exactly.  "Mostly the
same" is what produced the divergence in the first place, so MESSAGE
replaces the text, FORMAT sees the result of MESSAGE, OVERRIDE both
suppresses CHATFORMAT and lets FORMAT win outright, and history still
records the UN-mogrified message as the engine does.

## An engine bug fell out of it

s_chatformat_atr was a static, lazy-initialised ONCE PER PROCESS.
CHATFORMAT is a vattr, created the first time any player sets one -- so on
a game where nobody had one before the first channel message, the number
cached as 0 and CHATFORMAT was ignored for the entire life of the process,
including for every player who set one afterwards.  Restarting fixed it,
which is the shape that never gets reported as a bug.

It survived because nothing compared the implementations.  Now it caches
only a hit.

## tests/comsys_mogrify, and why it is not in comsys_handoff

Five cases, each driving both implementations and asserting they agree.
4 of 5 fail against the unfixed code, and case 3 fails on the ENGINE side,
which is what pins the cache fix.

It is a separate harness because comsys_handoff cannot test delivery.
That driver's shape is "establish state under one implementation, read it
under the other", and bConnected is runtime state set when a player joins
during that process -- it is not persisted.  A run inheriting membership
from an earlier run has user records with bConnected false and delivers to
nobody.  Each side must join and speak within one process.

That cost real time and briefly looked like "the module never delivers at
all".  It does; verified over a real socket against netmux before drawing
any conclusion.  A note in comsys_handoff records why the cases are not
there, so nobody adds them back.

Case 5 is weak by construction and kept deliberately: it asserts
CHATFORMAT is ABSENT under OVERRIDE, which is trivially true when
CHATFORMAT never works at all, so it passes in both columns.  It earns its
place only once the others pass, where it distinguishes OVERRIDE from
FORMAT alone.

make test green: 1561/1561 on all three smoke routes, handoff 13/13,
mogrify 5/5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 17:53:36 -06:00
..
run.sh fix(comsys): the module honours all five MOGRIFY hooks and CHATFORMAT (#1572) 2026-07-27 17:53:36 -06:00