This commit adds the read path (Cortex) to complement the write path (Spine): ## Crates - stemedb-api: HTTP API with axum + utoipa OpenAPI - /v1/assert, /v1/query, /v1/epoch, /v1/skeptic, /v1/trace, /v1/audit - Metered endpoints with quota enforcement - Ed25519 signature verification - stemedb-lens: Truth resolution lenses - RecencyLens, ConsensusLens, ConfidenceLens - VoteAwareConsensusLens (Ballot Box pattern) - TrustAwareAuthorityLens (The Hive pattern) - SkepticLens (conflict analysis) - EpochAwareLens (paradigm-safe queries) - stemedb-query: Query engine with materialized views ## Storage Extensions - VoteStore: Vote aggregation with cached counts - TrustRankStore: Agent reputation with decay - AuditStore: Query audit trail - IndexStore: SP/P/S index structures - SupersessionStore: Epoch supersession chains ## SDKs - sdk/go/steme: Go HTTP client with Ed25519 signing - sdk/go/adk: ADK-Go tools for AI agents ## Documentation - Updated CLAUDE.md, architecture.md, roadmap.md - New ai-lookup entries for all services - Use case docs for consumer health intelligence - Arena roadmap for simulation advancement Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2.8 KiB
2.8 KiB
Query Engine
Last Updated: 2026-02-01
Confidence: High
Status: Implemented in stemedb-query v0.1.0
Summary
The Query Engine provides lifecycle-aware filtering for reading assertions from the knowledge graph.
Key Facts:
- Filters by subject, predicate, lifecycle, epoch
- Fast path: checks
MV:{subject}:{predicate}for pre-computed winner (O(1)) - MV staleness control:
max_staleparameter to reject stale materialized views - Compound index:
SP:{subject}:{predicate}for subject+predicate lookups (O(1)) - Subject index:
S:{subject}for subject-only lookups (O(1)) - Falls back to full scan when no index available
File Pointers:
crates/stemedb-query/src/engine.rs- QueryEngine with fast-path and staleness checkcrates/stemedb-query/src/query.rs- Query and QueryResult types
Query Structure
pub struct Query {
pub subject: Option<String>,
pub predicate: Option<String>,
pub lifecycle: Option<LifecycleStage>,
pub epoch: Option<EpochId>,
pub limit: Option<usize>,
pub max_stale: Option<u64>, // Maximum MV age in seconds
}
Usage
let query = Query::builder()
.subject("Tesla")
.predicate("revenue")
.lifecycle(LifecycleStage::Approved)
.max_stale(300) // Only use MVs < 5 minutes old
.limit(10)
.build();
let result = engine.execute(&query).await?;
MV Staleness Control
The max_stale parameter controls whether the fast path (materialized view) is used:
max_stale |
Behavior |
|---|---|
None (default) |
Accept any MV age (backward compatible) |
Some(0) |
Only accept brand-new MVs (age = 0 seconds) |
Some(60) |
Only use MV if materialized within last 60 seconds |
Some(300) |
Only use MV if materialized within last 5 minutes |
When the MV is stale, the query falls through to the slow path (SP index lookup + lens resolution).
Use cases:
- Real-time dashboards:
max_stale(60)for fresh data - Audit investigations:
max_stale(0)to ensure current state - Batch processing:
Nonefor maximum performance
Query Execution Strategy
- Fast path (subject + predicate):
MV:{subject}:{predicate}→MaterializedView.winner(O(1))- Skips if MV doesn't exist
- Skips if MV is too stale (
max_stalecheck) - Skips if winner doesn't match filters (lifecycle, epoch)
- Compound index (subject + predicate):
SP:{subject}:{predicate}→ hashes (O(1)) - Subject index (subject only):
S:{subject}→ hashes (O(1)) - Full scan (no subject): Scan
H:prefix (O(n)) - Filter: Apply lifecycle/epoch filters on candidates
- Limit: Truncate if limit specified
Related Topics
- Materializer - Produces the MV: keys used by fast path
- Assertion
- Lifecycle Stages
- Lens Resolution