chore: sync state.rs and add RFC/spike documents

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Garcia 2026-01-24 20:32:32 -05:00
parent d3b0ee59c2
commit 19602c632b
9 changed files with 619 additions and 4 deletions

Binary file not shown.

View file

@ -0,0 +1,136 @@
# RFC 0011: MCP Workflow Guidance
| | |
|---|---|
| **Status** | In Progress |
| **Date** | 2026-01-25 |
| **Source Spike** | Inconsistent Worktree Creation in Claude MCP |
---
## Problem
Claude doesn't consistently create worktrees and feature branches when implementing RFCs via MCP. Investigation found five root causes:
1. **Tool descriptions lack workflow context** - `blue_worktree_create` says what it does but not *when* to use it
2. **CLI syntax in MCP responses** - `blue_next` says "Run 'blue worktree create'" instead of "Use blue_worktree_create"
3. **Hints don't name tools** - `generate_hint()` says "Want to start?" but doesn't say how
4. **No next_action on status change** - When RFC becomes "accepted", response has no guidance
5. **No warning on premature in-progress** - RFC can go in-progress without worktree, only detected later as "stalled"
The result: Claude skips worktree creation ~50% of the time, working directly on main branch.
## Goals
1. Claude creates worktrees consistently when implementing accepted RFCs
2. MCP responses guide Claude to the next workflow step
3. Tool descriptions explain their place in the workflow
4. Warnings surface when workflow is violated
## Non-Goals
- Enforcing worktree creation (just guiding)
- Changing the workflow itself
- CLI behavior changes (MCP only)
## Proposal
### 1. Add `next_action` field to status-changing responses
When `blue_rfc_update_status` changes status to "accepted":
```json
{
"status": "success",
"title": "my-feature",
"new_status": "accepted",
"next_action": {
"tool": "blue_worktree_create",
"args": { "title": "my-feature" },
"hint": "Create a worktree to start implementation"
}
}
```
### 2. Fix `blue_next` to use MCP tool syntax
Change:
```rust
"'{}' is ready to implement. Run 'blue worktree create {}' to start."
```
To:
```rust
"'{}' is ready to implement. Use blue_worktree_create with title='{}' to start."
```
### 3. Update `generate_hint()` to name tools
Change:
```rust
"'{}' is ready to implement. Want to start?"
```
To:
```rust
"'{}' is ready to implement. Use blue_worktree_create to begin."
```
### 4. Enhance tool descriptions with workflow context
Current:
```
"Create an isolated git worktree for RFC implementation."
```
Proposed:
```
"Create an isolated git worktree for RFC implementation. Use after an RFC is accepted, before starting work. Creates a feature branch and switches to isolated directory."
```
### 5. Add warning when RFC goes in-progress without worktree
In `handle_rfc_update_status`, when status becomes "in-progress":
```json
{
"status": "success",
"warning": "No worktree exists for this RFC. Consider creating one with blue_worktree_create.",
...
}
```
## Alternatives Considered
### A. Require worktree before in-progress
Rejected: Too restrictive. Some quick fixes don't need worktrees.
### B. Auto-create worktree on accept
Rejected: Side effects without explicit user action violate principle of least surprise.
### C. Add workflow documentation to MCP server description
Partial: Good idea but doesn't solve the in-context guidance problem.
## Implementation Plan
1. Add `next_action` struct and field to response types
2. Update `handle_rfc_update_status` to include next_action
3. Update `handle_next` to use MCP tool syntax
4. Update `generate_hint()` to name tools
5. Enhance tool descriptions in `handle_tools_list`
6. Add worktree warning in status transitions
## Test Plan
- [x] `blue_rfc_update_status` to "accepted" includes next_action with blue_worktree_create
- [x] `blue_next` output uses MCP tool syntax, not CLI syntax
- [x] `blue_status` hint mentions tool names
- [x] Tool description for blue_worktree_create includes workflow context
- [x] `blue_rfc_update_status` to "in-progress" warns if no worktree exists
- [ ] Manual test: Claude creates worktree after accepting RFC
---
*"Show, don't tell. But also tell, when showing isn't enough."*
— Blue

View file

@ -0,0 +1,180 @@
# RFC 0013: Git Forge Integration
| | |
|---|---|
| **Status** | Implemented |
| **Date** | 2026-01-25 |
| **Source Spike** | Git Forge Integration for Blue MCP |
---
## Problem
Blue's PR tools (`blue_pr_create`, `blue_pr_verify`, `blue_pr_merge`) shell out to `gh` CLI, which only works with GitHub. Users with Forgejo/Gitea remotes can't create PRs via Blue MCP - the commands fail silently or with cryptic errors.
This blocks the workflow for anyone not using GitHub.
## Goals
1. Native REST API integration for GitHub and Forgejo/Gitea
2. Auto-detect forge type from git remotes
3. Unified interface - same Blue tools work regardless of forge
4. No external CLI dependencies (`gh`, `tea`, etc.)
## Non-Goals
- GitLab support (different API, future RFC)
- Issue management (PRs only for now)
- Full forge feature parity (minimal surface for Blue's workflow)
## Proposal
### 1. Forge Trait
```rust
pub trait Forge: Send + Sync {
fn create_pr(&self, opts: CreatePrOpts) -> Result<PullRequest, ForgeError>;
fn get_pr(&self, owner: &str, repo: &str, number: u64) -> Result<PullRequest, ForgeError>;
fn merge_pr(&self, owner: &str, repo: &str, number: u64, strategy: MergeStrategy) -> Result<(), ForgeError>;
fn pr_is_merged(&self, owner: &str, repo: &str, number: u64) -> Result<bool, ForgeError>;
}
pub struct CreatePrOpts {
pub owner: String,
pub repo: String,
pub head: String, // branch with changes
pub base: String, // target branch
pub title: String,
pub body: Option<String>,
pub draft: bool,
}
pub enum MergeStrategy {
Merge,
Squash,
Rebase,
}
```
### 2. Implementations
**GitHubForge**
- Endpoint: `https://api.github.com/repos/{owner}/{repo}/pulls`
- Auth: `Authorization: Bearer {GITHUB_TOKEN}`
**ForgejoForge** (works with Gitea too)
- Endpoint: `https://{host}/api/v1/repos/{owner}/{repo}/pulls`
- Auth: `Authorization: token {FORGEJO_TOKEN}`
### 3. Auto-Detection
Parse git remotes to detect forge type:
```rust
fn detect_forge(remote_url: &str) -> ForgeType {
let url = parse_git_url(remote_url);
match url.host {
"github.com" => ForgeType::GitHub,
"codeberg.org" => ForgeType::Forgejo,
host if host.contains("gitea") => ForgeType::Forgejo,
host if host.contains("forgejo") => ForgeType::Forgejo,
_ => {
// Probe /api/v1/version - Forgejo/Gitea respond, GitHub doesn't
if probe_forgejo_api(&url.host) {
ForgeType::Forgejo
} else {
ForgeType::GitHub // fallback
}
}
}
}
```
Cache detected type in `.blue/config.yaml`:
```yaml
forge:
type: forgejo
host: git.beyondtheuniverse.superviber.com
owner: superviber
repo: blue
```
### 4. Token Resolution
Environment variables with fallback chain:
| Forge | Variables (in order) |
|-------|---------------------|
| GitHub | `GITHUB_TOKEN`, `GH_TOKEN` |
| Forgejo | `FORGEJO_TOKEN`, `GITEA_TOKEN` |
### 5. Updated MCP Tools
`blue_pr_create` changes:
- Remove `gh` CLI dependency
- Use detected forge's REST API
- Return PR URL directly
Response includes forge info:
```json
{
"status": "success",
"pr_url": "https://git.example.com/owner/repo/pulls/42",
"pr_number": 42,
"forge": "forgejo"
}
```
### 6. New Module Structure
```
crates/blue-core/src/
├── forge/
│ ├── mod.rs # Forge trait, ForgeType, detection
│ ├── github.rs # GitHub implementation
│ ├── forgejo.rs # Forgejo/Gitea implementation
│ └── git_url.rs # URL parsing utilities
```
## Alternatives Considered
### A. Keep shelling out to CLIs
Rejected: Requires users to install and configure `gh`/`tea`. Fragile, hard to get structured output.
### B. Use existing MCP servers (forgejo-mcp, github-mcp)
Rejected: Adds external dependencies. forgejo-mcp doesn't support PR creation. Better to own the integration.
### C. GitLab support in this RFC
Deferred: Different API patterns. Keep scope focused. Future RFC.
## Implementation Plan
1. Add `forge` module to blue-core with trait and types
2. Implement `ForgejoForge` with REST client
3. Implement `GitHubForge` with REST client
4. Add auto-detection logic with caching
5. Update `handle_pr_create` to use forge
6. Update `handle_pr_verify` and `handle_pr_merge`
7. Remove `gh` CLI dependency
## Test Plan
- [ ] ForgejoForge creates PR via REST API
- [ ] GitHubForge creates PR via REST API
- [ ] Auto-detection identifies github.com as GitHub
- [ ] Auto-detection identifies codeberg.org as Forgejo
- [ ] Auto-detection probes unknown hosts
- [ ] Token resolution finds FORGEJO_TOKEN
- [ ] Token resolution finds GITHUB_TOKEN
- [ ] blue_pr_create works with Forgejo remote
- [ ] blue_pr_create works with GitHub remote
- [ ] PR merge works with both forges
---
*"One interface, many forges. The abstraction serves the worker."*
— Blue

View file

@ -0,0 +1,22 @@
# RFC 0014: Test Workflow Guidance
| | |
|---|---|
| **Status** | Accepted |
| **Date** | 2026-01-25 |
---
## Summary
Test RFC to verify RFC 0011 workflow guidance works correctly.
## Test Plan
- [ ] TBD
---
*"Right then. Let's get to it."*
— Blue

View file

@ -0,0 +1,94 @@
# Spike: RFC Workflow Guidance Status
**Date:** 2025-01-24
**Time-box:** 30 minutes
**Status:** Complete
## Question
Does Blue have the RFC workflow baked in like coherence-mcp did?
## Short Answer
**No.** RFC 0011 was supposed to add this, but it's marked "Implemented" with all test items unchecked. The implementation is incomplete.
## Investigation
### What coherence-mcp Had (The Goal)
Baked-in workflow guidance that told Claude exactly what to do next:
- RFC accepted → "Use `blue_worktree_create` to start implementation"
- Worktree created → "Make your changes, then use `blue_pr_create`"
- PR merged → "Use `blue_worktree_cleanup` to finish"
Each response included `next_action` with the exact tool and args.
### What Blue Has Now
**Individual tools exist:**
- `blue_rfc_create` / `blue_rfc_update_status` / `blue_rfc_plan` / `blue_rfc_complete`
- `blue_worktree_create` / `blue_worktree_cleanup`
- `blue_pr_create` / `blue_pr_merge`
- `blue_status` / `blue_next`
**But no orchestration:**
- `blue_next` still uses CLI syntax: `"Run 'blue worktree create'"` (server.rs:2234)
- `blue_worktree_create` description lacks workflow context (server.rs:484)
- No `next_action` in RFC status changes
- No warning when RFC goes in-progress without worktree
### RFC 0011 Test Plan Status
| Test Item | Status |
|-----------|--------|
| `blue_rfc_update_status` to "accepted" includes next_action | ❌ Not done |
| `blue_next` uses MCP tool syntax | ❌ Not done |
| `blue_status` hint mentions tool names | ❌ Not done |
| `blue_worktree_create` description includes workflow context | ❌ Not done |
| `blue_rfc_update_status` warns if no worktree | ❌ Not done |
| Manual test: Claude creates worktree after accepting RFC | ❌ Not done |
**All 6 items unchecked, but RFC marked "Implemented".**
### Evidence from Code
```rust
// server.rs:2234 - Still uses CLI syntax
"'{}' is ready to implement. Run 'blue worktree create {}' to start."
// server.rs:484 - No workflow context
"description": "Create an isolated git worktree for RFC implementation."
// Only next_action in entire codebase (worktree.rs:256)
"next_action": "Execute the commands to sync with develop"
```
### What's Missing
1. **`next_action` struct** - Not added to response types
2. **MCP tool syntax in responses** - Still says "Run 'blue ...'" not "Use blue_..."
3. **Workflow context in descriptions** - Tools don't explain when to use them
4. **Worktree warnings** - No warning when RFC goes in-progress without worktree
5. **Generate hint improvements** - Hints don't name specific tools
## Root Cause
RFC 0011 was created and marked "Implemented" prematurely. There's even a worktree at `.blue/worktrees/mcp-workflow-guidance/` suggesting work started but wasn't completed.
## Recommendation
1. **Reopen RFC 0011** - Change status back to "in-progress"
2. **Implement the 6 test items** - They're well-specified already
3. **This will fix the worktree naming issue** - Claude will use Blue's tools instead of improvising
## Impact
Without this, Claude will continue to:
- Skip worktree creation ~50% of the time
- Invent its own worktree naming (like `../fungal-image-analysis-rfc0069`)
- Work directly on main branch
- Not follow the RFC workflow
## Outcome
RFC 0011 is the right solution but wasn't actually implemented. Completing it will give Blue the baked-in workflow guidance that coherence-mcp had.

View file

@ -0,0 +1,83 @@
# Spike: Worktree Naming Mismatch Investigation
**Date:** 2025-01-24
**Time-box:** 30 minutes
**Status:** Complete
## Problem
User reported seeing:
```
Done. Implementation complete in worktree ../fungal-image-analysis-rfc0069
(branch rfc0069-job-status-namespace)
```
The worktree/branch weren't created with the right names.
## Investigation
### Blue's Actual Worktree Naming Patterns
**Single-repo worktrees** (`crates/blue-mcp/src/handlers/worktree.rs`):
- Path: `~/.blue/worktrees/<stripped-name>` (e.g., `~/.blue/worktrees/job-status-namespace`)
- Branch: `<stripped-name>` (RFC number prefix stripped per RFC 0007)
- Example: RFC `0069-job-status-namespace` → branch `job-status-namespace`
**Realm multi-repo worktrees** (`crates/blue-mcp/src/handlers/realm.rs`):
- Path: `~/.blue/worktrees/<realm>/<rfc>/<repo>`
- Branch: `rfc/<rfc>` (prefixed with `rfc/`)
- Example: RFC `0069-job-status-namespace` → branch `rfc/0069-job-status-namespace`
### What the User Saw
- Path: `../fungal-image-analysis-rfc0069`
- Branch: `rfc0069-job-status-namespace`
### Key Finding: Not From Blue
The observed output doesn't match either Blue pattern:
| Aspect | Blue Single-Repo | Blue Realm | User Saw |
|--------|------------------|------------|----------|
| Path style | Absolute (`~/.blue/...`) | Absolute (`~/.blue/...`) | Relative (`../`) |
| Path components | `worktrees/<name>` | `worktrees/<realm>/<rfc>/<repo>` | `<repo>-<rfc>` |
| Branch format | `<stripped-name>` | `rfc/<rfc>` | `rfc<number>-<name>` (no slash) |
There's no code in Blue that:
1. Produces relative paths like `../`
2. Uses the squashed `rfc0069` format (no leading zeros, no separator)
3. Combines repo name with RFC number in a single path segment
## Root Cause
The message "Implementation complete in worktree" is **not from Blue** - it's from the LLM agent (Claude) that was implementing the feature.
The LLM agent likely:
1. **Constructed its own worktree path** instead of using `blue_worktree_create` or `blue_realm_worktree_create`
2. **Used `git worktree add` directly** via Bash, inventing its own naming convention
3. **Hallucinated the path/branch names** in its completion message
## Evidence
1. Searched Blue codebase for `../` pattern - not found
2. Searched for `rfc\d+` squashed format - not found (only `rfc3339` date formats)
3. Blue's worktree success messages don't include "Implementation complete"
4. Blue always uses absolute paths via `state.home.worktrees_path` or `DaemonPaths`
## Additional Issues Found
While investigating, identified these potential problems in Blue's worktree code:
1. **Inconsistent naming between single/realm**: Single-repo strips RFC number, realm preserves it with `rfc/` prefix
2. **Store failures silently ignored**: `let _ = state.store.add_worktree()` at worktree.rs:87
3. **Realm worktrees not persisted**: `realm.rs:551-691` never calls `add_worktree()`
## Recommendations
1. **Guide LLM agents**: Add clear instructions in `blue_guide` about always using Blue's worktree tools, never raw git worktree commands
2. **Validate in status**: `blue_status` could check for orphan worktrees (git worktrees not in Blue's store)
3. **Consider RFC for guidance**: Write an RFC for "LLM Agent Worktree Best Practices" if this recurs
## Outcome
The worktree naming wasn't wrong in Blue - the LLM agent bypassed Blue's tools entirely and invented its own naming. The fix is behavioral (prompt engineering/guidance) rather than code.

View file

@ -0,0 +1,17 @@
# Spike: Git Forge Integration for Blue MCP
| | |
|---|---|
| **Status** | In Progress |
| **Date** | 2026-01-25 |
| **Time Box** | 1 hour |
---
## Question
What APIs do Forgejo and GitHub expose for PR creation? How should Blue auto-detect which forge to use? What's the minimal API surface needed?
---
*Investigation notes by Blue*

View file

@ -0,0 +1,76 @@
# Spike: Develop Branch Workflow
| | |
|---|---|
| **Status** | Complete |
| **Date** | 2026-01-25 |
---
## Question
How should we implement the develop branch workflow for Blue, and what's needed to enforce it consistently?
---
## Findings
### Current State
| Branch | Location | Purpose |
|--------|----------|---------|
| `main` | forgejo, origin | Only branch - contains all production code |
| `git-forge-integration` | forgejo | RFC 0013 feature branch |
| `mcp-workflow-guidance` | forgejo | RFC 0011 feature branch |
**Problem:** `blue_pr_create` defaults to `develop` base and rejects `main`/`master`, but no `develop` branch exists. Feature branches can't be merged.
### The Workflow Model
```
main (production releases only)
↑ merge when releasing
develop (integration branch)
↑ PRs merge here
feature branches (rfc/*, feature/*)
```
**Why this matters:**
- `main` stays stable - only receives tested, integrated code
- `develop` is where features integrate before release
- Prevents accidental direct commits to production
- Enables release management (develop → main when ready)
### What's Needed
1. **Create `develop` branch** from current `main`
2. **Push to forgejo**
3. **Update forgejo settings** - set default branch to `develop`
4. **Rebase existing feature branches** onto `develop`
5. **Add `blue_release_create`** tool for develop → main merges
### Tool Enforcement (Already Done)
`blue_pr_create` in `pr.rs:59-71`:
- Defaults base to `develop`
- Rejects `main`/`master` with helpful message
- This is correct - just needs the branch to exist
## Recommendation
**Proceed.** Create the `develop` branch now. This is a one-time setup:
```bash
# From main branch
git checkout main
git checkout -b develop
git push forgejo develop
# On Forgejo: Settings → Branches → Default Branch → develop
```
Then existing feature branches can create PRs targeting `develop`.
## Outcome
Proceed with implementation - create develop branch and update forgejo settings.

View file

@ -180,6 +180,7 @@ impl ProjectState {
}
/// Generate a status hint for the user
/// Uses MCP tool syntax per RFC 0011
pub fn generate_hint(&self) -> String {
let active = self.active_items();
let ready = self.ready_items();
@ -187,20 +188,26 @@ impl ProjectState {
if !stalled.is_empty() {
return format!(
"'{}' might be stalled - it's in-progress but has no worktree. Use blue_worktree_create to fix.",
"'{}' is in-progress but has no worktree. Use blue_worktree_create to work in isolation.",
stalled[0].title
);
}
if !ready.is_empty() {
return format!("'{}' is ready to implement. Use blue_worktree_create to begin.", ready[0].title);
return format!(
"'{}' is ready to implement. Use blue_worktree_create to begin.",
ready[0].title
);
}
if !active.is_empty() {
return format!("{} item(s) currently in progress", active.len());
return format!(
"{} item(s) in progress. Use blue_rfc_complete when done.",
active.len()
);
}
"Nothing pressing right now. Good time to plan?".to_string()
"Nothing in flight. Use blue_rfc_create to start something new.".to_string()
}
/// Get project status summary