Output and replay formats
Every output line is one JSON object. The schema is identified by the project version in the startup record. Numeric temperature values have two decimal places when printed; JSON parsers may normalize those decimals. Logs never contain an echoed command or a device-owner identifier.
{"type":"startup","version":"1.0.0","synthetic":true,"threshold_c":28.00,"input_status":"missing"}
{"type":"sample","synthetic":true,"uptime_ms":1000,"temperature_c":26.00,"state":"NORMAL","error":"none"}
{"type":"sample","synthetic":true,"uptime_ms":5000,"temperature_c":null,"state":"FAULT","error":"nonfinite"}
{"type":"command","synthetic":true,"result":"accepted","threshold_c":30.00}
These four lines illustrate the schema; use the supplied executable/fixtures for authentic replay logs. Sample records always contain type, synthetic, uptime_ms, temperature_c, state, and error. State is NORMAL/ALERT/FAULT. Error is none/missing/nonfinite/stale/recovering. A recovering sample has a fresh numeric temperature but remains in FAULT. Missing, nonfinite and stale records contain null. Command result is accepted/malformed/too_long/out_of_range/truncated. Startup is the documented configuration before any event.
The fixture format is deliberately small: three comma-separated fields uptime_ms,event,value, without CSV quoting. Blank lines and # comments are ignored. CRLF and LF files work. Each non-comment row is at most 256 bytes; no NUL or additional comma is accepted. Supported events:
| Event | Value | Meaning |
|---|---|---|
| sample | finite number, missing, nan, or inf |
Supply a timestamped synthetic reading or failure |
| tick | empty | Advance the injected clock and check freshness |
| command | command bytes | Feed bytes followed by LF to the shared parser |
| truncated | command bytes | Feed bytes followed by EOF to the shared parser |
| reset | empty | Reset policy/configuration, then report missing input |
Timestamps are uint32 unsigned decimal. Equal timestamps and one rollover are supported; backward ordering or a gap >=2^31 ms is rejected. Fixture parse failure prints a line-number diagnostic to stderr and exits 2; prior valid output remains distinguishable. Successful execution exits 0 even when an intentional invalid sensor sample produces FAULT: that is expected policy behavior. Failed native assertions exit 1. Host command mode consumes stdin and terminates at EOF. Firmware serial framing has the same bounded parser but remains physically unverified.