Files
ten31-database/docs/PHASE_1.md
T
Keysat 3e199fd8d5 Phase 1 Workstream A+E: thesis substrate + dual-approval gate
- migration 0002_phase1_architect: thesis_lines (core spine + per-segment lines),
  thesis_nodes (+ append-only revisions), thesis_versions (one-canonical-per-line
  DB invariant), thesis_reviews (dual approval + feedback), segments. Reversible.
- backend/mcp/architect_tools.py: agent draft tools (node tree, versions,
  segments, get_canonical fails-closed) — NO self-approval path. MCP-exposed.
- backend/thesis_review.py + server.py routes: human-gated approval. Dual sign-off
  via thesis_required_approvals; atomic supersede; every action logged.
- docs/PHASE_1.md (kickoff brief); docs/OPERATIONS.md (partner guide);
  start9/0.4 "Resolve duplicate names" fuzzy action.

Verified on synthetic data: dual approval promotes correctly, exactly one
canonical survives supersede, get_canonical fails closed, full interaction_log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 10:20:00 -05:00

10 KiB
Raw Blame History

Phase 1 — The Architect: Kickoff Brief

Goal: stand up the Architect — a collaborative copilot that helps the partners converge on and then continually evolve a versioned, evidence-grounded, partner-approved canonical thesis (the "messaging source of truth"). The Architect drafts and pressure-tests; a partner signs off; the approved thesis becomes the single source every later agent reads. Internal-only, collaborative, no outbound (that's Scribe/Closer, later).

See CLAUDE.md for settled architecture + guardrails; docs/Ten31_Agentic_Build_Plan.md §35. This brief assumes Phase 0 is built and deployed (canonical entities, the CRM MCP server with retrieval modes + interaction_log, the ingest pipeline).

Design stance (the load-bearing constraint)

Grant: "we are gravitating towards what we think the key message is, but we have NOT landed on it, and we may iterate over time." So the Architect is not a one-shot generator of a finished thesis — it is a substrate for exploration → convergence → continual evolution. The unit of iteration is a small typed node (one claim, one proof-point, one throughline), not a monolithic doc, so partners can rework one claim without re-litigating the whole narrative, hold competing phrasings side by side, and promote a winner while keeping the rest recoverable.

What the partners must supply (the content the substrate can't invent)

The Architect sharpens an existing thesis; it does not author one from nothing. These are inputs, co-authored in the first Architect sessions:

  • Thesis seed (v1): the current-best throughline (scarcity / critical-infrastructure tying bitcoin ↔ AI infrastructure / energy / freedom tech) broken into 35 pillars and a first set of testable claims.
  • LP segments (build-plan open decision #4): confirm/define the distinct audiences (proposed starter set: family office, institution, bitcoin-native HNWI, energy player) and, per segment, what they need to hear and what to avoid saying.
  • Voice: tone/diction, "this is us / this is not us" before-after examples, sacred phrases, words we never use.
  • Approval policy: who may promote a thesis version to canonical (any admin? Grant specifically? dual partner sign-off?).

Workstream A — Thesis artifact + versioning (substrate; buildable now, no content needed)

Additive, reversible migration 0002_phase1_architect.sql (+ .down.sql) via the existing core_migrations.py runner, reusing every Phase-0 convention (full-length ids, soft-delete only, interaction_log on every write).

  • thesis_nodes — typed node tree (thesis_root → throughline/section → claim → proof_point → objection/rebuttal → segment_cut), ord as REAL (stable insert-between), variant_group for competing A/B phrasings, status (draft|candidate|approved|retired).
  • thesis_node_revisions — append-only per-node history (prior content + change_summary/change_reason/actor/claude_session_id): fine-grained undo + provenance.
  • thesis_versions — immutable named snapshots; a DB-level partial-unique index guarantees at most one canonical version per thesis. Each approved version also freezes a body_json (throughline, pillars, claims, proof-points, segment angles, voice, guardrails) — the stable, machine-readable Architect→Scribe contract.
  • Publish-on-approval: approving a version publishes only its nodes into the existing Qdrant crm_chunks collection under new thesis_* doc_types (idempotent), and prunes the prior version's thesis chunks — so a downstream search for "the message" returns the approved version, never a draft.

(Design decision to confirm: the fine-grained node tree (powerful for iteration) plus a frozen body_json snapshot per approved version (simple, stable contract for Scribe) — keep both; the tree is the editing surface, the snapshot is the published artifact.)

Workstream B — The collaborative loop (Architect skills)

The copilot session is turn-based propose → react → revise, delivered as Agent SDK skills (one per move, independently testable) over a new backend/mcp/architect_tools.py surface (drafts only, every move logged; the agent can stage candidates but cannot cross the canonical gate):

  1. Vary — generate ≥3 genuinely distinct framings of a target node, scored (sharpness, differentiation, evidence-backing, segment-portability, credibility).
  2. Revise — turn a free-text partner critique into a faithful before/after edit (never silently drop a framing the partner liked).
  3. Red-team — anticipate LP objections per segment, each with our drafted answer + an honest substantiated / hand-wavy flag.
  4. Consistency-check — when a throughline/pillar changes, surface every downstream node that now conflicts + a proposed reconciliation (apply none without partner acceptance).
  5. Substantiate (ground) — see Workstream D. Plus a session-orchestration skill that loads state, sequences moves, and resumes across sessions (replays deferred proposals, the open-objection ledger, still-weak claims) — proving iteration spans sessions, not just turns.

Workstream C — Segments & voice

segments table (versioned; one active row per segment_key); reuse the Phase-0 canonical_entities.segment field as the pointer tagging each LP to a segment (closes the loop between who an LP is and what we say to them). Voice + each segment cut become skills (ten31-voice, ten31-thesis-spine, ten31-segment-cut); a segment cut must trace every claim to a spine pillar (orphans/contradictions surfaced), and a drift flag fires when a cut's spine version falls behind the active spine.

Workstream D — Grounding & defensibility

The corpus is a defensibility oracle, not a generator. Each claim is a structured object (draft|grounded|contested|retired) that cannot leave draft without ≥1 citation bundle pinned to a stable source_model:source_id and a completed counter-evidence sweep (the negation framing, not just the claim). An objection register per claim is assembled from get_interaction_history + keyword_search (recurring LP pushback). Stale-evidence (>~12mo via date_ts) is flagged for revalidation. Uses the Phase-0 retrieval modes unchanged.

  • Sovereignty: retrieval + embeddings stay local. The thesis content is non-LP-specific messaging substance → generally fine to send to Claude as-is. But the evidence (real LP conversations) used to ground it is sensitive → the Claude-facing synthesis step routes through the redaction/re-hydration boundary (docs/redaction-rehydration.md). The Architect is the first agent to send retrieved record substance to Claude, so this boundary must be built here (scrub/rehydrate at Spark Control).

Workstream E — Approval gate & Scribe contract

Canonicalization is a logged human action, enforced by capability not convention:

  • The promote-to-canonical edge is a human-authenticated CRM route (POST /api/thesis/{id}/approve, Bearer + admin) on server.pynot exposed as an agent tool. It atomically supersedes the prior canonical and writes a thesis.approved interaction_log row (actor_type='human', real users.id).
  • A thin "Thesis review" view in the existing SPA (frontend/index.html): diff candidate vs canonical, Approve / Request-changes.
  • get_canonical_thesis() returns the one canonical version's body_json, fails closed if none — so Scribe can never generate against an unapproved thesis.
  • Architect↔Scribe boundary: Architect owns/articulates and writes only to thesis_versions (never outbound); Scribe is a read-only consumer of the canonical version, stamps each draft with the source thesis_version_id, and routes through its own separate review-before-publish gate.

Acceptance criteria

  • Migration 0002 (additive, reversible) creates the thesis tables with the one-canonical invariant; applies + reverses cleanly via the existing runner.
  • A thesis exists as a typed node tree with a seeded, partner-signed canonical v1; renders back to a coherent document; supports competing variants with logged, reversible promotion.
  • A partner can run a full session (load → intent → any of the 5 moves in any order → accept/reject/defer → converge) in one Agent SDK conversation; a later session resumes from prior state.
  • No claim promotes past draft without a pinned citation + counter-sweep; every citation is auditable back to its memo/call/email/note.
  • No version becomes canonical except through the human route; the agent has no self-promotion path (tested). Every transition is in interaction_log.
  • The redaction boundary is built and asserts no Tier-1 content / no real Tier-2 identifier reaches Claude in the grounding step (golden-file test).
  • The Architect→Scribe body_json contract is documented; a (future) Scribe draft is traceable to the exact approved thesis_version_id.
  • No outbound/publish/contact capability anywhere in the Architect surface (guardrails #4, #6).

Out of scope for Phase 1 (Architect sub-phase)

  • The Scribe build (distribution/publishing) — defined here only as the downstream contract; built as the next sub-phase with review-before-publish.
  • Any outbound send, public post, or LP contact. Scout/Analyst (Phase 2), Closer/Orchestrator (Phase 3).

Suggested order

A (substrate) → E (gate + contract) → B (loop skills) → C (segments/voice) → D (grounding + redaction boundary). A and E are buildable now without the thesis content; BD become useful once the partners seed v1. Start the content prep (the four inputs above) in parallel.

Open decisions for the owner

  1. One thesis line, or several (one throughline vs. per-vertical theses)?
  2. The four content inputs above (seed, segments, voice, approval policy) — the critical path.
  3. Approval: single-partner vs. dual sign-off; a dedicated thesis_approver capability vs. reuse admin.
  4. Grounding dials (partner-set, not Claude): rerank-score floor for "real" support; doc_type source-weighting (memo/transcript > one-line note?); counter-evidence threshold to mark a claim contested.
  5. Phase-1 evidence scope: internal corpus only, or admit external sources (web/filings) before Scout/Analyst? And is the Gmail corpus live/backfilled (thin email evidence if not)?
  6. May a claim be promoted while still contested/unsubstantiated (a deliberate bet), or must the gate block on unresolved weaknesses?