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>
250 lines
6.8 KiB
YAML
250 lines
6.8 KiB
YAML
meta:
|
|
id: agile-agent-team
|
|
title: "Agile AI Agent Team"
|
|
subtitle: "Knowledge Coordination with Episteme"
|
|
version: "4.0.0"
|
|
|
|
actors: {}
|
|
|
|
slides:
|
|
# ============================================
|
|
# TITLE
|
|
# ============================================
|
|
- type: title
|
|
id: title
|
|
|
|
# ============================================
|
|
# HOOK
|
|
# ============================================
|
|
- type: hook
|
|
id: hook
|
|
line: "Your agents have amnesia."
|
|
subline: "Every correction you make is forgotten by the next session."
|
|
|
|
# ============================================
|
|
# THE DRIFT - Pattern 1: Logging
|
|
# ============================================
|
|
- type: code
|
|
id: drift-logging
|
|
title: "Day 1: You correct the agent"
|
|
code: |
|
|
// Agent used console.log
|
|
// You: "We use winston, not console.log"
|
|
|
|
import { logger } from './logger';
|
|
|
|
logger.info('User authenticated', { userId });
|
|
|
|
- type: code
|
|
id: drift-logging-2
|
|
title: "Day 30: New session"
|
|
code: |
|
|
// Agent writes new code...
|
|
|
|
console.log('User authenticated');
|
|
console.log('userId:', userId);
|
|
|
|
// The correction from Day 1? Gone.
|
|
|
|
# ============================================
|
|
# THE DRIFT - Pattern 2: HTTP Client
|
|
# ============================================
|
|
- type: code
|
|
id: drift-http
|
|
title: "Day 45: You correct again"
|
|
code: |
|
|
// Agent used axios
|
|
// You: "We standardized on fetch"
|
|
|
|
const response = await fetch('/api/users', {
|
|
headers: { 'Authorization': `Bearer ${token}` }
|
|
});
|
|
|
|
- type: code
|
|
id: drift-http-2
|
|
title: "Day 60: Another new session"
|
|
code: |
|
|
// Agent writes new code...
|
|
|
|
import axios from 'axios';
|
|
|
|
const response = await axios.get('/api/users', {
|
|
headers: { 'Authorization': `Bearer ${token}` }
|
|
});
|
|
|
|
// Forgot again. Different session, different choices.
|
|
|
|
# ============================================
|
|
# THE SPIRAL
|
|
# ============================================
|
|
- type: code
|
|
id: spiral
|
|
title: "6 months later: 10 ways to do 1 thing"
|
|
code: |
|
|
// Logging
|
|
console.log() // 47 files
|
|
winston.info() // 23 files
|
|
pino.info() // 12 files
|
|
debug() // 8 files
|
|
|
|
// HTTP
|
|
fetch() // 31 files
|
|
axios.get() // 28 files
|
|
got() // 6 files
|
|
|
|
// Auth
|
|
RS256 // 4 services
|
|
ES256 // 3 services
|
|
HS256 // 2 services (why??)
|
|
|
|
- type: hook
|
|
id: spiral-question
|
|
line: "Which one is correct?"
|
|
subline: "Nobody knows. The decision was never recorded."
|
|
|
|
# ============================================
|
|
# THE CATASTROPHE
|
|
# ============================================
|
|
- type: code
|
|
id: catastrophe
|
|
title: "The Catastrophe"
|
|
code: |
|
|
// Auth service A expects RS256
|
|
// Auth service B was deployed with ES256
|
|
// An agent queried "what's our JWT algorithm?"
|
|
// Got the most recent answer: ES256 (from an RFC proposal)
|
|
|
|
HTTP 401 Unauthorized
|
|
{
|
|
error: "invalid_signature",
|
|
expected: "RS256",
|
|
received: "ES256"
|
|
}
|
|
|
|
// 3:00 AM. Pager fires. 47-minute outage.
|
|
|
|
- type: code
|
|
id: catastrophe-why
|
|
title: "The Root Cause"
|
|
code: |
|
|
// The RFC was stored without lifecycle state
|
|
// The query returned the most recent entry
|
|
// No way to distinguish "proposed" from "approved"
|
|
// The agent treated an idea as truth
|
|
|
|
// And now you have to audit 9 services
|
|
// to figure out which JWT algorithm is actually correct.
|
|
|
|
# ============================================
|
|
# THE FIX - Episteme
|
|
# ============================================
|
|
- type: hook
|
|
id: fix-intro
|
|
line: "What if corrections persisted?"
|
|
subline: "Across sessions. Across agents. Forever."
|
|
|
|
- type: code
|
|
id: fix-store
|
|
title: "Store decisions with context"
|
|
code: |
|
|
episteme.assert({
|
|
subject: "project/logging",
|
|
predicate: "library",
|
|
value: "winston",
|
|
|
|
lifecycle: "approved", // not proposed, not deprecated
|
|
confidence: 1.0, // this is a decision, not a guess
|
|
source: "adr-0012" // traceable to a decision record
|
|
});
|
|
|
|
- type: code
|
|
id: fix-query
|
|
title: "Query with lifecycle filter"
|
|
code: |
|
|
// Before writing code, agent checks constraints
|
|
|
|
const constraints = await episteme.query({
|
|
subject: "project/logging",
|
|
lifecycle: "approved"
|
|
});
|
|
|
|
// Returns: { library: "winston", confidence: 1.0 }
|
|
|
|
// Agent uses winston. Every time. Every session.
|
|
|
|
- type: code
|
|
id: fix-diff
|
|
title: "The difference"
|
|
code: |
|
|
// Without Episteme:
|
|
query({ subject: "auth/jwt", predicate: "algorithm" })
|
|
// Returns: ES256 (most recent entry - a proposal)
|
|
|
|
// With Episteme:
|
|
query({ subject: "auth/jwt", predicate: "algorithm", lifecycle: "approved" })
|
|
// Returns: RS256 (the actual decision)
|
|
|
|
# ============================================
|
|
# TIME TRAVEL
|
|
# ============================================
|
|
- type: code
|
|
id: time-travel
|
|
title: "Debug what you believed, not what you know now"
|
|
code: |
|
|
// Post-incident: what did we believe at 9pm?
|
|
|
|
episteme.query({
|
|
subject: "auth/jwt",
|
|
predicate: "algorithm",
|
|
as_of: "2024-01-15T21:00:00Z"
|
|
});
|
|
|
|
// Returns: ES256 (the belief at incident time)
|
|
|
|
episteme.diff({
|
|
subject: "auth/jwt",
|
|
from: "2024-01-15T14:00:00Z",
|
|
to: "2024-01-15T21:00:00Z"
|
|
});
|
|
|
|
// Shows: RFC proposal added at 2:32pm
|
|
// Root cause identified.
|
|
|
|
# ============================================
|
|
# CORRECTION
|
|
# ============================================
|
|
- type: code
|
|
id: correction
|
|
title: "Fix the record, not just the code"
|
|
code: |
|
|
// Mark the bad assertion
|
|
episteme.supersede({
|
|
target: "ax7f3k9...",
|
|
reason: "RFC was proposal, not approved decision",
|
|
corrected_by: "sre-oncall"
|
|
});
|
|
|
|
// Add a constraint so it never happens again
|
|
episteme.assert({
|
|
subject: "auth/jwt",
|
|
predicate: "algorithm",
|
|
value: "RS256",
|
|
lifecycle: "approved",
|
|
supersedes: "ax7f3k9..."
|
|
});
|
|
|
|
// Future sessions will see this. Forever.
|
|
|
|
# ============================================
|
|
# VISION
|
|
# ============================================
|
|
- type: vision
|
|
id: vision
|
|
title: "Episteme"
|
|
points:
|
|
- "Claims, not facts. Uncertainty is first-class."
|
|
- "Lifecycle awareness. Proposals ≠ decisions."
|
|
- "Corrections that persist across sessions."
|
|
- "Time travel for incident investigation."
|
|
tagline: "Git for Truth"
|