Major additions: - Community Next.js app (port 18187) for browsing claims with API docs - stemedb-chaos crate: Fault injection, chaos testing, CRDT properties - Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents - Disputed claims handling: Manual review workflows and validation - Aphoria security scanner: New extractors (SQL injection, command injection, weak crypto, TLS version), policy-based ignores, UAT reports - Docker infrastructure: Dockerfile, docker-compose.yml for full stack - VulnBank demo: Intentionally vulnerable multi-language test corpus SDK & API enhancements: - Source registry handlers for tracking data provenance - Metrics endpoint - Skeptic filtering improvements Code quality: - Split 14 large files (>500 lines) into focused modules - All files now under 500-line limit per project guidelines Documentation: - Chaos testing guide, circuit breakers, observability docs - Phase 7 UAT documentation updates - Martin Kleppmann technical writer agent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
125 lines
4.1 KiB
Go
125 lines
4.1 KiB
Go
// Package main demonstrates the Skeptic lens ("Trust but Verify").
|
|
//
|
|
// Unlike standard lenses that pick a single winner, the Skeptic lens
|
|
// shows all competing claims with their relative weights. This is critical
|
|
// for domains like medicine where you need to see disagreement.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/orchard9/stemedb-go/steme"
|
|
)
|
|
|
|
func main() {
|
|
// Setup client
|
|
signer, err := steme.GenerateSigner()
|
|
if err != nil {
|
|
log.Fatalf("Failed to generate signer: %v", err)
|
|
}
|
|
|
|
client := steme.NewClient("http://localhost:18180", signer)
|
|
|
|
// Seed some conflicting assertions about Semaglutide's muscle effects
|
|
seedConflictingData(client)
|
|
|
|
// Query with Skeptic lens
|
|
result, err := client.Skeptic(context.Background(), steme.SkepticQueryParams{
|
|
Subject: "Semaglutide",
|
|
Predicate: "muscle_effect",
|
|
})
|
|
if err != nil {
|
|
log.Fatalf("Failed to query: %v", err)
|
|
}
|
|
|
|
// Display the conflict analysis
|
|
fmt.Printf("=== Skeptic Analysis: Semaglutide muscle_effect ===\n\n")
|
|
|
|
fmt.Printf("Status: %s\n", result.Status)
|
|
fmt.Printf("Conflict Score: %.2f (0.0=unanimous, 1.0=chaos)\n", result.ConflictScore)
|
|
fmt.Printf("Candidates Considered: %d\n", result.CandidatesCount)
|
|
fmt.Printf("Computed At: %d\n\n", result.ComputedAt)
|
|
|
|
fmt.Printf("Competing Claims:\n\n")
|
|
|
|
for i, claim := range result.Claims {
|
|
fmt.Printf("Claim #%d: %v\n", i+1, claim.Value.Value)
|
|
fmt.Printf(" Weight Share: %.1f%%\n", claim.WeightShare*100)
|
|
fmt.Printf(" Assertions: %d\n", claim.AssertionCount)
|
|
fmt.Printf(" Representative: %s\n", claim.RepresentativeHash[:16]+"...")
|
|
fmt.Printf(" Source: %s\n", claim.Source.SourceHash[:16]+"...")
|
|
|
|
if len(claim.SupportingAgents) > 0 {
|
|
fmt.Printf(" Supporting Agents:\n")
|
|
for _, agent := range claim.SupportingAgents {
|
|
fmt.Printf(" - %s (trust: %.2f)\n", agent.AgentID[:16]+"...", agent.TrustScore)
|
|
}
|
|
}
|
|
|
|
fmt.Println()
|
|
}
|
|
|
|
// Interpretation guide
|
|
fmt.Printf("=== Interpretation ===\n\n")
|
|
|
|
switch result.Status {
|
|
case steme.ResolutionUnanimous:
|
|
fmt.Println("✓ Unanimous: All sources agree on the same value.")
|
|
fmt.Println(" You can trust this result with high confidence.")
|
|
case steme.ResolutionAgreed:
|
|
fmt.Println("⚠ Agreed: Strong majority (>75%) agrees, but some dissent exists.")
|
|
fmt.Println(" The consensus is likely reliable, but review minority claims.")
|
|
case steme.ResolutionContested:
|
|
fmt.Println("⚠️ Contested: No clear consensus. Significant disagreement exists.")
|
|
fmt.Println(" DO NOT rely on any single answer. Review all claims and sources.")
|
|
fmt.Println(" This requires human judgment or additional research.")
|
|
}
|
|
}
|
|
|
|
func seedConflictingData(client *steme.Client) {
|
|
ctx := context.Background()
|
|
|
|
// Claim 1: Significant muscle loss (Clinical evidence)
|
|
claim1 := steme.NewAssertion("Semaglutide", "muscle_effect").
|
|
WithText("significant_loss").
|
|
WithConfidence(0.85).
|
|
WithLifecycle(steme.LifecycleApproved).
|
|
WithSourceClass(steme.SourceClassClinical).
|
|
WithSourceHash("1111111111111111111111111111111111111111111111111111111111111111").
|
|
Build()
|
|
|
|
if _, err := client.Assert(ctx, claim1); err != nil {
|
|
log.Printf("Warning: Failed to seed claim1: %v", err)
|
|
}
|
|
|
|
// Claim 2: Minimal muscle loss (Observational evidence)
|
|
claim2 := steme.NewAssertion("Semaglutide", "muscle_effect").
|
|
WithText("minimal_loss").
|
|
WithConfidence(0.75).
|
|
WithLifecycle(steme.LifecycleApproved).
|
|
WithSourceClass(steme.SourceClassObservational).
|
|
WithSourceHash("2222222222222222222222222222222222222222222222222222222222222222").
|
|
Build()
|
|
|
|
if _, err := client.Assert(ctx, claim2); err != nil {
|
|
log.Printf("Warning: Failed to seed claim2: %v", err)
|
|
}
|
|
|
|
// Claim 3: No effect (Anecdotal evidence)
|
|
claim3 := steme.NewAssertion("Semaglutide", "muscle_effect").
|
|
WithText("no_effect").
|
|
WithConfidence(0.60).
|
|
WithLifecycle(steme.LifecycleProposed).
|
|
WithSourceClass(steme.SourceClassAnecdotal).
|
|
WithSourceHash("3333333333333333333333333333333333333333333333333333333333333333").
|
|
Build()
|
|
|
|
if _, err := client.Assert(ctx, claim3); err != nil {
|
|
log.Printf("Warning: Failed to seed claim3: %v", err)
|
|
}
|
|
|
|
fmt.Println("✓ Seeded 3 conflicting claims about Semaglutide muscle_effect")
|
|
}
|