4ae2297a35
Adds the incremental write path the tap-subscriber cycle streams record subscriptions through: TraceStore::begin_run opens a run directory and returns a TraceStreamer; per tap, TapTraceWriter appends (ts, cell) points into two temp column streams and finish() assembles the canonical ColumnarTrace JSON by streaming concatenation (io::copy), removing the temps. index.json is written last by TraceStreamer::finish, preserving the store's crash discipline (no index -> NotFound, treat-as-absent). Compatibility is pinned as an equality property, not a frozen byte assumption: a new test asserts the streamed output byte-identical to TraceStore::write's for the same rows (including empty and bool columns), so the two write paths cannot drift and every reader (read, read_family, chart) stays untouched. TraceStore::write is refactored onto shared write_tap_file/write_index helpers used by both paths. Temp streams open read+write (OpenOptions), since finish() seeks back and re-reads them. Verification: cargo test -p aura-registry — 78 passed (3 new: byte-equality incl. empty+bool, crash shape NotFound, caller-order index). refs #283