arborist-viz/arborist_viz/scripts/seed_demo.py
russell@unturf.com 0cd96ab1d7
Initial commit: arborist VIZ — Merkle command center
Pyramid web app for inspecting arborist Merkle trees over sharded SQLite:
document roots, inclusion proofs, an interactive 3D Merkle lattice
(six.js / WebGL with graceful fallback), audit-chain linkage, and a live
SSE event stream.

Generated artifacts (env/, vendored static/six/ bundles, demo databases)
are gitignored and rebuilt via the Makefile (venv, six, init-db, serve).
2026-05-28 09:22:59 -04:00

161 lines
6.7 KiB
Python

"""Seed a small arborist shard so dropping a hash visualizes something.
Usage:
arborist_viz_seed_demo data/demo_arborist.db
Ingests ~5 documents via ``arborist.embed.ingest_documents`` and prints
their ``document_root`` and a few sample ``leaf_hash`` values — the
operator copies one of these into the dashboard's hash input.
"""
from __future__ import annotations
import os
import sys
import sqlite3
try:
from arborist.embed import open_store, ingest_documents, Document, Edge
except Exception as exc:
print("ERROR: arborist not importable: {0}".format(exc), file=sys.stderr)
print("Run `make arborist` first (installs ~/git/arborist into the venv).", file=sys.stderr)
sys.exit(1)
SAMPLE_DOCS = [
Document(
uri="https://unturf.com/software/arborist",
title="Arborist — content-addressed memory for ML agents",
source_type="demo_unturf",
content=(
"Arborist is a content-addressed, Merkle-committed, audit-chained store "
"for documents an ML agent has read. Every document is canonicalized, "
"chunked, and rooted; every chunk is content-addressable; every ingest "
"produces one append-only audit event. Identical content collapses to a "
"single document_root. Mesh peers re-derive and cross-verify roots. "
"Embedders (e.g. neopig) hand arborist Document objects and arborist "
"owns the SQLite — no raw SQL in the embedder's app."
),
edges=[Edge(edge_type="references", dst_uri="https://unturf.com/software/")],
extra={"demo": True, "ix": 1},
),
Document(
uri="https://unturf.com/let-us-define-a-permacomputer",
title="Let us define a permacomputer",
source_type="demo_unturf",
content=(
"A permacomputer is a regenerative compute substrate: free execution for "
"anyone, infrastructure that outlasts its builders, code that outlasts "
"its authors. Russell Ballestrini's manifesto frames compute as a "
"commons, not a rent extraction surface. Workstations are nodes, edges "
"are queues, every patch must confirm downstream capacity before it "
"ships. Three drivers, three million people — fix the dispatch, but "
"stage the drivers first."
),
extra={"demo": True, "ix": 2},
),
Document(
uri="https://undefect.com/moad/moad-2026-0001",
title="MOAD-0001 — The Sedimentary Defect (CWE-407)",
source_type="demo_undefect",
content=(
"list.contains() inside a loop yields O(N^2) behaviour where a hash set "
"would give O(1). The sedimentary defect: written before O(1) was "
"idiomatic, still ships today. Patches land at the Java, Python, Go, "
"and JS layers — six.js carries the JS dogfood: three.js r175 plus a "
"scene-level BVH that drops raycaster scans from O(N) to O(log N). "
"Every six.js deploy adds a data point that the patch is production-safe."
),
extra={"demo": True, "ix": 3},
),
Document(
uri="https://undefect.com/moad/moad-2026-0005",
title="MOAD-0005 — The Thundering Herd",
source_type="demo_undefect",
content=(
"Cache get + null check + compute + put with no synchronization invites "
"N concurrent recomputations on a cold miss — the thundering herd. The "
"fix is computeIfAbsent or singleflight: one computation per key, the "
"rest park on the same future. Coupled with MOAD-0001: fix the O(N^2) "
"bottleneck and you flood every downstream cache simultaneously unless "
"the herd discipline is in place first."
),
extra={"demo": True, "ix": 4},
),
Document(
uri="https://unturf.com/eight-forms-of-capital",
title="Eight Forms of Capital",
source_type="demo_unturf",
content=(
"Roland and Landua's eight capitals: living, material, financial, "
"intellectual, experiential, social, cultural, spiritual. Nurture "
"capitals cannot be bought, only grown. Transactional capitals "
"facilitate exchange — they are tools, not goals. Regenerative systems "
"reinvest surplus back into living capital. Platform tax is O(N^2) "
"friction at the exchange layer: it drains workaholic nodes to feed "
"gluttons that feel no pain."
),
extra={"demo": True, "ix": 5},
),
]
def main(argv=sys.argv):
if len(argv) < 2:
print("usage: arborist_viz_seed_demo <db_path>", file=sys.stderr)
sys.exit(1)
db_path = argv[1]
os.makedirs(os.path.dirname(db_path) or ".", exist_ok=True)
print("[seed] opening {0} ...".format(db_path))
conn = open_store(db_path)
print("[seed] ingesting {0} demo documents (sentence chunker for richer trees) ...".format(len(SAMPLE_DOCS)))
# SentenceChunker (sent-v1) splits on sentence boundaries — one leaf per
# sentence. This makes the 3D Merkle lattice visually meaningful even on
# short demo docs. TokenChunker default (tok-512-v1) collapses our
# paragraph-sized samples into a single leaf each.
stats = ingest_documents(conn, SAMPLE_DOCS, source_type="demo", chunker_name="sent-v1")
print("[seed] stats: {0}".format(stats))
print("")
print("=" * 64)
print(" demo arborist shard ready — paste any of these into VIZ:")
print("=" * 64)
cur = conn.execute(
"SELECT document_root, title, "
" (SELECT COUNT(*) FROM chunks WHERE chunks.document_root = documents.document_root) AS n_leaves "
"FROM documents ORDER BY ingest_ts"
)
for row in cur:
# Sample one leaf per doc as well.
leaf = conn.execute(
"SELECT leaf_hash, idx FROM chunks WHERE document_root = ? ORDER BY idx LIMIT 1",
(row[0],),
).fetchone()
print("")
print(" document_root: {0}".format(row[0]))
print(" title: {0}".format(row[1]))
print(" leaves: {0}".format(row[2]))
if leaf:
print(" sample leaf: {0} (leaf #{1})".format(leaf[0], leaf[1]))
# And a sample audit event.
ev = conn.execute("SELECT event_hash, event_type FROM audit_events ORDER BY seq LIMIT 1").fetchone()
if ev:
print("")
print(" sample audit_event: {0} ({1})".format(ev[0], ev[1]))
print("")
print("=" * 64)
print(" Boot the VIZ: ARBORIST_VIZ_SHARDS={0} make serve".format(db_path))
print(" Or just: make serve-demo")
print("=" * 64)
print("")
conn.close()
if __name__ == "__main__":
main()