pub struct LearningStore { /* private fields */ }Implementations§
Source§impl LearningStore
impl LearningStore
pub fn default_root() -> Result<PathBuf>
Sourcepub fn open(root: impl Into<PathBuf>) -> Result<Self>
pub fn open(root: impl Into<PathBuf>) -> Result<Self>
Open the store, creating the layout (and, best-effort, the git repo) if it is not there yet. Git being absent degrades to plain files — the audit trail is lost, the data is not.
Sourcepub fn open_existing_default() -> Option<Self>
pub fn open_existing_default() -> Option<Self>
Open at the default location only if it already exists — for read paths (prompt assembly) that must not create state as a side effect.
pub fn root(&self) -> &Path
pub fn append_reflexion(&self, r: &Reflexion) -> Result<()>
pub fn reflexions(&self) -> Result<Vec<Reflexion>>
Sourcepub fn mined_sessions(&self) -> Result<HashSet<String>>
pub fn mined_sessions(&self) -> Result<HashSet<String>>
Sessions already mined, so mecha reflect never re-reads one.
pub fn mark_mined(&self, session_id: &str) -> Result<()>
Sourcepub fn mined_outbox(&self) -> Result<HashSet<String>>
pub fn mined_outbox(&self) -> Result<HashSet<String>>
Outbox items already mined for writing reflections — the outbox
counterpart of Self::mined_sessions, so the nightly pass never
re-argues the same edit.
pub fn mark_outbox_mined(&self, item_id: &str) -> Result<()>
Sourcepub fn distilled_sessions(&self) -> Result<HashSet<String>>
pub fn distilled_sessions(&self) -> Result<HashSet<String>>
Sessions already distilled to the knowledge graph — mecha distill’s
ledger. Kept in this store, not beside the sessions, for the same
reasons the mining ledgers are: the writer lock covers the
read-then-mark race between two detached session_end hooks, and the
git history says when each push happened.
pub fn mark_distilled(&self, session_id: &str) -> Result<()>
Sourcepub fn user_rules(&self, domain: &str) -> Result<Vec<Rule>>
pub fn user_rules(&self, domain: &str) -> Result<Vec<Rule>>
The user’s own rules. This file is never written by any pass — the immutability constraint from flowmail’s consolidation prompt, made structural.
pub fn learned_rules(&self, domain: &str) -> Result<Vec<Rule>>
Sourcepub fn write_learned_rules(&self, domain: &str, rules: &[Rule]) -> Result<()>
pub fn write_learned_rules(&self, domain: &str, rules: &[Rule]) -> Result<()>
Replace a domain’s learned rules. Only consolidation calls this. Written via a temp sibling and rename: the run-start injection path reads this file with no lock (a read must never wait on a learn pass), so the file on disk has to be complete at every instant — a torn TOML here would fail an unrelated run at startup.
Sourcepub fn rules_prompt_block(&self) -> Result<Option<String>>
pub fn rules_prompt_block(&self) -> Result<Option<String>>
The block injected into the system prompt: the user’s rules first, then
enabled learned rules, per domain. None when there is nothing to say
— an empty section would spend cache-prefix tokens on a heading.
Sourcepub fn over_budget_domains(&self) -> Result<Vec<(String, usize)>>
pub fn over_budget_domains(&self) -> Result<Vec<(String, usize)>>
Domains whose active learned rules exceed
MAX_ACTIVE_RULES_PER_DOMAIN — the always-loaded block drifting
past the adherence cliff. Startup warns on these (the routed-name
precedent); the learn gate refuses to grow them further.
Sourcepub fn lock(&self) -> Result<StoreLock>
pub fn lock(&self) -> Result<StoreLock>
Take the store’s writer lock, blocking until it is free.
Every pass that writes (reflect, learn) takes this before reading
the state it will act on — the read is where the race lives: two
reflects that both read mined_sessions before either marks would
mine the same session twice, which stopped being hypothetical the
moment reflect started running detached at every session close.
Advisory flock, so it serializes mecha’s own writers without doing
anything to the user’s $EDITOR — the store’s files staying humanly
editable is a requirement, not an accident. The kernel drops the lock
when the fd closes, crash included, so a dead pass can never wedge
the store. Read paths (prompt assembly, validate) do not take it:
a run start must never block on a learn pass, which is why every
rewrite in this module goes through a temp sibling and rename.
Source§impl LearningStore
impl LearningStore
Sourcepub fn write_proposal(&self, p: &Proposal) -> Result<()>
pub fn write_proposal(&self, p: &Proposal) -> Result<()>
Write (or rewrite) one proposal, atomically — mecha proposals list
must never read a half-written file from a nightly pass.
Sourcepub fn proposal(&self, id: &str) -> Result<Proposal>
pub fn proposal(&self, id: &str) -> Result<Proposal>
Find one proposal by id or unique prefix. Ambiguity is an error rather than a guess, same as session lookup.