docs: bring the documentation up to the daemon/client era

A large gap had opened between the docs and the code: the README and
INTEGRATION guide did not mention the gRPC daemon or the Python client at
all (the entire vendor surface), ARCHITECTURE still described secs_server
as the ~1200-line canonical wiring example (it is a ~110-line thin main
over EquipmentRuntime), and test counts across six files were stale
(445/2753 -> 473/3087 core + the separate 125-assertion daemon suite).

- README: new "Integrating your tool (pick a tier)" section — Python
  client / any-language gRPC / embedded C++ — plus daemon tests and
  tools/run_interop.sh in the Testing section.
- ARCHITECTURE: layer diagram gains the vendor-surface and
  EquipmentRuntime/default_handlers tiers; stale wiring row fixed.
- INTEGRATION: three-tier chooser up front (this guide = the C++ tier).
- ch30 tour: secs_gemd + secs_gemd_tests in the binaries table.
- ch31: example alarm used a nonexistent `alcd:` field with bit 7 set
  (which the validator forbids) -> real `category:`/`name:` fields, and
  the roles: block documented.
- ch35: handler-location note now points at default_handlers.cpp's 15
  per-capability register_* functions.
- ch40: built-artifacts list + sample output counts.
- ch50: secsgem::gem runtime/default_handlers/handler_slot/name_index
  includes + new secsgem::daemon namespace section.
- PROOFS: test-count table gains the runtime/handlers/daemon row so the
  tally adds up; daemon suite noted. VERIFICATION/COMPLIANCE counts.
- interop/README: the one-command runner + the two daemon-track harnesses
  (daemon_interop, pyclient_interop).

Audited via a docs-vs-code sweep (the audit itself under-reported: it
validated counts textually; reality was 473/3087).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 23:18:31 +02:00
parent 8686654b15
commit af1a159c59
12 changed files with 174 additions and 22 deletions
+53 -4
View File
@@ -19,7 +19,7 @@ Everything runs in Docker — no compiler or build tools on the host.
```bash
docker compose run --rm builder # configure + compile
docker compose run --rm tests # 445 cases / 2 753 assertions
docker compose run --rm tests # 473 cases / 3 087 assertions
docker compose up --no-deps server client # live two-container demo
```
@@ -28,6 +28,46 @@ through the data model. Watch the logs interleave.
---
## Integrating your tool (pick a tier)
Three ways in, same engine underneath:
1. **Python, no SEMI knowledge** — run the `secs_gemd` daemon and
`pip install` the pure-Python client in [clients/python](clients/python):
```python
from secsgem_client import Equipment
eq = Equipment("localhost:50051")
eq.set(ChamberPressure=2.5) # host sees it on its next poll
eq.fire("ProcessStarted") # S6F11, report auto-assembled
@eq.on("START") # host remote commands -> your function
def start(cmd):
run_recipe(cmd.params.get("PPID"))
eq.listen()
```
A complete tool is ~25 lines: [clients/python/examples/mini_tool.py](clients/python/examples/mini_tool.py).
2. **Any language over gRPC** — `secs_gemd` exposes the name-based API in
[proto/secsgem/v1/equipment.proto](proto/secsgem/v1/equipment.proto)
(variables, events, alarms, control state, health stream, and the
host-command stream with the SEMI-conformant HCACK-4 contract). The
daemon owns the durable HSMS link: your tool software can restart
without the fab host ever noticing.
3. **Embedded C++** — construct a `gem::EquipmentRuntime`, call the
per-capability `register_*` functions (or `register_default_handlers`
for all of GEM), and wire behaviour with `commands.set_handler`.
`apps/secs_server.cpp` is the ~110-line canonical example.
Status and remaining work for the daemon/client track:
[docs/DAEMON_ROADMAP.md](docs/DAEMON_ROADMAP.md).
---
## Documentation map
| File | What it covers |
@@ -50,8 +90,8 @@ through the data model. Watch the logs interleave.
## Testing
- **Unit + integration** — `docker compose run --rm tests` runs 445
cases / 2 753 assertions across every store, FSM, codec, parser, and
- **Unit + integration** — `docker compose run --rm tests` runs 473
cases / 3 087 assertions across every store, FSM, codec, parser, and
persistence path.
- **Live conformance harness** — 47 wire-level checks against the
passive server.
@@ -59,11 +99,20 @@ through the data model. Watch the logs interleave.
(55 checks), and Wireshark's HSMS dissector (69 frames, 0 malformed).
- **Soak + fuzz** — 100 000-op property test; libFuzzer with ASan +
UBSan over `secs2::decode` and the SML parser, 0 crashes.
- **Daemon** — `secs_gemd_tests` exercises the gRPC service over real
in-process channels (125 assertions), in Release and under
ThreadSanitizer; `interop/daemon_interop.py` and
`interop/pyclient_interop.py` prove the gRPC↔HSMS bridge and the
published Python client against a live daemon with secsgem-py as host.
- **One command for all of it** — `tools/run_interop.sh` runs every
validation step (build, both unit suites, secsgem-py host, C++
conformance, Python client, daemon bridge, spool restart, tshark,
secs4java8) with a PASS/FAIL summary.
- **Config validation** — `secs_server --validate-config` rejects
malformed YAML before startup.
- **CI** — [Gitea Actions](.gitea/workflows/ci.yml) runs the full
suite plus a `-fsanitize=thread` lane on every push to `main`; all
445 cases pass clean under TSan.
473 cases pass clean under TSan.
Exact commands, exit codes, and per-standard test counts are in
[docs/PROOFS.md](docs/PROOFS.md); the rationale behind the external