blue/.blue/docs/rfcs/0017-plan-file-authority.md
Eric Garcia 16d45d9a11 feat: alignment dialogue subagents, MCP instructions, and document batch
Alignment dialogues now use custom `alignment-expert` subagents with
max_turns: 10, tool restrictions (Read/Grep/Glob), and hard 400-word
output limits. Judge protocol injects as prose via RFC 0023. Moved
Blue voice patterns from CLAUDE.md to MCP server instructions field
for cross-repo portability.

Includes RFCs 0017-0026, spikes, and alignment dialogues from
2026-01-25/26 sessions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 07:09:39 -05:00

206 lines
5.8 KiB
Markdown

# RFC 0017: Plan File Authority
| | |
|---|---|
| **Status** | Superseded |
| **Superseded By** | [RFC 0022: Filesystem Authority](./0022-filesystem-authority.md) |
| **Date** | 2026-01-26 |
| **Dialogue** | [0001: Plan Files And Dialogue Separation](../dialogues/2026-01-25-plan-files-and-dialogue-separation.dialogue.md) |
---
## Summary
RFC task tracking currently requires loading entire RFC documents to check status. This creates token inefficiency and couples operational state with design documentation. By introducing `.plan.md` companion files as the authoritative source for task state (with SQLite as a derived index rebuilt on read), we achieve: 60-80% token reduction for status operations, cleaner git diffs, surgical commits, and separation of ephemeral operational state from permanent documentation.
## Problem
1. **Token Waste**: Loading a 2000-line RFC to check task status wastes tokens
2. **Coupled Concerns**: Operational state (tasks) mixed with design documentation (RFC content)
3. **Noisy Diffs**: Task status changes pollute RFC git history
4. **Cross-Repo Limitation**: When using Blue from another repo, no plan file support exists
5. **Header Format Drift**: RFC headers have drifted between table and inline formats
### Header Format Drift
The canonical RFC header uses a metadata table:
```markdown
# RFC 0058: Remove Training Infrastructure
| | |
|---|---|
| **Status** | Accepted |
| **Created** | 2026-01-24 |
| **Dialogue** | [0058-remove-training...](./0058-remove-training...) |
```
But some RFCs use inline format:
```markdown
# RFC 0075: Spot Capacity Providers
**Status**: Draft
**Created**: 2026-01-25
**Author**: Claude
```
The table format is canonical. Blue's `to_markdown()` generates it correctly, but manually-created or external RFCs may drift.
## Architecture
### Authority Inversion
The key insight: make `.plan.md` **authoritative**, not derived.
```
CURRENT (problematic):
RFC.md (source) → SQLite (derived) → .plan.md (derived)
Drift accumulates at each derivation step.
PROPOSED:
.plan.md (authoritative) → SQLite (derived index, rebuild-on-read)
Single source of truth. SQLite is ephemeral cache.
```
### File Structure
```
.blue/docs/rfcs/
├── 0017-plan-file-authority.md # Design documentation (permanent)
├── 0017-plan-file-authority.plan.md # Task state (ephemeral scaffolding)
└── ...
```
### Plan File Format
```markdown
# Plan: 0017-plan-file-authority
| | |
|---|---|
| **RFC** | 0017-plan-file-authority |
| **Status** | in-progress |
| **Updated** | 2026-01-26T10:30:00Z |
## Tasks
- [x] Define architecture
- [x] Run alignment dialogue
- [ ] Implement plan file parsing
- [ ] Add rebuild-on-read to SQLite
- [ ] Update blue_rfc_plan tool
- [ ] Update blue_rfc_task_complete tool
- [ ] Write tests
```
### Atomic Update Sequence
To prevent drift during writes:
```
1. Set RFC status: "updating-plan"
2. Write .plan.md file
3. Clear RFC status flag
4. SQLite rebuilds on next read
```
If interrupted between steps 1-3, the status flag indicates recovery needed.
### SQLite as Derived Index
```rust
// On any plan query:
fn get_plan_tasks(rfc_id: &str) -> Vec<Task> {
let plan_file = format!("{}.plan.md", rfc_id);
if plan_file.exists() && plan_file.mtime() > cache.mtime() {
// Rebuild cache from authoritative source
let tasks = parse_plan_markdown(&plan_file);
cache.rebuild(rfc_id, &tasks);
}
cache.get_tasks(rfc_id)
}
```
### API Unchanged
Existing tools work identically:
- `blue_rfc_plan` - Creates/updates `.plan.md` (now authoritative)
- `blue_rfc_task_complete` - Marks task done in `.plan.md`
Callers don't know or care about the authority change.
## Guardrails
From Git Workflow Expert (converged dialogue):
1. **Status Gating**: Plans only for `accepted` or `in-progress` RFCs
2. **File Limit**: Maximum 3 companion files per RFC (plan, test-plan, architecture notes)
3. **Single Responsibility**: Each companion file serves exactly one purpose
### Header Format Validation
Add `blue_lint` validation for RFC header format:
```rust
fn validate_rfc_header(content: &str) -> Result<(), LintError> {
// Must have table format, not inline
if content.contains("**Status**:") {
return Err(LintError::HeaderFormat {
expected: "| **Status** | value |",
found: "**Status**: value",
});
}
// Must have table structure
if !content.contains("| | |\n|---|---|") {
return Err(LintError::MissingMetadataTable);
}
Ok(())
}
```
The `blue_lint` tool should:
- Detect inline format (`**Status**: value`)
- Offer auto-fix to convert to table format
- Run on `blue_rfc_create` to catch manual edits
## Key Insight
> "Plans are like scaffolding - essential during construction, removed after completion."
The `.plan.md` file is **operational state**, not **documentation**. It exists to track work, then can be deleted or archived when the RFC completes. This "ephemeral framing" resolved documentation cohesion objections in the alignment dialogue.
## References
- **ADR 0005**: Single Source of Truth
- **ADR 0006**: Relationships (file co-location)
- **Dialogue 0001**: 12-expert alignment achieved 100% convergence on this architecture
## Test Plan
### Plan Files
- [ ] Create plan file for existing RFC
- [ ] Verify SQLite rebuilds from plan on read
- [ ] Verify atomic update sequence handles interruption
- [ ] Verify blue_rfc_plan creates companion file
- [ ] Verify blue_rfc_task_complete updates companion file
- [ ] Test cross-repo usage (Blue in external project)
- [ ] Verify status gating (no plans for draft RFCs)
### Header Format Validation
- [ ] Detect inline format (`**Status**: Draft`)
- [ ] Auto-fix inline to table format
- [ ] Validate table structure exists
- [ ] blue_lint reports header format errors
- [ ] blue_lint --fix converts inline to table
---
*"Right then. Let's get to it."*
— Blue