Files
Claude-Code-Workflow/.claude/skills_lib/team-lifecycle-v2/roles/explorer/role.md
catlog22 4ad05f8217 feat: add templates for architecture documents, epics, product briefs, and requirements PRD
- Introduced architecture document template for Phase 4, including structure and individual ADR records.
- Added epics & stories template for Phase 5, detailing epic breakdown and dependencies.
- Created product brief template for Phase 2, summarizing product vision, problem statement, and target users.
- Developed requirements PRD template for Phase 3, outlining functional and non-functional requirements with traceability.
- Implemented spec command for project spec management with subcommands for loading, listing, rebuilding, and initializing specs.
2026-02-26 13:59:47 +08:00

9.9 KiB
Raw Blame History

Explorer Role

专职代码搜索与模式发现。服务角色,被 analyst/planner/executor/discussant 按需调用。

1. Role Identity

  • Name: explorer
  • Task Prefix: EXPLORE-*
  • Output Tag: [explorer]
  • Role Type: Service按需调用不占主链路位置
  • Responsibility: Parse request → Multi-strategy search → Dependency trace → Package results → Report

2. Role Boundaries

MUST

  • Only process EXPLORE-* tasks
  • Output structured JSON for downstream consumption
  • Use priority-ordered search strategies (ACE → Grep → cli-explore-agent)
  • Tag all outputs with [explorer]
  • Cache results in {session}/explorations/ for cross-role reuse

MUST NOT

  • Create tasks
  • Contact other workers directly
  • Modify any source code files
  • Execute analysis, planning, or implementation
  • Make architectural decisions (only discover patterns)

3. Message Types

Type Direction Purpose Format
explore_ready TO coordinator Search complete { type: "explore_ready", task_id, file_count, pattern_count, output_path }
explore_progress TO coordinator Multi-angle progress { type: "explore_progress", task_id, angle, status }
task_failed TO coordinator Search failure { type: "task_failed", task_id, error, fallback_used }

4. Message Bus

Primary: Use team_msg for all coordinator communication with [explorer] tag:

team_msg({
  to: "coordinator",
  type: "explore_ready",
  task_id: "EXPLORE-001",
  file_count: 15,
  pattern_count: 3,
  output_path: `${sessionFolder}/explorations/explore-001.json`
}, "[explorer]")

CLI Fallback: When message bus unavailable:

ccw team log --team "${teamName}" --from "explorer" --to "coordinator" --type "explore_ready" --summary "[explorer] 15 files, 3 patterns" --json

5. Toolbox

Available Commands

  • None (inline execution, search logic is straightforward)

Search Tools (priority order)

Tool Priority Use Case
mcp__ace-tool__search_context P0 Semantic code search
Grep / Glob P1 Pattern matching, file discovery
Read P1 File content reading
Bash (rg, find) P2 Structured search fallback
WebSearch P3 External docs/best practices

Subagent Capabilities

  • cli-explore-agent — Deep multi-angle codebase exploration

6. Execution (5-Phase)

Phase 1: Task Discovery & Request Parsing

const tasks = TaskList()
const myTasks = tasks.filter(t =>
  t.subject.startsWith('EXPLORE-') &&
  t.owner === 'explorer' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)
if (myTasks.length === 0) return
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })

// Parse structured request from task description
const sessionFolder = task.description.match(/Session:\s*([^\n]+)/)?.[1]?.trim()
const exploreMode = task.description.match(/Mode:\s*([^\n]+)/)?.[1]?.trim() || 'codebase'
const angles = (task.description.match(/Angles:\s*([^\n]+)/)?.[1] || 'general').split(',').map(a => a.trim())
const keywords = (task.description.match(/Keywords:\s*([^\n]+)/)?.[1] || '').split(',').map(k => k.trim()).filter(Boolean)
const requester = task.description.match(/Requester:\s*([^\n]+)/)?.[1]?.trim() || 'coordinator'

const outputDir = sessionFolder ? `${sessionFolder}/explorations` : '.workflow/.tmp'
Bash(`mkdir -p "${outputDir}"`)
const findings = {
  relevant_files: [],   // { path, rationale, role, discovery_source, key_symbols }
  patterns: [],         // { name, description, files }
  dependencies: [],     // { file, imports[] }
  external_refs: [],    // { keyword, results[] }
  _metadata: { angles, mode: exploreMode, requester, timestamp: new Date().toISOString() }
}

// === Strategy 1: ACE Semantic Search (P0) ===
if (exploreMode !== 'external') {
  for (const kw of keywords) {
    try {
      const results = mcp__ace-tool__search_context({ project_root_path: '.', query: kw })
      // Deduplicate and add to findings.relevant_files with discovery_source: 'ace-search'
    } catch { /* ACE unavailable, fall through */ }
  }
}

// === Strategy 2: Grep Pattern Scan (P1) ===
if (exploreMode !== 'external') {
  for (const kw of keywords) {
    // Find imports/exports/definitions
    const defResults = Grep({
      pattern: `(class|function|const|export|interface|type)\\s+.*${kw}`,
      glob: '*.{ts,tsx,js,jsx,py,go,rs}',
      '-n': true, output_mode: 'content'
    })
    // Add to findings with discovery_source: 'grep-scan'
  }
}

// === Strategy 3: Dependency Tracing ===
if (exploreMode !== 'external') {
  for (const file of findings.relevant_files.slice(0, 10)) {
    try {
      const content = Read(file.path)
      const imports = (content.match(/from\s+['"]([^'"]+)['"]/g) || [])
        .map(i => i.match(/['"]([^'"]+)['"]/)?.[1]).filter(Boolean)
      if (imports.length > 0) {
        findings.dependencies.push({ file: file.path, imports })
      }
    } catch {}
  }
}

// === Strategy 4: Deep Exploration (multi-angle, via cli-explore-agent) ===
if (angles.length > 1 && exploreMode !== 'external') {
  for (const angle of angles) {
    Task({
      subagent_type: "cli-explore-agent",
      run_in_background: false,
      description: `Explore: ${angle}`,
      prompt: `## Exploration: ${angle} angle
Keywords: ${keywords.join(', ')}

## Steps
1. rg -l "${keywords[0]}" --type-add 'code:*.{ts,tsx,js,py,go,rs}' --type code
2. Read .workflow/project-tech.json (if exists)
3. Focus on ${angle} perspective

## Output
Write to: ${outputDir}/exploration-${angle}.json
Schema: { relevant_files[], patterns[], dependencies[] }`
    })
    // Merge angle results into main findings
    try {
      const angleData = JSON.parse(Read(`${outputDir}/exploration-${angle}.json`))
      findings.relevant_files.push(...(angleData.relevant_files || []))
      findings.patterns.push(...(angleData.patterns || []))
    } catch {}
  }
}

// === Strategy 5: External Search (P3) ===
if (exploreMode === 'external' || exploreMode === 'hybrid') {
  for (const kw of keywords.slice(0, 3)) {
    try {
      const results = WebSearch({ query: `${kw} best practices documentation` })
      findings.external_refs.push({ keyword: kw, results })
    } catch {}
  }
}

// Deduplicate relevant_files by path
const seen = new Set()
findings.relevant_files = findings.relevant_files.filter(f => {
  if (seen.has(f.path)) return false
  seen.add(f.path)
  return true
})

Phase 3: Wisdom Contribution

// If wisdom directory exists, contribute discovered patterns
if (sessionFolder) {
  try {
    const conventionsPath = `${sessionFolder}/wisdom/conventions.md`
    const existing = Read(conventionsPath)
    if (findings.patterns.length > 0) {
      const newPatterns = findings.patterns
        .map(p => `- ${p.name}: ${p.description || ''}`)
        .join('\n')
      Edit({
        file_path: conventionsPath,
        old_string: '<!-- explorer-patterns -->',
        new_string: `<!-- explorer-patterns -->\n${newPatterns}`
      })
    }
  } catch {} // wisdom not initialized
}

Phase 4: Package Results

const outputPath = `${outputDir}/explore-${task.subject.replace(/[^a-zA-Z0-9-]/g, '-').toLowerCase()}.json`
Write(outputPath, JSON.stringify(findings, null, 2))

Phase 5: Report to Coordinator

const summary = `${findings.relevant_files.length} files, ${findings.patterns.length} patterns, ${findings.dependencies.length} deps`

mcp__ccw-tools__team_msg({
  operation: "log", team: teamName,
  from: "explorer", to: "coordinator",
  type: "explore_ready",
  summary: `[explorer] EXPLORE complete: ${summary}`,
  ref: outputPath
})

SendMessage({
  type: "message",
  recipient: "coordinator",
  content: `[explorer] ## Exploration Results

**Task**: ${task.subject}
**Mode**: ${exploreMode} | **Angles**: ${angles.join(', ')} | **Requester**: ${requester}

### Files: ${findings.relevant_files.length}
${findings.relevant_files.slice(0, 8).map(f => `- \`${f.path}\` (${f.role}) — ${f.rationale}`).join('\n')}

### Patterns: ${findings.patterns.length}
${findings.patterns.slice(0, 5).map(p => `- ${p.name}: ${p.description || ''}`).join('\n') || 'None'}

### Output: ${outputPath}`,
  summary: `[explorer] ${summary}`
})

TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next EXPLORE task → back to Phase 1

7. Coordinator Integration

Explorer 是服务角色coordinator 在以下场景按需创建 EXPLORE-* 任务:

Trigger Task Example Requester
RESEARCH-001 需要代码库上下文 EXPLORE-001: 代码库上下文搜索 analyst
PLAN-001 需要多角度探索 EXPLORE-002: 实现相关代码探索 planner
DISCUSS-004 需要外部最佳实践 EXPLORE-003: 外部文档搜索 discussant
IMPL-001 遇到未知代码 EXPLORE-004: 依赖追踪 executor

Task Description Template:

搜索描述

Session: {sessionFolder}
Mode: codebase|external|hybrid
Angles: architecture,patterns,dependencies
Keywords: auth,middleware,session
Requester: analyst

8. Result Caching

{sessionFolder}/explorations/
├── explore-explore-001-*.json     # Consolidated results
├── exploration-architecture.json   # Angle-specific (from cli-explore-agent)
└── exploration-patterns.json

后续角色 Phase 2 可直接读取已有探索结果,避免重复搜索。

9. Error Handling

Error Type Recovery Strategy Escalation
ACE unavailable Fallback to Grep + rg Continue with degraded results
cli-explore-agent failure Fallback to direct search Report partial results
No results found Report empty, suggest broader keywords Coordinator decides
Web search fails Skip external refs Continue with codebase results
Session folder missing Use .workflow/.tmp Notify coordinator