import { Claim } from "@/components/ui/claim";
// import { TextSelectionExtractor } from "@/components/ui/text-selection-extractor";

// ============================================================================
// API Types (matching SkepticResponse from stemedb-api)
// ============================================================================

interface SourceMetadata {
  label: string;
  tier: number;
  tier_label: string;
  url?: string;
  status: string;
}

interface SourceSummary {
  source_hash: string;
  visual_hash?: string;
  source_metadata?: SourceMetadata;
}

interface AgentSummary {
  agent_id: string;
  trust_score: number;
}

interface ClaimSummaryApi {
  value: { type: string; value: string | number | boolean };
  weight_share: number;
  assertion_count: number;
  representative_hash: string;
  source: SourceSummary;
  supporting_agents: AgentSummary[];
}

interface SkepticResponse {
  subject: string;
  predicate: string;
  status: "Unanimous" | "Agreed" | "Contested";
  conflict_score: number;
  claims: ClaimSummaryApi[];
  candidates_count: number;
  computed_at: number;
  lens_name: string;
}

// ============================================================================
// Transform API response to component format
// ============================================================================

type SourceTier = 0 | 1 | 2 | 3 | 4 | 5;
type ConflictStatus = "unanimous" | "agreed" | "contested";
type SourceStatus = "active" | "deprecated" | "quarantined";

const tierLabels: Record<SourceTier, string> = {
  0: "Regulatory",
  1: "Clinical",
  2: "Observational",
  3: "Expert",
  4: "Community",
  5: "Anecdotal",
};

interface ClaimData {
  status: ConflictStatus;
  conflictScore: number;
  candidatesCount: number;
  computedAt: number;
  claims: {
    value: string;
    valueType: "text" | "number" | "boolean" | "reference";
    weightShare: number;
    assertionCount: number;
    representativeHash: string;
    source: {
      hash: string;
      label: string;
      tier: SourceTier;
      tierLabel: string;
      url?: string;
      status: SourceStatus;
      visualHash?: string;
    };
    supportingAgents: { agentId: string; trustScore: number }[];
    timestamp?: number;
  }[];
  note?: string;
}

function transformSkepticResponse(response: SkepticResponse, note?: string): ClaimData {
  return {
    status: response.status.toLowerCase() as ConflictStatus,
    conflictScore: response.conflict_score,
    candidatesCount: response.candidates_count,
    computedAt: response.computed_at * 1000, // Convert to milliseconds
    claims: response.claims.map((claim) => ({
      value: String(claim.value.value),
      valueType: (claim.value.type.toLowerCase() as "text" | "number" | "boolean" | "reference"),
      weightShare: claim.weight_share,
      assertionCount: claim.assertion_count,
      representativeHash: claim.representative_hash,
      source: {
        hash: claim.source.source_hash,
        label: claim.source.source_metadata?.label || "Unknown Source",
        tier: (claim.source.source_metadata?.tier ?? 3) as SourceTier,
        tierLabel: claim.source.source_metadata?.tier_label || tierLabels[(claim.source.source_metadata?.tier ?? 3) as SourceTier],
        url: claim.source.source_metadata?.url,
        status: (claim.source.source_metadata?.status || "active") as SourceStatus,
        visualHash: claim.source.visual_hash,
      },
      supportingAgents: claim.supporting_agents.map((agent) => ({
        agentId: agent.agent_id,
        trustScore: agent.trust_score,
      })),
      timestamp: response.computed_at * 1000, // Use computed_at as timestamp (API doesn't expose assertion timestamp yet)
    })),
    note,
  };
}

// ============================================================================
// Data Fetching
// ============================================================================

const API_URL = process.env.STEMEDB_API_URL || "http://127.0.0.1:18180";

async function fetchSkepticData(subject: string, predicate: string): Promise<SkepticResponse | null> {
  try {
    const url = `${API_URL}/v1/skeptic?subject=${encodeURIComponent(subject)}&predicate=${encodeURIComponent(predicate)}&include_source_metadata=true`;
    const response = await fetch(url, {
      cache: "no-store", // Always fetch fresh data
    });

    if (!response.ok) {
      console.warn(`Failed to fetch ${subject}/${predicate}: ${response.status}`);
      return null;
    }

    return await response.json();
  } catch (error) {
    console.warn(`Error fetching ${subject}/${predicate}:`, error);
    return null;
  }
}

// ============================================================================
// Fallback Mock Data (used when API is unavailable)
// ============================================================================

const fallbackSingleValue: ClaimData = {
  status: "agreed",
  conflictScore: 0.15,
  candidatesCount: 4,
  computedAt: Date.now(),
  claims: [
    {
      value: "Single value per key is the dominant paradigm",
      valueType: "text",
      weightShare: 0.85,
      assertionCount: 3,
      representativeHash: "7a3f8b2c9d4e5f6a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a",
      source: {
        hash: "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b",
        label: "PostgreSQL 16 Documentation - DDL Constraints",
        tier: 0,
        tierLabel: "Regulatory",
        url: "https://www.postgresql.org/docs/current/ddl-constraints.html",
        status: "active",
      },
      supportingAgents: [
        { agentId: "7a3f8b2c9d4e5f6a7b8c9d0e1f2a3b4c", trustScore: 0.92 },
      ],
      timestamp: Date.now() - 30 * 24 * 60 * 60 * 1000,
    },
  ],
  note: "Bitemporal databases and event stores are exceptions, addressed in Section 2.",
};

const fallbackCrdt: ClaimData = {
  status: "contested",
  conflictScore: 0.72,
  candidatesCount: 23,
  computedAt: Date.now(),
  claims: [
    {
      value: "CRDTs assume replicas are authoritative copies of same data",
      valueType: "text",
      weightShare: 0.42,
      assertionCount: 10,
      representativeHash: "5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f",
      source: {
        hash: "6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a",
        label: "Shapiro et al. - Conflict-free Replicated Data Types (SSS 2011)",
        tier: 1,
        tierLabel: "Clinical",
        url: "https://hal.inria.fr/inria-00609399/document",
        status: "active",
      },
      supportingAgents: [
        { agentId: "7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d", trustScore: 0.94 },
      ],
      timestamp: Date.now() - 14 * 24 * 60 * 60 * 1000,
    },
  ],
  note: "Active debate in distributed systems community.",
};

const fallbackContentAddressing: ClaimData = {
  status: "unanimous",
  conflictScore: 0.03,
  candidatesCount: 8,
  computedAt: Date.now(),
  claims: [
    {
      value: "Content-addressing provides deduplication, integrity, and efficient comparison",
      valueType: "text",
      weightShare: 0.97,
      assertionCount: 8,
      representativeHash: "7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c",
      source: {
        hash: "8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d",
        label: "BLAKE3 Specification - One Function, Fast Everywhere",
        tier: 0,
        tierLabel: "Regulatory",
        url: "https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf",
        status: "active",
      },
      supportingAgents: [
        { agentId: "9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a", trustScore: 0.96 },
      ],
      timestamp: Date.now() - 60 * 24 * 60 * 60 * 1000,
    },
  ],
  note: "Well-established cryptographic property.",
};

const fallbackRecency: ClaimData = {
  status: "agreed",
  conflictScore: 0.28,
  candidatesCount: 6,
  computedAt: Date.now(),
  claims: [
    {
      value: "RecencyLens is O(n) where n = candidates",
      valueType: "text",
      weightShare: 0.72,
      assertionCount: 4,
      representativeHash: "3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c",
      source: {
        hash: "4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d",
        label: "StemeDB Source Code - lens/recency.rs",
        tier: 0,
        tierLabel: "Regulatory",
        url: "https://github.com/orchard9/stemedb/blob/main/crates/stemedb-lens/src/recency.rs",
        status: "active",
      },
      supportingAgents: [
        { agentId: "5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a", trustScore: 0.88 },
      ],
      timestamp: Date.now() - 5 * 24 * 60 * 60 * 1000,
    },
  ],
  note: "Complexity claim based on code review.",
};

const fallbackStorage: ClaimData = {
  status: "unanimous",
  conflictScore: 0.05,
  candidatesCount: 5,
  computedAt: Date.now(),
  claims: [
    {
      value: "Append-only storage grows without bound",
      valueType: "text",
      weightShare: 0.95,
      assertionCount: 5,
      representativeHash: "0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d",
      source: {
        hash: "1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e",
        label: "Kleppmann - Designing Data-Intensive Applications",
        tier: 1,
        tierLabel: "Clinical",
        url: "https://dataintensive.net/",
        status: "active",
      },
      supportingAgents: [
        { agentId: "2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b", trustScore: 0.97 },
      ],
      timestamp: Date.now() - 120 * 24 * 60 * 60 * 1000,
    },
  ],
  note: "Fundamental tradeoff. Mitigated by semantic decay.",
};

const fallbackTrust: ClaimData = {
  status: "contested",
  conflictScore: 0.65,
  candidatesCount: 12,
  computedAt: Date.now(),
  claims: [
    {
      value: "Trust parameters (0.5 start, +0.05/-0.1) are reasonable heuristics",
      valueType: "text",
      weightShare: 0.48,
      assertionCount: 6,
      representativeHash: "5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c",
      source: {
        hash: "6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d",
        label: "StemeDB Implementation Notes",
        tier: 3,
        tierLabel: "Expert",
        status: "active",
      },
      supportingAgents: [
        { agentId: "7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a", trustScore: 0.72 },
      ],
      timestamp: Date.now() - 10 * 24 * 60 * 60 * 1000,
    },
  ],
  note: "Honest limitation. Trust parameters need domain-specific calibration.",
};

// ============================================================================
// Page Component
// ============================================================================

export default async function Home() {
  // Fetch all claim data in parallel
  const [
    singleValueApi,
    crdtApi,
    contentAddressingApi,
    recencyApi,
    storageApi,
    trustApi,
    blake3Api,
    ed25519Api,
    mvReadApi,
    skepticMetricApi,
    lensPropertiesApi,
    consensusComplexityApi,
    // New: Competing database claims from Introduction
    mainstreamStorageApi,
    postgresConflictApi,
    mongoConflictApi,
    neo4jConflictApi,
  ] = await Promise.all([
    fetchSkepticData("Episteme", "storage_model"),
    fetchSkepticData("CRDT", "replica_assumption"),
    fetchSkepticData("Episteme", "content_addressing"),
    fetchSkepticData("RecencyLens", "complexity"),
    fetchSkepticData("Episteme", "storage_growth"),
    fetchSkepticData("EigenTrust", "parameters"),
    fetchSkepticData("StemeDB", "hash_algorithm"),
    fetchSkepticData("Ed25519", "signature_size"),
    fetchSkepticData("MaterializedView", "read_complexity"),
    fetchSkepticData("SkepticLens", "conflict_metric"),
    fetchSkepticData("Lens", "property_stateless"),
    fetchSkepticData("ConsensusLens", "space_complexity"),
    // New: Competing database claims from Introduction
    fetchSkepticData("mainstream_databases", "storage_assumption"),
    fetchSkepticData("PostgreSQL", "conflict_resolution"),
    fetchSkepticData("MongoDB", "conflict_resolution"),
    fetchSkepticData("Neo4j", "conflict_resolution"),
  ]);

  // Transform or use fallbacks
  const singleValueClaim = singleValueApi
    ? transformSkepticResponse(singleValueApi, "Bitemporal databases and event stores are exceptions, addressed in Section 2.")
    : fallbackSingleValue;

  const crdtClaim = crdtApi
    ? transformSkepticResponse(crdtApi, "Active debate in distributed systems community. The distinction between 'replica disagreement' and 'source disagreement' is subtle but fundamental.")
    : fallbackCrdt;

  const contentAddressingClaim = contentAddressingApi
    ? transformSkepticResponse(contentAddressingApi, "Well-established cryptographic property. Git, IPFS, and many content-addressable systems rely on this.")
    : fallbackContentAddressing;

  const recencyComplexityClaim = recencyApi
    ? transformSkepticResponse(recencyApi, "Complexity claim based on code review. Benchmarking needed to validate real-world performance.")
    : fallbackRecency;

  const storageGrowthClaim = storageApi
    ? transformSkepticResponse(storageApi, "Fundamental tradeoff. Mitigated by semantic decay and tiered storage compaction.")
    : fallbackStorage;

  const trustParametersClaim = trustApi
    ? transformSkepticResponse(trustApi, "Honest limitation. Trust parameters need domain-specific calibration and formal analysis.")
    : fallbackTrust;

  // Additional claims for richer annotation
  const blake3Claim = blake3Api
    ? transformSkepticResponse(blake3Api, "BLAKE3 is the content-addressing hash used for all assertions. See BLAKE3 specification.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.02,
        candidatesCount: 3,
        computedAt: Date.now(),
        claims: [{
          value: "BLAKE3",
          valueType: "text" as const,
          weightShare: 0.98,
          assertionCount: 3,
          representativeHash: "blake3hash",
          source: {
            hash: "blake3src",
            label: "StemeDB Whitepaper - Section 3.3",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "blake3agent", trustScore: 0.95 }],
        }],
        note: "BLAKE3 is the content-addressing hash used for all assertions.",
      };

  const ed25519Claim = ed25519Api
    ? transformSkepticResponse(ed25519Api, "Ed25519 provides 64-byte signatures with 128-bit security level.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.01,
        candidatesCount: 2,
        computedAt: Date.now(),
        claims: [{
          value: "64 bytes",
          valueType: "text" as const,
          weightShare: 0.99,
          assertionCount: 2,
          representativeHash: "ed25519hash",
          source: {
            hash: "ed25519src",
            label: "Bernstein et al. - High-speed high-security signatures",
            tier: 1 as SourceTier,
            tierLabel: "Clinical",
            url: "https://ed25519.cr.yp.to/",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "ed25519agent", trustScore: 0.98 }],
        }],
        note: "Ed25519 provides 64-byte signatures with 128-bit security level.",
      };

  const mvReadClaim = mvReadApi
    ? transformSkepticResponse(mvReadApi, "Materialized views enable O(1) reads for common queries.")
    : {
        status: "agreed" as ConflictStatus,
        conflictScore: 0.15,
        candidatesCount: 4,
        computedAt: Date.now(),
        claims: [{
          value: "O(1)",
          valueType: "text" as const,
          weightShare: 0.85,
          assertionCount: 4,
          representativeHash: "mvhash",
          source: {
            hash: "mvsrc",
            label: "StemeDB Whitepaper - Section 4.4",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "mvagent", trustScore: 0.90 }],
        }],
        note: "Materialized views enable O(1) reads for common queries.",
      };

  const skepticMetricClaim = skepticMetricApi
    ? transformSkepticResponse(skepticMetricApi, "Shannon entropy normalized to [0,1] provides an information-theoretic measure of conflict.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.05,
        candidatesCount: 3,
        computedAt: Date.now(),
        claims: [{
          value: "normalized Shannon entropy",
          valueType: "text" as const,
          weightShare: 0.95,
          assertionCount: 3,
          representativeHash: "skeptichash",
          source: {
            hash: "skepticsrc",
            label: "StemeDB Whitepaper - Section 4.2.4",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "skepticagent", trustScore: 0.92 }],
        }],
        note: "Shannon entropy normalized to [0,1] provides an information-theoretic measure of conflict.",
      };

  const lensPropertiesClaim = lensPropertiesApi
    ? transformSkepticResponse(lensPropertiesApi, "Stateless, deterministic, and composable - these enable caching and parallel execution.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.03,
        candidatesCount: 4,
        computedAt: Date.now(),
        claims: [{
          value: "true",
          valueType: "boolean" as const,
          weightShare: 0.97,
          assertionCount: 4,
          representativeHash: "lensprops",
          source: {
            hash: "lenssrc",
            label: "StemeDB Whitepaper - Section 4",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "lensagent", trustScore: 0.94 }],
        }],
        note: "Stateless, deterministic, and composable - these enable caching and parallel execution.",
      };

  const consensusComplexityClaim = consensusComplexityApi
    ? transformSkepticResponse(consensusComplexityApi, "Space complexity depends on distinct values, not total candidates.")
    : {
        status: "agreed" as ConflictStatus,
        conflictScore: 0.18,
        candidatesCount: 3,
        computedAt: Date.now(),
        claims: [{
          value: "O(k)",
          valueType: "text" as const,
          weightShare: 0.82,
          assertionCount: 3,
          representativeHash: "consensushash",
          source: {
            hash: "consensussrc",
            label: "StemeDB Whitepaper - Section 4.2.2",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "consensusagent", trustScore: 0.88 }],
        }],
        note: "Space complexity depends on distinct values, not total candidates.",
      };

  // Transform competing database claims from Introduction
  const mainstreamStorageClaim = mainstreamStorageApi
    ? transformSkepticResponse(mainstreamStorageApi, "This is the single-value assumption that StemeDB challenges.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.05,
        candidatesCount: 4,
        computedAt: Date.now(),
        claims: [{
          value: "single value per key",
          valueType: "text" as const,
          weightShare: 0.95,
          assertionCount: 4,
          representativeHash: "mainstreamhash",
          source: {
            hash: "mainstreamsrc",
            label: "StemeDB Whitepaper - Introduction",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "mainstreamagent", trustScore: 0.90 }],
        }],
        note: "This is the single-value assumption that StemeDB challenges.",
      };

  const postgresConflictClaim = postgresConflictApi
    ? transformSkepticResponse(postgresConflictApi, "PostgreSQL uses last-writer-wins or raises conflict errors.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.02,
        candidatesCount: 1,
        computedAt: Date.now(),
        claims: [{
          value: "overwrite or reject",
          valueType: "text" as const,
          weightShare: 0.98,
          assertionCount: 1,
          representativeHash: "pghash",
          source: {
            hash: "pgsrc",
            label: "StemeDB Whitepaper - Introduction",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "pgagent", trustScore: 0.95 }],
        }],
        note: "PostgreSQL uses last-writer-wins or raises conflict errors.",
      };

  const mongoConflictClaim = mongoConflictApi
    ? transformSkepticResponse(mongoConflictApi, "MongoDB uses last-writer-wins or raises conflict errors.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.02,
        candidatesCount: 1,
        computedAt: Date.now(),
        claims: [{
          value: "overwrite or reject",
          valueType: "text" as const,
          weightShare: 0.98,
          assertionCount: 1,
          representativeHash: "mongohash",
          source: {
            hash: "mongosrc",
            label: "StemeDB Whitepaper - Introduction",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "mongoagent", trustScore: 0.95 }],
        }],
        note: "MongoDB uses last-writer-wins or raises conflict errors.",
      };

  const neo4jConflictClaim = neo4jConflictApi
    ? transformSkepticResponse(neo4jConflictApi, "Neo4j uses last-writer-wins or raises conflict errors.")
    : {
        status: "unanimous" as ConflictStatus,
        conflictScore: 0.02,
        candidatesCount: 1,
        computedAt: Date.now(),
        claims: [{
          value: "overwrite or reject",
          valueType: "text" as const,
          weightShare: 0.98,
          assertionCount: 1,
          representativeHash: "neo4jhash",
          source: {
            hash: "neo4jsrc",
            label: "StemeDB Whitepaper - Introduction",
            tier: 3 as SourceTier,
            tierLabel: "Expert",
            status: "active" as SourceStatus,
          },
          supportingAgents: [{ agentId: "neo4jagent", trustScore: 0.95 }],
        }],
        note: "Neo4j uses last-writer-wins or raises conflict errors.",
      };

  return (
    <div className="min-h-screen bg-background">
      <article className="mx-auto max-w-[800px] px-6 py-16 text-foreground">
        {/* Title and Abstract */}
        <header className="mb-16">
          <h1 className="text-3xl font-semibold mb-2">
            StemeDB: A Claim-Oriented Database with Read-Time Resolution
          </h1>
          <p className="text-sm text-muted-foreground mb-8">
            February 2026
          </p>

          <section className="border-l-2 border-muted-foreground/30 pl-6">
            <h2 className="sr-only">Abstract</h2>
            <p className="text-base leading-relaxed">
              Traditional databases enforce a single value per key, requiring
              conflicts to be resolved at write time. This paper presents
              StemeDB, a database that stores <em>claims</em> rather than facts,
              deferring conflict resolution to read time via composable
              resolution functions called Lenses. StemeDB combines an
              append-only Merkle DAG for storage, content-addressing via{" "}
              <Claim data={blake3Claim}>BLAKE3</Claim>
              {" "}for deduplication and integrity, and cryptographic signatures for
              provenance. We formalize the Lens abstraction, analyze the
              complexity characteristics of standard resolution strategies, and
              discuss the tradeoffs inherent in this approach. StemeDB is
              designed for domains where multiple sources provide conflicting
              information and the appropriate resolution strategy depends on the
              query context.
            </p>
          </section>
        </header>

        {/* Table of Contents */}
        <nav className="mb-12 p-4 bg-muted/30 rounded text-sm">
          <h2 className="font-medium mb-2">Contents</h2>
          <ol className="list-decimal list-inside space-y-1 text-muted-foreground">
            <li>
              <a href="#introduction" className="hover:text-foreground">
                Introduction: The Single-Value Assumption
              </a>
            </li>
            <li>
              <a href="#background" className="hover:text-foreground">
                Background and Related Work
              </a>
            </li>
            <li>
              <a href="#claim-model" className="hover:text-foreground">
                The Claim Model
              </a>
            </li>
            <li>
              <a href="#lenses" className="hover:text-foreground">
                Lenses: Read-Time Resolution
              </a>
            </li>
            <li>
              <a href="#storage" className="hover:text-foreground">
                Storage Architecture
              </a>
            </li>
            <li>
              <a href="#tradeoffs" className="hover:text-foreground">
                Tradeoffs and Limitations
              </a>
            </li>
            <li>
              <a href="#open-problems" className="hover:text-foreground">
                Open Problems
              </a>
            </li>
            <li>
              <a href="#conclusion" className="hover:text-foreground">
                Conclusion
              </a>
            </li>
          </ol>
        </nav>

        {/* Section 1: Introduction */}
        <section id="introduction" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">
            1. Introduction: The Single-Value Assumption
          </h2>

          <p className="mb-4">
            <Claim data={mainstreamStorageClaim}>
              Every mainstream database, from{" "}
              <Claim data={postgresConflictClaim}>PostgreSQL</Claim> to{" "}
              <Claim data={mongoConflictClaim}>MongoDB</Claim> to{" "}
              <Claim data={neo4jConflictClaim}>Neo4j</Claim>,
              enforces a fundamental assumption: at any given time, a key maps to
              exactly one value
            </Claim>
            . When a new value arrives for an existing key, the
            database must either overwrite the old value (last-writer-wins) or
            reject the write (conflict error). This assumption is so deeply
            embedded that we rarely question it.
          </p>

          <p className="mb-4">
            Yet many real-world domains violate this assumption. Consider a
            pharmaceutical safety database where an FDA label says a drug is
            well-tolerated, a clinical trial shows no statistically significant
            adverse events, and 8,500 patient reports in the adverse event
            reporting system describe serious complications. These are not three
            versions of one truth waiting to be resolved; they are three
            distinct claims from sources with different methodologies, biases,
            and epistemic status. Forcing them into a single value loses
            information.
          </p>

          <p className="mb-4">
            The single-value assumption creates three failure modes:
          </p>

          <ol className="list-decimal list-inside mb-6 space-y-2">
            <li>
              <strong>Premature resolution:</strong> Conflicts are resolved at
              write time, before the query context is known. A consumer asking
              &ldquo;what do patients report?&rdquo; and a regulator asking
              &ldquo;what do clinical trials show?&rdquo; need different
              answers, but the database has already picked one.
            </li>
            <li>
              <strong>Information loss:</strong> The fact that sources disagreed
              is often as important as what they said. When a database picks a
              winner, the losing claims vanish from the queryable state.
            </li>
            <li>
              <strong>Provenance opacity:</strong> After resolution, there is no
              structural way to ask &ldquo;why does the database believe
              this?&rdquo; The chain from source documents to stored values is
              broken.
            </li>
          </ol>

          <p className="mb-4">
            StemeDB addresses these failures by inverting the traditional
            model.{" "}
            <strong>
              Rather than storing facts, StemeDB stores claims. Rather than
              resolving conflicts at write time, it resolves them at read time.
            </strong>{" "}
            The database becomes a repository of assertions with full
            provenance, and resolution becomes a function applied at query
            time&mdash;a Lens that can vary by query.
          </p>

          <p className="mb-4">
            The analogy to version control is instructive. In Git, conflicting
            changes coexist on different branches until explicitly merged, and
            different merge strategies (recursive, ours, theirs) can be chosen
            at merge time. StemeDB applies similar logic to knowledge:
            conflicting claims coexist until explicitly resolved, and different
            resolution strategies (consensus, authority, recency) can be chosen
            at query time.
          </p>
        </section>

        {/* Section 2: Background and Related Work */}
        <section id="background" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">
            2. Background and Related Work
          </h2>

          <p className="mb-4">
            The problem of managing conflicting information has been approached
            from several angles. We survey four relevant areas and explain why
            each falls short for multi-source contested knowledge.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">2.1 Event Sourcing</h3>

          <p className="mb-4">
            Event sourcing stores state changes as an immutable log of events,
            reconstructing current state by replaying the log. This preserves
            history and enables temporal queries. However, event sourcing
            assumes events are authoritative facts about what happened in a
            system the application controls. It does not address the case where
            multiple external sources report conflicting observations about the
            same phenomenon. Event sourcing answers &ldquo;what happened?&rdquo;
            but not &ldquo;what do different sources claim happened, and how do
            we reconcile them?&rdquo;
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            2.2 Bitemporal Databases
          </h3>

          <p className="mb-4">
            Bitemporal databases (Snodgrass, 1999; SQL:2011 temporal extensions)
            track both valid time (when a fact was true in the world) and
            transaction time (when it was recorded in the database). This
            enables queries like &ldquo;what did we believe on date X about the
            state on date Y?&rdquo; However, bitemporal models still assume a
            single source of truth per (entity, attribute, valid-time) tuple.
            They handle corrections to the same source&rsquo;s view, not
            simultaneous conflicting views from multiple sources.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">2.3 CRDTs</h3>

          <p className="mb-4">
            Conflict-Free Replicated Data Types (Shapiro et al., 2011) enable
            eventually consistent replication by designing data structures that
            can be merged without coordination. CRDTs solve a different problem:{" "}
            <Claim data={crdtClaim}>
              they assume all replicas are authoritative copies of the same
              logical data
            </Claim>{" "}
            and design merge functions that preserve intent
            (e.g., last-writer-wins registers, grow-only sets). StemeDB&rsquo;s
            claims are not replicas of the same data; they are genuinely
            different assertions from different sources. A CRDT merge would lose
            the fact that sources disagreed.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">2.4 Knowledge Graphs</h3>

          <p className="mb-4">
            Knowledge graphs (RDF, property graphs) represent entities and
            relationships and can store multiple assertions about the same
            entity. However, standard knowledge graph query languages (SPARQL,
            Cypher) do not provide built-in mechanisms for weighted resolution
            across conflicting assertions. Provenance in RDF is typically
            handled via reification or named graphs, which adds complexity but
            does not provide resolution semantics. Furthermore, knowledge graphs
            do not typically enforce append-only immutability or
            content-addressing.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            2.5 What StemeDB Adds
          </h3>

          <p className="mb-4">StemeDB combines elements from these traditions:</p>

          <ul className="list-disc list-inside mb-4 space-y-1">
            <li>
              From event sourcing: append-only storage, immutable history,
              temporal queries
            </li>
            <li>
              From bitemporal databases: the distinction between when something
              was asserted and when it was true
            </li>
            <li>
              From CRDTs: the recognition that merge strategies matter and
              should be explicit
            </li>
            <li>
              From knowledge graphs: the subject-predicate-object data model,
              provenance tracking
            </li>
          </ul>

          <p className="mb-4">
            The novel contribution is the Lens abstraction: a composable,
            stateless function that collapses a set of conflicting claims into a
            resolution at read time, with the resolution strategy chosen by the
            query rather than fixed at write time.
          </p>
        </section>

        {/* Section 3: The Claim Model */}
        <section id="claim-model" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">3. The Claim Model</h2>

          <p className="mb-4">
            The atomic unit of storage in StemeDB is the <em>Assertion</em>: a
            claim about the world made by an identified agent, with full
            provenance.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            3.1 Assertion Structure
          </h3>

          <p className="mb-4">
            An Assertion is a triple extended with provenance metadata:
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`struct Assertion {
    // The proposition (subject-predicate-object triple)
    subject: EntityId,       // e.g., "semaglutide"
    predicate: RelationId,   // e.g., "has_side_effect"
    object: ObjectValue,     // e.g., Text("gastroparesis")

    // Provenance
    source_hash: Hash,       // BLAKE3 hash of source document
    source_class: SourceClass, // Authority tier (0-5)
    parent_hash: Option<Hash>, // Links to prior assertion if derived

    // Attribution
    signatures: Vec<SignatureEntry>, // Ed25519 signatures
    confidence: f32,         // Subjective certainty [0.0, 1.0]
    timestamp: u64,          // Unix timestamp

    // Lifecycle
    lifecycle: LifecycleStage, // Proposed | Approved | Deprecated
    epoch: Option<EpochId>,  // Paradigm context
}`}
          </pre>

          <p className="mb-4">
            The key distinction from a traditional row or document is that
            Assertions are <em>claims</em>, not facts. Two Assertions with the
            same (subject, predicate) but different objects are both stored;
            neither overwrites the other. The database holds the disagreement.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">3.2 Source Classes</h3>

          <p className="mb-4">
            Every Assertion carries a SourceClass that encodes its epistemic
            authority. This is not a filter applied after retrieval; it is
            structural metadata that affects how Lenses weight the assertion
            during resolution.
          </p>

          <div className="overflow-x-auto mb-4">
            <table className="w-full text-sm border border-border">
              <thead>
                <tr className="border-b border-border bg-muted/30">
                  <th className="text-left p-2 font-medium">Tier</th>
                  <th className="text-left p-2 font-medium">Class</th>
                  <th className="text-left p-2 font-medium">Example</th>
                  <th className="text-left p-2 font-medium">Default Weight</th>
                  <th className="text-left p-2 font-medium">Decay Half-Life</th>
                </tr>
              </thead>
              <tbody>
                <tr className="border-b border-border">
                  <td className="p-2">0</td>
                  <td className="p-2">Regulatory</td>
                  <td className="p-2">FDA label, SEC filing</td>
                  <td className="p-2">1.0</td>
                  <td className="p-2">None (until superseded)</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2">1</td>
                  <td className="p-2">Clinical</td>
                  <td className="p-2">Peer-reviewed RCT</td>
                  <td className="p-2">0.9</td>
                  <td className="p-2">2 years</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2">2</td>
                  <td className="p-2">Observational</td>
                  <td className="p-2">Real-world evidence</td>
                  <td className="p-2">0.7</td>
                  <td className="p-2">1 year</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2">3</td>
                  <td className="p-2">Expert</td>
                  <td className="p-2">Physician opinion</td>
                  <td className="p-2">0.5</td>
                  <td className="p-2">6 months</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2">4</td>
                  <td className="p-2">Community</td>
                  <td className="p-2">Patient registry</td>
                  <td className="p-2">0.2</td>
                  <td className="p-2">3 months</td>
                </tr>
                <tr>
                  <td className="p-2">5</td>
                  <td className="p-2">Anecdotal</td>
                  <td className="p-2">Social media post</td>
                  <td className="p-2">0.1</td>
                  <td className="p-2">30 days</td>
                </tr>
              </tbody>
            </table>
          </div>

          <p className="mb-4">
            A critical design decision: volume does not override authority. A
            million Tier-5 assertions cannot outvote a single Tier-0 regulatory
            assertion in authority-weighted resolution. However, anecdotal
            clusters can signal emerging issues that warrant clinical
            investigation.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            3.3 Content-Addressing
          </h3>

          <p className="mb-4">
            Every Assertion&rsquo;s identifier is the BLAKE3 hash of its
            serialized content.{" "}
            <Claim data={contentAddressingClaim}>
              This provides three properties: deduplication, integrity, and
              efficient comparison
            </Claim>:
          </p>

          <ol className="list-decimal list-inside mb-4 space-y-2">
            <li>
              <strong>Deduplication:</strong> Identical claims automatically
              share the same identifier.
            </li>
            <li>
              <strong>Integrity:</strong> Any modification to an Assertion would
              change its hash, making tampering detectable.
            </li>
            <li>
              <strong>Efficient comparison:</strong> Two nodes can determine
              whether they have the same Assertion by comparing 32-byte hashes
              rather than full content.
            </li>
          </ol>

          <h3 className="text-xl font-medium mb-3 mt-8">
            3.4 Cryptographic Signatures
          </h3>

          <p className="mb-4">
            Assertions carry{" "}
            <Claim data={ed25519Claim}>Ed25519 signatures</Claim>
            {" "}from the agents that vouch for
            them. This provides non-repudiation: an agent cannot deny having
            made an assertion if their signature is attached. Multiple agents
            can co-sign an assertion, which is relevant for consensus Lenses
            that weight by signer count or reputation.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`struct SignatureEntry {
    agent_id: [u8; 32],   // Ed25519 public key
    signature: [u8; 64],  // Signature over assertion content
    timestamp: u64,       // When signed
}`}
          </pre>
        </section>

        {/* Section 4: Lenses */}
        <section id="lenses" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">
            4. Lenses: Read-Time Resolution
          </h2>

          <p className="mb-4">
            A Lens is a function that takes a set of candidate Assertions
            (all assertions matching a query&rsquo;s subject and predicate
            filters) and returns a Resolution. The Lens abstraction has three
            key properties:
          </p>

          <ol className="list-decimal list-inside mb-6 space-y-2">
            <li>
              <Claim data={lensPropertiesClaim}>
                <strong>Stateless:</strong> A Lens has no side effects and
                maintains no internal state between calls
              </Claim>.
            </li>
            <li>
              <strong>Deterministic:</strong> Given the same set of candidates,
              a Lens always returns the same Resolution.
            </li>
            <li>
              <strong>Composable:</strong> Lenses can wrap other Lenses,
              enabling layered strategies (e.g., filter by epoch, then resolve
              by recency).
            </li>
          </ol>

          <h3 className="text-xl font-medium mb-3 mt-8">4.1 Formal Definition</h3>

          <p className="mb-4">
            Let <em>A</em> be the set of all Assertions. A Lens is a function:
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`L: P(A) -> Resolution

where Resolution = {
    winner: Option<Assertion>,  // The selected assertion, if any
    candidates_count: usize,    // Number of candidates considered
    confidence: f32,            // Confidence in the resolution [0, 1]
    conflict_score: f32         // Degree of disagreement [0, 1]
}`}
          </pre>

          <p className="mb-4">
            The Lens contract requires that L must be a pure function: no I/O,
            no mutation, no randomness. This enables caching, parallel
            execution, and reasoning about lens behavior.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            4.2 Standard Lens Implementations
          </h3>

          <h4 className="text-lg font-medium mb-2 mt-6">
            4.2.1 RecencyLens (Last-Writer-Wins)
          </h4>

          <p className="mb-4">
            Returns the assertion with the highest timestamp. This is the
            simplest strategy and mirrors traditional database semantics.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`RecencyLens(candidates) =
    max(candidates, key=timestamp)`}
          </pre>

          <p className="mb-4">
            <Claim data={recencyComplexityClaim}>
              Complexity: O(n) where n = |candidates|. Space: O(1)
            </Claim>.
          </p>

          <h4 className="text-lg font-medium mb-2 mt-6">
            4.2.2 ConsensusLens (Majority Value)
          </h4>

          <p className="mb-4">
            Groups assertions by their object value and returns a representative
            from the largest group. Confidence is the proportion of candidates
            in the winning group.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`ConsensusLens(candidates) =
    groups = group_by(candidates, a -> a.object)
    largest = max(groups, key=len)
    winner = max(largest, key=timestamp)
    confidence = len(largest) / len(candidates)`}
          </pre>

          <p className="mb-4 text-sm text-muted-foreground">
            Complexity: O(n) for grouping, O(n) for max.{" "}
            <Claim data={consensusComplexityClaim}>
              Space: O(k) where k = distinct object values
            </Claim>.
          </p>

          <h4 className="text-lg font-medium mb-2 mt-6">
            4.2.3 AuthorityLens (Reputation-Weighted)
          </h4>

          <p className="mb-4">
            Weights each assertion by the signer&rsquo;s trust score (looked up
            from a TrustRankStore) and returns the highest-weighted assertion.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`AuthorityLens(candidates, trust_store) =
    for each candidate:
        agent = primary_signer(candidate)
        score = trust_store.get(agent) * candidate.confidence
    winner = max(candidates, key=score)

Complexity: O(n) trust lookups (O(1) each if cached)
Space: O(1)`}
          </pre>

          <h4 className="text-lg font-medium mb-2 mt-6">
            4.2.4 SkepticLens (Conflict Analysis)
          </h4>

          <p className="mb-4">
            Unlike the previous lenses, SkepticLens does not pick a winner.
            Instead, it returns a ConflictAnalysis showing all competing claims
            with their weight shares. This implements the &ldquo;disagreement is
            the information&rdquo; thesis.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`SkepticLens(candidates, vote_store) =
    groups = group_by(candidates, a -> a.object)
    weights = []
    for (value, assertions) in groups:
        w = sum(vote_store.get_weight(a) for a in assertions)
        weights.append((value, w))

    conflict_score = normalized_shannon_entropy(weights)
    status = if conflict_score < 0.1: Unanimous
             elif conflict_score < 0.4: Agreed
             else: Contested

    return ConflictAnalysis { status, conflict_score, claims }

Complexity: O(n) for grouping, O(n) vote lookups, O(k) for entropy
Space: O(k) where k = distinct values`}
          </pre>

          <p className="mb-4">
            The conflict score uses{" "}
            <Claim data={skepticMetricClaim}>normalized Shannon entropy</Claim>:
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`H = -sum(p_i * log2(p_i)) for each claim proportion p_i
conflict_score = H / log2(k)  // Normalized to [0, 1]`}
          </pre>

          <h3 className="text-xl font-medium mb-3 mt-8">
            4.3 Lens Composition
          </h3>

          <p className="mb-4">
            Lenses can wrap other lenses to create layered strategies.
            EpochAwareLens demonstrates this pattern: it filters out assertions
            from superseded epochs before delegating to an inner lens.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`EpochAwareLens(candidates, inner_lens, epoch_store) =
    superseded = epoch_store.get_superseded_epochs()
    filtered = [a for a in candidates if a.epoch not in superseded]
    return inner_lens.resolve(filtered)

Example: EpochAwareLens(ConsensusLens) filters obsolete paradigms,
then resolves by consensus among remaining assertions.`}
          </pre>

          <h3 className="text-xl font-medium mb-3 mt-8">
            4.4 Materialized Views for O(1) Reads
          </h3>

          <p className="mb-4">
            Running lens resolution on every read would be prohibitively
            expensive for high-throughput queries. StemeDB maintains
            MaterializedViews: pre-computed resolutions stored at{" "}
            <code>MV:&#123;subject&#125;:&#123;predicate&#125;</code> that{" "}
            <Claim data={mvReadClaim}>
              provide O(1) lookup for standard lenses
            </Claim>.
          </p>

          <pre className="bg-muted p-4 rounded text-sm overflow-x-auto mb-4">
            {`struct MaterializedView {
    winner: Assertion,        // Pre-computed winner
    lens_name: String,        // Which lens computed this
    resolution_confidence: f32,
    candidates_count: usize,
    materialized_at: u64,     // When computed
}`}
          </pre>

          <p className="mb-4">
            A background Materializer process watches for new assertions and
            votes, recomputing affected MaterializedViews asynchronously. This
            creates eventual consistency between writes and materialized reads,
            with sub-millisecond read latency for common queries.
          </p>
        </section>

        {/* Section 5: Storage Architecture */}
        <section id="storage" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">5. Storage Architecture</h2>

          <h3 className="text-xl font-medium mb-3 mt-8">
            5.1 Append-Only Merkle DAG
          </h3>

          <p className="mb-4">
            StemeDB stores assertions in an append-only Merkle DAG.
            &ldquo;Append-only&rdquo; means assertions are never modified or
            deleted; new assertions can reference prior ones via{" "}
            <code>parent_hash</code>, but the referenced assertions remain
            immutable.
          </p>

          <p className="mb-4">
            The DAG structure (rather than a linear log) enables several
            capabilities:
          </p>

          <ul className="list-disc list-inside mb-4 space-y-2">
            <li>
              <strong>Derivation chains:</strong> When assertion B cites
              assertion A as its basis, this relationship is captured in the
              hash linkage. If A is later invalidated, all descendants can be
              identified by traversing the DAG.
            </li>
            <li>
              <strong>Efficient sync:</strong> Two nodes can identify their
              difference set by comparing Merkle roots and recursively walking
              the tree, similar to Git object negotiation.
            </li>
            <li>
              <strong>Tamper evidence:</strong> Any modification to an assertion
              would change its hash, breaking all links to its descendants.
            </li>
          </ul>

          <h3 className="text-xl font-medium mb-3 mt-8">5.2 Write Path</h3>

          <p className="mb-4">The write path follows this sequence:</p>

          <ol className="list-decimal list-inside mb-4 space-y-2">
            <li>
              <strong>Ingestion:</strong> Client submits assertion with
              signature.
            </li>
            <li>
              <strong>Validation:</strong> Signature verification, schema
              validation, rate limiting.
            </li>
            <li>
              <strong>WAL append:</strong> Assertion written to write-ahead log
              with fsync for durability.
            </li>
            <li>
              <strong>KV store:</strong> Assertion stored at{" "}
              <code>H:&#123;hash&#125;</code>; indexes updated at{" "}
              <code>S:&#123;subject&#125;</code> and{" "}
              <code>SP:&#123;subject&#125;:&#123;predicate&#125;</code>.
            </li>
            <li>
              <strong>Materialization (async):</strong> Background worker
              recomputes affected MaterializedViews.
            </li>
          </ol>

          <h3 className="text-xl font-medium mb-3 mt-8">5.3 Read Path</h3>

          <p className="mb-4">Two read paths exist:</p>

          <p className="mb-2">
            <strong>Fast path (O(1)):</strong> For queries using standard lenses
            with materialized views, read directly from{" "}
            <code>MV:&#123;subject&#125;:&#123;predicate&#125;</code>.
          </p>

          <p className="mb-4">
            <strong>Full resolution path (O(n)):</strong> For custom lenses or
            ad-hoc queries:
          </p>

          <ol className="list-decimal list-inside mb-4 space-y-2">
            <li>
              Index lookup: <code>SP:&#123;subject&#125;:&#123;predicate&#125;</code>{" "}
              returns list of assertion hashes.
            </li>
            <li>Hydrate: Load full assertions from content store.</li>
            <li>
              Resolve: Apply lens to candidates, return resolution.
            </li>
          </ol>

          <h3 className="text-xl font-medium mb-3 mt-8">
            5.4 Storage Layout
          </h3>

          <div className="overflow-x-auto mb-4">
            <table className="w-full text-sm border border-border">
              <thead>
                <tr className="border-b border-border bg-muted/30">
                  <th className="text-left p-2 font-medium">Key Pattern</th>
                  <th className="text-left p-2 font-medium">Value</th>
                  <th className="text-left p-2 font-medium">Purpose</th>
                </tr>
              </thead>
              <tbody>
                <tr className="border-b border-border">
                  <td className="p-2 font-mono text-xs">H:&#123;hash&#125;</td>
                  <td className="p-2">Assertion</td>
                  <td className="p-2">Content-addressed store</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2 font-mono text-xs">
                    S:&#123;subject&#125;
                  </td>
                  <td className="p-2">Vec&lt;Hash&gt;</td>
                  <td className="p-2">Subject index</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2 font-mono text-xs">
                    SP:&#123;subject&#125;:&#123;predicate&#125;
                  </td>
                  <td className="p-2">Vec&lt;Hash&gt;</td>
                  <td className="p-2">Compound index</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2 font-mono text-xs">
                    MV:&#123;subject&#125;:&#123;predicate&#125;
                  </td>
                  <td className="p-2">MaterializedView</td>
                  <td className="p-2">Pre-computed resolution</td>
                </tr>
                <tr className="border-b border-border">
                  <td className="p-2 font-mono text-xs">
                    V:&#123;hash&#125;:&#123;vote_hash&#125;
                  </td>
                  <td className="p-2">Vote</td>
                  <td className="p-2">Ballot box</td>
                </tr>
                <tr>
                  <td className="p-2 font-mono text-xs">
                    TR:&#123;agent_id&#125;
                  </td>
                  <td className="p-2">TrustRank</td>
                  <td className="p-2">Agent reputation</td>
                </tr>
              </tbody>
            </table>
          </div>

          <h3 className="text-xl font-medium mb-3 mt-8">
            5.5 Serialization: Zero-Copy with rkyv
          </h3>

          <p className="mb-4">
            StemeDB uses rkyv for serialization, which enables zero-copy
            deserialization: data can be accessed directly from memory-mapped
            storage without parsing overhead. This is critical for the read
            path, where a query may need to hydrate hundreds of candidate
            assertions before applying a lens.
          </p>
        </section>

        {/* Section 6: Tradeoffs and Limitations */}
        <section id="tradeoffs" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">
            6. Tradeoffs and Limitations
          </h2>

          <p className="mb-4">
            The claim-oriented model involves fundamental tradeoffs. We document
            them explicitly rather than minimizing them.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">6.1 Storage Growth</h3>

          <p className="mb-4">
            <Claim data={storageGrowthClaim}>
              Append-only storage means data grows without bound
            </Claim>. Unlike a
            traditional database where{" "}
            <code>UPDATE users SET email = ?</code> overwrites the previous
            value, StemeDB creates a new assertion while preserving the old one.
            For high-write workloads on frequently-updated entities, storage
            consumption can grow significantly.
          </p>

          <p className="mb-4">
            <strong>Mitigation:</strong> Semantic decay causes old, low-tier
            assertions to drop out of materialized views (though they remain in
            cold storage). Compaction can archive assertions beyond a certain
            age to cheaper storage tiers while preserving audit capability.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            6.2 Query Complexity
          </h3>

          <p className="mb-4">
            Full lens resolution is O(n) in the number of candidate assertions.
            For hot entities with thousands of conflicting claims, this can be
            expensive. The materialized view layer amortizes this cost for
            standard queries, but custom lenses or time-travel queries incur the
            full cost.
          </p>

          <p className="mb-4">
            <strong>Mitigation:</strong> Pre-compute materialized views for
            common (subject, predicate, lens) combinations. Use bloom filters
            for epoch filtering to reduce candidate set before full resolution.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            6.3 Eventual Consistency
          </h3>

          <p className="mb-4">
            Materialized views are updated asynchronously. A write followed
            immediately by a read may return stale data if the materialization
            has not completed. This is acceptable for the target use
            cases (research, due diligence, health information) where
            sub-second consistency is not required, but would be problematic for
            transactional workloads.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            6.4 When Not to Use StemeDB
          </h3>

          <p className="mb-4">
            StemeDB is not a general-purpose database. It is inappropriate for:
          </p>

          <ul className="list-disc list-inside mb-4 space-y-2">
            <li>
              <strong>Single source of truth:</strong> If you control the data
              source and it never conflicts with itself, use PostgreSQL.
            </li>
            <li>
              <strong>Transactional workloads:</strong> StemeDB does not support
              ACID transactions. Use a traditional RDBMS.
            </li>
            <li>
              <strong>High-frequency CRUD:</strong> The append-only model adds
              overhead for simple update/delete patterns.
            </li>
            <li>
              <strong>Strong consistency requirements:</strong> Materialized
              view lag makes StemeDB unsuitable for financial transactions or
              inventory management.
            </li>
          </ul>
        </section>

        {/* Section 7: Open Problems */}
        <section id="open-problems" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">7. Open Problems</h2>

          <p className="mb-4">
            Several significant questions remain open for future research and
            implementation:
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            7.1 Trust Score Dynamics
          </h3>

          <p className="mb-4">
            The TrustAwareAuthority lens weights assertions by agent reputation,
            but the dynamics of trust score evolution are not fully specified.
            Questions include: How should trust decay over time? What is the
            appropriate penalty for incorrect assertions? How do we prevent
            gaming of the trust system?{" "}
            <Claim data={trustParametersClaim}>
              Initial parameters (0.5 starting score, +0.05/-0.1 for
              correct/incorrect) are heuristics without theoretical foundation
            </Claim>.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            7.2 Semantic Similarity for Grouping
          </h3>

          <p className="mb-4">
            ConsensusLens currently groups assertions by exact object value
            match. Two assertions claiming &ldquo;47 million&rdquo; and
            &ldquo;$47M&rdquo; would be treated as different claims.
            Incorporating semantic similarity (via embeddings or normalization)
            would improve resolution quality but adds complexity and potential
            for false positives.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            7.3 Cross-Tier Conflict Metrics
          </h3>

          <p className="mb-4">
            The current conflict score measures disagreement among all
            candidates equally. A more nuanced metric would distinguish
            between within-tier disagreement (multiple clinical trials disagree)
            and cross-tier disagreement (clinical trials disagree with patient
            reports). The latter may be more informative for certain
            applications.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            7.4 Distributed Consensus
          </h3>

          <p className="mb-4">
            The current implementation assumes a single-node deployment.
            Distributing StemeDB across multiple nodes raises questions about
            how to maintain consistency of materialized views, how to partition
            the assertion space, and how to handle network partitions. The
            Merkle DAG structure enables efficient synchronization, but the
            coordination protocols are not yet specified.
          </p>

          <h3 className="text-xl font-medium mb-3 mt-8">
            7.5 Formal Verification of Lenses
          </h3>

          <p className="mb-4">
            Lenses are required to be deterministic and stateless, but these
            properties are enforced by convention rather than by the type
            system. Formal verification of lens implementations could provide
            stronger guarantees, particularly for high-stakes domains like
            medical knowledge.
          </p>
        </section>

        {/* Section 8: Conclusion */}
        <section id="conclusion" className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">8. Conclusion</h2>

          <p className="mb-4">
            StemeDB inverts the traditional database assumption that conflicts
            must be resolved at write time. By storing claims with full
            provenance and deferring resolution to read time via Lenses, it
            enables a new class of applications where disagreement is the
            information, not an error to be hidden.
          </p>

          <p className="mb-4">
            The core insight is epistemological: databases store data, but
            knowledge is not data. Knowledge is claims made by agents with
            varying authority, subject to revision, decay, and supersession.
            Representing knowledge as facts forces premature resolution and
            loses information. Representing knowledge as claims preserves the
            epistemic structure.
          </p>

          <p className="mb-4">
            The cost is complexity: more storage (append-only), more computation
            (lens resolution), and more careful schema design (source classes,
            provenance). These costs are justified when the alternative is a
            system that hides disagreement and loses provenance&mdash;failures
            with real consequences in domains like health, finance, and
            research.
          </p>

          <p className="mb-4">
            StemeDB is not a replacement for PostgreSQL. It is a specialized
            tool for a specific problem: managing contested, multi-source
            knowledge where resolution strategy depends on context. For that
            problem, the claim-oriented model with read-time resolution via
            Lenses provides capabilities that traditional databases cannot match.
          </p>
        </section>

        {/* References */}
        <section className="mb-16">
          <h2 className="text-2xl font-semibold mb-6">References</h2>

          <ol className="list-decimal list-inside space-y-2 text-sm">
            <li>
              Shapiro, M., Preguiça, N., Baquero, C., &amp; Zawirski, M. (2011).
              Conflict-free replicated data types. In <em>SSS 2011</em>.
            </li>
            <li>
              Snodgrass, R. T. (1999).{" "}
              <em>Developing Time-Oriented Database Applications in SQL</em>.
              Morgan Kaufmann.
            </li>
            <li>
              Merkle, R. C. (1988). A digital signature based on a conventional
              encryption function. In <em>Crypto 1987</em>.
            </li>
            <li>
              O&apos;Connor, J., Aumasson, J-P., Neves, S., &amp; Wilcox-O&apos;Hearn, Z.
              (2020). BLAKE3: One function, fast everywhere.
            </li>
            <li>
              Bernstein, D. J., Duif, N., Lange, T., Schwabe, P., &amp; Yang, B-Y.
              (2012). High-speed high-security signatures.{" "}
              <em>Journal of Cryptographic Engineering</em>, 2(2), 77-89.
            </li>
          </ol>
        </section>

        {/* Footer */}
        <footer className="border-t border-border pt-8 text-center">
          <div className="flex justify-center gap-6 text-sm">
            <a
              href="https://github.com/orchard9/stemedb"
              className="text-muted-foreground hover:text-foreground transition-colors"
            >
              GitHub
            </a>
            <a
              href="/docs"
              className="text-muted-foreground hover:text-foreground transition-colors"
            >
              Documentation
            </a>
            <a
              href="/docs/api"
              className="text-muted-foreground hover:text-foreground transition-colors"
            >
              API Reference
            </a>
          </div>
        </footer>
      </article>
    </div>
  );
}
