feat(team-lifecycle-v2): add explorer/architect roles + wisdom accumulation

New roles (on-demand, non-pipeline):
- explorer: multi-strategy code search & pattern discovery (EXPLORE-*)
- architect: multi-mode architecture assessment (ARCH-*)

New files:
- roles/explorer/role.md - service role with 5 search strategies
- roles/architect/role.md - consulting role with 5 consultation modes
- roles/architect/commands/assess.md - mode-specific assessment strategies

Updated:
- SKILL.md: architecture diagram, role router, message types, session dirs, wisdom protocol
- specs/team-config.json: new role definitions + wisdom/explorations/architecture dirs
- roles/coordinator/role.md: wisdom directory initialization on session create
This commit is contained in:
catlog22
2026-02-18 12:36:34 +08:00
parent f0dda075f0
commit c466ca7334
6 changed files with 1055 additions and 11 deletions

View File

@@ -29,6 +29,12 @@ Unified team skill covering specification, implementation, testing, and review.
│coordinator││analyst││writer││discussant││planner││executor││tester││reviewer│
│ roles/ ││roles/ ││roles/││ roles/ ││roles/ ││ roles/ ││roles/││ roles/ │
└──────────┘└───────┘└──────┘└──────────┘└───────┘└────────┘└──────┘└────────┘
↑ ↑
on-demand by coordinator
┌──────────┐ ┌─────────┐
│ explorer │ │architect│
│ (service)│ │(consult)│
└──────────┘ └─────────┘
```
## Command Architecture
@@ -65,11 +71,17 @@ roles/
│ ├── role.md
│ └── commands/
│ └── validate.md # Test-fix cycle
── reviewer/
├── role.md
── reviewer/
├── role.md
│ └── commands/
│ ├── code-review.md # 4-dimension code review
│ └── spec-quality.md # 5-dimension spec quality check
├── explorer/ # Service role (on-demand)
│ └── role.md # Multi-strategy code search & pattern discovery
└── architect/ # Consulting role (on-demand)
├── role.md # Multi-mode architecture assessment
└── commands/
── code-review.md # 4-dimension code review
└── spec-quality.md # 5-dimension spec quality check
── assess.md # Mode-specific assessment strategies
```
**Design principle**: role.md keeps Phase 1 (Task Discovery) and Phase 5 (Report) inline. Phases 2-4 either stay inline (simple logic) or delegate to `commands/*.md` via `Read("commands/xxx.md")` when they involve subagent delegation, CLI fan-out, or complex strategies.
@@ -106,7 +118,9 @@ const VALID_ROLES = {
"planner": { file: "roles/planner/role.md", prefix: "PLAN" },
"executor": { file: "roles/executor/role.md", prefix: "IMPL" },
"tester": { file: "roles/tester/role.md", prefix: "TEST" },
"reviewer": { file: "roles/reviewer/role.md", prefix: ["REVIEW", "QUALITY"] }
"reviewer": { file: "roles/reviewer/role.md", prefix: ["REVIEW", "QUALITY"] },
"explorer": { file: "roles/explorer/role.md", prefix: "EXPLORE", type: "service" },
"architect": { file: "roles/architect/role.md", prefix: "ARCH", type: "consulting" }
}
if (!VALID_ROLES[role]) {
@@ -183,6 +197,8 @@ if (!roleMatch) {
| `executor` | IMPL-* | Code implementation following plans | [roles/executor/role.md](roles/executor/role.md) |
| `tester` | TEST-* | Adaptive test-fix cycles, quality gates | [roles/tester/role.md](roles/tester/role.md) |
| `reviewer` | `REVIEW-*` + `QUALITY-*` | Code review + Spec quality validation (auto-switch by prefix) | [roles/reviewer/role.md](roles/reviewer/role.md) |
| `explorer` | EXPLORE-* | Code search, pattern discovery, dependency tracing (service role, on-demand) | [roles/explorer/role.md](roles/explorer/role.md) |
| `architect` | ARCH-* | Architecture assessment, tech feasibility, design review (consulting role, on-demand) | [roles/architect/role.md](roles/architect/role.md) |
## Shared Infrastructure
@@ -254,6 +270,8 @@ mcp__ccw-tools__team_msg({
| executor | `impl_complete`, `impl_progress`, `error` |
| tester | `test_result`, `impl_progress`, `fix_required`, `error` |
| reviewer | `review_result`, `quality_result`, `fix_required`, `error` |
| explorer | `explore_ready`, `explore_progress`, `task_failed` |
| architect | `arch_ready`, `arch_concern`, `arch_progress`, `error` |
### CLI Fallback
@@ -265,6 +283,59 @@ Bash(`ccw team list --team "${teamName}" --last 10 --json`)
Bash(`ccw team status --team "${teamName}" --json`)
```
### Wisdom Accumulation (All Roles)
跨任务知识积累机制。Coordinator 在 session 初始化时创建 `wisdom/` 目录,所有 worker 在执行过程中读取和贡献 wisdom。
**目录结构**:
```
{sessionFolder}/wisdom/
├── learnings.md # 发现的模式和洞察
├── decisions.md # 架构和设计决策
├── conventions.md # 代码库约定
└── issues.md # 已知风险和问题
```
**Phase 2 加载(所有 worker**:
```javascript
// Load wisdom context at start of Phase 2
const sessionFolder = task.description.match(/Session:\s*([^\n]+)/)?.[1]?.trim()
let wisdom = {}
if (sessionFolder) {
try { wisdom.learnings = Read(`${sessionFolder}/wisdom/learnings.md`) } catch {}
try { wisdom.decisions = Read(`${sessionFolder}/wisdom/decisions.md`) } catch {}
try { wisdom.conventions = Read(`${sessionFolder}/wisdom/conventions.md`) } catch {}
try { wisdom.issues = Read(`${sessionFolder}/wisdom/issues.md`) } catch {}
}
```
**Phase 4/5 贡献(任务完成时)**:
```javascript
// Contribute wisdom after task completion
if (sessionFolder) {
const timestamp = new Date().toISOString().substring(0, 10)
// Role-specific contributions:
// analyst → learnings (exploration dimensions, codebase patterns)
// writer → conventions (document structure, naming patterns)
// planner → decisions (task decomposition rationale)
// executor → learnings (implementation patterns), issues (bugs encountered)
// tester → issues (test failures, edge cases), learnings (test patterns)
// reviewer → conventions (code quality patterns), issues (review findings)
// explorer → conventions (codebase patterns), learnings (dependency insights)
// architect → decisions (architecture choices), issues (architectural risks)
try {
const targetFile = `${sessionFolder}/wisdom/${wisdomTarget}.md`
const existing = Read(targetFile)
const entry = `- [${timestamp}] [${role}] ${wisdomEntry}`
Write(targetFile, existing + '\n' + entry)
} catch {} // wisdom not initialized
}
```
**Coordinator 注入**: Coordinator 在 spawn worker 时通过 task description 传递 `Session: {sessionFolder}`worker 据此定位 wisdom 目录。已有 wisdom 内容为后续 worker 提供上下文,实现跨任务知识传递。
### Task Lifecycle (All Worker Roles)
```javascript
@@ -343,12 +414,21 @@ All session artifacts are stored under a single session folder:
│ └── spec-summary.md
├── discussions/ # Discussion records (discussant output)
│ └── discuss-001..006.md
── plan/ # Plan artifacts (planner output)
├── exploration-{angle}.json
├── explorations-manifest.json
├── plan.json
└── .task/
└── TASK-*.json
── plan/ # Plan artifacts (planner output)
├── exploration-{angle}.json
├── explorations-manifest.json
├── plan.json
└── .task/
└── TASK-*.json
├── explorations/ # Explorer output (cached for cross-role reuse)
│ └── explore-*.json
├── architecture/ # Architect output (assessment reports)
│ └── arch-*.json
└── wisdom/ # Cross-task accumulated knowledge
├── learnings.md # Patterns and insights discovered
├── decisions.md # Architectural decisions made
├── conventions.md # Codebase conventions found
└── issues.md # Known issues and risks
```
Messages remain at `.workflow/.team-msg/{team-name}/` (unchanged).

View File

@@ -0,0 +1,271 @@
# Assess Command
## Purpose
Multi-mode architecture assessment with mode-specific analysis strategies. Delegated from architect role.md Phase 3.
## Input Context
```javascript
// Provided by role.md Phase 2
const { consultMode, sessionFolder, wisdom, explorations, projectTech, task } = context
```
## Mode Strategies
### spec-review (ARCH-SPEC-*)
审查架构文档的技术合理性。
```javascript
const dimensions = [
{ name: 'consistency', weight: 0.25 },
{ name: 'scalability', weight: 0.25 },
{ name: 'security', weight: 0.25 },
{ name: 'tech-fitness', weight: 0.25 }
]
// Load architecture documents
const archIndex = Read(`${sessionFolder}/spec/architecture/_index.md`)
const adrFiles = Glob({ pattern: `${sessionFolder}/spec/architecture/ADR-*.md` })
const adrs = adrFiles.map(f => ({ path: f, content: Read(f) }))
// Check ADR consistency
const adrDecisions = adrs.map(adr => {
const status = adr.content.match(/status:\s*(\w+)/i)?.[1]
const context = adr.content.match(/## Context\n([\s\S]*?)##/)?.[1]?.trim()
const decision = adr.content.match(/## Decision\n([\s\S]*?)##/)?.[1]?.trim()
return { path: adr.path, status, context, decision }
})
// Cross-reference: ADR decisions vs architecture index
// Flag contradictions between ADRs
// Check if tech choices align with project-tech.json
for (const dim of dimensions) {
const score = evaluateDimension(dim.name, archIndex, adrs, projectTech)
assessment.dimensions.push({ name: dim.name, score, weight: dim.weight })
}
```
### plan-review (ARCH-PLAN-*)
审查实现计划的架构合理性。
```javascript
const plan = JSON.parse(Read(`${sessionFolder}/plan/plan.json`))
const taskFiles = Glob({ pattern: `${sessionFolder}/plan/.task/TASK-*.json` })
const tasks = taskFiles.map(f => JSON.parse(Read(f)))
// 1. Dependency cycle detection
function detectCycles(tasks) {
const graph = {}
tasks.forEach(t => { graph[t.id] = t.depends_on || [] })
const visited = new Set(), inStack = new Set()
function dfs(node) {
if (inStack.has(node)) return true // cycle
if (visited.has(node)) return false
visited.add(node); inStack.add(node)
for (const dep of (graph[node] || [])) {
if (dfs(dep)) return true
}
inStack.delete(node)
return false
}
return Object.keys(graph).filter(n => dfs(n))
}
const cycles = detectCycles(tasks)
if (cycles.length > 0) {
assessment.concerns.push({
severity: 'high',
concern: `Circular dependency detected: ${cycles.join(' → ')}`,
suggestion: 'Break cycle by extracting shared interface or reordering tasks'
})
}
// 2. Task granularity check
tasks.forEach(t => {
const fileCount = (t.files || []).length
if (fileCount > 8) {
assessment.concerns.push({
severity: 'medium',
task: t.id,
concern: `Task touches ${fileCount} files — may be too coarse`,
suggestion: 'Split into smaller tasks with clearer boundaries'
})
}
})
// 3. Convention compliance (from wisdom)
if (wisdom.conventions) {
// Check if plan follows discovered conventions
}
// 4. Architecture alignment (from wisdom.decisions)
if (wisdom.decisions) {
// Verify plan doesn't contradict previous architectural decisions
}
```
### code-review (ARCH-CODE-*)
评估代码变更的架构影响。
```javascript
const changedFiles = Bash(`git diff --name-only HEAD~1 2>/dev/null || git diff --name-only --cached`)
.split('\n').filter(Boolean)
// 1. Layer violation detection
function detectLayerViolation(file, content) {
// Check import depth — deeper layers should not import from shallower
const imports = (content.match(/from\s+['"]([^'"]+)['"]/g) || [])
.map(i => i.match(/['"]([^'"]+)['"]/)?.[1]).filter(Boolean)
return imports.filter(imp => isUpwardImport(file, imp))
}
// 2. New dependency analysis
const pkgChanges = changedFiles.filter(f => f.includes('package.json'))
if (pkgChanges.length > 0) {
for (const pkg of pkgChanges) {
const diff = Bash(`git diff HEAD~1 -- ${pkg} 2>/dev/null || git diff --cached -- ${pkg}`)
const newDeps = (diff.match(/\+\s+"([^"]+)":\s+"[^"]+"/g) || [])
.map(d => d.match(/"([^"]+)"/)?.[1]).filter(Boolean)
if (newDeps.length > 0) {
assessment.recommendations.push({
area: 'dependencies',
suggestion: `New dependencies added: ${newDeps.join(', ')}. Verify license compatibility and bundle size impact.`
})
}
}
}
// 3. Module boundary changes
const indexChanges = changedFiles.filter(f => f.endsWith('index.ts') || f.endsWith('index.js'))
if (indexChanges.length > 0) {
assessment.concerns.push({
severity: 'medium',
concern: `Module boundary files modified: ${indexChanges.join(', ')}`,
suggestion: 'Verify public API changes are intentional and backward compatible'
})
}
// 4. Architectural impact scoring
assessment.architectural_impact = changedFiles.length > 10 ? 'high'
: indexChanges.length > 0 || pkgChanges.length > 0 ? 'medium' : 'low'
```
### consult (ARCH-CONSULT-*)
回答架构决策咨询。
```javascript
const question = task.description
.replace(/Session:.*\n?/g, '')
.replace(/Requester:.*\n?/g, '')
.trim()
const isComplex = question.length > 200 ||
/architect|design|pattern|refactor|migrate|scalab/i.test(question)
if (isComplex) {
// Use cli-explore-agent for deep exploration
Task({
subagent_type: "cli-explore-agent",
run_in_background: false,
description: `Architecture consultation: ${question.substring(0, 80)}`,
prompt: `## Architecture Consultation
Question: ${question}
## Steps
1. Run: ccw tool exec get_modules_by_depth '{}'
2. Search for relevant architectural patterns in codebase
3. Read .workflow/project-tech.json (if exists)
4. Analyze architectural implications
## Output
Write to: ${sessionFolder}/architecture/consult-exploration.json
Schema: { relevant_files[], patterns[], architectural_implications[], options[] }`
})
// Parse exploration results into assessment
try {
const exploration = JSON.parse(Read(`${sessionFolder}/architecture/consult-exploration.json`))
assessment.recommendations = (exploration.options || []).map(opt => ({
area: 'architecture',
suggestion: `${opt.name}: ${opt.description}`,
trade_offs: opt.trade_offs || []
}))
} catch {}
} else {
// Simple consultation — direct analysis
assessment.recommendations.push({
area: 'architecture',
suggestion: `Direct answer based on codebase context and wisdom`
})
}
```
### feasibility (ARCH-FEASIBILITY-*)
技术可行性评估。
```javascript
const proposal = task.description
.replace(/Session:.*\n?/g, '')
.replace(/Requester:.*\n?/g, '')
.trim()
// 1. Tech stack compatibility
const techStack = projectTech?.tech_stack || {}
// Check if proposal requires technologies not in current stack
// 2. Codebase readiness
// Use ACE search to find relevant integration points
const searchResults = mcp__ace-tool__search_context({
project_root_path: '.',
query: proposal
})
// 3. Effort estimation
const touchPoints = (searchResults?.relevant_files || []).length
const effort = touchPoints > 20 ? 'high' : touchPoints > 5 ? 'medium' : 'low'
// 4. Risk assessment
assessment.verdict = 'FEASIBLE' // FEASIBLE | RISKY | INFEASIBLE
assessment.effort_estimate = effort
assessment.prerequisites = []
assessment.risks = []
if (touchPoints > 20) {
assessment.verdict = 'RISKY'
assessment.risks.push({
risk: 'High touch-point count suggests significant refactoring',
mitigation: 'Phase the implementation, start with core module'
})
}
```
## Verdict Logic
```javascript
function determineVerdict(assessment) {
const highConcerns = (assessment.concerns || []).filter(c => c.severity === 'high')
const mediumConcerns = (assessment.concerns || []).filter(c => c.severity === 'medium')
if (highConcerns.length >= 2) return 'BLOCK'
if (highConcerns.length >= 1 || mediumConcerns.length >= 3) return 'CONCERN'
return 'APPROVE'
}
assessment.overall_verdict = determineVerdict(assessment)
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Architecture docs not found | Assess from available context, note limitation in report |
| Plan file missing | Report to coordinator via arch_concern |
| Git diff fails (no commits) | Use staged changes or skip code-review mode |
| CLI exploration timeout | Provide partial assessment, flag as incomplete |
| Exploration results unparseable | Fall back to direct analysis without exploration |

View File

@@ -0,0 +1,368 @@
# Role: architect
架构顾问。提供架构决策咨询、技术可行性评估、设计模式建议。咨询角色,在 spec 和 impl 流程关键节点提供专业判断。
## Role Identity
- **Name**: `architect`
- **Task Prefix**: `ARCH-*`
- **Responsibility**: Context loading → Mode detection → Architecture analysis → Package assessment → Report
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[architect]`
- **Role Type**: Consulting咨询角色不阻塞主链路输出被引用
## Role Boundaries
### MUST
- 仅处理 `ARCH-*` 前缀的任务
- 所有输出SendMessage、team_msg、日志必须带 `[architect]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 输出结构化评估报告供调用方消费
- 根据任务前缀自动切换咨询模式
### MUST NOT
- ❌ 直接修改源代码文件
- ❌ 执行需求分析、代码实现、测试等其他角色职责
- ❌ 直接与其他 worker 角色通信
- ❌ 为其他角色创建任务
- ❌ 做最终决策(仅提供建议,决策权在 coordinator/用户)
- ❌ 在输出中省略 `[architect]` 标识
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `arch_ready` | architect → coordinator | Consultation complete | 架构评估/建议已就绪 |
| `arch_concern` | architect → coordinator | Significant risk found | 发现重大架构风险 |
| `arch_progress` | architect → coordinator | Long analysis progress | 复杂分析进度更新 |
| `error` | architect → coordinator | Analysis failure | 分析失败或上下文不足 |
## Message Bus
每次 SendMessage **前**,必须调用 `mcp__ccw-tools__team_msg` 记录消息:
```javascript
// Consultation complete
mcp__ccw-tools__team_msg({
operation: "log", team: teamName,
from: "architect", to: "coordinator",
type: "arch_ready",
summary: "[architect] ARCH complete: 3 recommendations, 1 concern",
ref: outputPath
})
// Risk alert
mcp__ccw-tools__team_msg({
operation: "log", team: teamName,
from: "architect", to: "coordinator",
type: "arch_concern",
summary: "[architect] RISK: circular dependency in module graph"
})
```
### CLI 回退
`mcp__ccw-tools__team_msg` MCP 不可用时,使用 `ccw team` CLI 作为等效回退:
```javascript
Bash(`ccw team log --team "${teamName}" --from "architect" --to "coordinator" --type "arch_ready" --summary "[architect] ARCH complete" --ref "${outputPath}" --json`)
```
**参数映射**: `team_msg(params)``ccw team log --team <team> --from architect --to coordinator --type <type> --summary "<text>" [--ref <path>] [--json]`
## Toolbox
### Available Commands
- `commands/assess.md` — Multi-mode architecture assessment (Phase 3)
### Subagent Capabilities
| Agent Type | Used By | Purpose |
|------------|---------|---------|
| `cli-explore-agent` | commands/assess.md | 深度架构探索(模块依赖、分层结构) |
### CLI Capabilities
| CLI Tool | Mode | Used By | Purpose |
|----------|------|---------|---------|
| `ccw cli --tool gemini --mode analysis` | analysis | commands/assess.md | 架构分析、模式评估 |
## Consultation Modes
根据任务 subject 前缀自动切换:
| Mode | Task Pattern | Focus | Output |
|------|-------------|-------|--------|
| `spec-review` | ARCH-SPEC-* | 审查架构文档ADR、组件图 | 架构评审报告 |
| `plan-review` | ARCH-PLAN-* | 审查实现计划的架构合理性 | 计划评审意见 |
| `code-review` | ARCH-CODE-* | 评估代码变更的架构影响 | 架构影响分析 |
| `consult` | ARCH-CONSULT-* | 回答架构决策咨询 | 决策建议 |
| `feasibility` | ARCH-FEASIBILITY-* | 技术可行性评估 | 可行性报告 |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('ARCH-') &&
t.owner === 'architect' &&
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: Context Loading & Mode Detection
```javascript
const sessionFolder = task.description.match(/Session:\s*([^\n]+)/)?.[1]?.trim()
// Auto-detect consultation mode from task subject
const MODE_MAP = {
'ARCH-SPEC': 'spec-review',
'ARCH-PLAN': 'plan-review',
'ARCH-CODE': 'code-review',
'ARCH-CONSULT': 'consult',
'ARCH-FEASIBILITY': 'feasibility'
}
const modePrefix = Object.keys(MODE_MAP).find(p => task.subject.startsWith(p))
const consultMode = modePrefix ? MODE_MAP[modePrefix] : 'consult'
// Load wisdom (accumulated knowledge from previous tasks)
let wisdom = {}
if (sessionFolder) {
try { wisdom.learnings = Read(`${sessionFolder}/wisdom/learnings.md`) } catch {}
try { wisdom.decisions = Read(`${sessionFolder}/wisdom/decisions.md`) } catch {}
try { wisdom.conventions = Read(`${sessionFolder}/wisdom/conventions.md`) } catch {}
}
// Load project tech context
let projectTech = {}
try { projectTech = JSON.parse(Read('.workflow/project-tech.json')) } catch {}
// Load exploration results if available
let explorations = []
if (sessionFolder) {
try {
const exploreFiles = Glob({ pattern: `${sessionFolder}/explorations/*.json` })
explorations = exploreFiles.map(f => {
try { return JSON.parse(Read(f)) } catch { return null }
}).filter(Boolean)
} catch {}
}
```
### Phase 3: Architecture Assessment
Delegate to command file for mode-specific analysis:
```javascript
try {
const assessCommand = Read("commands/assess.md")
// Execute mode-specific strategy defined in command file
// Input: consultMode, sessionFolder, wisdom, explorations, projectTech
// Output: assessment object
} catch {
// Fallback: inline execution (see below)
}
```
**Command**: [commands/assess.md](commands/assess.md)
**Inline Fallback** (when command file unavailable):
```javascript
const assessment = {
mode: consultMode,
overall_verdict: 'APPROVE', // APPROVE | CONCERN | BLOCK
dimensions: [],
concerns: [],
recommendations: [],
_metadata: { timestamp: new Date().toISOString(), wisdom_loaded: Object.keys(wisdom).length > 0 }
}
// Mode-specific analysis
if (consultMode === 'spec-review') {
// Load architecture documents, check ADR consistency, scalability, security
const archIndex = Read(`${sessionFolder}/spec/architecture/_index.md`)
const adrFiles = Glob({ pattern: `${sessionFolder}/spec/architecture/ADR-*.md` })
// Score dimensions: consistency, scalability, security, tech-fitness
}
if (consultMode === 'plan-review') {
// Load plan.json, check task granularity, dependency cycles, convention compliance
const plan = JSON.parse(Read(`${sessionFolder}/plan/plan.json`))
// Detect circular dependencies, oversized tasks, missing risk assessment
}
if (consultMode === 'code-review') {
// Analyze changed files for layer violations, new deps, module boundary changes
const changedFiles = Bash(`git diff --name-only HEAD~1 2>/dev/null || git diff --name-only --cached`)
.split('\n').filter(Boolean)
// Check import depth, package.json changes, index.ts modifications
}
if (consultMode === 'consult') {
// Free-form consultation — use CLI for complex questions
const question = task.description.replace(/Session:.*\n?/g, '').replace(/Requester:.*\n?/g, '').trim()
const isComplex = question.length > 200 || /architect|design|pattern|refactor|migrate/i.test(question)
if (isComplex) {
Bash({
command: `ccw cli -p "PURPOSE: Architecture consultation — ${question}
TASK: • Analyze architectural implications • Identify options with trade-offs • Recommend approach
MODE: analysis
CONTEXT: @**/*
EXPECTED: Structured analysis with options, trade-offs, recommendation
CONSTRAINTS: Architecture-level only" --tool gemini --mode analysis --rule analysis-review-architecture`,
run_in_background: true
})
// Wait for result, parse into assessment
}
}
if (consultMode === 'feasibility') {
// Assess technical feasibility against current codebase
// Output: verdict (FEASIBLE|RISKY|INFEASIBLE), risks, effort estimate, prerequisites
}
```
### Phase 4: Package & Wisdom Contribution
```javascript
// Write assessment to session
const outputPath = sessionFolder
? `${sessionFolder}/architecture/arch-${task.subject.replace(/[^a-zA-Z0-9-]/g, '-').toLowerCase()}.json`
: '.workflow/.tmp/arch-assessment.json'
Bash(`mkdir -p "$(dirname '${outputPath}')"`)
Write(outputPath, JSON.stringify(assessment, null, 2))
// Contribute to wisdom: record architectural decisions
if (sessionFolder && assessment.recommendations?.length > 0) {
try {
const decisionsPath = `${sessionFolder}/wisdom/decisions.md`
const existing = Read(decisionsPath)
const newDecisions = assessment.recommendations
.map(r => `- [${new Date().toISOString().substring(0, 10)}] ${r.area || r.dimension}: ${r.suggestion}`)
.join('\n')
Write(decisionsPath, existing + '\n' + newDecisions)
} catch {} // wisdom not initialized
}
```
### Phase 5: Report to Coordinator
```javascript
const verdict = assessment.overall_verdict || assessment.verdict || 'N/A'
const concernCount = (assessment.concerns || []).length
const highConcerns = (assessment.concerns || []).filter(c => c.severity === 'high').length
const recCount = (assessment.recommendations || []).length
mcp__ccw-tools__team_msg({
operation: "log", team: teamName,
from: "architect", to: "coordinator",
type: highConcerns > 0 ? "arch_concern" : "arch_ready",
summary: `[architect] ARCH ${consultMode}: ${verdict}, ${concernCount} concerns, ${recCount} recommendations`,
ref: outputPath
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `[architect] ## Architecture Assessment
**Task**: ${task.subject}
**Mode**: ${consultMode}
**Verdict**: ${verdict}
### Summary
- **Concerns**: ${concernCount} (${highConcerns} high)
- **Recommendations**: ${recCount}
${assessment.architectural_impact ? `- **Impact**: ${assessment.architectural_impact}` : ''}
${assessment.dimensions?.length > 0 ? `### Dimension Scores
${assessment.dimensions.map(d => `- **${d.name}**: ${d.score}%`).join('\n')}` : ''}
${concernCount > 0 ? `### Concerns
${assessment.concerns.map(c => `- [${(c.severity || 'medium').toUpperCase()}] ${c.task || c.file || ''}: ${c.concern}`).join('\n')}` : ''}
### Recommendations
${(assessment.recommendations || []).map(r => `- ${r.area || r.dimension || ''}: ${r.suggestion}`).join('\n') || 'None'}
### Output: ${outputPath}`,
summary: `[architect] ARCH ${consultMode}: ${verdict}`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next ARCH task → back to Phase 1
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('ARCH-') &&
t.owner === 'architect' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue → back to Phase 1
}
```
## Coordinator Integration
Architect 由 coordinator 在关键节点按需创建 ARCH-* 任务:
### Spec Pipeline (after DRAFT-003, before DISCUSS-004)
```javascript
TaskCreate({
subject: 'ARCH-SPEC-001: 架构文档专业评审',
description: `评审架构文档的技术合理性\n\nSession: ${sessionFolder}\n输入: ${sessionFolder}/spec/architecture/`,
activeForm: '架构评审中'
})
TaskUpdate({ taskId: archSpecId, owner: 'architect' })
// DISCUSS-004 addBlockedBy [archSpecId]
```
### Impl Pipeline (after PLAN-001, before IMPL-001)
```javascript
TaskCreate({
subject: 'ARCH-PLAN-001: 实现计划架构审查',
description: `审查实现计划的架构合理性\n\nSession: ${sessionFolder}\nPlan: ${sessionFolder}/plan/plan.json`,
activeForm: '计划审查中'
})
TaskUpdate({ taskId: archPlanId, owner: 'architect' })
// IMPL-001 addBlockedBy [archPlanId]
```
### On-Demand (any point via coordinator)
```javascript
TaskCreate({
subject: 'ARCH-CONSULT-001: 架构决策咨询',
description: `${question}\n\nSession: ${sessionFolder}\nRequester: ${role}`,
activeForm: '架构咨询中'
})
TaskUpdate({ taskId: archConsultId, owner: 'architect' })
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No ARCH-* tasks available | Idle, wait for coordinator assignment |
| Architecture documents not found | Assess from available context, note limitation |
| Plan file not found | Report to coordinator, request location |
| CLI analysis timeout | Provide partial assessment, note incomplete |
| Insufficient context | Request explorer to gather more context via coordinator |
| Conflicting requirements | Flag as concern, provide options |
| Command file not found | Fall back to inline execution |
| Unexpected error | Log error via team_msg, report to coordinator |

View File

@@ -366,6 +366,14 @@ TeamCreate({
Output(`[coordinator] Team created: ${teamId}`)
// Initialize wisdom directory
const wisdomDir = `${sessionFolder}/wisdom`
Bash(`mkdir -p "${wisdomDir}"`)
Write(`${wisdomDir}/learnings.md`, `# Learnings\n\n<!-- Auto-accumulated by team roles -->\n`)
Write(`${wisdomDir}/decisions.md`, `# Decisions\n\n<!-- Architectural and design decisions -->\n`)
Write(`${wisdomDir}/conventions.md`, `# Conventions\n\n<!-- Codebase conventions discovered -->\n<!-- explorer-patterns -->\n`)
Write(`${wisdomDir}/issues.md`, `# Known Issues\n\n<!-- Risks and issues found during execution -->\n`)
// Initialize session file
const sessionFile = `D:/Claude_dms3/.workflow/.sessions/${sessionId}.json`
const sessionData = {

View File

@@ -0,0 +1,301 @@
# 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:
```javascript
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:
```bash
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
```javascript
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}"`)
```
### Phase 2: Multi-Strategy Search
```javascript
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
```javascript
// 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
```javascript
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
```javascript
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 |

View File

@@ -47,6 +47,19 @@
"additional_prefixes": ["QUALITY"],
"responsibility": "Code review (REVIEW-*) + Spec quality validation (QUALITY-*)",
"message_types": ["review_result", "quality_result", "fix_required", "error"]
},
"explorer": {
"task_prefix": "EXPLORE",
"responsibility": "Code search, pattern discovery, dependency tracing. Service role — on-demand by coordinator",
"role_type": "service",
"message_types": ["explore_ready", "explore_progress", "task_failed"]
},
"architect": {
"task_prefix": "ARCH",
"responsibility": "Architecture assessment, tech feasibility, design pattern review. Consulting role — on-demand by coordinator",
"role_type": "consulting",
"consultation_modes": ["spec-review", "plan-review", "code-review", "consult", "feasibility"],
"message_types": ["arch_ready", "arch_concern", "arch_progress", "error"]
}
},
@@ -77,6 +90,9 @@
"spec": "spec/",
"discussions": "discussions/",
"plan": "plan/",
"explorations": "explorations/",
"architecture": "architecture/",
"wisdom": "wisdom/",
"messages": ".workflow/.team-msg/{team-name}/"
}
}