docs: Add 3 RFCs and 2 spikes from expert review

RFCs (95% expert-validated):
- 0001: Dialogue SQLite Metadata - index dialogues, keep content in markdown
- 0002: Runbook Action Lookup - action tags + lookup tool for runbooks
- 0003: Per-Repo Blue Folders - each repo gets its own .blue/

Spikes (completed):
- sqlite-storage-expansion - found spikes/plans already in SQLite
- per-repo-blue-folder - recommends per-repo .blue/ structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Garcia 2026-01-24 11:05:49 -05:00
parent e3ea201d45
commit f33a8d8879
6 changed files with 614 additions and 0 deletions

Binary file not shown.

View file

@ -0,0 +1,198 @@
# RFC 0001: Dialogue SQLite Metadata
| | |
|---|---|
| **Status** | Draft |
| **Date** | 2026-01-24 |
| **Source Spike** | sqlite-storage-expansion |
---
## Summary
Dialogue files (.dialogue.md) are not indexed in SQLite. Can't query them, link them to RFCs, or track relationships. Need to add DocType::Dialogue and store metadata while keeping content in markdown.
## Background
Dialogues are transcripts of conversations - different from RFCs/spikes which are living documents with status transitions.
Current state:
- Dialogues exist as `.dialogue.md` files in `docs/dialogues/`
- No SQLite tracking
- No way to search or link them
## Proposal
### 1. Add DocType::Dialogue
```rust
pub enum DocType {
Rfc,
Spike,
Adr,
Decision,
Prd,
Postmortem,
Runbook,
Dialogue, // NEW
}
```
### 2. Dialogue Metadata (SQLite)
Store in `documents` table:
- `doc_type`: "dialogue"
- `title`: Dialogue title
- `status`: "complete" (dialogues don't have status transitions)
- `file_path`: Path to .dialogue.md file
Store in `metadata` table:
- `date`: When dialogue occurred
- `participants`: Who was involved (e.g., "Claude, Eric")
- `linked_rfc`: RFC this dialogue relates to (optional)
- `topic`: Short description of what was discussed
### 3. New Tool: `blue_dialogue_create`
```
blue_dialogue_create title="realm-design-session" linked_rfc="cross-repo-realms"
```
Creates:
- Entry in documents table
- Metadata entries
- Skeleton .dialogue.md file
### 4. Dialogue File Format
```markdown
# Dialogue: Realm Design Session
| | |
|---|---|
| **Date** | 2026-01-24 |
| **Participants** | Claude, Eric |
| **Topic** | Designing cross-repo coordination |
| **Linked RFC** | [cross-repo-realms](../rfcs/0001-cross-repo-realms.md) |
---
## Context
[Why this dialogue happened]
## Key Decisions
- Decision 1
- Decision 2
## Transcript
[Full conversation or summary]
---
*Extracted by Blue*
```
### 5. Keep Content in Markdown
Unlike other doc types, dialogue content stays primarily in markdown:
- Full transcripts can be large
- Human-readable format preferred
- Git diff friendly
SQLite stores metadata only for:
- Fast searching
- Relationship tracking
- Listing/filtering
### 6. New Tool: `blue_dialogue_get`
```
blue_dialogue_get title="realm-design-session"
```
Returns dialogue metadata and file path.
### 7. New Tool: `blue_dialogue_list`
```
blue_dialogue_list linked_rfc="cross-repo-realms"
```
Returns all dialogues, optionally filtered by linked RFC.
### 8. Integration with `blue_extract_dialogue`
Existing `blue_extract_dialogue` extracts text from Claude JSONL. Extend to:
```
blue_extract_dialogue task_id="abc123" save_as="realm-design-session" linked_rfc="cross-repo-realms"
```
- Extract dialogue from JSONL
- Create .dialogue.md file
- Register in SQLite with metadata
### 9. Migration of Existing Dialogues
On first run, scan `docs/dialogues/` for `.dialogue.md` files:
- Parse frontmatter for metadata
- Register in documents table
- Preserve file locations
## Security Note
Dialogues may contain sensitive information discussed during development. Before committing:
- Review for credentials, API keys, or secrets
- Use `[REDACTED]` for sensitive values
- Consider if full transcript is needed vs summary
## Example Transcript Section
```markdown
## Transcript
**Eric**: How should we handle authentication for the API?
**Claude**: I'd recommend JWT tokens with short expiry. Here's why:
1. Stateless - no session storage needed
2. Can include claims for authorization
3. Easy to invalidate by changing signing key
**Eric**: What about refresh tokens?
**Claude**: Store refresh tokens in httpOnly cookies. When access token expires,
use refresh endpoint to get new pair. This balances security with UX.
**Decision**: Use JWT + refresh token pattern.
```
## Implementation
1. Add `DocType::Dialogue` to enum
2. Create `blue_dialogue_create` handler
3. Create `blue_dialogue_list` handler
4. Update `blue_search` to include dialogues
5. Add dialogue markdown generation
## Test Plan
- [ ] Create dialogue with metadata
- [ ] Link dialogue to RFC
- [ ] Dialogue without linked RFC works
- [ ] Search finds dialogues by title/topic
- [ ] List dialogues by RFC works
- [ ] List all dialogues works
- [ ] Get specific dialogue returns metadata
- [ ] Dialogue content stays in markdown
- [ ] Metadata stored in SQLite
- [ ] Existing dialogues migrated on first run
- [ ] Extract dialogue from JSONL creates proper entry
---
*"Right then. Let's get to it."*
— Blue

View file

@ -0,0 +1,227 @@
# RFC 0002: Runbook Action Lookup
| | |
|---|---|
| **Status** | Draft |
| **Date** | 2026-01-24 |
| **Source Spike** | runbook-driven-actions |
---
## Summary
No way to discover and follow runbooks when performing repo actions. Claude guesses instead of following documented procedures for docker builds, deploys, releases, etc.
## Proposal
### 1. Action Tags in Runbooks
Add `actions` field to runbook frontmatter:
```markdown
# Runbook: Docker Build
| | |
|---|---|
| **Status** | Active |
| **Actions** | docker build, build image, container build |
```
Store actions in SQLite metadata table for fast lookup.
### 2. New Tool: `blue_runbook_lookup`
```
blue_runbook_lookup action="docker build"
```
Returns structured response:
```json
{
"found": true,
"runbook": {
"title": "Docker Build",
"file": ".blue/docs/runbooks/docker-build.md",
"actions": ["docker build", "build image", "container build"],
"operations": [
{
"name": "Build Production Image",
"steps": ["...", "..."],
"verification": "docker images | grep myapp",
"rollback": "docker rmi myapp:latest"
}
]
},
"hint": "Follow the steps above. Use verification to confirm success."
}
```
If no match: `{ "found": false, "hint": "No runbook found. Proceed with caution." }`
### 3. New Tool: `blue_runbook_actions`
List all registered actions:
```
blue_runbook_actions
```
Returns:
```json
{
"actions": [
{ "action": "docker build", "runbook": "Docker Build" },
{ "action": "deploy staging", "runbook": "Deployment" },
{ "action": "run tests", "runbook": "Testing" }
]
}
```
### 4. Matching Algorithm
Word-based matching with priority:
1. **Exact match** - "docker build" matches "docker build" (100%)
2. **All words match** - "docker" matches "docker build" (90%)
3. **Partial words** - "build" matches "docker build" (80%)
If multiple runbooks match, return highest priority. Ties broken by most specific (more words in action).
### 5. Schema
```sql
-- In metadata table
INSERT INTO metadata (document_id, key, value)
VALUES (runbook_id, 'action', 'docker build');
-- Multiple actions = multiple rows
INSERT INTO metadata (document_id, key, value)
VALUES (runbook_id, 'action', 'build image');
```
### 6. Update `blue_runbook_create`
```
blue_runbook_create title="Docker Build" actions=["docker build", "build image"]
```
- Accept `actions` array parameter
- Store each action in metadata table
- Include in generated markdown
### 7. CLAUDE.md Guidance
Document the pattern for repos:
```markdown
## Runbooks
Before executing build, deploy, or release operations:
1. Check for runbook: `blue_runbook_lookup action="docker build"`
2. If found, follow the documented steps
3. Use verification commands to confirm success
4. If something fails, check rollback procedures
Available actions: `blue_runbook_actions`
```
## Security Note
Runbooks should **never** contain actual credentials or secrets. Use placeholders:
```markdown
**Steps**:
1. Export credentials: `export API_KEY=$YOUR_API_KEY`
2. Run deploy: `./deploy.sh`
```
Not:
```markdown
**Steps**:
1. Run deploy: `API_KEY=abc123 ./deploy.sh` # WRONG!
```
## Example Runbook
```markdown
# Runbook: Docker Build
| | |
|---|---|
| **Status** | Active |
| **Actions** | docker build, build image, container build |
| **Owner** | Platform Team |
---
## Overview
Build and tag Docker images for the application.
## Prerequisites
- [ ] Docker installed and running
- [ ] Access to container registry
- [ ] `.env` file configured
## Common Operations
### Operation: Build Production Image
**When to use**: Preparing for deployment
**Steps**:
1. Ensure on correct branch: `git branch --show-current`
2. Pull latest: `git pull origin main`
3. Build image: `docker build -t myapp:$(git rev-parse --short HEAD) .`
4. Tag as latest: `docker tag myapp:$(git rev-parse --short HEAD) myapp:latest`
**Verification**:
```bash
docker images | grep myapp
docker run --rm myapp:latest --version
```
**Rollback**:
```bash
docker rmi myapp:latest
docker tag myapp:previous myapp:latest
```
## Troubleshooting
### Symptom: Build fails with "no space left"
**Resolution**:
1. `docker system prune -a`
2. Retry build
```
## Implementation
1. Add `actions` parameter to `blue_runbook_create`
2. Store actions in metadata table
3. Implement `blue_runbook_lookup` with matching algorithm
4. Implement `blue_runbook_actions` for discovery
5. Parse runbook markdown to extract operations
6. Update runbook markdown generation
## Test Plan
- [ ] Create runbook with actions tags
- [ ] Lookup by exact action match
- [ ] Lookup by partial match (word subset)
- [ ] No match returns gracefully
- [ ] Multiple runbooks - highest priority wins
- [ ] List all actions works
- [ ] Actions stored in SQLite metadata
- [ ] Operations parsed from markdown correctly
- [ ] Malformed runbook returns partial data gracefully
---
*"Right then. Let's get to it."*
— Blue

View file

@ -0,0 +1,155 @@
# RFC 0003: Per Repo Blue Folders
| | |
|---|---|
| **Status** | Draft |
| **Date** | 2026-01-24 |
| **Source Spike** | per-repo-blue-folder |
---
## Summary
Currently all docs flow to one central .blue folder. Each repo should have its own .blue folder so docs live with code and git tracking works naturally.
## Current Behavior
```
blue/ # Central repo
├── .blue/
│ ├── repos/
│ │ ├── blue/docs/... # Blue's docs
│ │ └── other-repo/docs/ # Other repo's docs (wrong!)
│ └── data/
│ └── blue/blue.db
```
All repos' docs end up in the blue repo's `.blue/repos/`.
## Proposed Behavior
```
repo-a/
├── .blue/
│ ├── docs/
│ │ ├── rfcs/
│ │ ├── spikes/
│ │ └── runbooks/
│ └── blue.db
└── src/...
repo-b/
├── .blue/
│ ├── docs/...
│ └── blue.db
└── src/...
```
Each repo has its own `.blue/` with its own docs and database.
## Changes Required
### 1. Simplify BlueHome structure
```rust
pub struct BlueHome {
pub root: PathBuf, // Repo root
pub blue_dir: PathBuf, // .blue/
pub docs_path: PathBuf, // .blue/docs/
pub db_path: PathBuf, // .blue/blue.db
}
```
### 2. Change detect_blue behavior
- Find git repo root for current directory
- Look for `.blue/` there (don't search upward beyond repo)
- Auto-create on first blue command (no `blue init` required)
**Edge cases:**
- No git repo: Create `.blue/` in current directory with warning
- Monorepo: One `.blue/` at git root (packages share it)
- Subdirectory: Always resolve to git root
### 3. Flatten docs structure
Before: `.blue/repos/<project>/docs/rfcs/`
After: `.blue/docs/rfcs/`
No need for project subdirectory when per-repo.
### 4. Migration
Automatic on first run:
1. Detect old structure (`.blue/repos/` exists)
2. Find docs for current project in `.blue/repos/<project>/docs/`
3. Move to `.blue/docs/`
4. Migrate database entries
5. Clean up empty directories
6. Log what was migrated
**Conflict resolution:** If docs exist in both locations, prefer newer by mtime.
## Git Tracking
Repos should commit their `.blue/` folder:
**Track:**
- `.blue/docs/**` - RFCs, spikes, runbooks, etc.
- `.blue/blue.db` - SQLite database (source of truth)
- `.blue/config.yaml` - Configuration
**Gitignore:**
- `.blue/*.db-shm` - SQLite shared memory (transient)
- `.blue/*.db-wal` - SQLite write-ahead log (transient)
Recommended `.gitignore` addition:
```
# Blue transient files
.blue/*.db-shm
.blue/*.db-wal
```
## Cross-Repo Coordination
The daemon/realm system (RFC 0001) handles cross-repo concerns:
- Central daemon tracks active sessions
- Realms coordinate contracts between repos
- Each repo remains self-contained
## FAQ
**Q: Do I need to run `blue init`?**
A: No. Blue auto-creates `.blue/` on first command.
**Q: What about my existing docs in the central location?**
A: Auto-migrated on first run. Check git status to verify.
**Q: Should I commit `.blue/blue.db`?**
A: Yes. It's the source of truth for your project's Blue state.
**Q: What if I'm in a monorepo?**
A: One `.blue/` at the git root. All packages share it.
**Q: Can I use Blue without git?**
A: Yes, but with a warning. `.blue/` created in current directory.
**Q: How do I see cross-repo status?**
A: Use `blue realm_status` (requires daemon running).
## Test Plan
- [ ] New repo gets `.blue/` on first blue command
- [ ] Docs created in repo's own `.blue/docs/`
- [ ] Database at `.blue/blue.db`
- [ ] Old structure migrated automatically
- [ ] Realm/daemon still works across repos
- [ ] No git repo falls back gracefully with warning
- [ ] Monorepo uses single `.blue/` at root
---
*"Right then. Let's get to it."*
— Blue

View file

@ -0,0 +1,17 @@
# Spike: Per Repo Blue Folder
| | |
|---|---|
| **Status** | Complete |
| **Date** | 2026-01-24 |
| **Time Box** | 1 hour |
---
## Question
Should each repo have its own .blue folder with docs, or centralize in one location? What are the tradeoffs and what changes are needed?
---
*Investigation notes by Blue*

View file

@ -0,0 +1,17 @@
# Spike: Runbook Driven Actions
| | |
|---|---|
| **Status** | Complete |
| **Date** | 2026-01-24 |
| **Time Box** | 2 hours |
---
## Question
How can runbooks guide Claude Code through repo actions (docker builds, deploys, tests) so it follows the documented steps rather than guessing?
---
*Investigation notes by Blue*