Commit Graph

2 Commits

Author SHA1 Message Date
raphael db90a21e1d verify: expand secs4j harness 20 → 55 checks
tests / build-and-test (push) Successful in 2m2s
tests / thread-sanitizer (push) Successful in 2m28s
tests / tshark-dissector (push) Failing after 2m7s
tests / secs4j-interop (push) Failing after 0s
tests / libfuzzer (push) Successful in 3m9s
Every check the user could ask for now lands.  secs4j's
comm.send(stream, function, w, body) takes arbitrary S/F + arbitrary
Secs2 body, so coverage was never coverage-limited by the Java side
— the original 20 was just the minimum to fill the gaps secsgem-py
couldn't reach.

Adds:

- Status data:    S1F3, S1F11
- EC management:  S2F13, S2F15 (set TimeFormat), S2F29
- Event reports:  S2F33, S2F35, S2F37 (full define-link-enable
                  sequence), S6F15, S6F19, S6F21
- Remote control: S2F41 (modern RCMD=START + observed S6F11),
                  S2F21 (legacy RCMD=STOP),
                  S2F41 RCMD=FAULT + observed S5F1
- Alarms:         S5F3, S5F5, S5F7
- Spool:          S2F43, S6F23
- PP management:  S7F1, S7F3, S7F5, S7F17, S7F19
- Terminal:       S10F3 (single), S10F5 (multi-line)
- E40 PJ:         S16F11 (full E40 body — MF + PRRECIPEMETHOD +
                  RecipeSpec + mtrloutspec + processparams),
                  S16F7 (monitor), S16F13 (dequeue)
- Limits:         S2F45, S2F47
- Trace:          S2F23 (5-field body)
- E39:            S14F1 (GetAttr)

Plus a SecsMessageReceiveListener that captures every equipment-
initiated primary into a ConcurrentLinkedQueue and replies to S5F1
(ACKC5=0), S6F11 (ACKC6=0), S16F9 (W=0 no reply) so the
equipment's T3 doesn't fire on our watch.  Two checks now assert
the unsolicited path:

  - After RCMD=START, an S6F11 with the linked report must arrive
    within 400ms
  - After RCMD=FAULT, an S5F1 with the alarm must arrive within
    400ms

Both observed against the demo equipment.

Result: 55/55 PASS.  Two independent implementations
(secsgem-py + secs4java8) now corroborate the wire surface in
overlapping but distinct slices.  Full E40 body — the one that
defeated secsgem-py's SFDL grammar — round-trips cleanly through
secs4j.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 16:30:49 +02:00
raphael 2fce2fad0c verify: secs4j cross-validation (independent Java implementation)
20 cross-validation checks PASS against [secs4java8] (Apache 2.0,
kenta-shimizu) — an independent SECS/HSMS implementation in Java by
a different author from a different language ecosystem.  Distinct
implementer = independent spec interpretation.  Two libraries
agreeing on wire bytes is much stronger evidence of spec-correctness
than either alone.

Coverage targets the gap the secsgem-py interop deliberately skipped
(secsgem-py's SFDL grammar couldn't easily express GEM 300 bodies
with variable lists of named scalars):

  - S1F1/F13/F17/F19/F21/F23 — establish comms + namelists
  - S2F17 — clock
  - S2F23 — trace init (5-field body)
  - S2F49 — enhanced remote command (DATAID + OBJSPEC + RCMD + params)
  - S3F17/F19/F25/F27 — full E87 carrier surface (action, slot map
                        verify, transfer with port pair, cancel)
  - S5F13/F17 — exception recovery (EXID + EXRECVRA)
  - S14F9/F11 — E94 CJ create with prjobids list, CJ delete
  - S16F5/F27 — E40 PJ command, E94 CJ command
  - S1F15 — offline cleanup

20/20 PASS against the demo equipment.  Reply S/F matches the spec
for every transaction; specific ACK values vary by equipment state
(CarrierIDUnknown for an unknown carrier is just as valid as Accept
for a known one) so we assert on the wire shape, not the result.

Ship layout:
  interop/secs4j/Dockerfile          — eclipse-temurin:21-jdk + clone
                                       + build of secs4java8 → Export.jar
  interop/secs4j/Secs4jHostHarness.java
                                     — 20 round_trip assertions; uses
                                       Secs2.list/uint4/ascii to build
                                       full GEM 300 bodies; comm.send()
                                       for arbitrary S/F pairs
  interop/secs4j_validate.sh         — orchestrator: builds image,
                                       compiles harness, starts compose
                                       server, runs Java container on
                                       the secs network against it
  .gitea/workflows/ci.yml            — secs4j-interop job in CI
  README.md                          — proof table grows to 7 commands
  .gitignore                         — *.class

After this commit our proof chain has:
  - SEMI E5 KAT          (standards body's own arithmetic)
  - tshark dissector     (Wireshark's HSMS impl)
  - secsgem-py interop   (Python reference impl)
  - **secs4j interop**   (independent Java impl)
  + 426 unit tests, 47 conformance harness checks, 100k random ops,
    YAML validation

Four independent external proofs, three of them on overlapping wire
surface from independent angles.

Plan: VERIFICATION.md §3.

[secs4java8]: https://github.com/kenta-shimizu/secs4java8

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 16:12:44 +02:00