Asi belief-revision-log
install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/belief-revision-log" ~/.claude/skills/plurigrid-asi-belief-revision-log && rm -rf "$T"
manifest:
skills/belief-revision-log/SKILL.mdsource content
Belief Revision Log
Gap Addressed
<<<<<<< HEAD Closes G3 from
zig-syrup-propagator-interleave:
G3 | continuation.zig | No persistent belief revision log (only in-memory) | duckdb-timetravel, time-travel-crdt
======= Closes G3 from
zig-syrup-propagator-interleave: "No persistent belief revision log (only in-memory)".
origin/main
Formal Specification
Type
<<<<<<< HEAD BeliefRevisionOracle : (Proposition, Timestamp) → BeliefState BeliefState = { proposition: string entrenchment: f64 ∈ [0.0, 1.0] ======= BeliefRevisionOracle : (Proposition, Timestamp) -> BeliefState BeliefState = { proposition: string entrenchment: f64 in [0.0, 1.0] >>>>>>> origin/main trit: Trit -- -1=refuted, 0=suspended, +1=accepted revision_op: RevisionOp -- EXPAND | CONTRACT | REVISE timestamp: u64 -- Unix epoch milliseconds } <<<<<<< HEAD RevisionOp = EXPAND | CONTRACT | REVISE ======= >>>>>>> origin/main
Preconditions
- DuckDB database at
exists and is writable <<<<<<< HEAD~/.zig-syrup/beliefs.duckdb
table has been created (schema below)propositions- Queried timestamp is within the revision log range (not before first insertion)
- The oracle has exclusive write access OR is using DuckDB's WAL mode =======
table has been created (schema below)belief_revisions- Queried timestamp is within the revision log range
origin/main
Postconditions
- Returns exactly one
for given (proposition, timestamp) <<<<<<< HEADBeliefState - State is read via
— NOT by replaying all revisions up to TAS-OF JOIN - If no revision exists before timestamp T: returns
BeliefState.nothing
is derived fromtrit
via AGM thresholds (see below)entrenchment
======= 2. State is read via AS-OF pattern, NOT by replaying revisions 3. If no revision exists before timestamp T: returns nothing 4.
trit is derived from entrenchment via fixed thresholds: >0.70 = +1, >0.10 = 0, else -1
origin/main
Schema
<<<<<<< HEAD -- Requirement: DuckDB >= 0.10.0 (for AS-OF JOIN support) ======= -- Requirement: DuckDB >= 0.10.0 >>>>>>> origin/main -- Postcondition: every row is immutable after INSERT (append-only log) CREATE TABLE IF NOT EXISTS belief_revisions ( revision_id UHUGEINT DEFAULT gen_random_uuid() NOT NULL, proposition VARCHAR NOT NULL, entrenchment DOUBLE NOT NULL CHECK (entrenchment >= 0.0 AND entrenchment <= 1.0), trit INTEGER NOT NULL CHECK (trit IN (-1, 0, 1)), revision_op VARCHAR NOT NULL CHECK (revision_op IN ('EXPAND', 'CONTRACT', 'REVISE')), <<<<<<< HEAD agent_id VARCHAR NOT NULL, -- which agent revised this belief session_id VARCHAR NOT NULL, -- which continuation.zig session timestamp_ms BIGINT NOT NULL DEFAULT (epoch_ms(current_timestamp)), -- Immutable: never UPDATE or DELETE — append-only log PRIMARY KEY (revision_id) ); -- Index for AS-OF queries CREATE INDEX IF NOT EXISTS idx_belief_time ON belief_revisions (proposition, timestamp_ms); -- Trit view: derived column, not stored CREATE VIEW belief_current AS SELECT DISTINCT ON (proposition) proposition, entrenchment, CASE WHEN entrenchment > 0.70 THEN 1 -- accepted (same threshold as abductive oracle) WHEN entrenchment > 0.10 THEN 0 -- suspended ELSE -1 -- refuted END AS trit, revision_op, agent_id, timestamp_ms ======= agent_id VARCHAR NOT NULL, session_id VARCHAR NOT NULL, timestamp_ms BIGINT NOT NULL DEFAULT (epoch_ms(current_timestamp)), PRIMARY KEY (revision_id) ); CREATE INDEX IF NOT EXISTS idx_belief_time ON belief_revisions (proposition, timestamp_ms); CREATE VIEW belief_current AS SELECT DISTINCT ON (proposition) proposition, entrenchment, CASE WHEN entrenchment > 0.70 THEN 1 WHEN entrenchment > 0.10 THEN 0 ELSE -1 END AS trit, revision_op, agent_id, timestamp_ms >>>>>>> origin/main FROM belief_revisions ORDER BY proposition, timestamp_ms DESC;
<<<<<<< HEAD
Oracle Implementation
Time-Travel Query
import duckdb from datetime import datetime ======= ## Time-Travel Query ```python import duckdb >>>>>>> origin/main def belief_at( proposition: str, timestamp_ms: int, db_path: str = "~/.zig-syrup/beliefs.duckdb" ) -> dict | None: """ Requirement: belief_revisions table exists with INDEX on (proposition, timestamp_ms) Postcondition: returns the most recent BeliefState at or before timestamp_ms OR None if no revision exists before that time <<<<<<< HEAD Uses AS-OF JOIN pattern (point-in-time query): SELECT the last revision WHERE timestamp_ms <= query_timestamp """ con = duckdb.connect(db_path, read_only=True) result = con.execute(""" SELECT proposition, entrenchment, ======= """ con = duckdb.connect(db_path, read_only=True) result = con.execute(""" SELECT proposition, entrenchment, >>>>>>> origin/main CASE WHEN entrenchment > 0.70 THEN 1 WHEN entrenchment > 0.10 THEN 0 ELSE -1 END AS trit, <<<<<<< HEAD revision_op, agent_id, timestamp_ms FROM belief_revisions WHERE proposition = ? AND timestamp_ms <= ? ======= revision_op, agent_id, timestamp_ms FROM belief_revisions WHERE proposition = ? AND timestamp_ms <= ? >>>>>>> origin/main ORDER BY timestamp_ms DESC LIMIT 1 """, [proposition, timestamp_ms]).fetchone() con.close() if result is None: <<<<<<< HEAD return None # CellValue.nothing — no belief before this time return { "proposition": result[0], "entrenchment": result[1], "trit": result[2], "revision_op": result[3], "agent_id": result[4], "timestamp_ms": result[5], } def belief_history( proposition: str, start_ms: int, end_ms: int, ======= return None return { "proposition": result[0], "entrenchment": result[1], "trit": result[2], "revision_op": result[3], "agent_id": result[4], "timestamp_ms": result[5], } def belief_history( proposition: str, start_ms: int, end_ms: int, >>>>>>> origin/main db_path: str = "~/.zig-syrup/beliefs.duckdb" ) -> list[dict]: """ Requirement: start_ms < end_ms <<<<<<< HEAD Postcondition: returns ALL revisions of proposition in [start_ms, end_ms] ordered chronologically ======= Postcondition: returns ALL revisions of proposition in [start_ms, end_ms] chronologically >>>>>>> origin/main """ con = duckdb.connect(db_path, read_only=True) results = con.execute(""" SELECT proposition, entrenchment, trit, revision_op, agent_id, timestamp_ms <<<<<<< HEAD FROM belief_current WHERE proposition = ? AND timestamp_ms BETWEEN ? AND ? ORDER BY timestamp_ms ASC """, [proposition, start_ms, end_ms]).fetchall() con.close() return [dict(zip(["proposition","entrenchment","trit","revision_op","agent_id","timestamp_ms"], r)) for r in results]
Write Path (from continuation.zig)
// Requirement: DuckDB C API available (libduckdb) // Requirement: belief_revisions table exists // Postcondition: revision is persisted atomically before returning to caller // On error: continuation.zig rolls back to previous in-memory state ======= FROM belief_revisions WHERE proposition = ? AND timestamp_ms BETWEEN ? AND ? ORDER BY timestamp_ms ASC """, [proposition, start_ms, end_ms]).fetchall() con.close() return [dict(zip( ["proposition","entrenchment","trit","revision_op","agent_id","timestamp_ms"], r )) for r in results]
Write Path (from continuation.zig)
>>>>>>> origin/main const std = @import("std"); const duckdb = @cImport(@cInclude("duckdb.h")); const BeliefLogger = struct { db: duckdb.duckdb_database, conn: duckdb.duckdb_connection, agent_id: []const u8, session_id: []const u8, fn log_revision( self: *@This(), proposition: []const u8, entrenchment: f64, op: enum { expand, contract, revise }, ) !void { <<<<<<< HEAD // Compute trit from entrenchment ======= >>>>>>> origin/main const trit: i32 = if (entrenchment > 0.70) 1 else if (entrenchment > 0.10) 0 else -1; const op_str = switch (op) { .expand => "EXPAND", .contract => "CONTRACT", .revise => "REVISE", }; <<<<<<< HEAD // Parameterized INSERT — no string interpolation ======= >>>>>>> origin/main var stmt: duckdb.duckdb_prepared_statement = undefined; _ = duckdb.duckdb_prepare(self.conn, "INSERT INTO belief_revisions (proposition, entrenchment, trit, revision_op, agent_id, session_id) " ++ "VALUES (?, ?, ?, ?, ?, ?)", &stmt ); _ = duckdb.duckdb_bind_varchar(stmt, 1, proposition.ptr); _ = duckdb.duckdb_bind_double(stmt, 2, entrenchment); _ = duckdb.duckdb_bind_int32(stmt, 3, trit); _ = duckdb.duckdb_bind_varchar(stmt, 4, op_str.ptr); _ = duckdb.duckdb_bind_varchar(stmt, 5, self.agent_id.ptr); _ = duckdb.duckdb_bind_varchar(stmt, 6, self.session_id.ptr); const status = duckdb.duckdb_execute_prepared(stmt, null); duckdb.duckdb_destroy_prepared(&stmt); if (status == duckdb.DuckDBError) { return error.BeliefLogWriteFailed; <<<<<<< HEAD // Caller: do NOT apply revision to in-memory BeliefSet ======= >>>>>>> origin/main } } };
<<<<<<< HEAD
AGM Belief Revision → Log Integration
// continuation.zig with persistence hooked in const PersistentBeliefSet = struct { beliefs: std.ArrayList(Belief), // in-memory (same as original) logger: BeliefLogger, // persistence layer (NEW) fn expand(self: *@This(), b: Belief) !void { // Persist FIRST (before in-memory modification) ======= ## AGM Belief Revision Integration ```zig const PersistentBeliefSet = struct { beliefs: std.ArrayList(Belief), logger: BeliefLogger, fn expand(self: *@This(), b: Belief) !void { >>>>>>> origin/main try self.logger.log_revision(b.proposition, b.entrenchment, .expand); self.beliefs.append(b); } fn contract(self: *@This(), prop: []const u8) !void { <<<<<<< HEAD // Remove belief + negation from in-memory set // Persist with entrenchment = 0.0 (refuted) try self.logger.log_revision(prop, 0.0, .contract); // ... remove from self.beliefs ======= try self.logger.log_revision(prop, 0.0, .contract); >>>>>>> origin/main } fn revise(self: *@This(), b: Belief) !void { // Levi identity: (K - !p) + p <<<<<<< HEAD // Persist as single REVISE operation ======= >>>>>>> origin/main try self.logger.log_revision(b.proposition, b.entrenchment, .revise); self.contract(negate(b.proposition)); self.expand(b); } };
<<<<<<< HEAD
GF(3) Invariant Over Time
-- Invariant: at any timestamp T, the set of beliefs with trit ≠ 0 must form -- a GF(3)-consistent collection (no two contradictory beliefs both with trit = +1) -- Query to verify GF(3) conservation at timestamp T: WITH beliefs_at_T AS ( SELECT proposition, trit FROM ( SELECT proposition, trit, ROW_NUMBER() OVER (PARTITION BY proposition ORDER BY timestamp_ms DESC) as rn FROM belief_revisions WHERE timestamp_ms <= ? -- T ) WHERE rn = 1 AND trit != 0 ), triads AS ( -- Check all triads: for every (p1, p2, p3), if all are known, sum must = 0 mod 3 SELECT b1.trit + b2.trit + b3.trit AS trit_sum FROM beliefs_at_T b1 CROSS JOIN beliefs_at_T b2 CROSS JOIN beliefs_at_T b3 WHERE b1.proposition < b2.proposition AND b2.proposition < b3.proposition ) SELECT COUNT(*) AS violations FROM triads WHERE (trit_sum % 3) != 0; -- Postcondition: violations = 0 (GF(3) conservation holds across all time)
CRDT Integration (time-travel-crdt)
# For multi-agent belief revision where agents may diverge: # Requirement: time-travel-crdt skill available # Postcondition: merged belief state converges (LWW on entrenchment per proposition) def merge_belief_logs( log_A: list[dict], # from agent A's DuckDB log_B: list[dict], # from agent B's DuckDB ) -> list[dict]: """ LWW (Last-Writer-Wins) merge strategy: For each proposition, keep the revision with the highest timestamp_ms. Precondition: both logs are append-only (no updates/deletes) Postcondition: merged log has exactly one entry per (proposition, timestamp_ms) pair Convergence: any two agents that merge all revisions reach the same BeliefState ======= ## CRDT Integration (multi-agent merge) ```python def merge_belief_logs(log_A: list[dict], log_B: list[dict]) -> list[dict]: """ LWW (Last-Writer-Wins) merge strategy. Precondition: both logs are append-only Postcondition: merged log has one entry per (proposition, timestamp_ms) pair Convergence: any two agents merging all revisions reach the same BeliefState >>>>>>> origin/main """ from collections import defaultdict merged = defaultdict(list) for entry in log_A + log_B: merged[entry["proposition"]].append(entry) result = [] for prop, entries in merged.items(): <<<<<<< HEAD # LWW: highest timestamp wins per proposition ======= >>>>>>> origin/main result.append(max(entries, key=lambda e: e["timestamp_ms"])) return sorted(result, key=lambda e: e["timestamp_ms"])
<<<<<<< HEAD
Related Skills
— continuation.zig with in-memory AGM BeliefSet (Gap G3)zig-syrup-propagator-interleave
— AS-OF query patterns, temporal versioningduckdb-timetravel
— DuckDB infrastructure (connection management, schema patterns)duckdb-ies
— multi-agent convergence for distributed belief logstime-travel-crdt
— uses belief revision as its revision mechanismabductive-oracle
— universal hub where belief states route throughdynamic-sufficiency
— CellValue lattice (belief = Cell(f64) + trit classification)propagators
— append-only log + LWW merge = CRDT semantics =======crdt
origin/main