168 lines
7.2 KiB
SQL
168 lines
7.2 KiB
SQL
-- Spore Agent Commons — Core Primitives
|
|
-- Claims, Evidence, Attestations, Intents, Commitments
|
|
|
|
-- ============================================================
|
|
-- Claims (knowledge claims in the commons)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS claims (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
rid TEXT UNIQUE NOT NULL,
|
|
proposer_rid TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'proposed'
|
|
CHECK (status IN ('proposed', 'supported', 'challenged', 'superseded')),
|
|
confidence FLOAT DEFAULT 0.5,
|
|
anchor_type TEXT DEFAULT 'assertion',
|
|
embedding vector(1024),
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_claims_proposer ON claims (proposer_rid);
|
|
CREATE INDEX IF NOT EXISTS idx_claims_status ON claims (status);
|
|
CREATE INDEX IF NOT EXISTS idx_claims_metadata ON claims USING GIN (metadata);
|
|
|
|
-- ============================================================
|
|
-- Evidence (supports or challenges a claim)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS evidence (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
rid TEXT UNIQUE NOT NULL,
|
|
claim_id UUID NOT NULL REFERENCES claims(id) ON DELETE CASCADE,
|
|
relation TEXT NOT NULL CHECK (relation IN ('supports', 'challenges')),
|
|
body TEXT NOT NULL,
|
|
provenance JSONB NOT NULL DEFAULT '{}',
|
|
embedding vector(1024),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_evidence_claim ON evidence (claim_id);
|
|
CREATE INDEX IF NOT EXISTS idx_evidence_relation ON evidence (relation);
|
|
|
|
-- ============================================================
|
|
-- Attestations (endorse/dispute/abstain on a claim)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS attestations (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
rid TEXT UNIQUE NOT NULL,
|
|
claim_id UUID NOT NULL REFERENCES claims(id) ON DELETE CASCADE,
|
|
attester_rid TEXT NOT NULL,
|
|
verdict TEXT NOT NULL CHECK (verdict IN ('endorse', 'dispute', 'abstain')),
|
|
strength FLOAT NOT NULL DEFAULT 1.0,
|
|
reasoning TEXT DEFAULT '',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (claim_id, attester_rid)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_attestations_claim ON attestations (claim_id);
|
|
CREATE INDEX IF NOT EXISTS idx_attestations_attester ON attestations (attester_rid);
|
|
|
|
-- ============================================================
|
|
-- Claim strength (materialized view)
|
|
-- ============================================================
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS claim_strength AS
|
|
SELECT
|
|
c.id AS claim_id,
|
|
c.rid AS claim_rid,
|
|
c.status,
|
|
c.confidence,
|
|
COUNT(DISTINCT CASE WHEN a.verdict = 'endorse' THEN a.id END) AS endorse_count,
|
|
COUNT(DISTINCT CASE WHEN a.verdict = 'dispute' THEN a.id END) AS dispute_count,
|
|
COUNT(DISTINCT CASE WHEN a.verdict = 'abstain' THEN a.id END) AS abstain_count,
|
|
COUNT(DISTINCT CASE WHEN e.relation = 'supports' THEN e.id END) AS supporting_evidence,
|
|
COUNT(DISTINCT CASE WHEN e.relation = 'challenges' THEN e.id END) AS challenging_evidence,
|
|
COALESCE(
|
|
(COUNT(DISTINCT CASE WHEN a.verdict = 'endorse' THEN a.id END)::float -
|
|
COUNT(DISTINCT CASE WHEN a.verdict = 'dispute' THEN a.id END)::float) /
|
|
NULLIF(COUNT(DISTINCT a.id)::float, 0),
|
|
0
|
|
) AS net_sentiment,
|
|
GREATEST(
|
|
MAX(a.created_at),
|
|
MAX(e.created_at),
|
|
c.created_at
|
|
) AS last_activity
|
|
FROM claims c
|
|
LEFT JOIN attestations a ON a.claim_id = c.id
|
|
LEFT JOIN evidence e ON e.claim_id = c.id
|
|
GROUP BY c.id, c.rid, c.status, c.confidence;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_claim_strength_id ON claim_strength (claim_id);
|
|
|
|
-- ============================================================
|
|
-- Intents (need/offer/possibility)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS intents (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
rid TEXT UNIQUE NOT NULL,
|
|
publisher_rid TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
intent_type TEXT NOT NULL CHECK (intent_type IN ('need', 'offer', 'possibility')),
|
|
capacity JSONB NOT NULL DEFAULT '{}',
|
|
timing JSONB NOT NULL DEFAULT '{}',
|
|
governance_fit TEXT[] DEFAULT '{}',
|
|
state TEXT NOT NULL DEFAULT 'open'
|
|
CHECK (state IN ('open', 'matched', 'committed', 'expired', 'withdrawn')),
|
|
embedding vector(1024),
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_intents_publisher ON intents (publisher_rid);
|
|
CREATE INDEX IF NOT EXISTS idx_intents_type ON intents (intent_type);
|
|
CREATE INDEX IF NOT EXISTS idx_intents_state ON intents (state);
|
|
|
|
-- ============================================================
|
|
-- Intent matches (computed similarity pairs)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS intent_matches (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
intent_a_id UUID NOT NULL REFERENCES intents(id) ON DELETE CASCADE,
|
|
intent_b_id UUID NOT NULL REFERENCES intents(id) ON DELETE CASCADE,
|
|
similarity FLOAT NOT NULL,
|
|
match_details JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (intent_a_id, intent_b_id),
|
|
CHECK (intent_a_id < intent_b_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_intent_matches_a ON intent_matches (intent_a_id);
|
|
CREATE INDEX IF NOT EXISTS idx_intent_matches_b ON intent_matches (intent_b_id);
|
|
|
|
-- ============================================================
|
|
-- Commitments (lifecycle state machine)
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS commitments (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
rid TEXT UNIQUE NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
state TEXT NOT NULL DEFAULT 'proposed'
|
|
CHECK (state IN ('proposed', 'verified', 'active', 'evidence_linked',
|
|
'redeemed', 'disputed', 'resolved', 'cancelled')),
|
|
proposer_rid TEXT NOT NULL,
|
|
acceptor_rid TEXT,
|
|
settlement_type TEXT DEFAULT 'attestation',
|
|
terms JSONB NOT NULL DEFAULT '{}',
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_commitments_state ON commitments (state);
|
|
CREATE INDEX IF NOT EXISTS idx_commitments_proposer ON commitments (proposer_rid);
|
|
CREATE INDEX IF NOT EXISTS idx_commitments_acceptor ON commitments (acceptor_rid);
|
|
|
|
-- ============================================================
|
|
-- Commitment-Evidence links
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS commitment_evidence (
|
|
commitment_id UUID NOT NULL REFERENCES commitments(id) ON DELETE CASCADE,
|
|
evidence_id UUID NOT NULL REFERENCES evidence(id) ON DELETE CASCADE,
|
|
linked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (commitment_id, evidence_id)
|
|
);
|