pub struct Ledger {
pub paths: EddaPaths,
/* private fields */
}Expand description
The append-only event ledger (SQLite backend).
Fields§
§paths: EddaPathsImplementations§
Source§impl Ledger
impl Ledger
Sourcepub fn open(repo_root: impl Into<PathBuf>) -> Result<Self>
pub fn open(repo_root: impl Into<PathBuf>) -> Result<Self>
Open an existing workspace. Fails if .edda/ does not exist.
Sourcepub fn open_or_init(repo_root: impl Into<PathBuf>) -> Result<Self>
pub fn open_or_init(repo_root: impl Into<PathBuf>) -> Result<Self>
Open a workspace, auto-initializing .edda/ if missing.
Use this for read-path consumers (e.g. edda watch) that should
work without requiring the user to run edda init first.
This is a lightweight init — it only creates the ledger directory
layout and SQLite DB. Config files (policy.yaml, actors.yaml) and
bridge hooks are NOT created; those require edda init.
Sourcepub fn ensure_initialized(repo_root: impl Into<PathBuf>) -> Result<()>
pub fn ensure_initialized(repo_root: impl Into<PathBuf>) -> Result<()>
Ensure .edda/ and ledger exist, without returning a Ledger handle.
Use this when you only need the side effect (workspace creation) and will open the ledger separately later.
Sourcepub fn open_path(repo_root: &Path) -> Result<Self>
pub fn open_path(repo_root: &Path) -> Result<Self>
Convenience: open from a Path ref (avoids Into
Sourcepub fn head_branch(&self) -> Result<String>
pub fn head_branch(&self) -> Result<String>
Read the current HEAD branch name.
Sourcepub fn set_head_branch(&self, name: &str) -> Result<()>
pub fn set_head_branch(&self, name: &str) -> Result<()>
Write the HEAD branch name.
Sourcepub fn append_event(&self, event: &Event) -> Result<()>
pub fn append_event(&self, event: &Event) -> Result<()>
Append an event to the ledger. Append-only (CONTRACT LEDGER-02).
Sourcepub fn append_event_idempotent(&self, event: &Event) -> Result<bool>
pub fn append_event_idempotent(&self, event: &Event) -> Result<bool>
Append an event idempotently. Returns true if inserted, false if duplicate.
Sourcepub fn last_event_hash(&self) -> Result<Option<String>>
pub fn last_event_hash(&self) -> Result<Option<String>>
Get the hash of the last event, or None if the ledger is empty.
Sourcepub fn iter_events(&self) -> Result<Vec<Event>>
pub fn iter_events(&self) -> Result<Vec<Event>>
Read all events in the ledger.
Sourcepub fn get_event(&self, event_id: &str) -> Result<Option<Event>>
pub fn get_event(&self, event_id: &str) -> Result<Option<Event>>
Get a single event by event_id.
Sourcepub fn iter_events_by_type(&self, event_type: &str) -> Result<Vec<Event>>
pub fn iter_events_by_type(&self, event_type: &str) -> Result<Vec<Event>>
Get all events of a given type, filtered at the SQL level.
Sourcepub fn iter_branch_events(&self, branch: &str) -> Result<Vec<Event>>
pub fn iter_branch_events(&self, branch: &str) -> Result<Vec<Event>>
Get all events for a specific branch, filtered at the SQL level.
Sourcepub fn iter_events_filtered(
&self,
branch: &str,
event_type: Option<&str>,
keyword: Option<&str>,
after: Option<&str>,
before: Option<&str>,
limit: usize,
) -> Result<Vec<Event>>
pub fn iter_events_filtered( &self, branch: &str, event_type: Option<&str>, keyword: Option<&str>, after: Option<&str>, before: Option<&str>, limit: usize, ) -> Result<Vec<Event>>
Get events filtered by branch with optional type/keyword/date/limit,
all pushed down to SQL. Returns newest-first, capped at limit.
Find commit events related to a query by evidence chain or keyword match.
Find note events matching a keyword, excluding decisions and session digests.
Sourcepub fn events_after_rowid(&self, after_rowid: i64) -> Result<Vec<(i64, Event)>>
pub fn events_after_rowid(&self, after_rowid: i64) -> Result<Vec<(i64, Event)>>
Get all events with rowid strictly greater than after_rowid.
Returns (rowid, Event) pairs ordered by rowid, useful for cursor-based
polling (e.g. SSE streaming).
Sourcepub fn rowid_for_event_id(&self, event_id: &str) -> Result<Option<i64>>
pub fn rowid_for_event_id(&self, event_id: &str) -> Result<Option<i64>>
Look up the rowid for a given event_id.
Sourcepub fn branches_json(&self) -> Result<Value>
pub fn branches_json(&self) -> Result<Value>
Read branches.json content.
Sourcepub fn set_branches_json(&self, value: &Value) -> Result<()>
pub fn set_branches_json(&self, value: &Value) -> Result<()>
Write branches.json content.
Sourcepub fn active_decisions(
&self,
domain: Option<&str>,
key_pattern: Option<&str>,
after: Option<&str>,
before: Option<&str>,
) -> Result<Vec<DecisionView>>
pub fn active_decisions( &self, domain: Option<&str>, key_pattern: Option<&str>, after: Option<&str>, before: Option<&str>, ) -> Result<Vec<DecisionView>>
Query active decisions, optionally filtered by domain or key pattern.
after/before are optional ISO 8601 bounds for temporal filtering.
Sourcepub fn active_decisions_limited(
&self,
domain: Option<&str>,
key_pattern: Option<&str>,
after: Option<&str>,
before: Option<&str>,
limit: usize,
) -> Result<Vec<DecisionView>>
pub fn active_decisions_limited( &self, domain: Option<&str>, key_pattern: Option<&str>, after: Option<&str>, before: Option<&str>, limit: usize, ) -> Result<Vec<DecisionView>>
Query active decisions with limit for hot path optimization.
Sourcepub fn decision_timeline(
&self,
key: &str,
after: Option<&str>,
before: Option<&str>,
) -> Result<Vec<DecisionView>>
pub fn decision_timeline( &self, key: &str, after: Option<&str>, before: Option<&str>, ) -> Result<Vec<DecisionView>>
All decisions for a key (active + superseded), ordered by time.
after/before are optional ISO 8601 bounds for temporal filtering.
Sourcepub fn domain_timeline(
&self,
domain: &str,
after: Option<&str>,
before: Option<&str>,
) -> Result<Vec<DecisionView>>
pub fn domain_timeline( &self, domain: &str, after: Option<&str>, before: Option<&str>, ) -> Result<Vec<DecisionView>>
All decisions for a domain (active + superseded), ordered by time.
after/before are optional ISO 8601 bounds for temporal filtering.
Sourcepub fn list_domains(&self) -> Result<Vec<String>>
pub fn list_domains(&self) -> Result<Vec<String>>
Distinct domain values from active decisions.
Sourcepub fn village_stats(
&self,
village_id: &str,
after: Option<&str>,
before: Option<&str>,
) -> Result<VillageStats>
pub fn village_stats( &self, village_id: &str, after: Option<&str>, before: Option<&str>, ) -> Result<VillageStats>
Compute aggregate statistics for a village’s decisions.
Sourcepub fn detect_village_patterns(
&self,
village_id: &str,
after: &str,
min_occurrences: usize,
) -> Result<Vec<DetectedPattern>>
pub fn detect_village_patterns( &self, village_id: &str, after: &str, min_occurrences: usize, ) -> Result<Vec<DetectedPattern>>
Detect recurring patterns in a village’s decision history.
Sourcepub fn find_active_decision(
&self,
branch: &str,
key: &str,
) -> Result<Option<DecisionView>>
pub fn find_active_decision( &self, branch: &str, key: &str, ) -> Result<Option<DecisionView>>
Find the active decision for a specific key on a branch.
Sourcepub fn query_active_with_paths(
&self,
branch: Option<&str>,
limit: Option<usize>,
) -> Result<Vec<DecisionView>>
pub fn query_active_with_paths( &self, branch: Option<&str>, limit: Option<usize>, ) -> Result<Vec<DecisionView>>
Return active decisions that have non-empty affected_paths.
Used by Injection to get the candidate set for glob matching.
Sourcepub fn query_by_paths(
&self,
paths: &[&str],
branch: Option<&str>,
limit: Option<usize>,
) -> Result<Vec<DecisionView>>
pub fn query_by_paths( &self, paths: &[&str], branch: Option<&str>, limit: Option<usize>, ) -> Result<Vec<DecisionView>>
Given a list of file paths, return decisions whose affected_paths globs
match any of them. Uses globset for pattern matching.
This is the primary query for PreToolUse hook (Track E): “which active decisions govern the file I’m about to edit?”
§Arguments
paths: concrete file paths to check (e.g.,["crates/edda-ledger/src/lib.rs"])branch: optional branch filterlimit: max decisions to return
Query active decisions with shared or global scope.
Sourcepub fn is_already_imported(
&self,
source_project_id: &str,
source_event_id: &str,
) -> Result<bool>
pub fn is_already_imported( &self, source_project_id: &str, source_event_id: &str, ) -> Result<bool>
Check if a decision has already been imported from a source project.
Sourcepub fn insert_imported_decision(&self, params: ImportParams<'_>) -> Result<()>
pub fn insert_imported_decision(&self, params: ImportParams<'_>) -> Result<()>
Insert an imported decision from another project.
Sourcepub fn insert_dep(
&self,
source_key: &str,
target_key: &str,
dep_type: &str,
created_event: Option<&str>,
) -> Result<()>
pub fn insert_dep( &self, source_key: &str, target_key: &str, dep_type: &str, created_event: Option<&str>, ) -> Result<()>
Insert a dependency edge between two decision keys.
Sourcepub fn dependents_of(&self, key: &str) -> Result<Vec<DependencyEdge>>
pub fn dependents_of(&self, key: &str) -> Result<Vec<DependencyEdge>>
Who depends on key?
Sourcepub fn active_dependents_of(
&self,
key: &str,
) -> Result<Vec<(DependencyEdge, DecisionView)>>
pub fn active_dependents_of( &self, key: &str, ) -> Result<Vec<(DependencyEdge, DecisionView)>>
Who depends on key, joined with active decisions only.
Sourcepub fn decision_outcomes(
&self,
decision_event_id: &str,
) -> Result<Option<OutcomeMetrics>>
pub fn decision_outcomes( &self, decision_event_id: &str, ) -> Result<Option<OutcomeMetrics>>
Get aggregated outcome metrics for a decision.
Sourcepub fn executions_for_decision(
&self,
decision_event_id: &str,
) -> Result<Vec<ExecutionLinked>>
pub fn executions_for_decision( &self, decision_event_id: &str, ) -> Result<Vec<ExecutionLinked>>
Get all execution events linked to a decision via based_on provenance.
Sourcepub fn transitive_dependents_of(
&self,
key: &str,
max_depth: usize,
) -> Result<Vec<(DependencyEdge, DecisionView, usize)>>
pub fn transitive_dependents_of( &self, key: &str, max_depth: usize, ) -> Result<Vec<(DependencyEdge, DecisionView, usize)>>
Transitive dependents of key via BFS, up to max_depth hops.
Returns (DependencyEdge, DecisionView, depth) — only active decisions, deduplicated.
Sourcepub fn get_decision_by_event_id(
&self,
event_id: &str,
) -> Result<Option<DecisionView>>
pub fn get_decision_by_event_id( &self, event_id: &str, ) -> Result<Option<DecisionView>>
Look up a single decision by event_id.
Sourcepub fn causal_chain(
&self,
event_id: &str,
max_depth: usize,
) -> Result<Option<(DecisionView, Vec<ChainEntryView>)>>
pub fn causal_chain( &self, event_id: &str, max_depth: usize, ) -> Result<Option<(DecisionView, Vec<ChainEntryView>)>>
Traverse the causal chain from a root decision via unified BFS.
Sourcepub fn get_task_brief(&self, task_id: &str) -> Result<Option<TaskBriefRow>>
pub fn get_task_brief(&self, task_id: &str) -> Result<Option<TaskBriefRow>>
Get a task brief by task_id.
Sourcepub fn list_task_briefs(
&self,
status: Option<&str>,
intent: Option<&str>,
) -> Result<Vec<TaskBriefRow>>
pub fn list_task_briefs( &self, status: Option<&str>, intent: Option<&str>, ) -> Result<Vec<TaskBriefRow>>
List task briefs, optionally filtered by status and/or intent.
Sourcepub fn get_bundle(&self, bundle_id: &str) -> Result<Option<BundleRow>>
pub fn get_bundle(&self, bundle_id: &str) -> Result<Option<BundleRow>>
Get a review bundle by bundle_id.
Sourcepub fn list_bundles(&self, status: Option<&str>) -> Result<Vec<BundleRow>>
pub fn list_bundles(&self, status: Option<&str>) -> Result<Vec<BundleRow>>
List review bundles, optionally filtered by status.
Sourcepub fn insert_device_token(&self, row: &DeviceTokenRow) -> Result<()>
pub fn insert_device_token(&self, row: &DeviceTokenRow) -> Result<()>
Insert a new device token row.
Sourcepub fn validate_device_token(
&self,
token_hash: &str,
) -> Result<Option<DeviceTokenRow>>
pub fn validate_device_token( &self, token_hash: &str, ) -> Result<Option<DeviceTokenRow>>
Validate a device token by its SHA-256 hash. Returns the row if active.
Sourcepub fn list_device_tokens(&self) -> Result<Vec<DeviceTokenRow>>
pub fn list_device_tokens(&self) -> Result<Vec<DeviceTokenRow>>
List all device tokens (active and revoked).
Sourcepub fn revoke_device_token(
&self,
device_name: &str,
revoke_event_id: &str,
) -> Result<bool>
pub fn revoke_device_token( &self, device_name: &str, revoke_event_id: &str, ) -> Result<bool>
Revoke a device token by device name. Returns true if revoked.
Sourcepub fn revoke_all_device_tokens(&self, revoke_event_id: &str) -> Result<u64>
pub fn revoke_all_device_tokens(&self, revoke_event_id: &str) -> Result<u64>
Revoke all active device tokens. Returns count of revoked tokens.
Sourcepub fn insert_snapshot(&self, row: &DecideSnapshotRow) -> Result<()>
pub fn insert_snapshot(&self, row: &DecideSnapshotRow) -> Result<()>
Insert a row into the decide_snapshots materialized view.
Sourcepub fn query_snapshots(
&self,
village_id: Option<&str>,
engine_version: Option<&str>,
limit: usize,
) -> Result<Vec<DecideSnapshotRow>>
pub fn query_snapshots( &self, village_id: Option<&str>, engine_version: Option<&str>, limit: usize, ) -> Result<Vec<DecideSnapshotRow>>
Query snapshots with optional filtering by village_id and engine_version.
Sourcepub fn snapshots_by_context_hash(
&self,
context_hash: &str,
) -> Result<Vec<DecideSnapshotRow>>
pub fn snapshots_by_context_hash( &self, context_hash: &str, ) -> Result<Vec<DecideSnapshotRow>>
Find all snapshots for a given context_hash.
Sourcepub fn insert_suggestion(&self, row: &SuggestionRow) -> Result<()>
pub fn insert_suggestion(&self, row: &SuggestionRow) -> Result<()>
Insert a new suggestion row.
Sourcepub fn list_suggestions_by_status(
&self,
status: &str,
) -> Result<Vec<SuggestionRow>>
pub fn list_suggestions_by_status( &self, status: &str, ) -> Result<Vec<SuggestionRow>>
List suggestions filtered by status.
Sourcepub fn get_suggestion(&self, id: &str) -> Result<Option<SuggestionRow>>
pub fn get_suggestion(&self, id: &str) -> Result<Option<SuggestionRow>>
Get a single suggestion by id.