Seed the v5 thesis into the Architect Workshop (v0.1.0:53)
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>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Offline test for the v5 thesis seed (init_db auto-seed + idempotency).
|
||||
|
||||
Runs the real init_db against a throwaway DB (applies migration 0002 and the
|
||||
auto-seed), then asserts the Workshop substrate: a core line, one line per segment,
|
||||
the Option A/B banner as a 2-member variant group, the pillars/proof, and the
|
||||
segments table — and that re-seeding is a no-op.
|
||||
|
||||
Run: cd backend && python3 test_thesis_seed.py
|
||||
"""
|
||||
import os
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
_tmp = tempfile.mkdtemp()
|
||||
os.environ["CRM_DATA_DIR"] = _tmp
|
||||
os.environ["CRM_DB_PATH"] = os.path.join(_tmp, "crm.db")
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
import server # noqa: E402
|
||||
import thesis_seed # noqa: E402
|
||||
|
||||
FAILS = []
|
||||
|
||||
|
||||
def check(cond, msg):
|
||||
print((" PASS " if cond else " FAIL ") + msg)
|
||||
if not cond:
|
||||
FAILS.append(msg)
|
||||
|
||||
|
||||
def main():
|
||||
server.init_db()
|
||||
conn = sqlite3.connect(server.DB_PATH)
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
lines = {r["line_key"]: dict(r) for r in conn.execute("SELECT * FROM thesis_lines WHERE deleted_at IS NULL")}
|
||||
check("core" in lines and lines["core"]["is_core"] == 1, "core thesis line seeded (is_core)")
|
||||
seg_lines = [k for k in lines if k.startswith("seg_")]
|
||||
check(len(seg_lines) == 5, f"five per-segment lines seeded (got {len(seg_lines)}: {sorted(seg_lines)})")
|
||||
check(len(lines) == 6, f"exactly 6 lines total (got {len(lines)})")
|
||||
|
||||
core_id = lines["core"]["id"]
|
||||
nodes = [dict(r) for r in conn.execute("SELECT * FROM thesis_nodes WHERE line_id=?", (core_id,))]
|
||||
types = [n["node_type"] for n in nodes]
|
||||
check("throughline" in types, "core has a throughline node")
|
||||
check("proof_point" in types, "core has a proof_point node")
|
||||
variants = [n for n in nodes if n["variant_group"] == "positioning"]
|
||||
check(len(variants) == 2, f"Option A/B banner is a 2-member variant group (got {len(variants)})")
|
||||
pillars = [n for n in nodes if n["node_type"] == "claim" and n["title"] and n["title"][0] in "123"]
|
||||
check(len(pillars) == 3, f"three pillar claims (got {len(pillars)})")
|
||||
|
||||
segs = {r["segment_key"] for r in conn.execute("SELECT segment_key FROM segments WHERE status='active'")}
|
||||
check(segs == {"btc_native_hnwi", "institution", "family_office", "smaller_accredited", "ai_energy_operator"},
|
||||
f"five active segments (got {sorted(segs)})")
|
||||
|
||||
# segment lines each carry a segment_cut angle
|
||||
cut = conn.execute("""SELECT COUNT(*) FROM thesis_nodes n JOIN thesis_lines l ON l.id=n.line_id
|
||||
WHERE n.node_type='segment_cut' AND l.line_key LIKE 'seg_%'""").fetchone()[0]
|
||||
check(cut == 5, f"each segment line has a segment_cut angle (got {cut})")
|
||||
|
||||
# idempotency: re-seeding does nothing (thesis not empty)
|
||||
thesis_seed.ensure_thesis_seed(conn)
|
||||
conn.commit()
|
||||
n2 = conn.execute("SELECT COUNT(*) FROM thesis_lines WHERE deleted_at IS NULL").fetchone()[0]
|
||||
check(n2 == 6, f"re-seed is a no-op when thesis already exists (got {n2})")
|
||||
|
||||
conn.close()
|
||||
print()
|
||||
if FAILS:
|
||||
print(f"FAILED ({len(FAILS)})")
|
||||
sys.exit(1)
|
||||
print("ALL PASS (v5 thesis seed)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user