- 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>
10 KiB
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 §3–5. 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 3–5 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),ordas REAL (stable insert-between),variant_groupfor 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 onecanonicalversion per thesis. Each approved version also freezes abody_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_chunkscollection under newthesis_*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):
- Vary — generate ≥3 genuinely distinct framings of a target node, scored (sharpness, differentiation, evidence-backing, segment-portability, credibility).
- Revise — turn a free-text partner critique into a faithful before/after edit (never silently drop a framing the partner liked).
- Red-team — anticipate LP objections per segment, each with our drafted answer + an honest substantiated / hand-wavy flag.
- Consistency-check — when a throughline/pillar changes, surface every downstream node that now conflicts + a proposed reconciliation (apply none without partner acceptance).
- 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) onserver.py— not exposed as an agent tool. It atomically supersedes the prior canonical and writes athesis.approvedinteraction_logrow (actor_type='human', realusers.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'sbody_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 sourcethesis_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
draftwithout 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_jsoncontract is documented; a (future) Scribe draft is traceable to the exact approvedthesis_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; B–D become useful once the partners seed v1. Start the content prep (the four inputs above) in parallel.
Open decisions for the owner
- One thesis line, or several (one throughline vs. per-vertical theses)?
- The four content inputs above (seed, segments, voice, approval policy) — the critical path.
- Approval: single-partner vs. dual sign-off; a dedicated
thesis_approvercapability vs. reuseadmin. - 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. - 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)?
- May a claim be promoted while still
contested/unsubstantiated (a deliberate bet), or must the gate block on unresolved weaknesses?