mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
Add integration verification and validation phases, role templates, and static graph tests
- Implement Phase 4: Integration Verification to ensure skill package consistency. - Implement Phase 5: Validation to verify quality and deliver the final skill package. - Create role-template.md for generating per-role execution detail files. - Create skill-router-template.md for generating SKILL.md with role-based routing. - Add tests for static graph relationship writing during index build in test_static_graph_integration.py.
This commit is contained in:
333
.claude/skills/team-skill-designer/templates/role-template.md
Normal file
333
.claude/skills/team-skill-designer/templates/role-template.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Role File Template
|
||||
|
||||
Template for generating per-role execution detail files in `roles/{role-name}.md`.
|
||||
|
||||
## Purpose
|
||||
|
||||
| Phase | Usage |
|
||||
|-------|-------|
|
||||
| Phase 0 | Read to understand role file structure |
|
||||
| Phase 3 | Apply with role-specific content |
|
||||
|
||||
---
|
||||
|
||||
## Template
|
||||
|
||||
```markdown
|
||||
# Role: {{role_name}}
|
||||
|
||||
{{role_description}}
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `{{role_name}}`
|
||||
- **Task Prefix**: `{{task_prefix}}-*`
|
||||
- **Responsibility**: {{responsibility_type}}
|
||||
- **Communication**: SendMessage to coordinator only
|
||||
|
||||
## Message Types
|
||||
|
||||
| Type | Direction | Trigger | Description |
|
||||
|------|-----------|---------|-------------|
|
||||
{{#each message_types}}
|
||||
| `{{this.type}}` | {{../role_name}} → coordinator | {{this.trigger}} | {{this.description}} |
|
||||
{{/each}}
|
||||
|
||||
## Execution (5-Phase)
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
\`\`\`javascript
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('{{task_prefix}}-') &&
|
||||
t.owner === '{{role_name}}' &&
|
||||
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: {{phase2_name}}
|
||||
|
||||
{{phase2_content}}
|
||||
|
||||
### Phase 3: {{phase3_name}}
|
||||
|
||||
{{phase3_content}}
|
||||
|
||||
### Phase 4: {{phase4_name}}
|
||||
|
||||
{{phase4_content}}
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
\`\`\`javascript
|
||||
// Log message before SendMessage
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: teamName,
|
||||
from: "{{role_name}}",
|
||||
to: "coordinator",
|
||||
type: "{{primary_message_type}}",
|
||||
summary: \`{{task_prefix}} complete: \${task.subject}\`
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: \`## {{display_name}} Results
|
||||
|
||||
**Task**: \${task.subject}
|
||||
**Status**: \${resultStatus}
|
||||
|
||||
### Summary
|
||||
\${resultSummary}
|
||||
|
||||
### Details
|
||||
\${resultDetails}\`,
|
||||
summary: \`{{task_prefix}} complete\`
|
||||
})
|
||||
|
||||
// Mark task completed
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('{{task_prefix}}-') &&
|
||||
t.owner === '{{role_name}}' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
|
||||
if (nextTasks.length > 0) {
|
||||
// Continue with next task → back to Phase 1
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No {{task_prefix}}-* tasks available | Idle, wait for coordinator assignment |
|
||||
| Context/Plan file not found | Notify coordinator, request location |
|
||||
{{#if adaptive_routing}}
|
||||
| Sub-agent failure | Retry once, then fallback to direct execution |
|
||||
{{/if}}
|
||||
| Critical issue beyond scope | SendMessage fix_required to coordinator |
|
||||
| Unexpected error | Log error via team_msg, report to coordinator |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Template Sections by Responsibility Type
|
||||
|
||||
### Read-only analysis
|
||||
|
||||
**Phase 2: Context Loading**
|
||||
```javascript
|
||||
// Load plan for criteria reference
|
||||
const planPathMatch = task.description.match(/\.workflow\/\.team-plan\/[^\s]+\/plan\.json/)
|
||||
let plan = null
|
||||
if (planPathMatch) {
|
||||
try { plan = JSON.parse(Read(planPathMatch[0])) } 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 for analysis
|
||||
const fileContents = {}
|
||||
for (const file of changedFiles.slice(0, 20)) {
|
||||
try { fileContents[file] = Read(file) } catch {}
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 3: Analysis Execution**
|
||||
```javascript
|
||||
// Core analysis logic
|
||||
// Customize per specific analysis domain
|
||||
```
|
||||
|
||||
**Phase 4: Finding Summary**
|
||||
```javascript
|
||||
// Classify findings by severity
|
||||
const findings = {
|
||||
critical: [],
|
||||
high: [],
|
||||
medium: [],
|
||||
low: []
|
||||
}
|
||||
```
|
||||
|
||||
### Code generation
|
||||
|
||||
**Phase 2: Task & Plan Loading**
|
||||
```javascript
|
||||
const planPathMatch = task.description.match(/\.workflow\/\.team-plan\/[^\s]+\/plan\.json/)
|
||||
if (!planPathMatch) {
|
||||
SendMessage({ type: "message", recipient: "coordinator",
|
||||
content: `Cannot find plan.json in ${task.subject}`, summary: "Plan not found" })
|
||||
return
|
||||
}
|
||||
const plan = JSON.parse(Read(planPathMatch[0]))
|
||||
const planTasks = plan.task_ids.map(id =>
|
||||
JSON.parse(Read(`${planPathMatch[0].replace('plan.json', '')}.task/${id}.json`))
|
||||
)
|
||||
```
|
||||
|
||||
**Phase 3: Code Implementation**
|
||||
```javascript
|
||||
// Complexity-adaptive execution
|
||||
if (complexity === 'Low') {
|
||||
// Direct file editing
|
||||
} else {
|
||||
Task({
|
||||
subagent_type: "code-developer",
|
||||
run_in_background: false,
|
||||
description: "Implement plan tasks",
|
||||
prompt: `...`
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 4: Self-Validation**
|
||||
```javascript
|
||||
const syntaxResult = Bash(`tsc --noEmit 2>&1 || true`)
|
||||
const hasSyntaxErrors = syntaxResult.includes('error TS')
|
||||
```
|
||||
|
||||
### Orchestration
|
||||
|
||||
**Phase 2: Context & Complexity Assessment**
|
||||
```javascript
|
||||
function assessComplexity(desc) {
|
||||
let score = 0
|
||||
if (/refactor|architect|restructure|module|system/.test(desc)) score += 2
|
||||
if (/multiple|across|cross/.test(desc)) score += 2
|
||||
if (/integrate|api|database/.test(desc)) score += 1
|
||||
if (/security|performance/.test(desc)) score += 1
|
||||
return score >= 4 ? 'High' : score >= 2 ? 'Medium' : 'Low'
|
||||
}
|
||||
const complexity = assessComplexity(task.description)
|
||||
```
|
||||
|
||||
**Phase 3: Orchestrated Execution**
|
||||
```javascript
|
||||
// Launch parallel sub-agents or sequential stages
|
||||
```
|
||||
|
||||
**Phase 4: Result Aggregation**
|
||||
```javascript
|
||||
// Merge and summarize sub-agent results
|
||||
```
|
||||
|
||||
### Validation
|
||||
|
||||
**Phase 2: Environment Detection**
|
||||
```javascript
|
||||
const changedFiles = Bash(`git diff --name-only HEAD~1 2>/dev/null || git diff --name-only --cached`)
|
||||
.split('\n').filter(Boolean)
|
||||
```
|
||||
|
||||
**Phase 3: Execution & Fix Cycle**
|
||||
```javascript
|
||||
// Run validation, collect failures, attempt fixes, re-validate
|
||||
let iteration = 0
|
||||
const MAX_ITERATIONS = 5
|
||||
while (iteration < MAX_ITERATIONS) {
|
||||
const result = runValidation()
|
||||
if (result.passRate >= 0.95) break
|
||||
applyFixes(result.failures)
|
||||
iteration++
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 4: Result Analysis**
|
||||
```javascript
|
||||
// Analyze pass/fail patterns, coverage gaps
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Coordinator Role Template
|
||||
|
||||
The coordinator role is special and always generated. Its template differs from worker roles:
|
||||
|
||||
```markdown
|
||||
# Role: coordinator
|
||||
|
||||
Team coordinator. Orchestrates the pipeline: requirement clarification → task chain creation → dispatch → monitoring → reporting.
|
||||
|
||||
## Role Identity
|
||||
|
||||
- **Name**: `coordinator`
|
||||
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
|
||||
- **Responsibility**: Orchestration
|
||||
- **Communication**: SendMessage to all teammates
|
||||
|
||||
## Execution
|
||||
|
||||
### Phase 1: Requirement Clarification
|
||||
|
||||
Parse $ARGUMENTS, use AskUserQuestion for MVP scope and constraints.
|
||||
|
||||
### Phase 2: Create Team + Spawn Teammates
|
||||
|
||||
\`\`\`javascript
|
||||
TeamCreate({ team_name: teamName })
|
||||
|
||||
// Spawn each worker role
|
||||
{{#each worker_roles}}
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
team_name: teamName,
|
||||
name: "{{this.name}}",
|
||||
prompt: \`...Skill(skill="team-{{team_name}}", args="--role={{this.name}}")...\`
|
||||
})
|
||||
{{/each}}
|
||||
\`\`\`
|
||||
|
||||
### Phase 3: Create Task Chain
|
||||
|
||||
\`\`\`javascript
|
||||
{{task_chain_creation_code}}
|
||||
\`\`\`
|
||||
|
||||
### Phase 4: Coordination Loop
|
||||
|
||||
| Received Message | Action |
|
||||
|-----------------|--------|
|
||||
{{#each coordination_handlers}}
|
||||
| {{this.trigger}} | {{this.action}} |
|
||||
{{/each}}
|
||||
|
||||
### Phase 5: Report + Persist
|
||||
|
||||
Summarize results. AskUserQuestion for next requirement or shutdown.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Variable Reference
|
||||
|
||||
| Variable | Source | Description |
|
||||
|----------|--------|-------------|
|
||||
| `{{role_name}}` | config.role_name | Role identifier |
|
||||
| `{{task_prefix}}` | config.task_prefix | UPPERCASE task prefix |
|
||||
| `{{responsibility_type}}` | config.responsibility_type | Role type |
|
||||
| `{{display_name}}` | config.display_name | Human-readable |
|
||||
| `{{phase2_name}}` | patterns.phase_structure.phase2 | Phase 2 label |
|
||||
| `{{phase3_name}}` | patterns.phase_structure.phase3 | Phase 3 label |
|
||||
| `{{phase4_name}}` | patterns.phase_structure.phase4 | Phase 4 label |
|
||||
| `{{phase2_content}}` | Generated from responsibility template | Phase 2 code |
|
||||
| `{{phase3_content}}` | Generated from responsibility template | Phase 3 code |
|
||||
| `{{phase4_content}}` | Generated from responsibility template | Phase 4 code |
|
||||
| `{{message_types}}` | config.message_types | Array of message types |
|
||||
| `{{primary_message_type}}` | config.message_types[0].type | Primary type |
|
||||
| `{{adaptive_routing}}` | config.adaptive_routing | Boolean |
|
||||
@@ -0,0 +1,224 @@
|
||||
# Skill Router Template
|
||||
|
||||
Template for the generated SKILL.md with role-based routing.
|
||||
|
||||
## Purpose
|
||||
|
||||
| Phase | Usage |
|
||||
|-------|-------|
|
||||
| Phase 0 | Read to understand generated SKILL.md structure |
|
||||
| Phase 3 | Apply with team-specific content |
|
||||
|
||||
---
|
||||
|
||||
## Template
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: team-{{team_name}}
|
||||
description: Unified team skill for {{team_name}} team. All roles invoke this skill with --role arg for role-specific execution. Triggers on "team {{team_name}}".
|
||||
allowed-tools: {{all_roles_tools_union}}
|
||||
---
|
||||
|
||||
# Team {{team_display_name}}
|
||||
|
||||
Unified team skill. All team members invoke this skill with `--role=xxx` to route to role-specific execution.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
\`\`\`
|
||||
┌───────────────────────────────────────────┐
|
||||
│ Skill(skill="team-{{team_name}}") │
|
||||
│ args="--role=xxx" │
|
||||
└───────────────┬───────────────────────────┘
|
||||
│ Role Router
|
||||
┌───────────┼───────────┬───────────┐
|
||||
↓ ↓ ↓ ↓
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│coordinator│ │{{role_1}}│ │{{role_2}}│ │{{role_3}}│
|
||||
│ roles/ │ │ roles/ │ │ roles/ │ │ roles/ │
|
||||
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||
\`\`\`
|
||||
|
||||
## Role Router
|
||||
|
||||
### Input Parsing
|
||||
|
||||
Parse `$ARGUMENTS` to extract `--role`:
|
||||
|
||||
\`\`\`javascript
|
||||
const args = "$ARGUMENTS"
|
||||
const roleMatch = args.match(/--role[=\s]+(\w+)/)
|
||||
|
||||
if (!roleMatch) {
|
||||
// ERROR: --role is required
|
||||
// This skill must be invoked with: Skill(skill="team-{{team_name}}", args="--role=xxx")
|
||||
throw new Error("Missing --role argument. Available roles: {{role_list}}")
|
||||
}
|
||||
|
||||
const role = roleMatch[1]
|
||||
const teamName = "{{team_name}}"
|
||||
\`\`\`
|
||||
|
||||
### Role Dispatch
|
||||
|
||||
\`\`\`javascript
|
||||
const VALID_ROLES = {
|
||||
{{#each roles}}
|
||||
"{{this.name}}": { file: "roles/{{this.name}}.md", prefix: "{{this.task_prefix}}" },
|
||||
{{/each}}
|
||||
}
|
||||
|
||||
if (!VALID_ROLES[role]) {
|
||||
throw new Error(\`Unknown role: \${role}. Available: \${Object.keys(VALID_ROLES).join(', ')}\`)
|
||||
}
|
||||
|
||||
// Read and execute role-specific logic
|
||||
Read(VALID_ROLES[role].file)
|
||||
// → Execute the 5-phase process defined in that file
|
||||
\`\`\`
|
||||
|
||||
### Available Roles
|
||||
|
||||
| Role | Task Prefix | Responsibility | Role File |
|
||||
|------|-------------|----------------|-----------|
|
||||
{{#each roles}}
|
||||
| `{{this.name}}` | {{this.task_prefix}}-* | {{this.responsibility}} | [roles/{{this.name}}.md](roles/{{this.name}}.md) |
|
||||
{{/each}}
|
||||
|
||||
## Shared Infrastructure
|
||||
|
||||
### Team Configuration
|
||||
|
||||
\`\`\`javascript
|
||||
const TEAM_CONFIG = {
|
||||
name: "{{team_name}}",
|
||||
sessionDir: ".workflow/.team-plan/{{team_name}}/",
|
||||
msgDir: ".workflow/.team-msg/{{team_name}}/",
|
||||
roles: {{roles_json}}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Message Bus (All Roles)
|
||||
|
||||
Every SendMessage **before**, must call `mcp__ccw-tools__team_msg` to log:
|
||||
|
||||
\`\`\`javascript
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: "{{team_name}}",
|
||||
from: role, // current role name
|
||||
to: "coordinator",
|
||||
type: "<type>",
|
||||
summary: "<summary>",
|
||||
ref: "<file_path>" // optional
|
||||
})
|
||||
\`\`\`
|
||||
|
||||
**Message types by role**:
|
||||
|
||||
| Role | Types |
|
||||
|------|-------|
|
||||
{{#each roles}}
|
||||
| {{this.name}} | {{this.message_types_list}} |
|
||||
{{/each}}
|
||||
|
||||
### CLI 回退
|
||||
|
||||
当 `mcp__ccw-tools__team_msg` MCP 不可用时:
|
||||
|
||||
\`\`\`javascript
|
||||
Bash(\`ccw team log --team "{{team_name}}" --from "\${role}" --to "coordinator" --type "<type>" --summary "<摘要>" --json\`)
|
||||
\`\`\`
|
||||
|
||||
### Task Lifecycle (All Roles)
|
||||
|
||||
\`\`\`javascript
|
||||
// Standard task lifecycle every role follows
|
||||
// Phase 1: Discovery
|
||||
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 // idle
|
||||
const task = TaskGet({ taskId: myTasks[0].id })
|
||||
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
||||
|
||||
// Phase 2-4: Role-specific (see roles/{role}.md)
|
||||
|
||||
// Phase 5: Report + Loop
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: "{{team_name}}", from: role, to: "coordinator", type: "...", summary: "..." })
|
||||
SendMessage({ type: "message", recipient: "coordinator", content: "...", summary: "..." })
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
// Check for next task → back to Phase 1
|
||||
\`\`\`
|
||||
|
||||
## Pipeline
|
||||
|
||||
\`\`\`
|
||||
{{pipeline_diagram}}
|
||||
\`\`\`
|
||||
|
||||
## Coordinator Spawn Template
|
||||
|
||||
When coordinator creates teammates, use this pattern:
|
||||
|
||||
\`\`\`javascript
|
||||
TeamCreate({ team_name: "{{team_name}}" })
|
||||
|
||||
{{#each worker_roles}}
|
||||
// {{this.display_name}}
|
||||
Task({
|
||||
subagent_type: "general-purpose",
|
||||
team_name: "{{../team_name}}",
|
||||
name: "{{this.name}}",
|
||||
prompt: \`你是 team "{{../team_name}}" 的 {{this.name_upper}}.
|
||||
|
||||
当你收到 {{this.task_prefix}}-* 任务时,调用 Skill(skill="team-{{../team_name}}", args="--role={{this.name}}") 执行。
|
||||
|
||||
当前需求: \${taskDescription}
|
||||
约束: \${constraints}
|
||||
|
||||
## 消息总线(必须)
|
||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||
|
||||
工作流程:
|
||||
1. TaskList → 找到 {{this.task_prefix}}-* 任务
|
||||
2. Skill(skill="team-{{../team_name}}", args="--role={{this.name}}") 执行
|
||||
3. team_msg log + SendMessage 结果给 coordinator
|
||||
4. TaskUpdate completed → 检查下一个任务\`
|
||||
})
|
||||
{{/each}}
|
||||
\`\`\`
|
||||
|
||||
## 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 |
|
||||
| Task prefix conflict | Log warning, proceed |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Variable Reference
|
||||
|
||||
| Variable | Source | Description |
|
||||
|----------|--------|-------------|
|
||||
| `{{team_name}}` | config.team_name | Team identifier (lowercase) |
|
||||
| `{{team_display_name}}` | config.team_display_name | Human-readable team name |
|
||||
| `{{all_roles_tools_union}}` | Union of all roles' allowed-tools | Combined tool list |
|
||||
| `{{roles}}` | config.roles[] | Array of role definitions |
|
||||
| `{{role_list}}` | Role names joined by comma | e.g., "coordinator, planner, executor" |
|
||||
| `{{roles_json}}` | JSON.stringify(roles) | Roles as JSON |
|
||||
| `{{pipeline_diagram}}` | Generated from task chain | ASCII pipeline |
|
||||
| `{{worker_roles}}` | config.roles excluding coordinator | Non-coordinator roles |
|
||||
| `{{role.name}}` | Per-role name | e.g., "planner" |
|
||||
| `{{role.task_prefix}}` | Per-role task prefix | e.g., "PLAN" |
|
||||
| `{{role.responsibility}}` | Per-role responsibility | e.g., "Code exploration and planning" |
|
||||
| `{{role.message_types_list}}` | Per-role message types | e.g., "`plan_ready`, `error`" |
|
||||
Reference in New Issue
Block a user