test(gem): table-driven conformance sweep over the default handler set

One ordered in-process scenario drives 53 of the 56 registered handlers
through Router::dispatch — S1 identification/comms/control, S2 ECs/clock/
event-config/commands/trace/limits/spool, S5 alarms+exceptions, S6 reports,
S7 recipes, S10 terminal, S14/S16 E39+E40/E94 jobs, S3 carriers — asserting
every reply is the paired (stream, function+1) with a body, plus targeted
state checks (OnlineRemote after S1F17, PJ exists after S16F11, HostOffline
after S1F15) and the Router's SxF0 abort fallback for unregistered W=1
primaries. Same flow secs_conformance runs over a live socket, but cheap
enough for every build; closes the '56 handlers, 4 direct tests' gap from
the design review.

Also seeds message-level golden frames: S1F13's body pinned to bytes
hand-computed from the E5 encoding rules — an external check on message
composition, not our codec validating itself (TODO: S5F1, composed S6F11).

Suite: 466 cases / 3052 assertions (+236), all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 19:26:28 +02:00
parent 42044e92e2
commit b0a4c331cf
3 changed files with 196 additions and 3 deletions
+6 -3
View File
@@ -102,9 +102,12 @@ debts tax every later phase, and the most valuable tests aren't automated.
localhost, no docker-in-docker). ⬜ Verify the lanes on the first push.
3.**Fix `CompleteCommand` proto comment** — it described the rejected
blocking model; now states the HCACK-4 contract.
4. **Table-driven handler conformance test** ((request, expected-reply-shape)
pairs through `router.dispatch` for broad coverage of the 56 handlers) +
message-level golden wire frames (codec KATs exist; message-level don't).
4. 🚧 **Table-driven handler conformance test** — ✅
`tests/test_handler_conformance.cpp`: one ordered scenario drives 53 of the
56 handlers through `router.dispatch` in-process (236 assertions), asserting
paired replies, control-state landings, and the SxF0 abort fallback.
Message-level golden frames: seeded with a hand-computed (E5-rules, not
codec-derived) S1F13 pin — ⬜ extend to S5F1 + composed S6F11 (TODO in file).
5.**Decompose `register_default_handlers` per GEM capability** (it is a
relocated main(), not a designed component) and replace magic constants
(SVIDs 1/2 `refresh()`, CEIDs 400/401) with YAML role bindings