# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Overview MARTe2 component library providing real-time signal streaming (`UDPStreamer` DataSource → StreamHub → web/ImGui oscilloscopes) and zero-code-change debugging (`DebugService` Interface: trace/force/breakpoint via registry-patched broker wrappers). See `ARCHITECTURE.md` for full detail and `Docs/` for per-component references. ## Build & Test Requires MARTe2 and MARTe2-components built externally; `env.sh` sets `MARTe2_DIR`, `MARTe2_Components_DIR`, `TARGET=x86-linux`, and `LD_LIBRARY_PATH` (needed both for building and for running anything). ```bash source env.sh make -f Makefile.gcc core # all C++ MARTe2 components make -f Makefile.gcc apps # StreamHub standalone app make -f Makefile.gcc test # build GTest + Integration tests make -f Makefile.gcc clean # Run tests (after source env.sh) ./Build/x86-linux/GTest/MainGTest.ex # unit tests (UDPStreamer) ./Build/x86-linux/GTest/MainGTest.ex --gtest_filter='Name*' # single test ./Build/x86-linux/Test/Integration/Integration/IntegrationTests.ex # DebugService integration tests # Build a single component (each component dir has its own Makefile.gcc) make -C Source/Components/DataSources/UDPStreamer -f Makefile.gcc # Go clients cd Common/Client/go && go build ./... cd Client/debugger && go build ./... # ImGui desktop client (not a MARTe2 component; needs SDL2) cd Client/streamhub && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build # Qt desktop client (not a MARTe2 component; needs Qt5 or Qt6 Widgets + WebSockets) cd Client/streamhub-qt && cmake -B build && cmake --build build ``` End-to-end demo scripts (build + launch full stack, see headers for ports/options): `./run_combined_test.sh`, `./run_streamhub.sh`. **Streaming-chain E2E suite** (`Test/E2E/suite/`): `./run_e2e.sh [--skip-build] [--only ] [--cpp-coverage]` drives the full chain per scenario (`scenarios.py`) — generates typed/shaped input + both cfgs, runs MARTe2+StreamHub, records via the Go `chain-client` (live/zoom/window/trigger), and validates the recorded waveform against an analytic/fed oracle (`validate_waveform.py`: fidelity gates correctness, sine shape-fit is a gross-sanity gate + tracked metric pending Phase-A timestamp calibration). It then runs the unit suites + coverage (`collect.py`: C++ GTest, Go, Python; `--cpp-coverage` does an instrumented `--coverage` rebuild, captures with lcov restricted to `Source/*`+`Test/*`, then restores the clean build), consolidates everything into `report_data.json` with per-field progression/regression vs the previous run and trend plots (`report_build.py`, history in `Build/x86-linux/E2E/chain/history.jsonl`), and compiles a Typst PDF (`E2E_Report.typ`). Python framework unit tests: `python3 -m unittest tests_py` (in `Test/E2E/suite/`). Build output goes to `Build/x86-linux/` (shared libs per component, `.ex` executables). ## Architecture Two independent data paths: 1. **Streaming path**: `UDPStreamer` DataSource serialises signals each RT cycle to UDPS binary packets (UDP 44500, unicast/multicast) → `StreamHub` (`Source/Applications/StreamHub/`, headless C++ app: ring buffers, LTTB decimation, trigger FSM) → WebSocket 8090 → browser (`Client/udpstreamer`, Go), native ImGui client (`Client/streamhub`), or native Qt client (`Client/streamhub-qt`). 2. **Debug path**: `DebugService` patches the `ClassRegistryDatabase` at `Initialise()` so subsequent `ConfigureApplication()` instantiates `DebugBrokerWrapper` around all `MemoryMap*Broker` types — no application changes. RT hot path goes through `DebugServiceI` (abstract singleton in `DebugServiceI.h`) for forcing/tracing/breakpoints. Exposes TCP 8080 (text commands), UDP 8081 (trace telemetry), works with `TcpLogger` on 8082. Web UI: `Client/debugger` (Go). **Shared wire format**: `Common/UDP/UDPSProtocol.h` defines the UDPS binary protocol (17-byte packed header, 136-byte signal descriptors, little-endian). It is deliberately MARTe2-free so it's shared by C++ producers (`UDPStreamer`, `DebugService`), the C++ consumer (`Source/Components/Interfaces/UDPStream/UDPSClient`), and the Go decoder (`Common/Client/go/udpsprotocol`). Changes to the protocol must be mirrored across all of these, plus the JS client parsers. **StreamHub WebSocket protocol**: JSON text frames for commands/events, binary frames for data pushes — spec in `ARCHITECTURE.md` §6. The Go hub (`Client/udpstreamer`) and C++ StreamHub implement the identical protocol; both clients (browser JS and ImGui) must stay compatible with both. **StreamHub History**: `HistoryWriter` (`Source/Applications/StreamHub/HistoryWriter.{h,cpp}`) provides disk-backed circular storage of signal data. Each signal is stored in a separate `.shist` binary file with a 64-byte header and pre-allocated circular data region of `(float64 time, float64 value)` pairs. Configured via a `+History` block in the StreamHub config with keys: `Directory` (required), `DurationHours` (default 1), `Decimation` (default 1), `FlushIntervalSec` (default 5), `MinDiskFreeMB` (default 500). WS commands: `historyInfo` (returns metadata), `historyZoom` (reads time range from disk). Both the web SPA (`Client/udpstreamer/static/app.js`) and ImGui client support history zoom queries alongside in-memory ring zoom. ## Conventions - **No STL in MARTe2 components** (`Source/Components/`): use MARTe2 types (`StreamString`, `FastPollingMutexSem`, fixed arrays). STL/C++17 is fine in `Client/streamhub/` and `Source/Applications/StreamHub/` follows MARTe2 style but links MARTe2 core. - `FastPollingMutexSem` on RT hot paths (never OS mutexes). - Each component dir has `Makefile.gcc` (wrapper), `Makefile.inc` (sources/includes), and `depends.x86-linux`/`dependsRaw.x86-linux` (generated dependency files). - EUPL v1.1 license headers on C++ sources. **Qt client** (`Client/streamhub-qt/`): native Widgets oscilloscope, feature/UX-equivalent to the ImGui client, speaking the identical StreamHub WebSocket protocol. CMake autodetects Qt6 (preferred) or Qt5 (`find_package(QT NAMES Qt6 Qt5 ...)` then `Qt${QT_VERSION_MAJOR}::` targets) for old-Linux back-compat. It reuses `../streamhub/Protocol.{h,cpp}` and `SignalBuffer.h` verbatim (framework-free C++17); those structs have members named `signals`, which collide with Qt's `signals`/`slots`/`emit` macros, so the build sets `QT_NO_KEYWORDS` and all Qt classes use `Q_SIGNALS:`/`Q_SLOTS:`/`Q_EMIT`. Single GUI thread (QWebSocket signals arrive on the GUI thread, no locks); a 60 Hz QTimer drives repaint. Plotting is custom QPainter (no QtCharts/QCustomPlot) for ImPlot parity and zero extra deps. Run: `./build/StreamHubQtClient --host HOST --port 8090` (long `--` options; single-dash `-host` is misparsed as clustered short flags).