Files
Claude-Code-Workflow/.claude/skills/team-issue/roles/integrator.md
catlog22 80b7dfc817 feat: Add roles for issue resolution pipeline including planner, reviewer, integrator, and implementer
- Implemented `planner` role for solution design and task decomposition using issue-plan-agent.
- Introduced `reviewer` role for solution review, technical feasibility validation, and risk assessment.
- Created `integrator` role for queue formation and conflict detection using issue-queue-agent.
- Added `implementer` role for code implementation and test verification via code-developer.
- Defined message types and role boundaries for each role to ensure clear responsibilities.
- Established a team configuration file to manage roles, pipelines, and collaboration patterns for the issue processing pipeline.
2026-02-15 13:51:50 +08:00

7.7 KiB
Raw Blame History

Role: integrator

队列编排、冲突检测、执行顺序优化。内部调用 issue-queue-agent 进行智能队列形成。

Role Identity

  • Name: integrator
  • Task Prefix: MARSHAL-*
  • Responsibility: Orchestration (queue formation)
  • Communication: SendMessage to coordinator only
  • Output Tag: [integrator]

Role Boundaries

MUST

  • 仅处理 MARSHAL-* 前缀的任务
  • 所有输出必须带 [integrator] 标识
  • 使用 issue-queue-agent 进行队列编排
  • 确保所有 issue 都有 bound solution 才能编排

MUST NOT

  • 修改解决方案planner 职责)
  • 审查方案质量reviewer 职责)
  • 实现代码implementer 职责)
  • 直接与其他 worker 通信
  • 为其他角色创建任务

Message Types

Type Direction Trigger Description
queue_ready integrator → coordinator Queue formed successfully 队列就绪,可执行
conflict_found integrator → coordinator File conflicts detected, user input needed 发现冲突需要人工决策
error integrator → coordinator Blocking error 队列编排失败

Toolbox

Subagent Capabilities

Agent Type Purpose
issue-queue-agent Receives solutions from bound issues, uses Gemini for conflict detection, produces ordered execution queue

CLI Capabilities

CLI Command Purpose
ccw issue status <id> --json Load issue details
ccw issue solutions <id> --json Verify bound solution
ccw issue list --status planned --json List planned issues

Execution (5-Phase)

Phase 1: Task Discovery

const tasks = TaskList()
const myTasks = tasks.filter(t =>
  t.subject.startsWith('MARSHAL-') &&
  t.owner === 'integrator' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)

if (myTasks.length === 0) return // idle

const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })

Phase 2: Collect Bound Solutions

// Extract issue IDs from task description
const issueIds = task.description.match(/(?:GH-\d+|ISS-\d{8}-\d{6})/g) || []

// Verify all issues have bound solutions
const unbound = []
const boundIssues = []

for (const issueId of issueIds) {
  const solJson = Bash(`ccw issue solutions ${issueId} --json`)
  const sol = JSON.parse(solJson)
  
  if (sol.bound) {
    boundIssues.push({ id: issueId, solution: sol.bound })
  } else {
    unbound.push(issueId)
  }
}

if (unbound.length > 0) {
  mcp__ccw-tools__team_msg({
    operation: "log", team: "issue", from: "integrator", to: "coordinator",
    type: "error",
    summary: `[integrator] Unbound issues: ${unbound.join(', ')} — cannot form queue`
  })
  SendMessage({
    type: "message", recipient: "coordinator",
    content: `## [integrator] Error: Unbound Issues\n\nThe following issues have no bound solution:\n${unbound.map(id => `- ${id}`).join('\n')}\n\nPlanner must create solutions before queue formation.`,
    summary: `[integrator] error: ${unbound.length} unbound issues`
  })
  return
}

Phase 3: Queue Formation via issue-queue-agent

// Invoke issue-queue-agent for intelligent queue formation
const agentResult = Task({
  subagent_type: "issue-queue-agent",
  run_in_background: false,
  description: `Form queue for ${issueIds.length} issues`,
  prompt: `
## Issues to Queue

Issue IDs: ${issueIds.join(', ')}

## Bound Solutions

${boundIssues.map(bi => `- ${bi.id}: Solution ${bi.solution.id} (${bi.solution.task_count} tasks)`).join('\n')}

## Instructions

1. Load all bound solutions from .workflow/issues/solutions/
2. Analyze file conflicts between solutions using Gemini CLI
3. Determine optimal execution order (DAG-based)
4. Produce ordered execution queue

## Expected Output

Write queue to: .workflow/issues/queue/execution-queue.json

Schema: {
  queue: [{ issue_id, solution_id, order, depends_on[], estimated_files[] }],
  conflicts: [{ issues: [id1, id2], files: [...], resolution }],
  parallel_groups: [{ group: N, issues: [...] }]
}
`
})

// Parse queue result
const queuePath = `.workflow/issues/queue/execution-queue.json`
let queueResult
try {
  queueResult = JSON.parse(Read(queuePath))
} catch {
  queueResult = null
}

Phase 4: Conflict Resolution

if (!queueResult) {
  // Queue formation failed
  mcp__ccw-tools__team_msg({
    operation: "log", team: "issue", from: "integrator", to: "coordinator",
    type: "error",
    summary: `[integrator] Queue formation failed — no output from issue-queue-agent`
  })
  SendMessage({
    type: "message", recipient: "coordinator",
    content: `## [integrator] Error\n\nQueue formation failed. issue-queue-agent produced no output.`,
    summary: `[integrator] error: queue formation failed`
  })
  return
}

// Check for unresolved conflicts
const unresolvedConflicts = (queueResult.conflicts || []).filter(c => c.resolution === 'unresolved')

if (unresolvedConflicts.length > 0) {
  mcp__ccw-tools__team_msg({
    operation: "log", team: "issue", from: "integrator", to: "coordinator",
    type: "conflict_found",
    summary: `[integrator] ${unresolvedConflicts.length} unresolved conflicts in queue`
  })
  
  SendMessage({
    type: "message", recipient: "coordinator",
    content: `## [integrator] Conflicts Found

**Unresolved Conflicts**: ${unresolvedConflicts.length}

${unresolvedConflicts.map((c, i) => `### Conflict ${i + 1}
- **Issues**: ${c.issues.join(' vs ')}
- **Files**: ${c.files.join(', ')}
- **Recommendation**: User decision needed — which issue takes priority`).join('\n\n')}

**Action Required**: Coordinator should present conflicts to user for resolution, then re-trigger MARSHAL.`,
    summary: `[integrator] conflict_found: ${unresolvedConflicts.length} conflicts`
  })
  return
}

Phase 5: Report to Coordinator

const queueSize = queueResult.queue?.length || 0
const parallelGroups = queueResult.parallel_groups?.length || 1

mcp__ccw-tools__team_msg({
  operation: "log",
  team: "issue",
  from: "integrator",
  to: "coordinator",
  type: "queue_ready",
  summary: `[integrator] Queue ready: ${queueSize} items in ${parallelGroups} parallel groups`,
  ref: queuePath
})

SendMessage({
  type: "message",
  recipient: "coordinator",
  content: `## [integrator] Queue Ready

**Queue Size**: ${queueSize} items
**Parallel Groups**: ${parallelGroups}
**Resolved Conflicts**: ${(queueResult.conflicts || []).filter(c => c.resolution !== 'unresolved').length}

### Execution Order
${(queueResult.queue || []).map((q, i) => `${i + 1}. ${q.issue_id} (Solution: ${q.solution_id})${q.depends_on?.length ? ` — depends on: ${q.depends_on.join(', ')}` : ''}`).join('\n')}

### Parallel Groups
${(queueResult.parallel_groups || []).map(g => `- Group ${g.group}: ${g.issues.join(', ')}`).join('\n')}

**Queue File**: ${queuePath}
**Status**: Ready for BUILD phase`,
  summary: `[integrator] MARSHAL complete: ${queueSize} items queued`
})

TaskUpdate({ taskId: task.id, status: 'completed' })

// Check for next task
const nextTasks = TaskList().filter(t =>
  t.subject.startsWith('MARSHAL-') &&
  t.owner === 'integrator' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)

if (nextTasks.length > 0) {
  // Continue with next task → back to Phase 1
}

Error Handling

Scenario Resolution
No MARSHAL-* tasks available Idle, wait for coordinator
Issues without bound solutions Report to coordinator, block queue formation
issue-queue-agent failure Retry once, then report error
Unresolved file conflicts Escalate to coordinator for user decision (CP-5)
Single issue (no conflict possible) Create trivial queue with one entry