refactor(gem): decompose default handlers per GEM capability + YAML role bindings
register_default_handlers was a relocated app main(): one 1086-line function, all-or-nothing. It is now 15 per-capability registration functions along the lines GEM itself defines (S1F19): identification, equipment constants, clock, event reports, remote commands, trace/limits, spooling, alarms, exceptions, material tracking (E90/E116/E157), carriers (E87), recipes, object services (E39), jobs (E40/E94), terminal services. A sensor-class tool registers three functions instead of carrying carrier/job handlers it doesn't have; register_default_handlers composes all 15. Each function derives exactly the runtime aliases its handlers use (generated programmatically from the moved bodies with boundary/substitution guards — zero hand-retyping). Magic constants are gone: the control-state/clock SVIDs (were hardcoded 1/2) and the CJ Executing/Completed CEIDs (were 400/401) now come from a "roles:" block in equipment.yaml via EquipmentDescriptor, with historical defaults when absent, loader parsing, and validation (CEID roles must name declared events). The coupling is now visible in ONE file instead of silently split between YAML and C++ — the exact drift class this repo's spec-as-data philosophy exists to kill. Tests: capability subsetting, role-driven SVID refresh via S1F3, roles loader (shipped/custom/absent). Battery: core 473/3087 incl. the 53-handler conformance sweep, daemon 125/125, live GEM300 demo (client exit 0), daemon interop 20/20 vs secsgem-py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+16
-8
@@ -42,9 +42,11 @@ host and stays conformant while the tool software restarts/upgrades/crashes.
|
||||
- ✅ ~~**Alarms have no name key.**~~ Optional `name:` added to the alarm
|
||||
config (loader + validator + shipped equipment.yaml); daemon RPCs accept
|
||||
the name or the stringified ALID.
|
||||
- ⬜ **`pvd_tool` predates the behaviour hook.** It still hard-codes
|
||||
`if (rcmd=="START") recipe->start(...)` in a router handler. Migrate it to
|
||||
`commands.set_handler` so the flagship example showcases the intended seam.
|
||||
- ⬜ **`pvd_tool` predates the behaviour hook AND the runtime.** It still
|
||||
hard-codes START behaviour in a router handler and hand-wires its own
|
||||
main(). Migrate it to EquipmentRuntime + per-capability registration +
|
||||
`commands.set_handler` so the flagship example showcases the intended
|
||||
integration shape. (Phase C item 9.)
|
||||
- ✅ ~~**Interop harnesses are manual.**~~ `tools/run_interop.sh` runs all nine
|
||||
validation steps with one command (verified green); CI lanes added, pending
|
||||
first-push verification (Phase 0 item 2).
|
||||
@@ -106,11 +108,17 @@ debts tax every later phase, and the most valuable tests aren't automated.
|
||||
drives 53 of the 56 handlers through `router.dispatch` (236 assertions).
|
||||
Golden frames: S1F13, S5F1, and a composed S6F11, all hand-computed from
|
||||
E5 rules (external pins, not codec-derived).
|
||||
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
|
||||
(`control_state_svid:`, `cj_executing_ceid:` …). Gradual; aligns with the
|
||||
capability structure GEM itself defines (S1F19) and enables vendor subsetting.
|
||||
5. ✅ **Decomposed `register_default_handlers` into 15 per-capability
|
||||
functions** (identification, ECs, clock, event reports, remote commands,
|
||||
trace/limits, spooling, alarms, exceptions, material tracking, carriers,
|
||||
recipes, object services, jobs, terminal) — vendors register only what
|
||||
their equipment is; `register_default_handlers` = all 15. Magic constants
|
||||
replaced by YAML **role bindings** (`roles:` block — control_state_svid,
|
||||
clock_svid, cj_executing_ceid, cj_completed_ceid) parsed into the
|
||||
descriptor with historical defaults, validated (CEID roles must be
|
||||
declared). Tested: subset registration, role-driven SVID refresh, roles
|
||||
loader (present/custom/absent); full battery green (473/3087 core incl.
|
||||
the 53-handler sweep, live GEM300 demo, 20-check daemon interop).
|
||||
6. ✅ **Standardize the mutable-read pattern** — `EquipmentRuntime::read_sync`
|
||||
(post-to-io + future with deadline; nullopt => UNAVAILABLE at the RPC edge).
|
||||
Precedent set by `GetVariables`; every future mutable read copies it.
|
||||
|
||||
Reference in New Issue
Block a user