feat(domain): live-state agent — modèle + port (LS1)

Domaine pur du live-state des agents : `LiveState`/`LiveEntry`/`WorkStatus`.
- Fusion en keyed last-writer-wins : une entrée par clé, la plus récente
  écrase l'ancienne (ordonnancement déterministe).
- Invariants de bornes anti-dump : bornes douces (troncature) + rejet dur
  au-delà des limites, pour empêcher un agent de noyer le live-state.
- `prune` pour borner la rétention.
- Port `LiveStateStore` (lecture/écriture), sans dépendance d'infra.

9 nouveaux tests live_state (cargo test -p domain : 208 passed / 0 failed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 19:03:19 +02:00
parent 827d4774cd
commit 9815af01b1
3 changed files with 370 additions and 4 deletions

View File

@ -816,6 +816,35 @@ pub trait SkillStore: Send + Sync {
) -> Result<(), StoreError>;
}
/// Persistence for the agent **live-state** snapshot (programme live-state).
///
/// Mirrors the other stores ([`SkillStore`], [`MemoryStore`]): a driven port the
/// infrastructure implements. The contract is **keyed last-writer-wins**, never
/// append — [`upsert`](LiveStateStore::upsert) replaces the row for an agent and
/// [`prune`](LiveStateStore::prune) applies the TTL + cardinality bound, matching
/// [`LiveState`](crate::live_state::LiveState)'s pure semantics.
#[async_trait]
pub trait LiveStateStore: Send + Sync {
/// Loads the current live-state snapshot.
///
/// # Errors
/// [`StoreError`] on failure.
async fn load(&self) -> Result<crate::live_state::LiveState, StoreError>;
/// Inserts or replaces (keyed by `agent_id`) a single live-state row.
///
/// # Errors
/// [`StoreError`] on failure.
async fn upsert(&self, entry: crate::live_state::LiveEntry) -> Result<(), StoreError>;
/// Drops rows older than `ttl_ms` relative to `now_ms`, then bounds the set
/// to `max_n`, keeping the most recently updated rows.
///
/// # Errors
/// [`StoreError`] on failure.
async fn prune(&self, now_ms: u64, ttl_ms: u64, max_n: usize) -> Result<(), StoreError>;
}
/// CRUD for project [`Memory`] notes — the `.md` knowledge base under
/// `.ideai/memory/` (LOT A, étage 1). Notes are the single source of truth; the
/// aggregated `MEMORY.md` index is derived and kept in sync on every write.