feat: RFC 0051 Phase 1 - global perspective & tension tracking schema

RFC 0051 accepted and initial implementation:

- Added alignment_dialogues, alignment_experts, alignment_rounds tables
- Added alignment_perspectives, alignment_tensions with event tracking
- Added alignment_recommendations, alignment_evidence, alignment_claims
- Added alignment_refs table for cross-entity references
- Added alignment_verdicts table for final/interim/minority verdicts
- Created alignment_db.rs module with database operations
- Created alignment-expert skill with marker syntax reference

Schema version bumped from 8 to 9.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Garcia 2026-02-02 15:13:41 -05:00
parent e7f257a181
commit 401a6b1a45
5 changed files with 1999 additions and 2 deletions

View file

@ -2,7 +2,7 @@
| | |
|---|---|
| **Status** | Draft |
| **Status** | Accepted |
| **Date** | 2026-02-02 |
| **ADRs** | 0014 (Alignment Dialogue Agents), 0005 (Single Source), 0018 (DynamoDB-Portable Schema) |
| **Extends** | RFC 0048 (Expert Pools), RFC 0050 (Graduated Rotation) |

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
const _BLUE_SECRET_NAME: &str = "Sheepey"; // pronounced "Shee-paay"
pub mod alignment;
pub mod alignment_db;
pub mod daemon;
pub mod documents;
pub mod forge;

View file

@ -18,7 +18,7 @@ pub fn hash_content(content: &str) -> String {
}
/// Current schema version
const SCHEMA_VERSION: i32 = 8;
const SCHEMA_VERSION: i32 = 9;
/// Core database schema
const SCHEMA: &str = r#"
@ -1589,6 +1589,344 @@ impl DocumentStore {
)?;
}
// Migration from v8 to v9: Add alignment dialogue tables (RFC 0051)
if from_version < 9 {
debug!("Adding alignment dialogue tables (RFC 0051)");
// Root table for dialogues
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_dialogues (
dialogue_id TEXT PRIMARY KEY,
title TEXT NOT NULL,
question TEXT,
status TEXT NOT NULL DEFAULT 'open',
created_at TEXT NOT NULL,
converged_at TEXT,
total_rounds INTEGER DEFAULT 0,
total_alignment INTEGER DEFAULT 0,
output_dir TEXT,
calibrated INTEGER DEFAULT 0,
domain_id TEXT,
ethos_id TEXT,
background TEXT,
CHECK (status IN ('open', 'converging', 'converged', 'abandoned'))
)",
[],
)?;
self.conn.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS idx_alignment_dialogues_title_created
ON alignment_dialogues(title, created_at)",
[],
)?;
// Experts table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_experts (
dialogue_id TEXT NOT NULL,
expert_slug TEXT NOT NULL,
role TEXT NOT NULL,
description TEXT,
focus TEXT,
tier TEXT NOT NULL,
source TEXT NOT NULL,
relevance REAL,
creation_reason TEXT,
color TEXT,
scores TEXT,
raw_content TEXT,
total_score INTEGER DEFAULT 0,
first_round INTEGER,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, expert_slug),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (tier IN ('Core', 'Adjacent', 'Wildcard')),
CHECK (source IN ('pool', 'created', 'retained'))
)",
[],
)?;
// Rounds table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_rounds (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
title TEXT,
score INTEGER NOT NULL,
summary TEXT,
status TEXT NOT NULL DEFAULT 'open',
created_at TEXT NOT NULL,
completed_at TEXT,
PRIMARY KEY (dialogue_id, round),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (status IN ('open', 'in_progress', 'completed'))
)",
[],
)?;
// Perspectives table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_perspectives (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
seq INTEGER NOT NULL,
label TEXT NOT NULL,
content TEXT NOT NULL,
contributors TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open',
refs TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, round, seq),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (status IN ('open', 'refined', 'conceded', 'merged'))
)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_perspectives_dialogue_round
ON alignment_perspectives(dialogue_id, round, created_at)",
[],
)?;
// Perspective events
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_perspective_events (
dialogue_id TEXT NOT NULL,
perspective_round INTEGER NOT NULL,
perspective_seq INTEGER NOT NULL,
event_type TEXT NOT NULL,
event_round INTEGER NOT NULL,
actors TEXT NOT NULL,
result_id TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, perspective_round, perspective_seq, created_at),
FOREIGN KEY (dialogue_id, perspective_round, perspective_seq)
REFERENCES alignment_perspectives(dialogue_id, round, seq),
CHECK (event_type IN ('created', 'refined', 'conceded', 'merged'))
)",
[],
)?;
// Tensions table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_tensions (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
seq INTEGER NOT NULL,
label TEXT NOT NULL,
description TEXT NOT NULL,
contributors TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open',
refs TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, round, seq),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (status IN ('open', 'addressed', 'resolved', 'reopened'))
)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_tensions_status
ON alignment_tensions(dialogue_id, status)",
[],
)?;
// Tension events
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_tension_events (
dialogue_id TEXT NOT NULL,
tension_round INTEGER NOT NULL,
tension_seq INTEGER NOT NULL,
event_type TEXT NOT NULL,
event_round INTEGER NOT NULL,
actors TEXT NOT NULL,
reason TEXT,
reference TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, tension_round, tension_seq, created_at),
FOREIGN KEY (dialogue_id, tension_round, tension_seq)
REFERENCES alignment_tensions(dialogue_id, round, seq),
CHECK (event_type IN ('created', 'addressed', 'resolved', 'reopened', 'commented'))
)",
[],
)?;
// Recommendations table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_recommendations (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
seq INTEGER NOT NULL,
label TEXT NOT NULL,
content TEXT NOT NULL,
contributors TEXT NOT NULL,
parameters TEXT,
status TEXT NOT NULL DEFAULT 'proposed',
refs TEXT,
adopted_in_verdict TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, round, seq),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (status IN ('proposed', 'amended', 'adopted', 'rejected'))
)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_recommendations_status
ON alignment_recommendations(dialogue_id, status)",
[],
)?;
// Recommendation events
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_recommendation_events (
dialogue_id TEXT NOT NULL,
rec_round INTEGER NOT NULL,
rec_seq INTEGER NOT NULL,
event_type TEXT NOT NULL,
event_round INTEGER NOT NULL,
actors TEXT NOT NULL,
result_id TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, rec_round, rec_seq, created_at),
FOREIGN KEY (dialogue_id, rec_round, rec_seq)
REFERENCES alignment_recommendations(dialogue_id, round, seq),
CHECK (event_type IN ('created', 'amended', 'adopted', 'rejected'))
)",
[],
)?;
// Evidence table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_evidence (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
seq INTEGER NOT NULL,
label TEXT NOT NULL,
content TEXT NOT NULL,
contributors TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'cited',
refs TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, round, seq),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (status IN ('cited', 'challenged', 'confirmed', 'refuted'))
)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_evidence_status
ON alignment_evidence(dialogue_id, status)",
[],
)?;
// Claims table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_claims (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
seq INTEGER NOT NULL,
label TEXT NOT NULL,
content TEXT NOT NULL,
contributors TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'asserted',
refs TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, round, seq),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (status IN ('asserted', 'supported', 'opposed', 'adopted', 'withdrawn'))
)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_claims_status
ON alignment_claims(dialogue_id, status)",
[],
)?;
// Cross-references table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_refs (
dialogue_id TEXT NOT NULL,
source_type TEXT NOT NULL,
source_id TEXT NOT NULL,
ref_type TEXT NOT NULL,
target_type TEXT NOT NULL,
target_id TEXT NOT NULL,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, source_id, ref_type, target_id),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (source_type IN ('P', 'R', 'T', 'E', 'C')),
CHECK (target_type IN ('P', 'R', 'T', 'E', 'C')),
CHECK (ref_type IN ('support', 'oppose', 'refine', 'address', 'resolve', 'reopen', 'question', 'depend'))
)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_refs_target
ON alignment_refs(dialogue_id, target_id, ref_type)",
[],
)?;
self.conn.execute(
"CREATE INDEX IF NOT EXISTS idx_alignment_refs_source
ON alignment_refs(dialogue_id, source_id)",
[],
)?;
// Dialogue moves table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_moves (
dialogue_id TEXT NOT NULL,
round INTEGER NOT NULL,
seq INTEGER NOT NULL,
expert_slug TEXT NOT NULL,
move_type TEXT NOT NULL,
targets TEXT NOT NULL,
context TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, round, expert_slug, seq),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (move_type IN ('defend', 'challenge', 'bridge', 'request', 'concede', 'converge'))
)",
[],
)?;
// Verdicts table
self.conn.execute(
"CREATE TABLE IF NOT EXISTS alignment_verdicts (
dialogue_id TEXT NOT NULL,
verdict_id TEXT NOT NULL,
verdict_type TEXT NOT NULL,
round INTEGER NOT NULL,
author_expert TEXT,
recommendation TEXT NOT NULL,
description TEXT NOT NULL,
conditions TEXT,
vote TEXT,
confidence TEXT,
tensions_resolved TEXT,
tensions_accepted TEXT,
recommendations_adopted TEXT,
key_evidence TEXT,
key_claims TEXT,
supporting_experts TEXT,
ethos_compliance TEXT,
created_at TEXT NOT NULL,
PRIMARY KEY (dialogue_id, verdict_id),
FOREIGN KEY (dialogue_id) REFERENCES alignment_dialogues(dialogue_id),
CHECK (verdict_type IN ('interim', 'final', 'minority', 'dissent'))
)",
[],
)?;
}
// Update schema version
self.conn.execute(
"UPDATE schema_version SET version = ?1",

View file

@ -0,0 +1,209 @@
---
name: alignment-expert
description: Marker syntax reference for alignment dialogue expert agents (RFC 0051)
---
# Alignment Expert Skill
You are an expert participating in an ALIGNMENT dialogue. Structure your response using these markers.
## Local ID Format
Use your expert slug (UPPERCASE) with type prefix and 4-digit round+seq:
- `{EXPERT}-P{round:02d}{seq:02d}` — Perspective (e.g., MUFFIN-P0101)
- `{EXPERT}-R{round:02d}{seq:02d}` — Recommendation (e.g., MUFFIN-R0101)
- `{EXPERT}-T{round:02d}{seq:02d}` — Tension (e.g., MUFFIN-T0101)
- `{EXPERT}-E{round:02d}{seq:02d}` — Evidence (e.g., MUFFIN-E0101)
- `{EXPERT}-C{round:02d}{seq:02d}` — Claim (e.g., MUFFIN-C0101)
**Examples:**
- Your first perspective in round 1: `MUFFIN-P0101`
- Your second evidence in round 2: `MUFFIN-E0202`
- Your first recommendation in round 0: `MUFFIN-R0001`
The Judge will register these with global IDs (e.g., `P0101`, `R0001`).
## First-Class Entities
### Perspectives (P)
New viewpoints you're surfacing. Write with label and content:
```
[MUFFIN-P0101: Income mandate mismatch]
NVIDIA's zero dividend directly conflicts with the trust's 4% income requirement.
The gap is substantial: zero income from a $2.1M position that must contribute
to annual distributions.
```
### Recommendations (R)
Actionable proposals. Include parameters when applicable:
```
[MUFFIN-R0101: Options collar structure]
Implement a 30-delta covered call strategy on NVDA shares.
| Parameter | Value | Rationale |
|-----------|-------|-----------|
| Covered call delta | 0.20-0.25 | Balance premium vs upside |
| Protective put delta | -0.15 | Tail risk protection |
| DTE | 30-45 | Optimal theta decay |
```
### Tensions (T)
Unresolved issues requiring attention:
```
[MUFFIN-T0101: Growth vs income obligation]
Fundamental conflict between NVIDIA's growth profile (zero dividend) and the
trust's income mandate (4% annual distribution). One objective must yield.
```
### Evidence (E)
Concrete data supporting positions:
```
[MUFFIN-E0101: Historical options premium data]
NVDA 30-day ATM IV averaged 45% over past 24 months. 30-delta calls yielded
2.1-2.8% monthly premium. This data supports the viability of income generation
via options overlay.
```
### Claims (C)
Position statements that synthesize evidence and perspectives:
```
[MUFFIN-C0101: Income mandate resolved via options]
The 4% income mandate can be satisfied through covered call premium generation,
eliminating the primary objection to NVDA exposure. This claim depends on
E0101 (premium data) and is supported by P0001 (options viability).
```
## Cross-Reference Syntax
Reference other entities using `RE:TYPE` markers:
| Marker | Meaning | Example |
|--------|---------|---------|
| `RE:SUPPORT` | Strengthens target | `[RE:SUPPORT P0001]` — backs this perspective |
| `RE:OPPOSE` | Challenges target | `[RE:OPPOSE R0001]` — disagrees with recommendation |
| `RE:REFINE` | Improves on target (same type) | `[RE:REFINE P0001]` — builds on perspective |
| `RE:ADDRESS` | Speaks to a tension | `[RE:ADDRESS T0001]` — contributes to resolution |
| `RE:RESOLVE` | Claims to resolve tension | `[RE:RESOLVE T0001]` — proposes complete solution |
| `RE:DEPEND` | Requires target to hold | `[RE:DEPEND E0001]` — relies on this evidence |
| `RE:QUESTION` | Raises doubt about target | `[RE:QUESTION C0001]` — needs clarification |
**Usage in entity definitions:**
```
[MUFFIN-P0102: Options viability confirmed]
[RE:REFINE P0001] [RE:SUPPORT R0001] [RE:ADDRESS T0001]
The 30-delta covered call strategy is viable. Testing against historical data
confirms premium generation exceeds income requirements.
```
## Dialogue Moves
Signal your intent in the dialogue:
| Move | Use When |
|------|----------|
| `[MOVE:DEFEND target]` | Strengthening a challenged position |
| `[MOVE:CHALLENGE target]` | Raising concerns about a position |
| `[MOVE:BRIDGE targets]` | Reconciling conflicting perspectives |
| `[MOVE:REQUEST expert]` | Asking another expert for input |
| `[MOVE:CONCEDE target]` | Acknowledging another's point |
| `[MOVE:CONVERGE]` | Signaling agreement with emerging consensus |
**Example:**
```
[MOVE:BRIDGE P0001, R0001]
The income concern (P0001) and options strategy (R0001) can coexist.
Premium generation addresses income while preserving upside exposure.
```
## Verdict Markers (for Dissent)
If you disagree with the emerging verdict:
```
[DISSENT]
I cannot support the majority position. The concentration risk remains
unaddressed despite the income solution. My vote is REJECT.
[MINORITY VERDICT]
**Recommendation**: REJECT full position swap
**Conditions**: Maximum 50% conversion with phased entry
**Supporting experts**: Churro, Eclair
```
## Response Structure
Your response should flow naturally but include:
1. **Opening** — Your quick take on the current state
2. **Entities** — Perspectives, recommendations, tensions, evidence, claims with proper IDs
3. **Cross-references** — How your contributions relate to others
4. **Moves** — What you're doing in the dialogue (defend, challenge, bridge)
5. **Closing position** — One-sentence stance with confidence
**Example Response:**
```markdown
## Muffin (Value Analyst) — Round 1
The options overlay addresses my primary concern about income generation. However,
I want to ensure we've stress-tested this approach.
[MUFFIN-P0101: Options viability confirmed]
[RE:REFINE P0001] [RE:SUPPORT R0001] [RE:ADDRESS T0001]
Historical premium data supports the collar strategy. 30-delta covered calls on
NVDA yielded 2.1-2.8% monthly over the past 24 months—exceeding the 4% annual target.
[MUFFIN-E0101: Historical premium validation]
[RE:SUPPORT MUFFIN-P0101]
Backtested R0001 parameters against 2022-2024 data:
- Premium capture rate: 94%
- Called-away events: 3/24 months
- Effective annual yield: 26.4% (before assignment losses)
[MUFFIN-C0101: Income mandate resolved via options]
[RE:DEPEND MUFFIN-E0101] [RE:RESOLVE T0001]
The 4% income mandate can be satisfied through covered call premium generation,
eliminating the primary objection to NVDA exposure.
[MOVE:CONCEDE P0003]
Donut's original options proposal was directionally correct. My refinement adds
the quantitative backing.
**Position**: Conditional APPROVE with options overlay as specified in R0001.
**Confidence**: 0.85
```
## Scoring Principles
Your contribution is scored on **PRECISION**, not volume. One sharp insight beats ten paragraphs.
| Dimension | What Earns Points |
|-----------|-------------------|
| **Wisdom** | New perspectives, unique synthesis |
| **Consistency** | Internal logic, pattern adherence |
| **Truth** | Evidence-backed claims, grounded reasoning |
| **Relationships** | Productive cross-references, building on others |
## Key Rules
1. **Use local IDs**`MUFFIN-P0101`, not `P0101`. The Judge assigns global IDs.
2. **Be precise** — One sharp insight > ten paragraphs
3. **Build on others** — Use cross-references liberally
4. **Show your work** — Evidence supports claims supports positions
5. **Converge gracefully** — It's not about winning, it's about ALIGNMENT
---
*"The blind men describe what they touch. The elephant becomes visible."*