#!/usr/bin/env python3 """Test the one-time Architect positioning-framings seed (thesis_seed.ensure_positioning_framings). Verifies: the 5 framings land as CANDIDATE options under the core line's positioning variant group (beside Option A/B); the insert is idempotent; an interaction_log sentinel prevents resurrection after a partner soft-deletes one; and per-framing + sentinel audit rows are written. Synthetic schema only (guardrail #9). Run: cd backend && python3 test_positioning_framings.py """ import os import sqlite3 import sys import tempfile sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import thesis_seed as ts # noqa: E402 SCHEMA = """ CREATE TABLE thesis_lines (id TEXT PRIMARY KEY, line_key TEXT, name TEXT, segment_key TEXT, is_core INT, description TEXT, created_at TEXT, updated_at TEXT, deleted_at TEXT); CREATE TABLE thesis_nodes (id TEXT PRIMARY KEY, line_id TEXT, parent_id TEXT, node_type TEXT, ord REAL, title TEXT, body TEXT, status TEXT, variant_group TEXT, created_at TEXT, updated_at TEXT, deleted_at TEXT); CREATE TABLE segments (id TEXT PRIMARY KEY, segment_key TEXT, name TEXT, definition TEXT, needs_to_hear TEXT, avoid TEXT, version_no INT, status TEXT, created_at TEXT, updated_at TEXT); CREATE TABLE interaction_log (id TEXT PRIMARY KEY, ts TEXT, actor_type TEXT, actor_id TEXT, action TEXT, target_type TEXT, target_id TEXT, payload TEXT, source TEXT, created_at TEXT); """ FAILS = [] def check(cond, msg): print((" PASS " if cond else " FAIL ") + msg) if not cond: FAILS.append(msg) def positioning(conn): return conn.execute( "SELECT title, status FROM thesis_nodes WHERE variant_group='positioning' AND deleted_at IS NULL ORDER BY ord" ).fetchall() def main(): db = os.path.join(tempfile.mkdtemp(), "t.db") conn = sqlite3.connect(db) conn.executescript(SCHEMA) conn.commit() ts.ensure_thesis_seed(conn) # core line + Option A/B + segments ts.ensure_positioning_framings(conn) # + 5 Architect framings opts = positioning(conn) check(len(opts) == 7, f"7 positioning options after seed (A,B + 5 framings), got {len(opts)}") check(all(s == "candidate" for _, s in opts), "every positioning option is candidate (nothing canonical)") check(sum("Architect" in t for t, _ in opts) == 5, "exactly 5 Architect framings inserted") ts.ensure_positioning_framings(conn) # idempotent check(len(positioning(conn)) == 7, "second run adds nothing (idempotent)") # a partner soft-deletes one framing; a restart must NOT resurrect it conn.execute("UPDATE thesis_nodes SET deleted_at='x' WHERE title LIKE 'Option C%'") conn.commit() ts.ensure_positioning_framings(conn) check(len(positioning(conn)) == 6, "soft-deleted framing is not resurrected on re-run (sentinel guard)") sentinel = conn.execute("SELECT COUNT(*) FROM interaction_log WHERE action='thesis.positioning_framings_seeded'").fetchone()[0] perframe = conn.execute("SELECT COUNT(*) FROM interaction_log WHERE action='thesis.framing_seeded'").fetchone()[0] check(sentinel == 1, f"exactly one sentinel row (got {sentinel})") check(perframe == 5, f"one audit row per framing (got {perframe})") conn.close() if FAILS: print(f"\nFAILED ({len(FAILS)})") for f in FAILS: print(" - " + f) sys.exit(1) print("\nALL PASS (positioning framings seed)") if __name__ == "__main__": main()