Skip to main content

MemConfig

Struct MemConfig 

Source
pub struct MemConfig {
Show 21 fields pub format: Option<u32>, pub name: Option<String>, pub version: Option<Version>, pub description: Option<String>, pub title: Option<String>, pub subject: Option<MemSubject>, pub authors: Option<Vec<String>>, pub process_mem: Option<String>, pub schema: Option<SchemaRef>, pub write_guidance: HashMap<String, Value>, pub rules: Option<Value>, pub publish: Option<PublishConfig>, pub language: Option<String>, pub read_mems: BTreeMap<String, ReadMemSpec>, pub community: Option<CommunityOverride>, pub vcs: Option<VcsConfig>, pub unregistered_at: Option<String>, pub sync_state: BTreeMap<String, String>, pub review_mark: Option<String>, pub mutation_stamp: Option<MutationStamp>, pub extra: HashMap<String, Value>,
}
Expand description

Full mem configuration loaded from .memstead/config.json.

Fields§

§format: Option<u32>

Workspace mem-config format version. Absent means version 1 — the healthy common case; real mems carry no key — and an unknown value REFUSES at parse, matching every sibling store (the binding record, WorkspaceConfig, the anchors sidecar). Until 2026-08-28 this field was not modeled at all, so serde silently dropped whatever value a config carried and "format": 99 verified clean. Distinct from PUBLISHED_MEM_FORMAT, the sealed-archive config’s own version line with its own gate. Read through Self::format_version.

§name: Option<String>

Optional mem name. The leaf folder name under __MEMSTEAD:mems/ (and the disk basename on the legacy disk path) is authoritative; engine-written configs omit this field. Tolerated on read for pre-cutover configs and for the PublishedMemConfig conversion path that still requires an explicit identity (the caller passes the name in when projecting).

§version: Option<Version>

Semver version of the mem content. Read at mem-archive export time so the engine always knows the current version without manual tracking. Parsed at config load — invalid version strings fail fast with a source-attributed serde error rather than slipping through to export (where the issue only surfaces when a downstream loader tries to resolve a semver::VersionReq against the mem).

§description: Option<String>

One-line description of the mem, surfaced in mem-archive metadata and UI.

§title: Option<String>

Human-readable display title. Display text, NOT identity: no slug grammar, no uniqueness rule — the mem name stays the sole handle everywhere (paths, grants, namespace patterns, cross-mem references, archive filenames). Surfaces that print a mem prefer this and fall back to the name. Published in PublishedMemConfig.

§subject: Option<MemSubject>

The mem’s subject — scope, method, deliberate exclusions. Published verbatim; clears as a unit.

§authors: Option<Vec<String>>

Optional author attribution, surfaced in mem-archive metadata.

§process_mem: Option<String>

Declared process-mem pairing (agent-trust plan 14): the name of the mem holding this mem’s process tier (verification targets, findings, inquiry entries). Declaration wins over the binding-name derivation the brief renderer and the open-questions health axis otherwise use; a declaration naming an unmounted mem surfaces as a typed health finding, never a silent fallback. Absent means “derive by convention” — the pre-declaration behaviour, unchanged.

§schema: Option<SchemaRef>

Schema this mem is pinned to. Exact <name>@<version> pin only — bare-name forms are rejected at config load. Exactly one schema per mem. The Option keeps serde tolerant so a missing key surfaces as a structured error from check_config rather than a deserialize panic; a None value is a validation error.

§write_guidance: HashMap<String, Value>

Opaque string-map passed through by the engine. Agents and plugin prompt renderers are free to invent their own keys; the engine does not parse, validate, or interpret any value inside. Stripped from PublishedMemConfig — guidance is workspace- local authorship metadata, not part of the published identity.

Pre-2026-04-24 this field was Option<Value>; the workspace rewrite normalised it to a map so the shape on the wire is stable and the engine’s pass-through guarantee is type-checked.

§rules: Option<Value>§publish: Option<PublishConfig>§language: Option<String>§read_mems: BTreeMap<String, ReadMemSpec>

Legacy since 2026-08. A read-only sealed-archive mem attaches to the WORKSPACE mount roster (.memstead/state/mounts.json), not to a host mem’s config. Nothing writes this field any more; it survives on the struct so the one-way boot migration (migrate_legacy_read_mems) can recognise a pre-cutover registration, turn it into a mount, and strip the key. An empty or omitted map is the healthy state.

Key is the mem name (matching the archive’s config name).

BTreeMap (not HashMap) so iteration and serialization order are stable — reproducible log output and diff-friendly config on disk. Explicit rename = "readMems" documents the on-disk name at the field (the struct-level rename_all = "camelCase" already handles it, but explicit rename is greppable from either side).

§community: Option<CommunityOverride>§vcs: Option<VcsConfig>

Optional VCS layout override. When absent, memstead-git-branch resolves the default at init time: .git/ at mem root with . as worktree. When present, gitdir and worktree are paths relative to the mem root. Stripped from PublishedMemConfig — VCS layout is workspace-local mechanics, not part of the published mem’s identity.

Deserialization is tolerant of legacy non-object values (e.g. "vcs": "system" — the sentinel an older macOS Mem-mode UI wrote): any non-object form deserializes to None and falls back to the default-resolution path. The object form is validated strictly.

§unregistered_at: Option<String>

Tombstone marker written by memstead mem unregister. ISO-8601 UTC timestamp (YYYY-MM-DDTHH:MM:SSZ) recorded at the moment the mem was unregistered while its storage was preserved. When memstead mem init <same-name> probes the storage and finds an unregistered_at value, it treats the residue as deliberate operator state and defaults to the Reattach recovery action (adopting the preserved entities and clearing the tombstone). Absence (None) on otherwise-present residue triggers MEM_STORAGE_RESIDUE_DETECTED unless the caller passes an explicit recovery flag. Stripped from PublishedMemConfig — tombstones are workspace-local lifecycle state, not part of the published mem’s identity.

§sync_state: BTreeMap<String, String>

Per-source “last successfully synced source state”, written by the ingest layer and surfaced verbatim on the workspace dump. The engine never parses, validates, or interprets a value: each token is opaque, its meaning owned by the medium-type layer that produced it (git → commit id, graph → snapshot token, filesystem → a small stat digest the plugin JSON-stringifies). The key is likewise opaque — the binding layer keys per (binding, facet) (conventionally "<binding-id>/<facet>#synced", D4), but the engine treats it as an arbitrary string. This is the durable, shared baseline against which a fresh ingest iteration diffs “what changed since last time”; it survives a skill-cache wipe and a machine change because it lives in engine-held mem config, not ephemeral plugin cache.

Stripped from PublishedMemConfig — sync state is workspace-local ingest bookkeeping, not part of a published mem’s identity. BTreeMap (not HashMap) for stable serialization order: diff-friendly config on disk and reproducible dump output.

§review_mark: Option<String>

The mem’s review mark: the last human-approved state, in the backend-opaque cursor vocabulary changes_since consumes (git-branch: commit SHA; folder: changelog RFC3339 timestamp). Absent is a first-class state — a mem with no mark is ordinary, never an error, and marks never gate writes. One mark per mem; wire key reviewMark (camelCase per the config’s convention).

Stripped from PublishedMemConfig (allowlist projection) — review state is workspace-collaboration bookkeeping, not part of a published mem’s identity.

§mutation_stamp: Option<MutationStamp>

Engine-owned version stamp of the last successful mutation: which engine version and which resolved schema performed it. Written by the engine after a mutation and only when the values changed (a binary upgrade or a schema repin), never by authors, never on read-only loads — a boot writes nothing. Boot compares the running binary against the stamp and surfaces a divergence as the warn-tier ENGINE_VERSION_SKEW hint; absence of a stamp is a first-class state (pre-stamp mems), never skew. The stamp is the substrate any future migration machinery would consult — deliberately built without that machinery.

Stripped from PublishedMemConfig (allowlist projection) — workspace-local engine bookkeeping, not published identity. Wire key mutationStamp (camelCase per the config convention).

§extra: HashMap<String, Value>

Extra fields not in the known set (captured for round-tripping).

Historical tombstones:

  • defaultSchema (pre-2026-04): legacy per-mem default type. Per-entity type: frontmatter is authoritative now.
  • types: [...] (pre-schema-artifact, 2026-04): replaced by schema: "<name>@<version>". Legacy entries are hard-rejected by check_config.

Implementations§

Source§

impl MemConfig

Source

pub fn format_version(&self) -> u32

The effective config format version: the declared value, or MEM_CONFIG_FORMAT when the key is absent.

Trait Implementations§

Source§

impl Clone for MemConfig

Source§

fn clone(&self) -> MemConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MemConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for MemConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for MemConfig

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.