made_core/ports/memory_reader.rs
1use async_trait::async_trait;
2
3use crate::error::DomainError;
4use crate::ports::MemoryRecollection;
5use crate::value_objects::{MemoryCapabilities, MemoryEntryId, MemoryMoment, MemoryScope};
6
7/// Reading what earlier sessions learned, and why.
8///
9/// Three ways of reading, because three different questions get asked:
10/// what is known about this at all, what was known at a moment, and how
11/// one thing here came from another. The second is not the first
12/// filtered by date — it excludes what was learned later about earlier
13/// events, which is the whole point of asking it.
14///
15/// Every method here has a consumer: `recall` is what a session reads
16/// when it starts, and the other two are what the conformance suite
17/// states as the contract (ADR-013). A method with neither is a shape
18/// answering to the backend it was drawn from, which is why the one
19/// that had neither is gone.
20#[async_trait]
21pub trait MemoryReaderPort: Send + Sync {
22 /// Everything memory holds about `scope`.
23 async fn recall(&self, scope: &MemoryScope) -> Result<MemoryRecollection, DomainError>;
24
25 /// What was known about `scope` at `moment`.
26 async fn as_known_at(
27 &self,
28 scope: &MemoryScope,
29 moment: MemoryMoment,
30 ) -> Result<MemoryRecollection, DomainError>;
31
32 /// The chain of reasons leading from `from` back to `to`.
33 ///
34 /// The question the whole contract exists to answer, and the only
35 /// one whose failure means the memory has stopped being worth
36 /// keeping: everything else can be reconstructed by reading, and
37 /// this cannot.
38 ///
39 /// It answers with the reasons and not with the prose — the edges
40 /// on the path, in the order they connect. What each end says is
41 /// what `recall` is for, and a backend that padded the chain with
42 /// text would make two contracts out of one.
43 ///
44 /// An empty chain is a real answer: the two are not connected by
45 /// anything anyone wrote down.
46 async fn follow(
47 &self,
48 scope: &MemoryScope,
49 from: &MemoryEntryId,
50 to: &MemoryEntryId,
51 ) -> Result<MemoryRecollection, DomainError>;
52
53 fn capabilities(&self) -> MemoryCapabilities;
54}