Skip to main content

Store

Struct Store 

Source
pub struct Store {
    pub root: PathBuf,
    pub config: Config,
}
Expand description

An opened db.md store: its root path plus the parsed DB.md Config.

Construct via Store::open; that is the only path in, and it validates the DB.md marker so downstream code can assume a real store.

Fields§

§root: PathBuf

The store root (the directory containing DB.md).

§config: Config

The parsed DB.md config (agent instructions, policies, schemas).

Implementations§

Source§

impl Store

Source

pub fn is_db_md_store(path: &Path) -> bool

True if path is a db.md store root: an uppercase DB.md file exists at path. On case-sensitive filesystems a lowercase db.md must NOT count (the lowercase name refers to the project/spec, not the marker).

Source

pub fn open(path: &Path) -> Result<Store, NotAStore>

Open path as a db.md store: confirm the DB.md marker (else NotAStore) and parse the DB.md config. Every store-walking subcommand opens through here.

Source

pub fn walk(&self) -> Result<Vec<PathBuf>, StoreError>

SWEEP. Recursively iterate every .md content file across sources/, records/, and wiki/, skipping hidden dirs and log/. Used only by validate --all, index rebuild, and stats — never on the interactive loop.

Source

pub fn walk_layer(&self, layer: Layer) -> Result<Vec<PathBuf>, StoreError>

SWEEP. Like Store::walk but scoped to a single layer.

Source

pub fn walk_type_folder( &self, type_folder: &Path, ) -> Result<Vec<PathBuf>, StoreError>

Enumerate every .md file in a single type-folder, recursing through its date-shards (sources/emails/**/*.md). The unit the index builder and per-folder rebuild operate on. SWEEP-class (scoped to one folder).

Source

pub fn recent_in_type_folder( &self, type_folder: &Path, n: usize, ) -> Result<Vec<PathBuf>, StoreError>

The ≤n most-recent files in a type-folder by frontmatter updated (descending), ties broken by store-relative path (ascending) — a total order, so write-through and rebuild never disagree on #500 vs #501.

Reads updated across the folder’s shards — a SWEEP cost absorbed into index rebuild. The write-through path never calls this. The cap-selection primitive for the 500-entry index.md browse view.

Source

pub fn type_shards(&self, type_: &str) -> bool

The shard/flat predicate: true if the type date-shards, false if it stays flat. True for source types and event record types (expense/invoice/meeting + custom order/ticket/transaction), or when DB.md ## Schemas declares shard: by-date. False for dedup-bounded entity types (contact/company/decision) and wiki/.

Source

pub fn shard_path_for( &self, type_: &str, frontmatter: &Frontmatter, name: &str, ) -> Result<PathBuf, StoreError>

Compute the canonical write path for a new file. For a sharding type (per Store::type_shards) insert <YYYY>/<MM>/ from the type’s primary date field (email.date, expense.date, … fallback created) under the type folder; flat types and wiki/ get no shard segment. Deterministic + stable: same input → same path, so a record never moves once written.

Source

pub fn shard_path_in( &self, folder: &Path, type_: &str, frontmatter: &Frontmatter, name: &str, ) -> Result<PathBuf, StoreError>

Like Store::shard_path_for, but compute the path under an explicit, caller-resolved type-folder rather than the canonical default. This lets a write surface honour an agent-supplied conforming sub-folder — e.g. wiki/projects/, wiki/people/, wiki/synthesis/ (the SPEC files a wiki-page under wiki/<topic>/, i.e. ANY topic sub-folder, not only the wiki/topics default) — while still applying date-sharding for sharding types. The folder must be a conforming <layer>/<type-folder> (2 components, recognized layer); the caller is responsible for that (see the CLI’s resolve_write_path), so it is taken as given here.

Sharding is still a property of the type: a sharding type gets the <YYYY>/<MM> segment under folder; a flat type lands directly in it.

Find files with an incoming wiki-link to target, via embedded ripgrep for [[target]] across all layers. Loop-fast; no whole-graph build. Returns store-relative paths.

Find every file with an incoming wiki-link to any of targets, in a single embedded-ripgrep pass over the store (one .md walk, one presence-only scan per file). This is the batch incoming-linker finder the working-set crate::validate::validate_working_set sits on: it must find the linkers for the whole changed set without paying a full store read per changed object. Cost is therefore one store scan (O(store)), NOT targets.len() × store — calling find_links_to in a loop would reread every .md once per target and is the exact O(changed × store) blow-up this method exists to prevent. Returns store-relative paths (deduped, sorted).

Why content scan and not the sidecar links field: the sidecar projects only the frontmatter links: array, so it misses edges written in the body or in typed fields (company: [[…]]). Finding an incoming link to an arbitrary path therefore requires reading file content — the same reason the single-target finder uses ripgrep.

Source

pub fn find_by_type(&self, type_: &str) -> Result<Vec<IndexRecord>, StoreError>

Candidate set for a type query: read the relevant type-folder index.jsonl sidecar(s) and return their records. Complete and cold-cache-proof — NOT a walk-and-parse or a frontmatter ripgrep scan, and never a store-wide read. The common path is one sequential read of the canonical type-folder sidecar (O(entities)); when that sidecar is absent the read is bounded to the type’s single layer subtree (O(entities-in-layer)), so a --type proposal query before that folder has been indexed still stays inside the interactive loop’s O(entities) contract instead of fanning out across every sidecar in the store.

Source

pub fn find_by_where( &self, key: &str, value: &str, ) -> Result<Vec<IndexRecord>, StoreError>

Candidate set for a key=value frontmatter query, store-wide: read every type-folder index.jsonl sidecar and filter their records. The unscoped pre-write dedup primitive; prefer Store::find_by_where_in with a layer scope to stay O(entities-in-layer) on the interactive loop.

Source

pub fn find_by_where_in( &self, key: &str, value: &str, layer: Option<Layer>, ) -> Result<Vec<IndexRecord>, StoreError>

Candidate set for a key=value frontmatter query, scoped to one layer when layer is Some: the sidecar walk is confined to that layer’s subtree (<root>/<layer>/), so the I/O is O(entities-in-layer), not O(store records). None keeps the store-wide read.

This is what makes --in <layer> an I/O scope, not just a result filter: a --where-only query (no --type) used to read every sidecar in the store and narrow by layer in memory, breaking the O(entities) contract the interactive loop depends on. With a layer in hand we walk only that layer’s sidecars.

Source

pub fn sidecar_records( &self, layer: Option<Layer>, ) -> Result<Vec<IndexRecord>, StoreError>

Every record across the type-folder index.jsonl sidecars, scoped to one layer when layer is Some (the walk is confined to <root>/<layer>/) else store-wide. Sequential, complete sidecar reads — never a walk-and-parse of the content tree.

This is the unfiltered sidecar-enumeration primitive the relationship loop sits on: crate::graph::backlinks_filtered uses it to bound its candidate set to the relevant layer (or the whole store) without opening the content tree, then confirms each candidate’s edge by parsing the file.

Source

pub fn read_type_index( &self, index_jsonl: &Path, ) -> Result<Vec<IndexRecord>, StoreError>

Parse a type-folder’s index.jsonl into IndexRecords, applying last-write-wins by path over any un-compacted lines. The sidecar-read primitive every structured query sits on.

Source

pub fn abs_path(&self, store_relative: &Path) -> PathBuf

Resolve a store-relative path to its absolute on-disk path under root.

Source

pub fn rel_path(&self, abs: &Path) -> Option<PathBuf>

Convert an absolute path under the store into its store-relative form.

Trait Implementations§

Source§

impl Clone for Store

Source§

fn clone(&self) -> Store

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 Store

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Store

§

impl RefUnwindSafe for Store

§

impl Send for Store

§

impl Sync for Store

§

impl Unpin for Store

§

impl UnsafeUnpin for Store

§

impl UnwindSafe for Store

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> 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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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 = Infallible

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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,