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>
90 lines
3.1 KiB
Markdown
90 lines
3.1 KiB
Markdown
---
|
|
name: stemedb-lens
|
|
description: Guidelines for implementing Lenses (Resolution Logic). Use when working on query resolution or ranking.
|
|
---
|
|
|
|
# StemeDB Lens Implementation
|
|
|
|
## Identity
|
|
|
|
You are building the **Cortex** of Episteme. Lenses allow us to view a contradictory reality and get a deterministic answer.
|
|
|
|
## The Lens Traits
|
|
|
|
```rust
|
|
// Synchronous lens — for pure logic (Recency, Consensus, Authority)
|
|
pub trait Lens {
|
|
fn resolve(&self, candidates: &[Assertion]) -> Resolution;
|
|
fn name(&self) -> &'static str;
|
|
}
|
|
|
|
// Async lens — for I/O-backed resolution (VoteAwareConsensus, TrustAwareAuthority)
|
|
pub trait AsyncLens {
|
|
async fn resolve_async(&self, candidates: &[Assertion]) -> Resolution;
|
|
fn name(&self) -> &'static str;
|
|
}
|
|
```
|
|
|
|
## Current Implementations
|
|
|
|
| Lens | Trait | Strategy | File |
|
|
|------|-------|----------|------|
|
|
| RecencyLens | Lens | Highest timestamp wins | `recency.rs` |
|
|
| ConsensusLens | Lens | Most common object value wins | `consensus.rs` |
|
|
| ConfidenceLens | Lens | Highest confidence field wins | `confidence.rs` |
|
|
| VoteAwareConsensusLens | AsyncLens | VoteStore vote counts | `vote_aware_consensus.rs` |
|
|
| TrustAwareAuthorityLens | AsyncLens | confidence * TrustRank | `trust_aware_authority.rs` |
|
|
|
|
**API Mapping:** In the API, `LensDto::Authority` and `LensDto::TrustAwareAuthority` both route to `TrustAwareAuthorityLens`. Use `LensDto::Confidence` to get the simple confidence-field selector.
|
|
|
|
## Principles
|
|
|
|
* **Stateless**: Sync lenses must be stateless (logic only).
|
|
* **Deterministic**: Same input + Same context = Same output.
|
|
* **Fast**: This runs on every read. Avoid allocations.
|
|
* **Instrumented**: Every `resolve`/`resolve_async` impl MUST have `#[instrument]`.
|
|
|
|
## Tracing Pattern (Required)
|
|
|
|
Every lens resolve method must be instrumented:
|
|
|
|
```rust
|
|
use tracing::instrument;
|
|
|
|
impl Lens for MyLens {
|
|
#[instrument(skip(self, candidates), fields(candidates_count = candidates.len(), lens = "MyLens"))]
|
|
fn resolve(&self, candidates: &[Assertion]) -> Resolution {
|
|
// ...
|
|
}
|
|
}
|
|
```
|
|
|
|
## Common Strategies
|
|
|
|
### 1. Recency (LWW)
|
|
Sort by `timestamp` descending. Return first. Tiebreaker: `source_hash`.
|
|
|
|
### 2. Consensus (Voting)
|
|
Map `object` -> `count`. Return object with `max(count)`. From largest group, pick most recent.
|
|
|
|
### 3. Confidence
|
|
Return assertion with highest `confidence` field. Tiebreaker: most recent timestamp.
|
|
Uses the assertion's self-declared confidence, NOT agent reputation.
|
|
|
|
### 4. Vote-Aware Consensus (Phase 2+)
|
|
Query VoteStore for real vote counts per assertion. Tiebreaker: confidence then timestamp.
|
|
|
|
### 5. Trust-Aware Authority (Phase 2+)
|
|
weighted_score = confidence * TrustRank. Query TrustRankStore for agent reputation.
|
|
|
|
## Do
|
|
* Handle empty candidate sets gracefully (return `Resolution::empty()`).
|
|
* Implement `Default` for standard lenses.
|
|
* Document the ranking logic clearly.
|
|
* Add `#[instrument]` with `candidates_count` and `lens` fields.
|
|
* Use `Resolution::with_winner()` for consistent output.
|
|
|
|
## Do Not
|
|
* Perform I/O inside a sync `Lens` (use `AsyncLens` if DB lookups are needed).
|
|
* Use `unwrap()` or `expect()` — workspace lints deny these.
|