mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
feat: Add 4 new team skills with Generator-Critic loops, shared memory, and dynamic pipelines
Create team-brainstorm (ideator↔challenger GC, quick/deep/full pipelines), team-testing (generator↔executor GC, L1/L2/L3 test layers), team-iterdev (developer↔reviewer GC, task-ledger sprint tracking), and team-uidesign (designer↔reviewer GC, CP-9 dual-track with sync points). Each team includes SKILL.md router, 5 roles, and team-config.json.
This commit is contained in:
372
.claude/skills/team-iterdev/SKILL.md
Normal file
372
.claude/skills/team-iterdev/SKILL.md
Normal file
@@ -0,0 +1,372 @@
|
||||
---
|
||||
name: team-iterdev
|
||||
description: Unified team skill for iterative development team. All roles invoke this skill with --role arg for role-specific execution. Triggers on "team iterdev".
|
||||
allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*)
|
||||
---
|
||||
|
||||
# Team IterDev
|
||||
|
||||
持续迭代开发团队技能。通过 Generator-Critic 循环(developer↔reviewer,最多3轮)、任务账本(task-ledger.json)实时进度追踪、共享记忆(Sprint间学习)和动态管道选择,实现增量交付开发。所有团队成员通过 `--role=xxx` 路由。
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Skill(skill="team-iterdev", args="--role=xxx") │
|
||||
└───────────────────┬──────────────────────────────┘
|
||||
│ Role Router
|
||||
┌───────────┬───┼───────────┬───────────┐
|
||||
↓ ↓ ↓ ↓ ↓
|
||||
┌──────────┐┌─────────┐┌─────────┐┌──────┐┌────────┐
|
||||
│coordinator││architect││developer││tester││reviewer│
|
||||
│ roles/ ││ roles/ ││ roles/ ││roles/││ roles/ │
|
||||
└──────────┘└─────────┘└─────────┘└──────┘└────────┘
|
||||
```
|
||||
|
||||
## Role Router
|
||||
|
||||
### Input Parsing
|
||||
|
||||
```javascript
|
||||
const args = "$ARGUMENTS"
|
||||
const roleMatch = args.match(/--role[=\s]+(\w+)/)
|
||||
|
||||
if (!roleMatch) {
|
||||
throw new Error("Missing --role argument. Available roles: coordinator, architect, developer, tester, reviewer")
|
||||
}
|
||||
|
||||
const role = roleMatch[1]
|
||||
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "iterdev"
|
||||
```
|
||||
|
||||
### Role Dispatch
|
||||
|
||||
```javascript
|
||||
const VALID_ROLES = {
|
||||
"coordinator": { file: "roles/coordinator.md", prefix: null },
|
||||
"architect": { file: "roles/architect.md", prefix: "DESIGN" },
|
||||
"developer": { file: "roles/developer.md", prefix: "DEV" },
|
||||
"tester": { file: "roles/tester.md", prefix: "VERIFY" },
|
||||
"reviewer": { file: "roles/reviewer.md", prefix: "REVIEW" }
|
||||
}
|
||||
|
||||
if (!VALID_ROLES[role]) {
|
||||
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
|
||||
}
|
||||
|
||||
Read(VALID_ROLES[role].file)
|
||||
```
|
||||
|
||||
### Available Roles
|
||||
|
||||
| Role | Task Prefix | Responsibility | Role File |
|
||||
|------|-------------|----------------|-----------|
|
||||
| `coordinator` | N/A | Sprint规划、积压管理、任务账本维护 | [roles/coordinator.md](roles/coordinator.md) |
|
||||
| `architect` | DESIGN-* | 技术设计、任务分解、架构决策 | [roles/architect.md](roles/architect.md) |
|
||||
| `developer` | DEV-* | 代码实现、增量交付 | [roles/developer.md](roles/developer.md) |
|
||||
| `tester` | VERIFY-* | 测试执行、修复循环、回归检测 | [roles/tester.md](roles/tester.md) |
|
||||
| `reviewer` | REVIEW-* | 代码审查、质量评分、改进建议 | [roles/reviewer.md](roles/reviewer.md) |
|
||||
|
||||
## Shared Infrastructure
|
||||
|
||||
### Role Isolation Rules
|
||||
|
||||
#### Output Tagging(强制)
|
||||
|
||||
```javascript
|
||||
SendMessage({ content: `## [${role}] ...`, summary: `[${role}] ...` })
|
||||
mcp__ccw-tools__team_msg({ summary: `[${role}] ...` })
|
||||
```
|
||||
|
||||
#### Coordinator 隔离
|
||||
|
||||
| 允许 | 禁止 |
|
||||
|------|------|
|
||||
| Sprint 规划 (AskUserQuestion) | ❌ 直接编写代码 |
|
||||
| 创建任务链 (TaskCreate) | ❌ 直接执行测试/审查 |
|
||||
| 维护任务账本 (task-ledger.json) | ❌ 调用 code-developer 等实现类 subagent |
|
||||
| 监控进度 | ❌ 绕过 worker 自行完成 |
|
||||
|
||||
#### Worker 隔离
|
||||
|
||||
| 允许 | 禁止 |
|
||||
|------|------|
|
||||
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
|
||||
| 读写 shared-memory.json (自己的字段) | ❌ 为其他角色创建任务 |
|
||||
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
|
||||
|
||||
### Team Configuration
|
||||
|
||||
```javascript
|
||||
const TEAM_CONFIG = {
|
||||
name: "iterdev",
|
||||
sessionDir: ".workflow/.team/IDS-{slug}-{date}/",
|
||||
msgDir: ".workflow/.team-msg/iterdev/",
|
||||
sharedMemory: "shared-memory.json",
|
||||
taskLedger: "task-ledger.json"
|
||||
}
|
||||
```
|
||||
|
||||
### Task Ledger (创新模式 — 任务账本)
|
||||
|
||||
实时追踪所有 Sprint 任务进度:
|
||||
|
||||
```javascript
|
||||
// task-ledger.json structure
|
||||
{
|
||||
"sprint_id": "sprint-1",
|
||||
"sprint_goal": "...",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "DEV-001",
|
||||
"title": "...",
|
||||
"owner": "developer",
|
||||
"status": "completed", // pending | in_progress | completed | blocked
|
||||
"started_at": "...",
|
||||
"completed_at": "...",
|
||||
"gc_rounds": 0, // Generator-Critic iterations
|
||||
"review_score": null, // reviewer 评分
|
||||
"test_pass_rate": null // tester 通过率
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"total": 5,
|
||||
"completed": 3,
|
||||
"in_progress": 1,
|
||||
"blocked": 0,
|
||||
"velocity": 3 // tasks completed this sprint
|
||||
}
|
||||
}
|
||||
|
||||
// Coordinator updates ledger at each task transition
|
||||
function updateLedger(sessionFolder, taskId, updates) {
|
||||
const ledger = JSON.parse(Read(`${sessionFolder}/task-ledger.json`))
|
||||
const task = ledger.tasks.find(t => t.id === taskId)
|
||||
if (task) Object.assign(task, updates)
|
||||
// Recalculate metrics
|
||||
ledger.metrics.completed = ledger.tasks.filter(t => t.status === 'completed').length
|
||||
ledger.metrics.in_progress = ledger.tasks.filter(t => t.status === 'in_progress').length
|
||||
Write(`${sessionFolder}/task-ledger.json`, JSON.stringify(ledger, null, 2))
|
||||
}
|
||||
```
|
||||
|
||||
### Shared Memory (Sprint间学习)
|
||||
|
||||
```javascript
|
||||
// shared-memory.json — accumulated across sprints
|
||||
{
|
||||
"sprint_history": [
|
||||
{
|
||||
"sprint_id": "sprint-1",
|
||||
"what_worked": ["..."],
|
||||
"what_failed": ["..."],
|
||||
"patterns_learned": ["..."]
|
||||
}
|
||||
],
|
||||
"architecture_decisions": [],
|
||||
"implementation_context": [],
|
||||
"review_feedback_trends": []
|
||||
}
|
||||
```
|
||||
|
||||
### Message Bus
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: role, to: "coordinator",
|
||||
type: "<type>", summary: `[${role}] <summary>`, ref: "<file_path>"
|
||||
})
|
||||
```
|
||||
|
||||
| Role | Types |
|
||||
|------|-------|
|
||||
| coordinator | `sprint_started`, `gc_loop_trigger`, `sprint_complete`, `task_unblocked`, `error`, `shutdown` |
|
||||
| architect | `design_ready`, `design_revision`, `error` |
|
||||
| developer | `dev_complete`, `dev_progress`, `error` |
|
||||
| tester | `verify_passed`, `verify_failed`, `fix_required`, `error` |
|
||||
| reviewer | `review_passed`, `review_revision`, `review_critical`, `error` |
|
||||
|
||||
### CLI Fallback
|
||||
|
||||
```javascript
|
||||
Bash(`ccw team log --team "${teamName}" --from "${role}" --to "coordinator" --type "<type>" --summary "<summary>" --json`)
|
||||
```
|
||||
|
||||
### Task Lifecycle (All Worker Roles)
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
|
||||
t.owner === role && 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' })
|
||||
// Phase 2-4: Role-specific
|
||||
// Phase 5: Report + Loop
|
||||
```
|
||||
|
||||
## Three-Pipeline Architecture
|
||||
|
||||
```
|
||||
Patch (简单修复):
|
||||
DEV-001 → VERIFY-001
|
||||
|
||||
Sprint (标准特性):
|
||||
DESIGN-001 → DEV-001 → [VERIFY-001 + REVIEW-001](parallel)
|
||||
|
||||
Multi-Sprint (大型特性):
|
||||
Sprint 1: DESIGN-001 → DEV-001 → DEV-002(incremental) → VERIFY-001 → DEV-fix → REVIEW-001
|
||||
Sprint 2: DESIGN-002(refined) → DEV-003 → VERIFY-002 → REVIEW-002
|
||||
...
|
||||
```
|
||||
|
||||
### Generator-Critic Loop
|
||||
|
||||
developer ↔ reviewer 循环,最多3轮:
|
||||
|
||||
```
|
||||
DEV → REVIEW → (if review.critical_count > 0 || review.score < 7)
|
||||
→ DEV-fix → REVIEW-2 → (if still issues) → DEV-fix-2 → REVIEW-3
|
||||
→ (max 3 rounds, then accept with warning)
|
||||
```
|
||||
|
||||
### Multi-Sprint Dynamic Downgrade
|
||||
|
||||
```javascript
|
||||
// If Sprint N is progressing well, downgrade Sprint N+1 complexity
|
||||
if (sprintMetrics.velocity >= expectedVelocity && sprintMetrics.review_avg >= 8) {
|
||||
// Next sprint: skip detailed design, use simplified pipeline
|
||||
nextPipeline = 'sprint' // downgrade from multi-sprint
|
||||
}
|
||||
```
|
||||
|
||||
## Unified Session Directory
|
||||
|
||||
```
|
||||
.workflow/.team/IDS-{slug}-{YYYY-MM-DD}/
|
||||
├── team-session.json
|
||||
├── shared-memory.json # Sprint间学习: what_worked / what_failed / patterns_learned
|
||||
├── task-ledger.json # 实时任务进度账本
|
||||
├── design/ # Architect output
|
||||
│ ├── design-001.md
|
||||
│ └── task-breakdown.json
|
||||
├── code/ # Developer tracking
|
||||
│ └── dev-log.md
|
||||
├── verify/ # Tester output
|
||||
│ └── verify-001.json
|
||||
└── review/ # Reviewer output
|
||||
└── review-001.md
|
||||
```
|
||||
|
||||
## Coordinator Spawn Template
|
||||
|
||||
```javascript
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
// Architect
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
team_name: teamName,
|
||||
name: "architect",
|
||||
prompt: `你是 team "${teamName}" 的 ARCHITECT。
|
||||
当你收到 DESIGN-* 任务时,调用 Skill(skill="team-iterdev", args="--role=architect") 执行。
|
||||
当前需求: ${taskDescription}
|
||||
约束: ${constraints}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 DESIGN-* 前缀的任务
|
||||
- 所有输出必须带 [architect] 标识前缀
|
||||
- 仅与 coordinator 通信
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 DESIGN-* 任务
|
||||
2. Skill(skill="team-iterdev", args="--role=architect") 执行
|
||||
3. team_msg log + SendMessage
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
|
||||
// Developer
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
team_name: teamName,
|
||||
name: "developer",
|
||||
prompt: `你是 team "${teamName}" 的 DEVELOPER。
|
||||
当你收到 DEV-* 任务时,调用 Skill(skill="team-iterdev", args="--role=developer") 执行。
|
||||
当前需求: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 DEV-* 前缀的任务
|
||||
- 所有输出必须带 [developer] 标识前缀
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 DEV-* 任务
|
||||
2. Skill(skill="team-iterdev", args="--role=developer") 执行
|
||||
3. team_msg log + SendMessage
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
|
||||
// Tester
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
team_name: teamName,
|
||||
name: "tester",
|
||||
prompt: `你是 team "${teamName}" 的 TESTER。
|
||||
当你收到 VERIFY-* 任务时,调用 Skill(skill="team-iterdev", args="--role=tester") 执行。
|
||||
当前需求: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 VERIFY-* 前缀的任务
|
||||
- 所有输出必须带 [tester] 标识前缀
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 VERIFY-* 任务
|
||||
2. Skill(skill="team-iterdev", args="--role=tester") 执行
|
||||
3. team_msg log + SendMessage
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
|
||||
// Reviewer
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
team_name: teamName,
|
||||
name: "reviewer",
|
||||
prompt: `你是 team "${teamName}" 的 REVIEWER。
|
||||
当你收到 REVIEW-* 任务时,调用 Skill(skill="team-iterdev", args="--role=reviewer") 执行。
|
||||
当前需求: ${taskDescription}
|
||||
|
||||
## 角色准则(强制)
|
||||
- 你只能处理 REVIEW-* 前缀的任务
|
||||
- 所有输出必须带 [reviewer] 标识前缀
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 REVIEW-* 任务
|
||||
2. Skill(skill="team-iterdev", args="--role=reviewer") 执行
|
||||
3. team_msg log + SendMessage
|
||||
4. TaskUpdate completed → 检查下一个任务`
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| Unknown --role value | Error with available role list |
|
||||
| Missing --role arg | Error with usage hint |
|
||||
| Role file not found | Error with expected path |
|
||||
| GC loop exceeds 3 rounds | Accept with warning, record in shared memory |
|
||||
| Sprint velocity drops below 50% | Coordinator alerts user, suggests scope reduction |
|
||||
| Task ledger corrupted | Rebuild from TaskList state |
|
||||
179
.claude/skills/team-iterdev/roles/architect.md
Normal file
179
.claude/skills/team-iterdev/roles/architect.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Role: architect
|
||||
|
||||
技术架构师。负责技术设计、任务分解、架构决策记录。
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `architect`
|
||||
- **Task Prefix**: `DESIGN-*`
|
||||
- **Responsibility**: Read-only analysis (技术设计)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[architect]`
|
||||
|
||||
## Role Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `DESIGN-*` 前缀的任务
|
||||
- 所有输出必须带 `[architect]` 标识
|
||||
- Phase 2 读取 shared-memory.json,Phase 5 写入 architecture_decisions
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 编写实现代码、执行测试或代码审查
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 为其他角色创建任务
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `design_ready` | architect → coordinator | Design completed | 设计完成 |
|
||||
| `design_revision` | architect → coordinator | Design revised | 设计修订 |
|
||||
| `error` | architect → coordinator | Processing failure | 错误上报 |
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('DESIGN-') && t.owner === 'architect' &&
|
||||
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' })
|
||||
```
|
||||
|
||||
### Phase 2: Context Loading + Codebase Exploration
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
|
||||
// Multi-angle codebase exploration
|
||||
Task({
|
||||
subagent_type: "cli-explore-agent",
|
||||
run_in_background: false,
|
||||
description: "Explore architecture",
|
||||
prompt: `Explore codebase architecture for: ${task.description}
|
||||
Focus on: existing patterns, module structure, dependencies, similar implementations.
|
||||
Report relevant files and integration points.`
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 3: Technical Design + Task Decomposition
|
||||
|
||||
```javascript
|
||||
const designNum = task.subject.match(/DESIGN-(\d+)/)?.[1] || '001'
|
||||
const designPath = `${sessionFolder}/design/design-${designNum}.md`
|
||||
const breakdownPath = `${sessionFolder}/design/task-breakdown.json`
|
||||
|
||||
// Generate design document
|
||||
const designContent = `# Technical Design — ${designNum}
|
||||
|
||||
**Requirement**: ${task.description}
|
||||
**Sprint**: ${sharedMemory.sprint_history?.length + 1 || 1}
|
||||
|
||||
## Architecture Decision
|
||||
|
||||
**Approach**: ${selectedApproach}
|
||||
**Rationale**: ${rationale}
|
||||
**Alternatives Considered**: ${alternatives.join(', ')}
|
||||
|
||||
## Component Design
|
||||
|
||||
${components.map(c => `### ${c.name}
|
||||
- **Responsibility**: ${c.responsibility}
|
||||
- **Dependencies**: ${c.dependencies.join(', ')}
|
||||
- **Files**: ${c.files.join(', ')}
|
||||
- **Complexity**: ${c.complexity}
|
||||
`).join('\n')}
|
||||
|
||||
## Task Breakdown
|
||||
|
||||
${taskBreakdown.map((t, i) => `### Task ${i + 1}: ${t.title}
|
||||
- **Files**: ${t.files.join(', ')}
|
||||
- **Estimated Complexity**: ${t.complexity}
|
||||
- **Dependencies**: ${t.dependencies.join(', ') || 'None'}
|
||||
`).join('\n')}
|
||||
|
||||
## Integration Points
|
||||
|
||||
${integrationPoints.map(ip => `- **${ip.name}**: ${ip.description}`).join('\n')}
|
||||
|
||||
## Risks
|
||||
|
||||
${risks.map(r => `- **${r.risk}**: ${r.mitigation}`).join('\n')}
|
||||
`
|
||||
|
||||
Write(designPath, designContent)
|
||||
|
||||
// Generate task breakdown JSON for developer
|
||||
const breakdown = {
|
||||
design_id: `design-${designNum}`,
|
||||
tasks: taskBreakdown.map((t, i) => ({
|
||||
id: `task-${i + 1}`,
|
||||
title: t.title,
|
||||
files: t.files,
|
||||
complexity: t.complexity,
|
||||
dependencies: t.dependencies,
|
||||
acceptance_criteria: t.acceptance
|
||||
})),
|
||||
total_files: [...new Set(taskBreakdown.flatMap(t => t.files))].length,
|
||||
execution_order: taskBreakdown.map((t, i) => `task-${i + 1}`)
|
||||
}
|
||||
Write(breakdownPath, JSON.stringify(breakdown, null, 2))
|
||||
```
|
||||
|
||||
### Phase 4: Design Validation
|
||||
|
||||
```javascript
|
||||
// Verify design completeness
|
||||
const hasComponents = components.length > 0
|
||||
const hasBreakdown = taskBreakdown.length > 0
|
||||
const hasDependencies = components.every(c => c.dependencies !== undefined)
|
||||
```
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.architecture_decisions.push({
|
||||
design_id: `design-${designNum}`,
|
||||
approach: selectedApproach,
|
||||
rationale: rationale,
|
||||
components: components.map(c => c.name),
|
||||
task_count: taskBreakdown.length
|
||||
})
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "architect", to: "coordinator",
|
||||
type: "design_ready",
|
||||
summary: `[architect] Design complete: ${components.length} components, ${taskBreakdown.length} tasks`,
|
||||
ref: designPath
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message", recipient: "coordinator",
|
||||
content: `## [architect] Design Ready\n\n**Components**: ${components.length}\n**Tasks**: ${taskBreakdown.length}\n**Design**: ${designPath}\n**Breakdown**: ${breakdownPath}`,
|
||||
summary: `[architect] Design: ${taskBreakdown.length} tasks`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No DESIGN-* tasks | Idle |
|
||||
| Codebase exploration fails | Design based on task description alone |
|
||||
| Too many components | Simplify, suggest phased approach |
|
||||
| Conflicting patterns found | Document in design, recommend resolution |
|
||||
266
.claude/skills/team-iterdev/roles/coordinator.md
Normal file
266
.claude/skills/team-iterdev/roles/coordinator.md
Normal file
@@ -0,0 +1,266 @@
|
||||
# Role: coordinator
|
||||
|
||||
持续迭代开发团队协调者。负责 Sprint 规划、积压管理、任务账本维护、Generator-Critic 循环控制(developer↔reviewer,最多3轮)和 Sprint 间学习。
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `coordinator`
|
||||
- **Task Prefix**: N/A
|
||||
- **Responsibility**: Orchestration
|
||||
- **Communication**: SendMessage to all teammates
|
||||
- **Output Tag**: `[coordinator]`
|
||||
|
||||
## Role Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 所有输出必须带 `[coordinator]` 标识
|
||||
- 维护 task-ledger.json 实时进度
|
||||
- 管理 developer↔reviewer 的 GC 循环(最多3轮)
|
||||
- Sprint 结束时记录学习到 shared-memory.json
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 直接编写代码、设计架构、执行测试或代码审查
|
||||
- ❌ 直接调用实现类 subagent
|
||||
- ❌ 修改源代码
|
||||
|
||||
## Execution
|
||||
|
||||
### Phase 1: Sprint Planning
|
||||
|
||||
```javascript
|
||||
const args = "$ARGUMENTS"
|
||||
const teamName = args.match(/--team-name[=\s]+([\w-]+)/)?.[1] || `iterdev-${Date.now().toString(36)}`
|
||||
const taskDescription = args.replace(/--team-name[=\s]+[\w-]+/, '').replace(/--role[=\s]+\w+/, '').trim()
|
||||
|
||||
// Assess complexity for pipeline selection
|
||||
function assessComplexity(desc) {
|
||||
let score = 0
|
||||
const changedFiles = Bash(`git diff --name-only HEAD~1 2>/dev/null || echo ""`).split('\n').filter(Boolean)
|
||||
score += changedFiles.length > 10 ? 3 : changedFiles.length > 3 ? 2 : 0
|
||||
if (/refactor|architect|restructure|system|module/.test(desc)) score += 3
|
||||
if (/multiple|across|cross/.test(desc)) score += 2
|
||||
if (/fix|bug|typo|patch/.test(desc)) score -= 2
|
||||
return { score, fileCount: changedFiles.length }
|
||||
}
|
||||
|
||||
const { score, fileCount } = assessComplexity(taskDescription)
|
||||
const suggestedPipeline = score >= 5 ? 'multi-sprint' : score >= 2 ? 'sprint' : 'patch'
|
||||
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "选择开发模式:",
|
||||
header: "Mode",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: suggestedPipeline === 'patch' ? "patch (推荐)" : "patch", description: "补丁模式:实现→验证(简单修复)" },
|
||||
{ label: suggestedPipeline === 'sprint' ? "sprint (推荐)" : "sprint", description: "Sprint模式:设计→实现→验证+审查" },
|
||||
{ label: suggestedPipeline === 'multi-sprint' ? "multi-sprint (推荐)" : "multi-sprint", description: "多Sprint:增量迭代交付(大型特性)" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 2: Create Team + Initialize Ledger
|
||||
|
||||
```javascript
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
const topicSlug = taskDescription.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 40)
|
||||
const dateStr = new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString().substring(0, 10)
|
||||
const sessionId = `IDS-${topicSlug}-${dateStr}`
|
||||
const sessionFolder = `.workflow/.team/${sessionId}`
|
||||
|
||||
Bash(`mkdir -p "${sessionFolder}/design" "${sessionFolder}/code" "${sessionFolder}/verify" "${sessionFolder}/review"`)
|
||||
|
||||
// Initialize task ledger
|
||||
const taskLedger = {
|
||||
sprint_id: "sprint-1",
|
||||
sprint_goal: taskDescription,
|
||||
pipeline: selectedPipeline,
|
||||
tasks: [],
|
||||
metrics: { total: 0, completed: 0, in_progress: 0, blocked: 0, velocity: 0 }
|
||||
}
|
||||
Write(`${sessionFolder}/task-ledger.json`, JSON.stringify(taskLedger, null, 2))
|
||||
|
||||
// Initialize shared memory with sprint learning
|
||||
const sharedMemory = {
|
||||
sprint_history: [],
|
||||
architecture_decisions: [],
|
||||
implementation_context: [],
|
||||
review_feedback_trends: [],
|
||||
gc_round: 0,
|
||||
max_gc_rounds: 3
|
||||
}
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
const teamSession = {
|
||||
session_id: sessionId, team_name: teamName, task: taskDescription,
|
||||
pipeline: selectedPipeline, status: "active", sprint_number: 1,
|
||||
created_at: new Date().toISOString(), updated_at: new Date().toISOString(),
|
||||
completed_tasks: []
|
||||
}
|
||||
Write(`${sessionFolder}/team-session.json`, JSON.stringify(teamSession, null, 2))
|
||||
```
|
||||
|
||||
Spawn workers (see SKILL.md Coordinator Spawn Template).
|
||||
|
||||
### Phase 3: Create Task Chain + Update Ledger
|
||||
|
||||
#### Patch Pipeline
|
||||
|
||||
```javascript
|
||||
TaskCreate({ subject: "DEV-001: 实现修复", description: `${taskDescription}\n\nSession: ${sessionFolder}`, activeForm: "实现中" })
|
||||
TaskUpdate({ taskId: devId, owner: "developer" })
|
||||
|
||||
TaskCreate({ subject: "VERIFY-001: 验证修复", description: `验证 DEV-001\n\nSession: ${sessionFolder}`, activeForm: "验证中" })
|
||||
TaskUpdate({ taskId: verifyId, owner: "tester", addBlockedBy: [devId] })
|
||||
|
||||
// Update ledger
|
||||
updateLedger(sessionFolder, null, {
|
||||
tasks: [
|
||||
{ id: "DEV-001", title: "实现修复", owner: "developer", status: "pending", gc_rounds: 0 },
|
||||
{ id: "VERIFY-001", title: "验证修复", owner: "tester", status: "pending", gc_rounds: 0 }
|
||||
],
|
||||
metrics: { total: 2, completed: 0, in_progress: 0, blocked: 0, velocity: 0 }
|
||||
})
|
||||
```
|
||||
|
||||
#### Sprint Pipeline
|
||||
|
||||
```javascript
|
||||
TaskCreate({ subject: "DESIGN-001: 技术设计与任务分解", description: `${taskDescription}\n\nSession: ${sessionFolder}\n输出: ${sessionFolder}/design/design-001.md + task-breakdown.json`, activeForm: "设计中" })
|
||||
TaskUpdate({ taskId: designId, owner: "architect" })
|
||||
|
||||
TaskCreate({ subject: "DEV-001: 实现设计方案", description: `按设计方案实现\n\nSession: ${sessionFolder}\n设计: design/design-001.md\n分解: design/task-breakdown.json`, activeForm: "实现中" })
|
||||
TaskUpdate({ taskId: devId, owner: "developer", addBlockedBy: [designId] })
|
||||
|
||||
// VERIFY-001 and REVIEW-001 parallel, both blockedBy DEV-001
|
||||
TaskCreate({ subject: "VERIFY-001: 测试验证", description: `验证实现\n\nSession: ${sessionFolder}`, activeForm: "验证中" })
|
||||
TaskUpdate({ taskId: verifyId, owner: "tester", addBlockedBy: [devId] })
|
||||
|
||||
TaskCreate({ subject: "REVIEW-001: 代码审查", description: `审查实现\n\nSession: ${sessionFolder}\n设计: design/design-001.md`, activeForm: "审查中" })
|
||||
TaskUpdate({ taskId: reviewId, owner: "reviewer", addBlockedBy: [devId] })
|
||||
```
|
||||
|
||||
#### Multi-Sprint Pipeline
|
||||
|
||||
```javascript
|
||||
// Sprint 1 — created dynamically, subsequent sprints created after Sprint N completes
|
||||
// Each sprint: DESIGN → DEV-1..N(incremental) → VERIFY → DEV-fix → REVIEW
|
||||
```
|
||||
|
||||
### Phase 4: Coordination Loop + GC Control + Ledger Updates
|
||||
|
||||
| Received Message | Action |
|
||||
|-----------------|--------|
|
||||
| architect: design_ready | Read design → update ledger → unblock DEV |
|
||||
| developer: dev_complete | Update ledger → unblock VERIFY + REVIEW |
|
||||
| tester: verify_passed | Update ledger (test_pass_rate) |
|
||||
| tester: verify_failed | Create DEV-fix task |
|
||||
| tester: fix_required | Create DEV-fix task → assign developer |
|
||||
| reviewer: review_passed | Update ledger (review_score) → mark complete |
|
||||
| reviewer: review_revision | **GC loop** → create DEV-fix → REVIEW-next |
|
||||
| reviewer: review_critical | **GC loop** → create DEV-fix → REVIEW-next |
|
||||
|
||||
#### Generator-Critic Loop Control (developer↔reviewer)
|
||||
|
||||
```javascript
|
||||
if (msgType === 'review_revision' || msgType === 'review_critical') {
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
const gcRound = sharedMemory.gc_round || 0
|
||||
|
||||
if (gcRound < sharedMemory.max_gc_rounds) {
|
||||
sharedMemory.gc_round = gcRound + 1
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
// Create DEV-fix task
|
||||
TaskCreate({
|
||||
subject: `DEV-fix-${gcRound + 1}: 根据审查修订代码`,
|
||||
description: `审查反馈:\n${reviewFeedback}\n\nSession: ${sessionFolder}\n审查: review/review-${reviewNum}.md`,
|
||||
activeForm: "修订代码中"
|
||||
})
|
||||
TaskUpdate({ taskId: fixId, owner: "developer" })
|
||||
|
||||
// Create REVIEW-next task
|
||||
TaskCreate({
|
||||
subject: `REVIEW-${reviewNum + 1}: 验证修订`,
|
||||
description: `验证 DEV-fix-${gcRound + 1} 的修订\n\nSession: ${sessionFolder}`,
|
||||
activeForm: "复审中"
|
||||
})
|
||||
TaskUpdate({ taskId: nextReviewId, owner: "reviewer", addBlockedBy: [fixId] })
|
||||
|
||||
// Update ledger
|
||||
updateLedger(sessionFolder, `DEV-fix-${gcRound + 1}`, { status: 'pending', gc_rounds: gcRound + 1 })
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator", to: "developer",
|
||||
type: "gc_loop_trigger",
|
||||
summary: `[coordinator] GC round ${gcRound + 1}/${sharedMemory.max_gc_rounds}: review requires revision`
|
||||
})
|
||||
} else {
|
||||
// Max rounds — accept with warning
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator", to: "all",
|
||||
type: "sprint_complete",
|
||||
summary: `[coordinator] GC loop exhausted (${gcRound} rounds), accepting current state`
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 5: Sprint Retrospective + Persist
|
||||
|
||||
```javascript
|
||||
const ledger = JSON.parse(Read(`${sessionFolder}/task-ledger.json`))
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
|
||||
// Record sprint learning
|
||||
const sprintRetro = {
|
||||
sprint_id: ledger.sprint_id,
|
||||
velocity: ledger.metrics.velocity,
|
||||
gc_rounds: sharedMemory.gc_round,
|
||||
what_worked: [], // extracted from review/verify feedback
|
||||
what_failed: [], // extracted from failures
|
||||
patterns_learned: [] // derived from GC loop patterns
|
||||
}
|
||||
sharedMemory.sprint_history.push(sprintRetro)
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
SendMessage({
|
||||
content: `## [coordinator] Sprint 完成
|
||||
|
||||
**需求**: ${taskDescription}
|
||||
**管道**: ${selectedPipeline}
|
||||
**完成**: ${ledger.metrics.completed}/${ledger.metrics.total}
|
||||
**GC 轮次**: ${sharedMemory.gc_round}
|
||||
|
||||
### 任务账本
|
||||
${ledger.tasks.map(t => `- ${t.id}: ${t.status} ${t.review_score ? '(Review: ' + t.review_score + '/10)' : ''}`).join('\n')}`,
|
||||
summary: `[coordinator] Sprint complete: ${ledger.metrics.completed}/${ledger.metrics.total}`
|
||||
})
|
||||
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "Sprint 已完成。下一步:",
|
||||
header: "Next",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "下一个Sprint", description: "继续迭代(携带学习记忆)" },
|
||||
{ label: "新需求", description: "新的开发需求" },
|
||||
{ label: "关闭团队", description: "关闭所有 teammate" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| GC 循环超限 (3轮) | 接受当前代码,记录到 sprint_history |
|
||||
| Velocity 低于 50% | 上报用户,建议缩小范围 |
|
||||
| 任务账本损坏 | 从 TaskList 重建 |
|
||||
| 设计被拒 3+ 次 | Coordinator 介入简化设计 |
|
||||
| 测试持续失败 | 创建 DEV-fix 给 developer |
|
||||
212
.claude/skills/team-iterdev/roles/developer.md
Normal file
212
.claude/skills/team-iterdev/roles/developer.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# Role: developer
|
||||
|
||||
代码实现者。负责按设计方案编码、增量交付。作为 Generator-Critic 循环中的 Generator 角色(与 reviewer 配对)。
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `developer`
|
||||
- **Task Prefix**: `DEV-*`
|
||||
- **Responsibility**: Code generation (代码实现)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[developer]`
|
||||
|
||||
## Role Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `DEV-*` 前缀的任务
|
||||
- 所有输出必须带 `[developer]` 标识
|
||||
- Phase 2 读取 shared-memory.json + design,Phase 5 写入 implementation_context
|
||||
- 修订任务(DEV-fix-*)时参考 review 反馈
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 执行测试、代码审查或架构设计
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 为其他角色创建任务
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `dev_complete` | developer → coordinator | Implementation done | 实现完成 |
|
||||
| `dev_progress` | developer → coordinator | Incremental progress | 进度更新 |
|
||||
| `error` | developer → coordinator | Processing failure | 错误上报 |
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('DEV-') && t.owner === 'developer' &&
|
||||
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' })
|
||||
```
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
|
||||
// Read design and breakdown
|
||||
let design = null, breakdown = null
|
||||
try {
|
||||
design = Read(`${sessionFolder}/design/design-001.md`)
|
||||
breakdown = JSON.parse(Read(`${sessionFolder}/design/task-breakdown.json`))
|
||||
} catch {}
|
||||
|
||||
// Check if this is a fix task (GC loop)
|
||||
const isFixTask = task.subject.includes('fix')
|
||||
let reviewFeedback = null
|
||||
if (isFixTask) {
|
||||
const reviewFiles = Glob({ pattern: `${sessionFolder}/review/*.md` })
|
||||
if (reviewFiles.length > 0) {
|
||||
reviewFeedback = Read(reviewFiles[reviewFiles.length - 1])
|
||||
}
|
||||
}
|
||||
|
||||
// Previous implementation context from shared memory
|
||||
const prevContext = sharedMemory.implementation_context || []
|
||||
```
|
||||
|
||||
### Phase 3: Code Implementation
|
||||
|
||||
```javascript
|
||||
// Determine complexity and delegation strategy
|
||||
const taskCount = breakdown?.tasks?.length || 1
|
||||
|
||||
if (isFixTask) {
|
||||
// === GC Fix Mode ===
|
||||
// Focus on review feedback items
|
||||
// Parse critical/high issues from review
|
||||
// Fix each issue directly
|
||||
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: "Fix review issues",
|
||||
prompt: `Fix the following code review issues:
|
||||
|
||||
${reviewFeedback}
|
||||
|
||||
Focus on:
|
||||
1. Critical issues (must fix)
|
||||
2. High issues (should fix)
|
||||
3. Medium issues (if time permits)
|
||||
|
||||
Do NOT change code that wasn't flagged.
|
||||
Maintain existing code style and patterns.`
|
||||
})
|
||||
|
||||
} else if (taskCount <= 2) {
|
||||
// Direct implementation
|
||||
for (const t of (breakdown?.tasks || [])) {
|
||||
for (const file of (t.files || [])) {
|
||||
try { Read(file) } catch {} // Read existing file
|
||||
// Edit or Write as needed
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Delegate to code-developer
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: `Implement ${taskCount} tasks`,
|
||||
prompt: `## Design
|
||||
${design}
|
||||
|
||||
## Task Breakdown
|
||||
${JSON.stringify(breakdown, null, 2)}
|
||||
|
||||
${prevContext.length > 0 ? `## Previous Context\n${prevContext.map(c => `- ${c}`).join('\n')}` : ''}
|
||||
|
||||
Implement each task following the design. Complete tasks in the specified execution order.`
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 4: Self-Validation
|
||||
|
||||
```javascript
|
||||
// Syntax check
|
||||
const syntaxResult = Bash(`npx tsc --noEmit 2>&1 || python -m py_compile *.py 2>&1 || true`)
|
||||
const hasSyntaxErrors = syntaxResult.includes('error')
|
||||
|
||||
// List changed files
|
||||
const changedFiles = Bash(`git diff --name-only`).split('\n').filter(Boolean)
|
||||
|
||||
// Log implementation progress
|
||||
const devLog = `# Dev Log — ${task.subject}
|
||||
|
||||
**Changed Files**: ${changedFiles.length}
|
||||
**Syntax Clean**: ${!hasSyntaxErrors}
|
||||
**Fix Task**: ${isFixTask}
|
||||
|
||||
## Files Changed
|
||||
${changedFiles.map(f => `- ${f}`).join('\n')}
|
||||
`
|
||||
Write(`${sessionFolder}/code/dev-log.md`, devLog)
|
||||
```
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.implementation_context.push({
|
||||
task: task.subject,
|
||||
changed_files: changedFiles,
|
||||
is_fix: isFixTask,
|
||||
syntax_clean: !hasSyntaxErrors
|
||||
})
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "developer", to: "coordinator",
|
||||
type: "dev_complete",
|
||||
summary: `[developer] ${isFixTask ? 'Fix' : 'Implementation'} complete: ${changedFiles.length} files changed`,
|
||||
ref: `${sessionFolder}/code/dev-log.md`
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message", recipient: "coordinator",
|
||||
content: `## [developer] ${isFixTask ? 'Fix' : 'Implementation'} Complete
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Changed Files**: ${changedFiles.length}
|
||||
**Syntax Clean**: ${!hasSyntaxErrors}
|
||||
${isFixTask ? `**GC Round**: ${sharedMemory.gc_round}` : ''}
|
||||
|
||||
### Files
|
||||
${changedFiles.slice(0, 10).map(f => `- ${f}`).join('\n')}`,
|
||||
summary: `[developer] ${changedFiles.length} files ${isFixTask ? 'fixed' : 'implemented'}`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('DEV-') && t.owner === 'developer' &&
|
||||
t.status === 'pending' && t.blockedBy.length === 0
|
||||
)
|
||||
if (nextTasks.length > 0) { /* back to Phase 1 */ }
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No DEV-* tasks | Idle |
|
||||
| Design not found | Implement based on task description |
|
||||
| Syntax errors after implementation | Attempt auto-fix, report remaining errors |
|
||||
| Review feedback unclear | Implement best interpretation, note in dev-log |
|
||||
| Code-developer agent fails | Retry once, then implement inline |
|
||||
206
.claude/skills/team-iterdev/roles/reviewer.md
Normal file
206
.claude/skills/team-iterdev/roles/reviewer.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Role: reviewer
|
||||
|
||||
代码审查者。负责多维度审查、质量评分、改进建议。作为 Generator-Critic 循环中的 Critic 角色(与 developer 配对)。
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `reviewer`
|
||||
- **Task Prefix**: `REVIEW-*`
|
||||
- **Responsibility**: Read-only analysis (代码审查)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[reviewer]`
|
||||
|
||||
## Role Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `REVIEW-*` 前缀的任务
|
||||
- 所有输出必须带 `[reviewer]` 标识
|
||||
- Phase 2 读取 shared-memory.json + design,Phase 5 写入 review_feedback_trends
|
||||
- 标记每个问题的严重度 (CRITICAL/HIGH/MEDIUM/LOW)
|
||||
- 提供质量评分 (1-10)
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 编写实现代码、设计架构或执行测试
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 为其他角色创建任务
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `review_passed` | reviewer → coordinator | No critical issues, score >= 7 | 审查通过 |
|
||||
| `review_revision` | reviewer → coordinator | Issues found, score < 7 | 需要修订 (触发GC) |
|
||||
| `review_critical` | reviewer → coordinator | Critical issues found | 严重问题 (触发GC) |
|
||||
| `error` | reviewer → coordinator | Processing failure | 错误上报 |
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('REVIEW-') && t.owner === 'reviewer' &&
|
||||
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' })
|
||||
```
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
|
||||
// Read design for requirements alignment
|
||||
let design = null
|
||||
try { design = Read(`${sessionFolder}/design/design-001.md`) } catch {}
|
||||
|
||||
// Get changed files
|
||||
const changedFiles = Bash(`git diff --name-only HEAD~1 2>/dev/null || git diff --name-only --cached`).split('\n').filter(Boolean)
|
||||
|
||||
// Read file contents
|
||||
const fileContents = {}
|
||||
for (const file of changedFiles.slice(0, 20)) {
|
||||
try { fileContents[file] = Read(file) } catch {}
|
||||
}
|
||||
|
||||
// Previous review trends
|
||||
const prevTrends = sharedMemory.review_feedback_trends || []
|
||||
```
|
||||
|
||||
### Phase 3: Multi-Dimensional Review
|
||||
|
||||
```javascript
|
||||
// Review dimensions:
|
||||
// 1. Correctness — 逻辑正确性、边界处理
|
||||
// 2. Completeness — 是否覆盖设计要求
|
||||
// 3. Maintainability — 可读性、代码风格、DRY
|
||||
// 4. Security — 安全漏洞、输入验证
|
||||
|
||||
// Optional: CLI-assisted review
|
||||
Bash(`ccw cli -p "PURPOSE: Code review for correctness and security
|
||||
TASK: Review changes in: ${changedFiles.join(', ')}
|
||||
MODE: analysis
|
||||
CONTEXT: @${changedFiles.join(' @')}
|
||||
EXPECTED: Issues with severity (CRITICAL/HIGH/MEDIUM/LOW) and file:line
|
||||
CONSTRAINTS: Focus on correctness and security" --tool gemini --mode analysis`, { run_in_background: true })
|
||||
|
||||
const reviewNum = task.subject.match(/REVIEW-(\d+)/)?.[1] || '001'
|
||||
const outputPath = `${sessionFolder}/review/review-${reviewNum}.md`
|
||||
|
||||
// Scoring
|
||||
const score = calculateScore(findings)
|
||||
const criticalCount = findings.filter(f => f.severity === 'CRITICAL').length
|
||||
const highCount = findings.filter(f => f.severity === 'HIGH').length
|
||||
|
||||
const reviewContent = `# Code Review — Round ${reviewNum}
|
||||
|
||||
**Files Reviewed**: ${changedFiles.length}
|
||||
**Quality Score**: ${score}/10
|
||||
**Critical Issues**: ${criticalCount}
|
||||
**High Issues**: ${highCount}
|
||||
|
||||
## Findings
|
||||
|
||||
${findings.map((f, i) => `### ${i + 1}. [${f.severity}] ${f.title}
|
||||
|
||||
**File**: ${f.file}:${f.line}
|
||||
**Dimension**: ${f.dimension}
|
||||
**Description**: ${f.description}
|
||||
**Suggestion**: ${f.suggestion}
|
||||
`).join('\n')}
|
||||
|
||||
## Scoring Breakdown
|
||||
|
||||
| Dimension | Score | Notes |
|
||||
|-----------|-------|-------|
|
||||
| Correctness | ${scores.correctness}/10 | ${scores.correctnessNotes} |
|
||||
| Completeness | ${scores.completeness}/10 | ${scores.completenessNotes} |
|
||||
| Maintainability | ${scores.maintainability}/10 | ${scores.maintainabilityNotes} |
|
||||
| Security | ${scores.security}/10 | ${scores.securityNotes} |
|
||||
| **Overall** | **${score}/10** | |
|
||||
|
||||
## Signal
|
||||
|
||||
${criticalCount > 0 ? '**CRITICAL** — Critical issues must be fixed before merge'
|
||||
: score < 7 ? '**REVISION_NEEDED** — Quality below threshold (7/10)'
|
||||
: '**APPROVED** — Code meets quality standards'}
|
||||
|
||||
${design ? `## Design Alignment\n${designAlignmentNotes}` : ''}
|
||||
`
|
||||
|
||||
Write(outputPath, reviewContent)
|
||||
```
|
||||
|
||||
### Phase 4: Trend Analysis
|
||||
|
||||
```javascript
|
||||
// Compare with previous reviews to detect trends
|
||||
const currentIssueTypes = findings.map(f => f.dimension)
|
||||
const trendNote = prevTrends.length > 0
|
||||
? `Recurring: ${findRecurring(prevTrends, currentIssueTypes).join(', ')}`
|
||||
: 'First review'
|
||||
```
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.review_feedback_trends.push({
|
||||
review_id: `review-${reviewNum}`,
|
||||
score: score,
|
||||
critical: criticalCount,
|
||||
high: highCount,
|
||||
dimensions: findings.map(f => f.dimension),
|
||||
gc_round: sharedMemory.gc_round || 0
|
||||
})
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
const msgType = criticalCount > 0 ? "review_critical"
|
||||
: score < 7 ? "review_revision"
|
||||
: "review_passed"
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "reviewer", to: "coordinator",
|
||||
type: msgType,
|
||||
summary: `[reviewer] Review ${msgType}: score=${score}/10, ${criticalCount}C/${highCount}H`,
|
||||
ref: outputPath
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message", recipient: "coordinator",
|
||||
content: `## [reviewer] Code Review Results
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**Score**: ${score}/10
|
||||
**Signal**: ${msgType.toUpperCase()}
|
||||
**Critical**: ${criticalCount}, **High**: ${highCount}
|
||||
**Output**: ${outputPath}
|
||||
|
||||
### Top Issues
|
||||
${findings.filter(f => ['CRITICAL', 'HIGH'].includes(f.severity)).slice(0, 5).map(f =>
|
||||
`- **[${f.severity}]** ${f.title} (${f.file}:${f.line})`
|
||||
).join('\n')}`,
|
||||
summary: `[reviewer] ${msgType}: ${score}/10`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No REVIEW-* tasks | Idle |
|
||||
| No changed files | Review files referenced in design |
|
||||
| CLI review fails | Fall back to inline analysis |
|
||||
| All issues LOW | Score high, approve |
|
||||
| Design not found | Review against general quality standards |
|
||||
146
.claude/skills/team-iterdev/roles/tester.md
Normal file
146
.claude/skills/team-iterdev/roles/tester.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Role: tester
|
||||
|
||||
测试验证者。负责测试执行、修复循环、回归检测。
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `tester`
|
||||
- **Task Prefix**: `VERIFY-*`
|
||||
- **Responsibility**: Validation (测试验证)
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
- **Output Tag**: `[tester]`
|
||||
|
||||
## Role Boundaries
|
||||
|
||||
### MUST
|
||||
|
||||
- 仅处理 `VERIFY-*` 前缀的任务
|
||||
- 所有输出必须带 `[tester]` 标识
|
||||
- Phase 2 读取 shared-memory.json,Phase 5 写入 test_patterns
|
||||
|
||||
### MUST NOT
|
||||
|
||||
- ❌ 编写实现代码、设计架构或代码审查
|
||||
- ❌ 直接与其他 worker 通信
|
||||
- ❌ 为其他角色创建任务
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
| `verify_passed` | tester → coordinator | All tests pass | 验证通过 |
|
||||
| `verify_failed` | tester → coordinator | Tests fail | 验证失败 |
|
||||
| `fix_required` | tester → coordinator | Issues found needing fix | 需要修复 |
|
||||
| `error` | tester → coordinator | Environment failure | 错误上报 |
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('VERIFY-') && t.owner === 'tester' &&
|
||||
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' })
|
||||
```
|
||||
|
||||
### Phase 2: Context Loading
|
||||
|
||||
```javascript
|
||||
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
|
||||
const sessionFolder = sessionMatch?.[1]?.trim()
|
||||
|
||||
const memoryPath = `${sessionFolder}/shared-memory.json`
|
||||
let sharedMemory = {}
|
||||
try { sharedMemory = JSON.parse(Read(memoryPath)) } catch {}
|
||||
|
||||
// Detect test framework and test command
|
||||
const testCommand = detectTestCommand()
|
||||
const changedFiles = Bash(`git diff --name-only`).split('\n').filter(Boolean)
|
||||
```
|
||||
|
||||
### Phase 3: Test Execution + Fix Cycle
|
||||
|
||||
```javascript
|
||||
let iteration = 0
|
||||
const MAX_ITERATIONS = 5
|
||||
let lastResult = null
|
||||
let passRate = 0
|
||||
|
||||
while (iteration < MAX_ITERATIONS) {
|
||||
lastResult = Bash(`${testCommand} 2>&1 || true`)
|
||||
passRate = parsePassRate(lastResult)
|
||||
|
||||
if (passRate >= 0.95) break
|
||||
|
||||
if (iteration < MAX_ITERATIONS - 1) {
|
||||
// Delegate fix to code-developer
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: `Fix test failures (iteration ${iteration + 1})`,
|
||||
prompt: `Test failures:\n${lastResult.substring(0, 3000)}\n\nFix failing tests. Changed files: ${changedFiles.join(', ')}`
|
||||
})
|
||||
}
|
||||
iteration++
|
||||
}
|
||||
|
||||
// Save verification results
|
||||
const verifyNum = task.subject.match(/VERIFY-(\d+)/)?.[1] || '001'
|
||||
const resultData = {
|
||||
verify_id: `verify-${verifyNum}`,
|
||||
pass_rate: passRate,
|
||||
iterations: iteration,
|
||||
passed: passRate >= 0.95,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
Write(`${sessionFolder}/verify/verify-${verifyNum}.json`, JSON.stringify(resultData, null, 2))
|
||||
```
|
||||
|
||||
### Phase 4: Regression Check
|
||||
|
||||
```javascript
|
||||
// Run full test suite for regression
|
||||
const regressionResult = Bash(`${testCommand} --all 2>&1 || true`)
|
||||
const regressionPassed = !regressionResult.includes('FAIL')
|
||||
resultData.regression_passed = regressionPassed
|
||||
```
|
||||
|
||||
### Phase 5: Report to Coordinator + Shared Memory Write
|
||||
|
||||
```javascript
|
||||
sharedMemory.test_patterns = sharedMemory.test_patterns || []
|
||||
if (passRate >= 0.95) {
|
||||
sharedMemory.test_patterns.push(`verify-${verifyNum}: passed in ${iteration} iterations`)
|
||||
}
|
||||
Write(memoryPath, JSON.stringify(sharedMemory, null, 2))
|
||||
|
||||
const msgType = resultData.passed ? "verify_passed" : (iteration >= MAX_ITERATIONS ? "fix_required" : "verify_failed")
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "tester", to: "coordinator",
|
||||
type: msgType,
|
||||
summary: `[tester] ${msgType}: pass_rate=${(passRate*100).toFixed(1)}%, iterations=${iteration}`,
|
||||
ref: `${sessionFolder}/verify/verify-${verifyNum}.json`
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message", recipient: "coordinator",
|
||||
content: `## [tester] Verification Results\n\n**Pass Rate**: ${(passRate*100).toFixed(1)}%\n**Iterations**: ${iteration}/${MAX_ITERATIONS}\n**Regression**: ${resultData.regression_passed ? '✅' : '❌'}\n**Status**: ${resultData.passed ? '✅ PASSED' : '❌ NEEDS FIX'}`,
|
||||
summary: `[tester] ${resultData.passed ? 'PASSED' : 'FAILED'}: ${(passRate*100).toFixed(1)}%`
|
||||
})
|
||||
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No VERIFY-* tasks | Idle |
|
||||
| Test command not found | Try common commands (npm test, pytest, vitest) |
|
||||
| Max iterations exceeded | Report fix_required to coordinator |
|
||||
| Test environment broken | Report error, suggest manual fix |
|
||||
94
.claude/skills/team-iterdev/specs/team-config.json
Normal file
94
.claude/skills/team-iterdev/specs/team-config.json
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"team_name": "team-iterdev",
|
||||
"team_display_name": "Team IterDev",
|
||||
"description": "Iterative development team with Generator-Critic loop, task ledger, sprint learning, and dynamic pipeline",
|
||||
"version": "1.0.0",
|
||||
|
||||
"roles": {
|
||||
"coordinator": {
|
||||
"task_prefix": null,
|
||||
"responsibility": "Sprint planning, backlog management, task ledger maintenance, GC loop control",
|
||||
"message_types": ["sprint_started", "gc_loop_trigger", "sprint_complete", "task_unblocked", "error", "shutdown"]
|
||||
},
|
||||
"architect": {
|
||||
"task_prefix": "DESIGN",
|
||||
"responsibility": "Technical design, task decomposition, architecture decisions",
|
||||
"message_types": ["design_ready", "design_revision", "error"]
|
||||
},
|
||||
"developer": {
|
||||
"task_prefix": "DEV",
|
||||
"responsibility": "Code implementation, incremental delivery",
|
||||
"message_types": ["dev_complete", "dev_progress", "error"]
|
||||
},
|
||||
"tester": {
|
||||
"task_prefix": "VERIFY",
|
||||
"responsibility": "Test execution, fix cycle, regression detection",
|
||||
"message_types": ["verify_passed", "verify_failed", "fix_required", "error"]
|
||||
},
|
||||
"reviewer": {
|
||||
"task_prefix": "REVIEW",
|
||||
"responsibility": "Code review, quality scoring, improvement suggestions",
|
||||
"message_types": ["review_passed", "review_revision", "review_critical", "error"]
|
||||
}
|
||||
},
|
||||
|
||||
"pipelines": {
|
||||
"patch": {
|
||||
"description": "Simple fix: implement → verify",
|
||||
"task_chain": ["DEV-001", "VERIFY-001"],
|
||||
"gc_loops": 0
|
||||
},
|
||||
"sprint": {
|
||||
"description": "Standard feature: design → implement → verify + review (parallel)",
|
||||
"task_chain": ["DESIGN-001", "DEV-001", "VERIFY-001", "REVIEW-001"],
|
||||
"gc_loops": 3,
|
||||
"parallel_groups": [["VERIFY-001", "REVIEW-001"]]
|
||||
},
|
||||
"multi-sprint": {
|
||||
"description": "Large feature: multiple sprint cycles with incremental delivery",
|
||||
"task_chain": "dynamic — coordinator creates per-sprint chains",
|
||||
"gc_loops": 3,
|
||||
"sprint_count": "dynamic"
|
||||
}
|
||||
},
|
||||
|
||||
"innovation_patterns": {
|
||||
"generator_critic": {
|
||||
"generator": "developer",
|
||||
"critic": "reviewer",
|
||||
"max_rounds": 3,
|
||||
"convergence_trigger": "review.critical_count === 0 && review.score >= 7"
|
||||
},
|
||||
"task_ledger": {
|
||||
"file": "task-ledger.json",
|
||||
"updated_by": "coordinator",
|
||||
"tracks": ["status", "gc_rounds", "review_score", "test_pass_rate", "velocity"]
|
||||
},
|
||||
"shared_memory": {
|
||||
"file": "shared-memory.json",
|
||||
"fields": {
|
||||
"architect": "architecture_decisions",
|
||||
"developer": "implementation_context",
|
||||
"tester": "test_patterns",
|
||||
"reviewer": "review_feedback_trends"
|
||||
},
|
||||
"persistent_fields": ["sprint_history", "what_worked", "what_failed", "patterns_learned"]
|
||||
},
|
||||
"dynamic_pipeline": {
|
||||
"selector": "coordinator",
|
||||
"criteria": "file_count + module_count + complexity_assessment",
|
||||
"downgrade_rule": "velocity >= expected && review_avg >= 8 → simplify next sprint"
|
||||
}
|
||||
},
|
||||
|
||||
"collaboration_patterns": ["CP-1", "CP-3", "CP-5", "CP-6"],
|
||||
|
||||
"session_dirs": {
|
||||
"base": ".workflow/.team/IDS-{slug}-{YYYY-MM-DD}/",
|
||||
"design": "design/",
|
||||
"code": "code/",
|
||||
"verify": "verify/",
|
||||
"review": "review/",
|
||||
"messages": ".workflow/.team-msg/{team-name}/"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user