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:
parent
e3ea201d45
commit
f33a8d8879
6 changed files with 614 additions and 0 deletions
Binary file not shown.
198
.blue/repos/blue/docs/rfcs/0001-dialogue-sqlite-metadata.md
Normal file
198
.blue/repos/blue/docs/rfcs/0001-dialogue-sqlite-metadata.md
Normal 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
|
||||
227
.blue/repos/blue/docs/rfcs/0002-runbook-action-lookup.md
Normal file
227
.blue/repos/blue/docs/rfcs/0002-runbook-action-lookup.md
Normal 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
|
||||
155
.blue/repos/blue/docs/rfcs/0003-per-repo-blue-folders.md
Normal file
155
.blue/repos/blue/docs/rfcs/0003-per-repo-blue-folders.md
Normal 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
|
||||
|
|
@ -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*
|
||||
|
|
@ -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*
|
||||
Loading…
Reference in a new issue