persistence: CarrierStore + LoadPortStore enable_persistence(dir)

Mirrors SpoolStore: per-record file with atomic .tmp+rename, magic+
version-prefixed binary layout, replay on enable, delete on remove.
FSMs gain a restore_state() that bypasses the transition table and
handlers since a replay isn't a transition.

Six new tests cover write+restart+replay across every CIDS/CSMS/CAS
axis, remove-deletes-journal, malformed-record drop-not-poison, and
the persistence-disabled no-op path.

Closes #1 in the test-gap backlog.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 10:25:50 +02:00
parent 29f646c7ca
commit f56639ba17
5 changed files with 571 additions and 43 deletions
+11
View File
@@ -144,6 +144,17 @@ class CarrierStateMachine {
bool on_slot_map_event(SlotMapEvent e);
bool on_access_event(CarrierAccessEvent e);
// Direct state-restore (persistence replay only). Bypasses the
// transition tables and does NOT fire change handlers — a restored
// state isn't a transition, it's a checkpoint. Callers must ensure
// the (id, sm, acc) triple was a legal state at write time.
void restore_state(CarrierIDStatus id, SlotMapStatus sm,
CarrierAccessStatus acc) {
id_state_ = id;
sm_state_ = sm;
acc_state_ = acc;
}
private:
CarrierIDTable id_table_;
SlotMapTable sm_table_;