49d384a0fb
backend/thesis_seed.py builds the starting "living messaging source of truth" from docs/thesis-seed-v5.md: a core line (throughline; the open Option A/B banner as a competing variant group; the three pillars; the proof; voice rules), one line per LP segment carrying that segment's angle, and the five segment definitions. ensure_thesis_seed(conn) runs from init_db, seeding ONLY when the Workshop is empty (no thesis lines) — idempotent and non-destructive, so it bootstraps once and never overwrites partner edits. Everything lands draft/candidate; nothing is made canonical (that stays the partners' dual-approval action, guardrail #4). Content is Ten31's own messaging, not LP data. Test: backend/test_thesis_seed.py runs init_db and asserts the core line, 5 segment lines, the 2-member Option A/B variant group, 3 pillars, segment_cuts, and segment defs, plus re-seed-is-a-no-op (11/11). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
203 lines
10 KiB
Python
203 lines
10 KiB
Python
"""Seed the Ten31 v5 thesis into the Architect's substrate (Phase 1).
|
|
|
|
Builds the starting "living messaging source of truth" the partners iterate on in
|
|
the Thesis Workshop: a CORE line (throughline, the open Option A/B banner debate as
|
|
competing variants, the three pillars, the proof, and the voice rules) plus one
|
|
LINE PER SEGMENT carrying that segment's angle, and the segment definitions.
|
|
|
|
Content is Ten31's OWN messaging (docs/thesis-seed-v5.md) — not LP data — so it is
|
|
safe to ship in code. Everything lands as DRAFT/CANDIDATE nodes: nothing is made
|
|
canonical here (that is the partners' dual-approval action — guardrail #4).
|
|
|
|
`ensure_thesis_seed(conn)` is idempotent: it seeds ONLY when no thesis lines exist,
|
|
so it bootstraps an empty Workshop once and never clobbers partner edits afterward.
|
|
"""
|
|
import json
|
|
import sqlite3
|
|
import uuid
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
def _now():
|
|
return datetime.now(timezone.utc).replace(tzinfo=None).isoformat() + "Z"
|
|
|
|
|
|
def _eid(prefix):
|
|
return f"{prefix}_{uuid.uuid4().hex[:16]}"
|
|
|
|
|
|
def _log(conn, action, target_id, payload):
|
|
conn.execute(
|
|
"""INSERT INTO interaction_log
|
|
(id, ts, actor_type, actor_id, action, target_type, target_id, payload, source, created_at)
|
|
VALUES (?,?, 'system', 'thesis_seed', ?, 'thesis', ?, ?, 'seed', ?)""",
|
|
(str(uuid.uuid4()), _now(), action, target_id, json.dumps(payload) if payload is not None else None, _now()),
|
|
)
|
|
|
|
|
|
def _line(conn, line_key, name, segment_key=None, is_core=False, description=None):
|
|
lid = _eid("thl")
|
|
conn.execute(
|
|
"""INSERT INTO thesis_lines (id, line_key, name, segment_key, is_core, description, created_at, updated_at)
|
|
VALUES (?,?,?,?,?,?,?,?)""",
|
|
(lid, line_key, name, segment_key, 1 if is_core else 0, description, _now(), _now()),
|
|
)
|
|
_log(conn, "thesis.line_seeded", lid, {"line_key": line_key, "is_core": bool(is_core)})
|
|
return lid
|
|
|
|
|
|
def _node(conn, line_id, parent_id, node_type, ordn, title, body, status="draft", variant_group=None):
|
|
nid = _eid("thn")
|
|
conn.execute(
|
|
"""INSERT INTO thesis_nodes (id, line_id, parent_id, node_type, ord, title, body, status, variant_group, created_at, updated_at)
|
|
VALUES (?,?,?,?,?,?,?,?,?,?,?)""",
|
|
(nid, line_id, parent_id, node_type, float(ordn), title, body, status, variant_group, _now(), _now()),
|
|
)
|
|
return nid
|
|
|
|
|
|
# ── v5 content (docs/thesis-seed-v5.md) ──────────────────────────────────────
|
|
|
|
THROUGHLINE = (
|
|
"Bitcoin, AI, and energy are three of the largest growth markets of the next decade, "
|
|
"and they depend on the same scarce resources: cheap energy and computing power. We "
|
|
"believe that energy, compute, and AI infrastructure will settle on money that is hard "
|
|
"to produce. That is not the case today, and connecting these markets to bitcoin is the "
|
|
"part of the thesis that very few others are making, even as broader crypto tries to "
|
|
"attach itself to AI and energy. Ten31 invests in that infrastructure with strong conviction."
|
|
)
|
|
|
|
OPTION_A = (
|
|
"Ten31 invests in the infrastructure of scarcity. We back the bitcoin, energy, and AI "
|
|
"companies that produce and secure the scarce resources these markets are built on."
|
|
)
|
|
OPTION_B = (
|
|
"Ten31 invests in freedom technology. We back the bitcoin, energy, and AI companies "
|
|
"building the foundation for a more sovereign, less centralized economy."
|
|
)
|
|
|
|
PILLAR_1 = (
|
|
"Every one of these markets is bottlenecked on something scarce. AI and bitcoin both "
|
|
"compete for cheap energy and compute. And we believe energy, compute, and AI "
|
|
"infrastructure will increasingly settle on money that is hard to produce, which points "
|
|
"directly at bitcoin. The companies that own and supply the scarce side of that equation "
|
|
"capture the value as demand grows. That is where we invest. (The bitcoin connection is a "
|
|
"forward-looking conviction, not a description of today. That gap is the opportunity.)"
|
|
)
|
|
PILLAR_2 = (
|
|
"We invest in foundational infrastructure with real revenue: the companies that generate "
|
|
"energy, secure capital, and power computation. Real businesses earning real money from "
|
|
"real demand today."
|
|
)
|
|
PILLAR_3 = (
|
|
"Founders come to us because of our experience and our genuine alignment with bitcoin. We "
|
|
"pursue and lead opportunities exclusive to us. People in this ecosystem know our track "
|
|
"record and want us on their side."
|
|
)
|
|
|
|
PROOF = (
|
|
"$200M+ deployed across two funds into 30+ of the strongest companies in the space "
|
|
"(Strike, Start9, energy and mining infrastructure). A six-year track record that includes "
|
|
"large-scale M&A and public-markets activity unmatched by others in this space. Fund III "
|
|
"continues the same strategy."
|
|
)
|
|
|
|
VOICE = (
|
|
"Direct, concrete, conviction-driven. No \"betting\" language, no em dashes, no \"X, not Y\" "
|
|
"phrasing, no kitchen-sink lists. Plain sentences a serious LP can verify in their head."
|
|
)
|
|
|
|
POSITIONING_NOTE = (
|
|
"Open partner decision: which banner do we lead with? Option A frames Ten31 around "
|
|
"scarcity; Option B frames it around freedom technology (a banner in the spirit of a16z's "
|
|
"\"American Dynamism\"). Both wordings are still being refined — use the Architect to draft "
|
|
"more options."
|
|
)
|
|
|
|
# segment_key -> (display name, definition, needs_to_hear angle)
|
|
SEGMENTS = [
|
|
("btc_native_hnwi", "Bitcoin-native HNWIs (OGs)",
|
|
"Long-time bitcoin holders with significant net worth who care about the ecosystem succeeding.",
|
|
"Bitcoin only wins if people build on it. Holding is not enough. You care about making "
|
|
"bitcoin succeed, and so do we. We put capital behind the companies that turn bitcoin into "
|
|
"a working economy.",
|
|
"Don't lecture OGs or imply they don't understand bitcoin; don't suggest that simply holding is the goal."),
|
|
("institution", "Institutions",
|
|
"Institutional allocators evaluating exposure to the bitcoin, energy, and AI buildout.",
|
|
"Exposure to the bitcoin, energy, and AI buildout through a team with a six-year "
|
|
"institutional track record, including large-scale M&A and public-markets activity unmatched "
|
|
"by others in this space (and Grant's prior institutional experience on top of that).",
|
|
"No hype or moonshot framing. Lead with the verifiable track record, not vision."),
|
|
("family_office", "Family offices",
|
|
"Multi-generational capital seeking durable, long-horizon allocations.",
|
|
"A long-horizon allocation grounded in real businesses, run by a team with deep credibility "
|
|
"and a real track record.",
|
|
"Avoid short-term or trader framing; emphasize durability, real businesses, and horizon."),
|
|
("smaller_accredited", "Smaller accredited ($100k)",
|
|
"Accredited investors entering at a more accessible commitment size.",
|
|
"The same thesis our most convicted investors back, at an accessible entry point.",
|
|
"Don't talk down to them; it is the same thesis, just an accessible entry point."),
|
|
("ai_energy_operator", "AI & energy operators",
|
|
"Operators in AI and energy who are not yet focused on bitcoin.",
|
|
"You may not be focused on bitcoin today, and that is exactly the point. We believe bitcoin "
|
|
"becomes a larger component of energy and compute over time, and most operators in your "
|
|
"space are not yet positioned for it. We are, and we invest across the stack that connects them.",
|
|
"Don't assume they're bitcoin-focused and don't preach; connect bitcoin as a growing "
|
|
"component of their world over time."),
|
|
]
|
|
|
|
|
|
def seed_v5(conn):
|
|
"""Insert the full v5 thesis (core line + per-segment lines + segments). Assumes
|
|
the caller has confirmed the thesis is empty; uses fresh ids."""
|
|
# ── segments table ──
|
|
for key, name, definition, needs, avoid in SEGMENTS:
|
|
sid = _eid("seg")
|
|
conn.execute(
|
|
"""INSERT INTO segments (id, segment_key, name, definition, needs_to_hear, avoid, version_no, status, created_at, updated_at)
|
|
VALUES (?,?,?,?,?,?,1,'active',?,?)""",
|
|
(sid, key, name, definition, needs, avoid, _now(), _now()),
|
|
)
|
|
|
|
# ── core line ──
|
|
core = _line(conn, "core", "Core Thesis", is_core=True,
|
|
description="The shared spine of the Ten31 thesis — throughline, banner, pillars, and proof.")
|
|
root = _node(conn, core, None, "thesis_root", 0, "Ten31 — Core Thesis", "")
|
|
_node(conn, core, root, "throughline", 1, "Throughline", THROUGHLINE)
|
|
|
|
pos = _node(conn, core, root, "section", 2, "Positioning / Banner (open debate)", POSITIONING_NOTE)
|
|
_node(conn, core, pos, "claim", 1, "Option A — Scarcity-forward", OPTION_A, status="candidate", variant_group="positioning")
|
|
_node(conn, core, pos, "claim", 2, "Option B — Freedom tech as the banner", OPTION_B, status="candidate", variant_group="positioning")
|
|
|
|
pillars = _node(conn, core, root, "section", 3, "Pillars", "")
|
|
_node(conn, core, pillars, "claim", 1, "1. Scarcity is the whole opportunity", PILLAR_1)
|
|
_node(conn, core, pillars, "claim", 2, "2. Foundational infrastructure with real revenue", PILLAR_2)
|
|
_node(conn, core, pillars, "claim", 3, "3. Founders seek us out, and we lead deals others never see", PILLAR_3)
|
|
|
|
_node(conn, core, root, "proof_point", 4, "The proof", PROOF)
|
|
_node(conn, core, root, "section", 5, "Voice", VOICE)
|
|
|
|
# ── per-segment lines ──
|
|
for key, name, _definition, needs, _avoid in SEGMENTS:
|
|
lid = _line(conn, f"seg_{key}", name, segment_key=key, is_core=False,
|
|
description=f"Segment-specific angle for {name}.")
|
|
sroot = _node(conn, lid, None, "thesis_root", 0, name, "")
|
|
_node(conn, lid, sroot, "segment_cut", 1, "Angle", needs)
|
|
|
|
return {"core_line": core, "segments": len(SEGMENTS)}
|
|
|
|
|
|
def ensure_thesis_seed(conn):
|
|
"""Seed the v5 thesis once, only when the Workshop is empty (no thesis lines).
|
|
Idempotent and non-destructive: never overwrites partner edits."""
|
|
try:
|
|
n = conn.execute("SELECT COUNT(*) FROM thesis_lines WHERE deleted_at IS NULL").fetchone()[0]
|
|
except sqlite3.OperationalError:
|
|
return # thesis tables not present yet (migration 0002 not applied)
|
|
if n:
|
|
return
|
|
out = seed_v5(conn)
|
|
_log(conn, "thesis.seeded_v5", out["core_line"], {"segments": out["segments"], "source": "thesis-seed-v5"})
|
|
conn.commit()
|
|
print(f"[thesis] seeded v5 thesis (core line + {out['segments']} segment lines)")
|