--- # Authoritative formal design for realtime machine M4: conversation compaction. # # Companion to: # - docs/design/realtime-state-machines.md (the map + invariants) # - core/http/endpoints/openai/compactcoord (the Go implementation) # # The Go MBT adapter maps each action below onto compactcoord.Coordinator.Apply # and the StateGetter onto compactcoord.Coordinator.State, so this spec is the # source of truth the implementation is checked against. # # The property: at most one background compaction runs per conversation at a time, # so two goroutines never summarize+evict the same overflow concurrently (Part 4, # invariant #9). The legacy guard is a `compacting atomic.Bool` CAS; here `active` # is the number of in-flight compactions, started only from Idle. # # NOTE: FizzBee is pre-1.0. Validate the exact syntax/CLI against the version # pinned in formal-verification/README.md before trusting the gate. deadlock_detection: false --- role Compactor: action Init: self.active = 0 # compactions in flight -- MUST stay in {0,1} self.torn = 0 # session torn down (Terminated) -- absorbing # maybeCompact wants to start a compaction. THE FIX: it starts one only when # none is running (single-flight) and not after teardown. To reproduce the # legacy race where two goroutines could both compact the same overflow, # delete the `self.active == 0` guard (always increment): the checker then # reports SingleFlight violated. atomic action Trigger: if self.active == 0 and self.torn == 0: self.active += 1 # StartCompaction # The background compaction goroutine finished (success, error, or timeout). atomic action Finished: if self.active > 0: self.active -= 1 # Teardown: the connection (M1) parent cancels + joins the in-flight # compaction, then terminates the coordinator so none can start afterwards. atomic action Shutdown: self.active = 0 # cancelled + joined self.torn = 1 action Init: c = Compactor() # SAFETY: at most one compaction is ever in flight (Part 4, invariant #9). always assertion SingleFlight: return c.active >= 0 and c.active <= 1 # SAFETY: no compaction is in flight once torn (it was cancelled + joined at # teardown), so none outlives the session. always assertion NoneAfterTeardown: return c.torn == 0 or c.active == 0