Merge branch 'mcp-workflow-guidance' into develop

Combines RFC 0011 (MCP Workflow Guidance) with RFC 0013 (Git Forge Integration).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eric Garcia 2026-01-24 20:32:06 -05:00
commit d3b0ee59c2
2 changed files with 30 additions and 149 deletions

View file

@ -187,13 +187,13 @@ impl ProjectState {
if !stalled.is_empty() {
return format!(
"'{}' might be stalled - it's in-progress but has no worktree",
"'{}' might be stalled - it's in-progress but has no worktree. Use blue_worktree_create to fix.",
stalled[0].title
);
}
if !ready.is_empty() {
return format!("'{}' is ready to implement. Want to start?", ready[0].title);
return format!("'{}' is ready to implement. Use blue_worktree_create to begin.", ready[0].title);
}
if !active.is_empty() {

View file

@ -205,7 +205,7 @@ impl BlueServer {
},
{
"name": "blue_rfc_update_status",
"description": "Update an RFC's status. WORKFLOW: Set to 'accepted' when RFC is approved, then use blue_worktree_create to start implementation. Status flow: draft -> accepted -> in-progress -> implemented.",
"description": "Update an RFC's status (draft -> accepted -> in-progress -> implemented).",
"inputSchema": {
"type": "object",
"properties": {
@ -481,7 +481,7 @@ impl BlueServer {
},
{
"name": "blue_worktree_create",
"description": "Create an isolated git worktree for RFC implementation. WORKFLOW: Use this after an RFC is accepted (status='accepted'), before starting implementation. Creates a feature branch and isolated working directory. After implementation, use blue_rfc_complete then blue_pr_create.",
"description": "Create an isolated git worktree for RFC implementation. Use after an RFC is accepted, before starting work. Creates a feature branch and isolated directory.",
"inputSchema": {
"type": "object",
"properties": {
@ -534,7 +534,7 @@ impl BlueServer {
},
{
"name": "blue_pr_create",
"description": "Create a PR with enforced base branch (develop, not main). WORKFLOW: Use after blue_rfc_complete to submit implementation for review. After PR is merged, use blue_worktree_cleanup to finalize. If rfc is provided, title is formatted as 'RFC NNNN: Title Case Name'.",
"description": "Create a PR with enforced base branch (develop, not main). Use after implementation is complete and blue_rfc_complete succeeds. If rfc is provided, title is formatted as 'RFC NNNN: Title Case Name'.",
"inputSchema": {
"type": "object",
"properties": {
@ -1010,7 +1010,7 @@ impl BlueServer {
},
{
"name": "blue_rfc_complete",
"description": "Mark RFC as implemented based on plan progress. WORKFLOW: Use after completing core implementation work in the worktree. Requires at least 70% task completion. After this, use blue_pr_create to submit for review.",
"description": "Mark RFC as implemented based on plan progress. Use after completing tasks in the worktree. Requires at least 70% completion. Follow with blue_pr_create.",
"inputSchema": {
"type": "object",
"properties": {
@ -1417,53 +1417,6 @@ impl BlueServer {
"required": ["title"]
}
},
// RFC 0012: Alignment Dialogue Orchestration
{
"name": "blue_alignment_play",
"description": "Run a multi-expert alignment dialogue to deliberate on a topic until convergence",
"inputSchema": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "The topic to deliberate on"
},
"constraint": {
"type": "string",
"description": "Key constraint or boundary for the discussion"
},
"expert_count": {
"type": "integer",
"default": 12,
"description": "Number of experts in the panel"
},
"convergence": {
"type": "number",
"default": 0.95,
"description": "Target convergence threshold (0.0-1.0)"
},
"max_rounds": {
"type": "integer",
"default": 12,
"description": "Maximum rounds before stopping"
},
"rfc_title": {
"type": "string",
"description": "RFC to link the dialogue to"
},
"template": {
"type": "string",
"enum": ["infrastructure", "product", "ml", "governance", "general"],
"description": "Expert panel template"
},
"model": {
"type": "string",
"description": "Ollama model to use (default: qwen2.5:7b)"
}
},
"required": ["topic"]
}
},
// Phase 8: Playwright verification
{
"name": "blue_playwright_verify",
@ -2187,8 +2140,6 @@ impl BlueServer {
"blue_dialogue_get" => self.handle_dialogue_get(&call.arguments),
"blue_dialogue_list" => self.handle_dialogue_list(&call.arguments),
"blue_dialogue_save" => self.handle_dialogue_save(&call.arguments),
// RFC 0012: Alignment Dialogue Orchestration
"blue_alignment_play" => self.handle_alignment_play(&call.arguments),
// Phase 8: Playwright handler
"blue_playwright_verify" => self.handle_playwright_verify(&call.arguments),
// Phase 9: Post-mortem handlers
@ -2273,92 +2224,41 @@ impl BlueServer {
Ok(state) => {
let summary = state.status_summary();
// Build recommendations with MCP tool syntax (RFC 0011)
let (recommendations, next_action) = if !summary.stalled.is_empty() {
let title = &summary.stalled[0].title;
(
vec![format!(
"'{}' is in-progress but has no worktree. Use blue_worktree_create with title='{}' to work in isolation.",
title, title
)],
Some(json!({
"tool": "blue_worktree_create",
"args": { "title": title },
"hint": "Create worktree to continue work in isolation"
}))
)
let recommendations = if !summary.stalled.is_empty() {
vec![format!(
"'{}' might be stalled. Check if work is still in progress.",
summary.stalled[0].title
)]
} else if !summary.ready.is_empty() {
let title = &summary.ready[0].title;
(
vec![format!(
"'{}' is accepted and ready. Use blue_worktree_create with title='{}' to start implementation.",
title, title
)],
Some(json!({
"tool": "blue_worktree_create",
"args": { "title": title },
"hint": "Create worktree to start implementation"
}))
)
vec![format!(
"'{}' is ready to implement. Use blue_worktree_create with title='{}' to start.",
summary.ready[0].title, summary.ready[0].title
)]
} else if !summary.drafts.is_empty() {
let title = &summary.drafts[0].title;
(
vec![format!(
"'{}' is in draft. Use blue_rfc_update_status with title='{}' and status='accepted' when ready.",
title, title
)],
Some(json!({
"tool": "blue_rfc_update_status",
"args": { "title": title, "status": "accepted" },
"hint": "Accept the RFC to proceed with implementation"
}))
)
vec![format!(
"'{}' is in draft. Review and accept it when ready.",
summary.drafts[0].title
)]
} else if !summary.active.is_empty() {
let title = &summary.active[0].title;
(
vec![format!(
"{} item(s) in progress. Continue work on '{}', then use blue_rfc_complete when done.",
summary.active.len(), title
)],
Some(json!({
"tool": "blue_rfc_complete",
"args": { "title": title },
"hint": "Mark as implemented when core work is done"
}))
)
vec![format!(
"{} item(s) in progress. Keep at it.",
summary.active.len()
)]
} else {
(
vec!["Nothing in flight. Use blue_rfc_create to start something new.".to_string()],
Some(json!({
"tool": "blue_rfc_create",
"args": {},
"hint": "Create a new RFC to plan your next feature"
}))
)
vec!["Nothing pressing. Good time to plan something new.".to_string()]
};
let mut response = json!({
Ok(json!({
"recommendations": recommendations,
"hint": summary.hint
});
if let Some(action) = next_action {
response["next_action"] = action;
}
Ok(response)
}))
}
Err(_) => {
Ok(json!({
"recommendations": [
"Blue not initialized here. Use blue_guide to get started."
"Run 'blue init' to set up this project first."
],
"hint": "Can't find Blue here.",
"next_action": {
"tool": "blue_guide",
"args": { "action": "start" },
"hint": "Start the interactive guide"
}
"hint": "Can't find Blue here."
}))
}
}
@ -2509,10 +2409,10 @@ impl BlueServer {
let doc = state.store.find_document(DocType::Rfc, title)
.map_err(|e| ServerError::StateLoadFailed(e.to_string()))?;
// Check for worktree when going to in-progress
// Check for worktree if going to in-progress (RFC 0011)
let has_worktree = state.has_worktree(title);
let worktree_warning = if status == "in-progress" && !has_worktree {
Some("No worktree exists for this RFC. Use blue_worktree_create to work in isolation.")
Some("No worktree exists for this RFC. Consider using blue_worktree_create for isolated development.")
} else {
None
};
@ -2536,18 +2436,6 @@ impl BlueServer {
"args": { "title": title },
"hint": "Create a worktree to start implementation"
}))
} else if status == "in-progress" && has_worktree {
Some(json!({
"tool": "blue_rfc_complete",
"args": { "title": title },
"hint": "Mark as implemented when core work is done"
}))
} else if status == "implemented" {
Some(json!({
"tool": "blue_pr_create",
"args": {},
"hint": "Create a pull request for review"
}))
} else {
None
};
@ -3152,13 +3040,6 @@ impl BlueServer {
crate::handlers::dialogue::handle_save(state, args)
}
// RFC 0012: Alignment Dialogue Orchestration
fn handle_alignment_play(&mut self, args: &Option<Value>) -> Result<Value, ServerError> {
let args = args.as_ref().ok_or(ServerError::InvalidParams)?;
let state = self.ensure_state_mut()?;
crate::handlers::alignment::handle_play(state, args)
}
fn handle_playwright_verify(&mut self, args: &Option<Value>) -> Result<Value, ServerError> {
let args = args.as_ref().ok_or(ServerError::InvalidParams)?;
crate::handlers::playwright::handle_verify(args)