Picks up the file renames that landed alongside the previous commit
and fixes everything that pointed at the old root locations:
- README.md doc-map updated: every entry now points at docs/X.md,
with a new "docs/" lead entry pointing at the guided-tour index.
- README inline cross-refs (ARCHITECTURE / INTEGRATION / SECURITY /
BENCHMARKS / MES_INTEROP / PROOFS) repointed to docs/.
- README "Interop" section rewritten — used to mention only
secsgem-py; now covers all four external validators (secsgem-py
31 / secs4java8 55 / tshark 69 frames / libFuzzer 200 k+ runs)
with a one-line summary each, plus pointers to interop/README.md
and docs/VERIFICATION.md.
- README "Deferred follow-ups" cleaned: dropped the explanatory
"Listed here so reviewers don't go looking for them in
COMPLIANCE.md and find an 'out of scope' entry that sounds
defensive" sentence — the section header speaks for itself.
- docs/00_index.md "Where the rest of the docs live" table: dropped
every `../` prefix since the docs are now siblings.
- docs/01_what_is_secs_gem.md PROOFS reference updated to sibling.
- docs/02_the_cast.md INTEGRATION + MES_INTEROP refs updated to
siblings; dropped the stale "at the repo root" wording.
- interop/README.md: VERIFICATION + PROOFS refs updated to
../docs/X.md; stale "~24 + 4 checks" updated to 31 (matches
PROOFS.md and README).
- examples/pvd_tool/README.md: every doc cross-ref now points at
../../docs/X.md.
- Source / data / CI comments mentioning doc names (e.g.
"INTEGRATION.md §3", "COMPLIANCE.md gap") rewritten to
"docs/INTEGRATION.md §3" etc. — affects 9 files across
include/, apps/, tests/, data/, examples/, .gitea/workflows/.
Verified: full build under docker passes, 445/445 test cases pass,
2 753/2 753 assertions pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
INTEGRATION.md §3 used to show a sensor-poll thread calling
model->svids.set_value() directly while the io_context thread reads
the same SVID for an inbound S1F3. That's a data race — there are
zero locks anywhere in EquipmentDataModel and there's no intention
to add them. The library is single-threaded by design; the doc was
just inviting trouble.
This commit makes the actual contract explicit:
- INTEGRATION.md §3: thread-safety callout box. All access must run
on the io_context that drives the HSMS connection. Sensor updates
from other threads marshal via asio::post(io.get_executor(), ...).
Same applies to set_*_change_handler callbacks (they fire on the
io_context thread; observers must be thread-safe or hand work off).
- README.md §3 (Monitoring & observability): added a paragraph noting
that hooks fire on the io_context thread, blocking I/O inside a
handler stalls the dispatcher, and metrics exporters must respect
the same contract.
- tests/test_thread_safety.cpp: two scenarios that exercise the
canonical pattern — N producer threads asio::post sensor updates
onto a worker-driven io_context; reads marshal back through the
io. Catches obvious regressions (e.g. someone adding a
"convenience" cross-thread mutator that bypasses the strand).
A passing run isn't proof of race-freedom under ThreadSanitizer —
it pins down the *pattern* customers should follow. TSan integration
is a separate workstream.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>