mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
feat: Enhance team skill router with command architecture and role isolation rules
- Added command architecture section to skill router template, detailing role organization and command delegation. - Updated role router input parsing to reflect new file structure for roles. - Introduced role isolation rules to enforce strict boundaries on role responsibilities and output tagging. - Enhanced team configuration section to include role-specific guidelines and message bus requirements. feat: Improve terminal dashboard with session status indicators - Integrated terminal status indicators in the session group tree, displaying active, idle, error, paused, and resuming states. - Updated session click handling to focus on existing panes or assign sessions to available panes. feat: Add session lifecycle controls in terminal pane - Implemented restart, pause, and resume functionalities for terminal sessions with loading states. - Enhanced UI buttons for session control with appropriate loading indicators and tooltips. i18n: Update terminal dashboard localization for session controls - Added translations for restart, pause, and resume session actions in English and Chinese. chore: Create role command template for command file generation - Established a comprehensive template for generating command files in roles, including sections for strategy, execution steps, and error handling. - Included pre-built command patterns for common tasks like exploration, analysis, implementation, validation, review, dispatch, and monitoring.
This commit is contained in:
@@ -46,11 +46,21 @@ Meta-skill for creating unified team skills where all team members invoke ONE sk
|
|||||||
.claude/skills/team-{name}/
|
.claude/skills/team-{name}/
|
||||||
├── SKILL.md → Skill(skill="team-{name}", args="--role=xxx")
|
├── SKILL.md → Skill(skill="team-{name}", args="--role=xxx")
|
||||||
├── roles/
|
├── roles/
|
||||||
│ ├── coordinator.md
|
│ ├── coordinator/
|
||||||
│ ├── planner.md
|
│ │ ├── role.md # Orchestrator
|
||||||
│ ├── executor.md
|
│ │ └── commands/ # Modular command files
|
||||||
│ ├── tester.md
|
│ ├── planner/
|
||||||
│ └── reviewer.md
|
│ │ ├── role.md
|
||||||
|
│ │ └── commands/
|
||||||
|
│ ├── executor/
|
||||||
|
│ │ ├── role.md
|
||||||
|
│ │ └── commands/
|
||||||
|
│ ├── tester/
|
||||||
|
│ │ ├── role.md
|
||||||
|
│ │ └── commands/
|
||||||
|
│ └── reviewer/
|
||||||
|
│ ├── role.md
|
||||||
|
│ └── commands/
|
||||||
└── specs/
|
└── specs/
|
||||||
└── team-config.json
|
└── team-config.json
|
||||||
```
|
```
|
||||||
@@ -70,15 +80,25 @@ Task({
|
|||||||
├── SKILL.md # Role router + shared infrastructure
|
├── SKILL.md # Role router + shared infrastructure
|
||||||
│ ├─ Frontmatter
|
│ ├─ Frontmatter
|
||||||
│ ├─ Architecture Overview (role routing diagram)
|
│ ├─ Architecture Overview (role routing diagram)
|
||||||
│ ├─ Role Router (parse --role → Read roles/{role}.md → execute)
|
│ ├─ Command Architecture (folder structure explanation)
|
||||||
|
│ ├─ Role Router (parse --role → Read roles/{role}/role.md → execute)
|
||||||
│ ├─ Shared Infrastructure (message bus, task lifecycle)
|
│ ├─ Shared Infrastructure (message bus, task lifecycle)
|
||||||
│ ├─ Coordinator Spawn Template
|
│ ├─ Coordinator Spawn Template
|
||||||
│ └─ Error Handling
|
│ └─ Error Handling
|
||||||
├── roles/ # Role-specific execution detail
|
├── roles/ # Role-specific execution detail (folder-based)
|
||||||
│ ├── coordinator.md # Orchestration logic
|
│ ├── coordinator/
|
||||||
│ ├── {role-1}.md # First worker role
|
│ │ ├── role.md # Orchestrator (Phase 1/5 inline, Phase 2-4 delegate)
|
||||||
│ ├── {role-2}.md # Second worker role
|
│ │ └── commands/
|
||||||
│ └── ...
|
│ │ ├── dispatch.md # Task chain creation
|
||||||
|
│ │ └── monitor.md # Progress monitoring
|
||||||
|
│ ├── {role-1}/
|
||||||
|
│ │ ├── role.md # Worker orchestrator
|
||||||
|
│ │ └── commands/
|
||||||
|
│ │ └── *.md # Role-specific command files
|
||||||
|
│ └── {role-2}/
|
||||||
|
│ ├── role.md
|
||||||
|
│ └── commands/
|
||||||
|
│ └── *.md
|
||||||
└── specs/ # [Optional] Team-specific config
|
└── specs/ # [Optional] Team-specific config
|
||||||
└── team-config.json
|
└── team-config.json
|
||||||
```
|
```
|
||||||
@@ -91,7 +111,7 @@ SKILL.md parses `$ARGUMENTS` to extract `--role`:
|
|||||||
```
|
```
|
||||||
Input: Skill(skill="team-{name}", args="--role=planner")
|
Input: Skill(skill="team-{name}", args="--role=planner")
|
||||||
↓ Parse --role=planner
|
↓ Parse --role=planner
|
||||||
↓ Read roles/planner.md
|
↓ Read roles/planner/role.md
|
||||||
↓ Execute planner-specific 5-phase logic
|
↓ Execute planner-specific 5-phase logic
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -107,11 +127,13 @@ SKILL.md defines ONCE, all roles inherit:
|
|||||||
|
|
||||||
### Pattern 3: Role Files = Full Execution Detail
|
### Pattern 3: Role Files = Full Execution Detail
|
||||||
|
|
||||||
Each `roles/{role}.md` contains:
|
Each `roles/{role}/role.md` contains:
|
||||||
- Role-specific 5-phase implementation
|
- Toolbox section (available commands, subagent capabilities, CLI capabilities)
|
||||||
|
- Role-specific 5-phase implementation (Phase 1/5 inline, Phase 2-4 delegate or inline)
|
||||||
- Per-role message types
|
- Per-role message types
|
||||||
- Per-role task prefix
|
- Per-role task prefix
|
||||||
- Complete code (no `Ref:` back to SKILL.md)
|
- Complete code (no `Ref:` back to SKILL.md)
|
||||||
|
- Command files in `commands/` for complex phases (subagent delegation, CLI fan-out)
|
||||||
|
|
||||||
### Pattern 4: Batch Role Generation
|
### Pattern 4: Batch Role Generation
|
||||||
|
|
||||||
@@ -124,9 +146,9 @@ Phase 1 collects ALL roles at once (not one at a time):
|
|||||||
|
|
||||||
Design pattern specs are included locally in `specs/`:
|
Design pattern specs are included locally in `specs/`:
|
||||||
```
|
```
|
||||||
specs/team-design-patterns.md # Infrastructure patterns (8) + collaboration index
|
specs/team-design-patterns.md # Infrastructure patterns (9) + collaboration index
|
||||||
specs/collaboration-patterns.md # 10 collaboration patterns with convergence control
|
specs/collaboration-patterns.md # 10 collaboration patterns with convergence control
|
||||||
specs/quality-standards.md # Quality criteria
|
specs/quality-standards.md # Quality criteria (incl. command file standards)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -147,8 +169,9 @@ specs/quality-standards.md # Quality criteria
|
|||||||
|
|
||||||
| Document | Purpose |
|
| Document | Purpose |
|
||||||
|----------|---------|
|
|----------|---------|
|
||||||
| [templates/skill-router-template.md](templates/skill-router-template.md) | Generated SKILL.md template with role router |
|
| [templates/skill-router-template.md](templates/skill-router-template.md) | Generated SKILL.md template with role router + command architecture |
|
||||||
| [templates/role-template.md](templates/role-template.md) | Generated role file template |
|
| [templates/role-template.md](templates/role-template.md) | Generated role file template with Toolbox + command delegation |
|
||||||
|
| [templates/role-command-template.md](templates/role-command-template.md) | Command file template with 7 pre-built patterns |
|
||||||
|
|
||||||
### Existing Reference
|
### Existing Reference
|
||||||
|
|
||||||
@@ -188,8 +211,9 @@ Phase 2: Pattern Analysis
|
|||||||
|
|
||||||
Phase 3: Skill Package Generation
|
Phase 3: Skill Package Generation
|
||||||
-> Ref: phases/03-skill-generation.md
|
-> Ref: phases/03-skill-generation.md
|
||||||
- Generate SKILL.md (role router + shared infrastructure)
|
- Generate SKILL.md (role router + command architecture + shared infrastructure)
|
||||||
- Generate roles/*.md (per-role execution detail)
|
- Generate roles/{name}/role.md (per-role orchestrator with Toolbox)
|
||||||
|
- Generate roles/{name}/commands/*.md (modular command files)
|
||||||
- Generate specs/team-config.json
|
- Generate specs/team-config.json
|
||||||
- Output: .claude/skills/team-{name}/ complete package
|
- Output: .claude/skills/team-{name}/ complete package
|
||||||
|
|
||||||
@@ -238,8 +262,15 @@ Bash(`mkdir -p "${workDir}"`);
|
|||||||
└── preview/ # Phase 3 output (preview before delivery)
|
└── preview/ # Phase 3 output (preview before delivery)
|
||||||
├── SKILL.md
|
├── SKILL.md
|
||||||
├── roles/
|
├── roles/
|
||||||
│ ├── coordinator.md
|
│ ├── coordinator/
|
||||||
│ └── {role-N}.md
|
│ │ ├── role.md
|
||||||
|
│ │ └── commands/
|
||||||
|
│ │ ├── dispatch.md
|
||||||
|
│ │ └── monitor.md
|
||||||
|
│ └── {role-N}/
|
||||||
|
│ ├── role.md
|
||||||
|
│ └── commands/
|
||||||
|
│ └── *.md
|
||||||
└── specs/
|
└── specs/
|
||||||
└── team-config.json
|
└── team-config.json
|
||||||
|
|
||||||
@@ -247,8 +278,12 @@ Final delivery:
|
|||||||
.claude/skills/team-{name}/
|
.claude/skills/team-{name}/
|
||||||
├── SKILL.md
|
├── SKILL.md
|
||||||
├── roles/
|
├── roles/
|
||||||
│ ├── coordinator.md
|
│ ├── coordinator/
|
||||||
│ └── ...
|
│ │ ├── role.md
|
||||||
|
│ │ └── commands/
|
||||||
|
│ └── {role-N}/
|
||||||
|
│ ├── role.md
|
||||||
|
│ └── commands/
|
||||||
└── specs/
|
└── specs/
|
||||||
└── team-config.json
|
└── team-config.json
|
||||||
```
|
```
|
||||||
@@ -281,5 +316,7 @@ Final delivery:
|
|||||||
|-------|----------|
|
|-------|----------|
|
||||||
| Generated SKILL.md missing router | Check templates/skill-router-template.md |
|
| Generated SKILL.md missing router | Check templates/skill-router-template.md |
|
||||||
| Role file missing message bus | Check templates/role-template.md |
|
| Role file missing message bus | Check templates/role-template.md |
|
||||||
|
| Command file not found | Check templates/role-command-template.md |
|
||||||
|
| Role folder structure wrong | Verify roles/{name}/role.md + commands/ layout |
|
||||||
| Integration check fails | Review phases/04-integration-verification.md |
|
| Integration check fails | Review phases/04-integration-verification.md |
|
||||||
| Quality score below threshold | Review specs/quality-standards.md |
|
| Quality score below threshold | Review specs/quality-standards.md |
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Phase 1: Requirements Collection (Batch Mode)
|
# Phase 1: Requirements Collection (Task-Driven Inference)
|
||||||
|
|
||||||
Collect team definition and ALL role definitions in one pass.
|
Analyze task requirements, infer appropriate roles, and generate team configuration.
|
||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
- Determine team name and display name
|
- Determine team name and display name
|
||||||
- Collect ALL roles (coordinator + workers) in batch
|
- **Analyze task description → infer needed roles** (coordinator always included)
|
||||||
- For each role: name, responsibility, task prefix, capabilities
|
- For each role: name, responsibility, task prefix, capabilities
|
||||||
- Define pipeline (task chain order)
|
- Build pipeline from inferred roles
|
||||||
- Generate team-config.json
|
- Generate team-config.json
|
||||||
|
|
||||||
## Input
|
## Input
|
||||||
@@ -17,7 +17,7 @@ Collect team definition and ALL role definitions in one pass.
|
|||||||
|
|
||||||
## Execution Steps
|
## Execution Steps
|
||||||
|
|
||||||
### Step 1: Team Basic Information
|
### Step 1: Team Name + Task Description
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const teamInfo = await AskUserQuestion({
|
const teamInfo = await AskUserQuestion({
|
||||||
@@ -28,29 +28,30 @@ const teamInfo = await AskUserQuestion({
|
|||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
options: [
|
options: [
|
||||||
{ label: "自定义", description: "输入自定义团队名称" },
|
{ label: "自定义", description: "输入自定义团队名称" },
|
||||||
{ label: "dev", description: "开发团队(plan/execute/test/review)" },
|
{ label: "dev", description: "通用开发团队" },
|
||||||
{ label: "spec", description: "规格文档团队(analyst/writer/reviewer/discuss)" },
|
{ label: "spec", description: "规格文档团队" },
|
||||||
{ label: "security", description: "安全审计团队" }
|
{ label: "security", description: "安全审计团队" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "团队使用什么 pipeline 模型?",
|
question: "这个团队的核心任务是什么?(描述目标场景,系统将自动推断所需角色)",
|
||||||
header: "Pipeline",
|
header: "Task Desc",
|
||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
options: [
|
options: [
|
||||||
{ label: "Standard (Recommended)", description: "PLAN → IMPL → TEST + REVIEW(标准开发流水线)" },
|
{ label: "自定义", description: "输入具体任务描述,如:实现新功能并确保质量" },
|
||||||
{ label: "Document Chain", description: "RESEARCH → DRAFT → DISCUSS → REVIEW(文档工作流)" },
|
{ label: "全栈开发", description: "需求分析 → 规划 → 编码 → 测试 → 审查" },
|
||||||
{ label: "Custom", description: "自定义 pipeline" }
|
{ label: "代码审查与重构", description: "代码分析 → 问题发现 → 重构实施 → 验证" },
|
||||||
|
{ label: "文档编写", description: "调研 → 讨论 → 撰写 → 审校" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 2: Role Definitions (Batch)
|
### Step 2: Role Inference (Task-Driven)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Always include coordinator
|
// Coordinator 始终存在
|
||||||
const roles = [{
|
const roles = [{
|
||||||
name: "coordinator",
|
name: "coordinator",
|
||||||
responsibility_type: "Orchestration",
|
responsibility_type: "Orchestration",
|
||||||
@@ -58,50 +59,124 @@ const roles = [{
|
|||||||
description: "Pipeline orchestration, team lifecycle, cross-stage coordination"
|
description: "Pipeline orchestration, team lifecycle, cross-stage coordination"
|
||||||
}]
|
}]
|
||||||
|
|
||||||
// Collect worker roles based on pipeline model
|
// 角色需求分析矩阵 — 根据任务描述中的意图信号推断角色
|
||||||
const pipelineType = teamInfo["Pipeline"]
|
const taskDesc = teamInfo["Task Desc"]
|
||||||
|
|
||||||
if (pipelineType.includes("Standard")) {
|
const ROLE_SIGNALS = {
|
||||||
// Pre-fill standard development roles
|
planner: {
|
||||||
roles.push(
|
signals: /规划|计划|设计|架构|plan|design|architect|分析需求|探索|explore/i,
|
||||||
{ name: "planner", responsibility_type: "Orchestration", task_prefix: "PLAN", description: "Code exploration and implementation planning" },
|
role: { name: "planner", responsibility_type: "Orchestration", task_prefix: "PLAN", description: "Code exploration and implementation planning" }
|
||||||
{ name: "executor", responsibility_type: "Code generation", task_prefix: "IMPL", description: "Code implementation following approved plan" },
|
},
|
||||||
{ name: "tester", responsibility_type: "Validation", task_prefix: "TEST", description: "Test execution and fix cycles" },
|
executor: {
|
||||||
{ name: "reviewer", responsibility_type: "Read-only analysis", task_prefix: "REVIEW", description: "Multi-dimensional code review" }
|
signals: /实现|开发|编码|编写|创建|构建|implement|develop|build|code|create|重构|refactor|迁移|migrate/i,
|
||||||
)
|
role: { name: "executor", responsibility_type: "Code generation", task_prefix: "IMPL", description: "Code implementation following approved plan" }
|
||||||
} else if (pipelineType.includes("Document")) {
|
},
|
||||||
roles.push(
|
tester: {
|
||||||
{ name: "analyst", responsibility_type: "Orchestration", task_prefix: "RESEARCH", description: "Seed analysis, codebase exploration, context collection" },
|
signals: /测试|验证|质量|test|verify|validate|QA|回归|regression|修复|fix|bug/i,
|
||||||
{ name: "writer", responsibility_type: "Code generation", task_prefix: "DRAFT", description: "Document drafting following templates" },
|
role: { name: "tester", responsibility_type: "Validation", task_prefix: "TEST", description: "Test execution and fix cycles" }
|
||||||
{ name: "reviewer", responsibility_type: "Read-only analysis", task_prefix: "QUALITY", description: "Cross-document quality verification" },
|
},
|
||||||
{ name: "discuss", responsibility_type: "Orchestration", task_prefix: "DISCUSS", description: "Structured team discussion and consensus building" }
|
reviewer: {
|
||||||
)
|
signals: /审查|审核|review|audit|检查|inspect|代码质量|code quality/i,
|
||||||
} else {
|
role: { name: "reviewer", responsibility_type: "Read-only analysis", task_prefix: "REVIEW", description: "Multi-dimensional code review" }
|
||||||
// Custom: ask user for each role
|
},
|
||||||
|
analyst: {
|
||||||
|
signals: /调研|研究|分析|research|analyze|探索|investigate|诊断|diagnose/i,
|
||||||
|
role: { name: "analyst", responsibility_type: "Orchestration", task_prefix: "RESEARCH", description: "Codebase exploration and context collection" }
|
||||||
|
},
|
||||||
|
writer: {
|
||||||
|
signals: /文档|撰写|编写文档|document|write doc|生成报告|report/i,
|
||||||
|
role: { name: "writer", responsibility_type: "Code generation", task_prefix: "DRAFT", description: "Document drafting following templates" }
|
||||||
|
},
|
||||||
|
debugger: {
|
||||||
|
signals: /debug|调试|排查|定位问题|根因|root cause|故障|troubleshoot/i,
|
||||||
|
role: { name: "debugger", responsibility_type: "Orchestration", task_prefix: "DEBUG", description: "Bug diagnosis and root cause analysis" }
|
||||||
|
},
|
||||||
|
security: {
|
||||||
|
signals: /安全|漏洞|security|vulnerability|渗透|penetration|OWASP|合规|compliance/i,
|
||||||
|
role: { name: "security", responsibility_type: "Read-only analysis", task_prefix: "SEC", description: "Security analysis and vulnerability assessment" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 推断角色:匹配信号 + 隐含角色补全
|
||||||
|
const inferredRoles = []
|
||||||
|
for (const [key, entry] of Object.entries(ROLE_SIGNALS)) {
|
||||||
|
if (entry.signals.test(taskDesc)) {
|
||||||
|
inferredRoles.push(entry.role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐含角色补全规则:
|
||||||
|
// - 有 executor 必有 planner(编码前需要规划)
|
||||||
|
// - 有 executor 必有 tester(编码后需要验证)
|
||||||
|
// - 有 debugger 必有 tester(调试需要验证修复)
|
||||||
|
// - 有 writer 必有 reviewer(文档需要审校)
|
||||||
|
const hasRole = name => inferredRoles.some(r => r.name === name)
|
||||||
|
if (hasRole('executor') && !hasRole('planner')) {
|
||||||
|
inferredRoles.unshift(ROLE_SIGNALS.planner.role)
|
||||||
|
}
|
||||||
|
if (hasRole('executor') && !hasRole('tester')) {
|
||||||
|
inferredRoles.push(ROLE_SIGNALS.tester.role)
|
||||||
|
}
|
||||||
|
if (hasRole('debugger') && !hasRole('tester')) {
|
||||||
|
inferredRoles.push(ROLE_SIGNALS.tester.role)
|
||||||
|
}
|
||||||
|
if (hasRole('writer') && !hasRole('reviewer')) {
|
||||||
|
inferredRoles.push(ROLE_SIGNALS.reviewer.role)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最少保证 2 个 worker 角色
|
||||||
|
if (inferredRoles.length < 2) {
|
||||||
|
// 回退:标准 plan → implement → test → review
|
||||||
|
inferredRoles.length = 0
|
||||||
|
inferredRoles.push(
|
||||||
|
ROLE_SIGNALS.planner.role,
|
||||||
|
ROLE_SIGNALS.executor.role,
|
||||||
|
ROLE_SIGNALS.tester.role,
|
||||||
|
ROLE_SIGNALS.reviewer.role
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去重 + 加入总角色列表
|
||||||
|
const seen = new Set()
|
||||||
|
for (const role of inferredRoles) {
|
||||||
|
if (!seen.has(role.name)) {
|
||||||
|
seen.add(role.name)
|
||||||
|
roles.push(role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 推断 pipeline 类型标签(用于后续 Step 5)
|
||||||
|
const pipelineType = inferredRoles.some(r => r.name === 'writer') ? 'Document'
|
||||||
|
: inferredRoles.some(r => r.name === 'debugger') ? 'Debug'
|
||||||
|
: 'Standard'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 3: Role Customization (Interactive)
|
### Step 3: Role Confirmation (Interactive)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Allow user to customize pre-filled roles
|
// 展示推断结果,让用户确认或调整
|
||||||
const customization = await AskUserQuestion({
|
const workerRoles = roles.filter(r => r.name !== 'coordinator')
|
||||||
|
const rolesSummary = workerRoles
|
||||||
|
.map(r => `${r.name} (${r.responsibility_type}, ${r.task_prefix})`)
|
||||||
|
.join('\n')
|
||||||
|
|
||||||
|
const confirmation = await AskUserQuestion({
|
||||||
questions: [
|
questions: [
|
||||||
{
|
{
|
||||||
question: "是否需要自定义角色?(默认角色已根据 pipeline 预填充)",
|
question: `根据任务描述,推断出以下角色:\n${rolesSummary}\n\n是否需要调整?`,
|
||||||
header: "Customize",
|
header: "Confirm",
|
||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
options: [
|
options: [
|
||||||
{ label: "使用默认 (Recommended)", description: "直接使用预填充的角色定义" },
|
{ label: "确认使用 (Recommended)", description: "使用推断的角色组合" },
|
||||||
{ label: "添加角色", description: "在默认基础上添加新角色" },
|
{ label: "添加角色", description: "在推断结果基础上添加角色" },
|
||||||
{ label: "修改角色", description: "修改默认角色定义" },
|
{ label: "移除角色", description: "移除某些不需要的角色" },
|
||||||
{ label: "从零开始", description: "清空默认,逐个定义角色" }
|
{ label: "重新描述", description: "重新输入任务描述,重新推断" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
if (customization["Customize"].includes("添加角色")) {
|
if (confirmation["Confirm"].includes("添加角色")) {
|
||||||
const newRole = await AskUserQuestion({
|
const newRole = await AskUserQuestion({
|
||||||
questions: [
|
questions: [
|
||||||
{
|
{
|
||||||
@@ -196,39 +271,118 @@ roles[0].message_types = [
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 5: Pipeline Definition
|
### Step 4b: Toolbox Inference (Per Role)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Build pipeline from roles and their task chain positions
|
// Infer commands, subagents, and CLI tools based on responsibility type
|
||||||
function buildPipeline(roles, pipelineType) {
|
const toolboxMap = {
|
||||||
if (pipelineType.includes("Standard")) {
|
"Read-only analysis": {
|
||||||
return {
|
commands: ["review", "analyze"],
|
||||||
stages: [
|
subagents: [],
|
||||||
{ name: "PLAN", role: "planner", blockedBy: [] },
|
cli_tools: [
|
||||||
{ name: "IMPL", role: "executor", blockedBy: ["PLAN"] },
|
{ tool: "gemini", mode: "analysis", purpose: "Multi-perspective code analysis" },
|
||||||
{ name: "TEST", role: "tester", blockedBy: ["IMPL"] },
|
{ tool: "codex", mode: "review", purpose: "Git-aware code review" }
|
||||||
{ name: "REVIEW", role: "reviewer", blockedBy: ["IMPL"] }
|
],
|
||||||
],
|
phase_commands: { phase2: null, phase3: "analyze", phase4: null }
|
||||||
diagram: "需求 → [PLAN: planner] → coordinator 审批 → [IMPL: executor] → [TEST + REVIEW: tester/reviewer] → 汇报"
|
},
|
||||||
}
|
"Code generation": {
|
||||||
|
commands: ["implement", "validate"],
|
||||||
|
subagents: [
|
||||||
|
{ type: "code-developer", purpose: "Complex implementation delegation" }
|
||||||
|
],
|
||||||
|
cli_tools: [],
|
||||||
|
phase_commands: { phase2: null, phase3: "implement", phase4: "validate" }
|
||||||
|
},
|
||||||
|
"Orchestration": {
|
||||||
|
commands: ["explore", "plan"],
|
||||||
|
subagents: [
|
||||||
|
{ type: "cli-explore-agent", purpose: "Multi-angle codebase exploration" },
|
||||||
|
{ type: "cli-lite-planning-agent", purpose: "Structured planning" }
|
||||||
|
],
|
||||||
|
cli_tools: [
|
||||||
|
{ tool: "gemini", mode: "analysis", purpose: "Architecture analysis" }
|
||||||
|
],
|
||||||
|
phase_commands: { phase2: "explore", phase3: null, phase4: null }
|
||||||
|
},
|
||||||
|
"Validation": {
|
||||||
|
commands: ["validate"],
|
||||||
|
subagents: [
|
||||||
|
{ type: "code-developer", purpose: "Test-fix iteration" }
|
||||||
|
],
|
||||||
|
cli_tools: [],
|
||||||
|
phase_commands: { phase2: null, phase3: "validate", phase4: null }
|
||||||
}
|
}
|
||||||
if (pipelineType.includes("Document")) {
|
|
||||||
return {
|
|
||||||
stages: [
|
|
||||||
{ name: "RESEARCH", role: "analyst", blockedBy: [] },
|
|
||||||
{ name: "DISCUSS-scope", role: "discuss", blockedBy: ["RESEARCH"] },
|
|
||||||
{ name: "DRAFT", role: "writer", blockedBy: ["DISCUSS-scope"] },
|
|
||||||
{ name: "DISCUSS-eval", role: "discuss", blockedBy: ["DRAFT"] },
|
|
||||||
{ name: "QUALITY", role: "reviewer", blockedBy: ["DRAFT"] }
|
|
||||||
],
|
|
||||||
diagram: "RESEARCH → DISCUSS → DRAFT → DISCUSS → QUALITY → Deliver"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Custom pipeline
|
|
||||||
return { stages: [], diagram: "Custom pipeline" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pipeline = buildPipeline(roles, pipelineType)
|
for (const role of roles.filter(r => r.name !== 'coordinator')) {
|
||||||
|
const toolbox = toolboxMap[role.responsibility_type] || { commands: [], subagents: [], cli_tools: [], phase_commands: {} }
|
||||||
|
role.commands = toolbox.commands
|
||||||
|
role.subagents = toolbox.subagents
|
||||||
|
role.cli_tools = toolbox.cli_tools
|
||||||
|
role.phase_commands = toolbox.phase_commands
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coordinator always gets dispatch + monitor
|
||||||
|
roles[0].commands = ["dispatch", "monitor"]
|
||||||
|
roles[0].subagents = []
|
||||||
|
roles[0].cli_tools = []
|
||||||
|
roles[0].phase_commands = { phase2: null, phase3: "dispatch", phase4: "monitor" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Pipeline Definition (Dynamic)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 从推断的角色动态构建 pipeline
|
||||||
|
// 排序权重:分析/探索类 < 规划类 < 实现类 < 验证/审查类
|
||||||
|
const PHASE_ORDER = {
|
||||||
|
analyst: 1, debugger: 1, security: 1,
|
||||||
|
planner: 2,
|
||||||
|
executor: 3, writer: 3,
|
||||||
|
tester: 4, reviewer: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPipeline(roles) {
|
||||||
|
const workers = roles
|
||||||
|
.filter(r => r.name !== 'coordinator')
|
||||||
|
.sort((a, b) => (PHASE_ORDER[a.name] || 3) - (PHASE_ORDER[b.name] || 3))
|
||||||
|
|
||||||
|
// 按阶段分组
|
||||||
|
const phaseGroups = {}
|
||||||
|
for (const r of workers) {
|
||||||
|
const order = PHASE_ORDER[r.name] || 3
|
||||||
|
if (!phaseGroups[order]) phaseGroups[order] = []
|
||||||
|
phaseGroups[order].push(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建依赖链:每个阶段依赖前一阶段的所有角色
|
||||||
|
const stages = []
|
||||||
|
const sortedPhases = Object.keys(phaseGroups).map(Number).sort((a, b) => a - b)
|
||||||
|
let prevPrefixes = []
|
||||||
|
|
||||||
|
for (const phase of sortedPhases) {
|
||||||
|
const group = phaseGroups[phase]
|
||||||
|
for (const r of group) {
|
||||||
|
stages.push({
|
||||||
|
name: r.task_prefix,
|
||||||
|
role: r.name,
|
||||||
|
blockedBy: [...prevPrefixes]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
prevPrefixes = group.map(r => r.task_prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 pipeline 图
|
||||||
|
const diagramParts = sortedPhases.map(phase => {
|
||||||
|
const group = phaseGroups[phase]
|
||||||
|
if (group.length === 1) return `[${group[0].task_prefix}: ${group[0].name}]`
|
||||||
|
return `[${group.map(r => `${r.task_prefix}`).join(' + ')}: ${group.map(r => r.name).join('/')}]`
|
||||||
|
})
|
||||||
|
const diagram = `需求 → ${diagramParts.join(' → ')} → 汇报`
|
||||||
|
|
||||||
|
return { stages, diagram }
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipeline = buildPipeline(roles)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 6: Generate Configuration
|
### Step 6: Generate Configuration
|
||||||
|
|||||||
@@ -117,6 +117,33 @@ roleAnalysis.forEach(ra => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Step 4b: Command-to-Phase Mapping
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Map commands to phases and determine extraction criteria
|
||||||
|
roleAnalysis.forEach(ra => {
|
||||||
|
const role = config.worker_roles.find(r => r.name === ra.role_name)
|
||||||
|
|
||||||
|
ra.command_mapping = {
|
||||||
|
commands: role.commands || [],
|
||||||
|
phase_commands: role.phase_commands || {},
|
||||||
|
extraction_reasons: []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine extraction reasons per command
|
||||||
|
for (const cmd of (role.commands || [])) {
|
||||||
|
const reasons = []
|
||||||
|
if ((role.subagents || []).length > 0) reasons.push("subagent-delegation")
|
||||||
|
if ((role.cli_tools || []).length > 0) reasons.push("cli-fan-out")
|
||||||
|
if (role.adaptive_routing) reasons.push("complexity-adaptive")
|
||||||
|
ra.command_mapping.extraction_reasons.push({ command: cmd, reasons })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pattern 9 selection
|
||||||
|
ra.uses_pattern_9 = (role.subagents || []).length > 0 || (role.cli_tools || []).length > 0
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
### Step 5: Collaboration Pattern Selection
|
### Step 5: Collaboration Pattern Selection
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -191,6 +218,15 @@ const analysis = {
|
|||||||
role_router: "Parse --role from $ARGUMENTS → dispatch to roles/{role}.md",
|
role_router: "Parse --role from $ARGUMENTS → dispatch to roles/{role}.md",
|
||||||
shared_infrastructure: "Message bus + task lifecycle defined once in SKILL.md",
|
shared_infrastructure: "Message bus + task lifecycle defined once in SKILL.md",
|
||||||
progressive_loading: "Only read roles/{role}.md when that role executes"
|
progressive_loading: "Only read roles/{role}.md when that role executes"
|
||||||
|
},
|
||||||
|
command_architecture: {
|
||||||
|
enabled: true,
|
||||||
|
role_commands: roleAnalysis.map(ra => ({
|
||||||
|
role: ra.role_name,
|
||||||
|
commands: ra.command_mapping?.commands || [],
|
||||||
|
phase_commands: ra.command_mapping?.phase_commands || {},
|
||||||
|
uses_pattern_9: ra.uses_pattern_9 || false
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
# Phase 3: Skill Package Generation
|
# Phase 3: Skill Package Generation
|
||||||
|
|
||||||
Generate the unified team skill package: SKILL.md (role router) + roles/*.md (per-role execution).
|
Generate the unified team skill package: SKILL.md (role router) + roles/{name}/role.md (per-role orchestrator) + roles/{name}/commands/*.md (command modules).
|
||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
- Generate SKILL.md with role router and shared infrastructure
|
- Generate SKILL.md with role router and shared infrastructure
|
||||||
- Generate roles/coordinator.md
|
- Generate roles/coordinator/role.md + commands/
|
||||||
- Generate roles/{worker-role}.md for each worker role
|
- Generate roles/{worker-role}/role.md + commands/ for each worker role
|
||||||
- Generate specs/team-config.json
|
- Generate specs/team-config.json
|
||||||
- All files written to preview directory first
|
- All files written to preview directory first
|
||||||
|
|
||||||
## Input
|
## Input
|
||||||
|
|
||||||
- Dependency: `team-config.json` (Phase 1), `pattern-analysis.json` (Phase 2)
|
- Dependency: `team-config.json` (Phase 1), `pattern-analysis.json` (Phase 2)
|
||||||
- Templates: `templates/skill-router-template.md`, `templates/role-template.md`
|
- Templates: `templates/skill-router-template.md`, `templates/role-template.md`, `templates/role-command-template.md`
|
||||||
- Reference: existing team commands (read in Phase 0)
|
- Reference: existing team commands (read in Phase 0)
|
||||||
|
|
||||||
## Execution Steps
|
## Execution Steps
|
||||||
@@ -25,10 +25,12 @@ const config = JSON.parse(Read(`${workDir}/team-config.json`))
|
|||||||
const analysis = JSON.parse(Read(`${workDir}/pattern-analysis.json`))
|
const analysis = JSON.parse(Read(`${workDir}/pattern-analysis.json`))
|
||||||
const routerTemplate = Read(`${skillDir}/templates/skill-router-template.md`)
|
const routerTemplate = Read(`${skillDir}/templates/skill-router-template.md`)
|
||||||
const roleTemplate = Read(`${skillDir}/templates/role-template.md`)
|
const roleTemplate = Read(`${skillDir}/templates/role-template.md`)
|
||||||
|
const commandTemplate = Read(`${skillDir}/templates/role-command-template.md`)
|
||||||
|
|
||||||
// Create preview directory
|
// Create preview directory with folder-based role structure
|
||||||
const previewDir = `${workDir}/preview`
|
const previewDir = `${workDir}/preview`
|
||||||
Bash(`mkdir -p "${previewDir}/roles" "${previewDir}/specs"`)
|
const roleDirs = config.roles.map(r => `"${previewDir}/roles/${r.name}/commands"`).join(' ')
|
||||||
|
Bash(`mkdir -p ${roleDirs} "${previewDir}/specs"`)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 2: Generate SKILL.md (Role Router)
|
### Step 2: Generate SKILL.md (Role Router)
|
||||||
@@ -37,11 +39,11 @@ This is the unified entry point. All roles invoke this skill with `--role=xxx`.
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const rolesTable = config.roles.map(r =>
|
const rolesTable = config.roles.map(r =>
|
||||||
`| \`${r.name}\` | ${r.task_prefix || 'N/A'} | ${r.description} | [roles/${r.name}.md](roles/${r.name}.md) |`
|
`| \`${r.name}\` | ${r.task_prefix || 'N/A'} | ${r.description} | [roles/${r.name}/role.md](roles/${r.name}/role.md) |`
|
||||||
).join('\n')
|
).join('\n')
|
||||||
|
|
||||||
const roleDispatchEntries = config.roles.map(r =>
|
const roleDispatchEntries = config.roles.map(r =>
|
||||||
` "${r.name}": { file: "roles/${r.name}.md", prefix: "${r.task_prefix || 'N/A'}" }`
|
` "${r.name}": { file: "roles/${r.name}/role.md", prefix: "${r.task_prefix || 'N/A'}" }`
|
||||||
).join(',\n')
|
).join(',\n')
|
||||||
|
|
||||||
const messageBusTable = config.worker_roles.map(r =>
|
const messageBusTable = config.worker_roles.map(r =>
|
||||||
@@ -328,10 +330,20 @@ AskUserQuestion({
|
|||||||
| Review finds critical | Create fix task for executor |
|
| Review finds critical | Create fix task for executor |
|
||||||
`
|
`
|
||||||
|
|
||||||
Write(`${previewDir}/roles/coordinator.md`, coordinatorMd)
|
Write(`${previewDir}/roles/coordinator/role.md`, coordinatorMd)
|
||||||
|
|
||||||
|
// Generate coordinator command files
|
||||||
|
const coordinatorCommands = config.roles[0].commands || ["dispatch", "monitor"]
|
||||||
|
for (const cmd of coordinatorCommands) {
|
||||||
|
// Read pre-built command pattern from template
|
||||||
|
const cmdTemplate = commandTemplate // templates/role-command-template.md
|
||||||
|
// Extract matching pre-built pattern section and customize for this team
|
||||||
|
const cmdContent = generateCommandFile(cmd, "coordinator", config)
|
||||||
|
Write(`${previewDir}/roles/coordinator/commands/${cmd}.md`, cmdContent)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Step 4: Generate Worker Role Files
|
### Step 4: Generate Worker Role Files (Folder Structure)
|
||||||
|
|
||||||
For each worker role, generate a complete role file with 5-phase execution.
|
For each worker role, generate a complete role file with 5-phase execution.
|
||||||
|
|
||||||
@@ -620,7 +632,126 @@ ${role.adaptive_routing ? '| Sub-agent failure | Retry once, fallback to direct
|
|||||||
| Unexpected error | Log via team_msg, report |
|
| Unexpected error | Log via team_msg, report |
|
||||||
`
|
`
|
||||||
|
|
||||||
Write(`${previewDir}/roles/${role.name}.md`, roleMd)
|
Write(`${previewDir}/roles/${role.name}/role.md`, roleMd)
|
||||||
|
|
||||||
|
// Generate command files for this role
|
||||||
|
const roleCommands = role.commands || []
|
||||||
|
for (const cmd of roleCommands) {
|
||||||
|
const cmdContent = generateCommandFile(cmd, role.name, config)
|
||||||
|
Write(`${previewDir}/roles/${role.name}/commands/${cmd}.md`, cmdContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper: Generate command file from pre-built patterns
|
||||||
|
function generateCommandFile(cmdName, roleName, config) {
|
||||||
|
// 7 pre-built command patterns (from templates/role-command-template.md)
|
||||||
|
const prebuiltPatterns = {
|
||||||
|
"explore": {
|
||||||
|
description: "Multi-angle codebase exploration using parallel cli-explore-agent instances.",
|
||||||
|
delegation: "Subagent Fan-out",
|
||||||
|
agentType: "cli-explore-agent",
|
||||||
|
phase: 2
|
||||||
|
},
|
||||||
|
"analyze": {
|
||||||
|
description: "Multi-perspective code analysis using parallel ccw cli calls.",
|
||||||
|
delegation: "CLI Fan-out",
|
||||||
|
cliTool: "gemini",
|
||||||
|
phase: 3
|
||||||
|
},
|
||||||
|
"implement": {
|
||||||
|
description: "Code implementation via code-developer subagent delegation with batch routing.",
|
||||||
|
delegation: "Sequential Delegation",
|
||||||
|
agentType: "code-developer",
|
||||||
|
phase: 3
|
||||||
|
},
|
||||||
|
"validate": {
|
||||||
|
description: "Iterative test-fix cycle with max iteration control.",
|
||||||
|
delegation: "Sequential Delegation",
|
||||||
|
agentType: "code-developer",
|
||||||
|
phase: 3
|
||||||
|
},
|
||||||
|
"review": {
|
||||||
|
description: "4-dimensional code review with optional codex review integration.",
|
||||||
|
delegation: "CLI Fan-out",
|
||||||
|
cliTool: "gemini",
|
||||||
|
phase: 3
|
||||||
|
},
|
||||||
|
"dispatch": {
|
||||||
|
description: "Task chain creation with dependency management for coordinator.",
|
||||||
|
delegation: "Direct",
|
||||||
|
phase: 3
|
||||||
|
},
|
||||||
|
"monitor": {
|
||||||
|
description: "Message bus polling and coordination loop for coordinator.",
|
||||||
|
delegation: "Direct",
|
||||||
|
phase: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = prebuiltPatterns[cmdName]
|
||||||
|
if (!pattern) {
|
||||||
|
// Custom command: generate from template skeleton
|
||||||
|
return `# Command: ${cmdName}\n\n> Custom command for ${roleName}\n\n## When to Use\n\n- Custom trigger conditions\n\n## Strategy\n\n### Delegation Mode\n\n**Mode**: TBD\n\n## Execution Steps\n\n### Step 1: Context Preparation\n\n### Step 2: Execute Strategy\n\n### Step 3: Result Processing\n\n## Output Format\n\n## Error Handling\n\n| Scenario | Resolution |\n|----------|------------|\n| Agent/CLI failure | Retry once, then fallback to inline execution |\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read full pattern from template file and customize
|
||||||
|
// The template contains all 7 patterns with complete implementation
|
||||||
|
// Extract and customize the matching pattern section
|
||||||
|
const cmdContent = `# Command: ${cmdName}
|
||||||
|
|
||||||
|
> ${pattern.description}
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase ${pattern.phase} of ${roleName} role in team "${config.team_name}"
|
||||||
|
- See templates/role-command-template.md for full pattern specification
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: ${pattern.delegation}
|
||||||
|
${pattern.agentType ? `**Agent Type**: \`${pattern.agentType}\`` : ''}
|
||||||
|
${pattern.cliTool ? `**CLI Tool**: \`${pattern.cliTool}\`\n**CLI Mode**: \`analysis\`` : ''}
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Load task context
|
||||||
|
const task = TaskGet({ taskId: currentTaskId })
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// See templates/role-command-template.md → "${cmdName}" pattern for full implementation
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Aggregate and format results
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
## ${cmdName.charAt(0).toUpperCase() + cmdName.slice(1)} Results
|
||||||
|
### Summary
|
||||||
|
### Details
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| Agent/CLI failure | Retry once, then fallback to inline execution |
|
||||||
|
| Timeout (>5 min) | Report partial results, notify coordinator |
|
||||||
|
| No results | Report empty, suggest alternative approach |
|
||||||
|
`
|
||||||
|
return cmdContent
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -647,20 +778,27 @@ Write(`${previewDir}/specs/team-config.json`, JSON.stringify({
|
|||||||
|
|
||||||
- **Directory**: `{workDir}/preview/`
|
- **Directory**: `{workDir}/preview/`
|
||||||
- **Files**:
|
- **Files**:
|
||||||
- `preview/SKILL.md` - Role router + shared infrastructure
|
- `preview/SKILL.md` - Role router + shared infrastructure + command architecture
|
||||||
- `preview/roles/coordinator.md` - Coordinator execution
|
- `preview/roles/coordinator/role.md` - Coordinator orchestrator
|
||||||
- `preview/roles/{role}.md` - Per-worker role execution
|
- `preview/roles/coordinator/commands/*.md` - Coordinator command files (dispatch, monitor)
|
||||||
|
- `preview/roles/{role}/role.md` - Per-worker role orchestrator
|
||||||
|
- `preview/roles/{role}/commands/*.md` - Per-worker command files
|
||||||
- `preview/specs/team-config.json` - Team configuration
|
- `preview/specs/team-config.json` - Team configuration
|
||||||
|
|
||||||
## Quality Checklist
|
## Quality Checklist
|
||||||
|
|
||||||
- [ ] SKILL.md contains role router with all roles
|
- [ ] SKILL.md contains role router with all roles (dispatch to `roles/{name}/role.md`)
|
||||||
|
- [ ] SKILL.md contains command architecture section
|
||||||
- [ ] SKILL.md contains shared infrastructure (message bus, task lifecycle)
|
- [ ] SKILL.md contains shared infrastructure (message bus, task lifecycle)
|
||||||
- [ ] SKILL.md contains coordinator spawn template
|
- [ ] SKILL.md contains coordinator spawn template
|
||||||
- [ ] Every role has a file in roles/
|
- [ ] Every role has a folder in roles/ with role.md
|
||||||
- [ ] Every role file has 5-phase execution
|
- [ ] Every role.md has 5-phase execution (Phase 1/5 inline, Phase 2-4 delegate or inline)
|
||||||
- [ ] Every role file has message types table
|
- [ ] Every role.md has Toolbox section (commands, subagents, cli_tools)
|
||||||
- [ ] Every role file has error handling
|
- [ ] Every role.md has message types table
|
||||||
|
- [ ] Every role.md has error handling
|
||||||
|
- [ ] Command files exist for each entry in role.md Toolbox
|
||||||
|
- [ ] Command files are self-contained (Strategy, Execution Steps, Error Handling)
|
||||||
|
- [ ] No cross-command references between command files
|
||||||
- [ ] team-config.json is valid JSON
|
- [ ] team-config.json is valid JSON
|
||||||
|
|
||||||
## Next Phase
|
## Next Phase
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const skillMd = Read(`${previewDir}/SKILL.md`)
|
|||||||
const roleFiles = {}
|
const roleFiles = {}
|
||||||
for (const role of config.roles) {
|
for (const role of config.roles) {
|
||||||
try {
|
try {
|
||||||
roleFiles[role.name] = Read(`${previewDir}/roles/${role.name}.md`)
|
roleFiles[role.name] = Read(`${previewDir}/roles/${role.name}/role.md`)
|
||||||
} catch {
|
} catch {
|
||||||
roleFiles[role.name] = null
|
roleFiles[role.name] = null
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ for (const role of config.roles) {
|
|||||||
const routerChecks = config.roles.map(role => {
|
const routerChecks = config.roles.map(role => {
|
||||||
const hasRouterEntry = skillMd.includes(`"${role.name}"`)
|
const hasRouterEntry = skillMd.includes(`"${role.name}"`)
|
||||||
const hasRoleFile = roleFiles[role.name] !== null
|
const hasRoleFile = roleFiles[role.name] !== null
|
||||||
const hasRoleLink = skillMd.includes(`roles/${role.name}.md`)
|
const hasRoleLink = skillMd.includes(`roles/${role.name}/role.md`)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
role: role.name,
|
role: role.name,
|
||||||
@@ -127,6 +127,42 @@ const patternChecks = Object.entries(roleFiles).map(([name, content]) => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Step 6b: Command File Verification
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const commandChecks = config.worker_roles.map(role => {
|
||||||
|
const commands = role.commands || []
|
||||||
|
if (commands.length === 0) return { role: role.name, status: 'SKIP', reason: 'No commands' }
|
||||||
|
|
||||||
|
const checks = commands.map(cmd => {
|
||||||
|
const cmdPath = `${previewDir}/roles/${role.name}/commands/${cmd}.md`
|
||||||
|
let content = null
|
||||||
|
try { content = Read(cmdPath) } catch {}
|
||||||
|
|
||||||
|
if (!content) return { command: cmd, status: 'MISSING' }
|
||||||
|
|
||||||
|
const requiredSections = {
|
||||||
|
has_strategy: /## Strategy/.test(content),
|
||||||
|
has_execution_steps: /## Execution Steps/.test(content),
|
||||||
|
has_error_handling: /## Error Handling/.test(content),
|
||||||
|
has_when_to_use: /## When to Use/.test(content),
|
||||||
|
is_self_contained: !/Read\("\.\.\//.test(content) // No cross-command references
|
||||||
|
}
|
||||||
|
|
||||||
|
const passCount = Object.values(requiredSections).filter(Boolean).length
|
||||||
|
return {
|
||||||
|
command: cmd,
|
||||||
|
checks: requiredSections,
|
||||||
|
pass_count: passCount,
|
||||||
|
total: Object.keys(requiredSections).length,
|
||||||
|
status: passCount === Object.keys(requiredSections).length ? 'PASS' : 'PARTIAL'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return { role: role.name, commands: checks, status: checks.every(c => c.status === 'PASS') ? 'PASS' : 'NEEDS_ATTENTION' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
### Step 7: Generate Report
|
### Step 7: Generate Report
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -134,7 +170,8 @@ const overallStatus = [
|
|||||||
...routerChecks.map(c => c.status),
|
...routerChecks.map(c => c.status),
|
||||||
prefixCheck.status,
|
prefixCheck.status,
|
||||||
...spawnChecks.map(c => c.status),
|
...spawnChecks.map(c => c.status),
|
||||||
...patternChecks.map(c => c.status)
|
...patternChecks.map(c => c.status),
|
||||||
|
...commandChecks.filter(c => c.status !== 'SKIP').map(c => c.status)
|
||||||
].every(s => s === 'PASS') ? 'PASS' : 'NEEDS_ATTENTION'
|
].every(s => s === 'PASS') ? 'PASS' : 'NEEDS_ATTENTION'
|
||||||
|
|
||||||
const report = {
|
const report = {
|
||||||
@@ -145,7 +182,8 @@ const report = {
|
|||||||
prefix_uniqueness: prefixCheck,
|
prefix_uniqueness: prefixCheck,
|
||||||
message_types: msgChecks,
|
message_types: msgChecks,
|
||||||
spawn_template: spawnChecks,
|
spawn_template: spawnChecks,
|
||||||
pattern_compliance: patternChecks
|
pattern_compliance: patternChecks,
|
||||||
|
command_files: commandChecks
|
||||||
},
|
},
|
||||||
overall: overallStatus,
|
overall: overallStatus,
|
||||||
file_count: {
|
file_count: {
|
||||||
|
|||||||
@@ -94,6 +94,46 @@ for (const [name, content] of Object.entries(roleContents)) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Step 3b: Command File Quality Check
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const commandQuality = {}
|
||||||
|
for (const [name, content] of Object.entries(roleContents)) {
|
||||||
|
if (!content) continue
|
||||||
|
|
||||||
|
// Check if role has commands directory
|
||||||
|
const role = config.roles.find(r => r.name === name)
|
||||||
|
const commands = role?.commands || []
|
||||||
|
if (commands.length === 0) {
|
||||||
|
commandQuality[name] = { status: 'N/A', score: 100 }
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmdChecks = commands.map(cmd => {
|
||||||
|
let cmdContent = null
|
||||||
|
try { cmdContent = Read(`${previewDir}/roles/${name}/commands/${cmd}.md`) } catch {}
|
||||||
|
|
||||||
|
if (!cmdContent) return { command: cmd, score: 0 }
|
||||||
|
|
||||||
|
const checks = [
|
||||||
|
{ name: "When to Use section", pass: /## When to Use/.test(cmdContent) },
|
||||||
|
{ name: "Strategy section", pass: /## Strategy/.test(cmdContent) },
|
||||||
|
{ name: "Delegation mode declared", pass: /Delegation Mode/.test(cmdContent) },
|
||||||
|
{ name: "Execution Steps section", pass: /## Execution Steps/.test(cmdContent) },
|
||||||
|
{ name: "Error Handling section", pass: /## Error Handling/.test(cmdContent) },
|
||||||
|
{ name: "Output Format section", pass: /## Output Format/.test(cmdContent) },
|
||||||
|
{ name: "Self-contained (no cross-ref)", pass: !/Read\("\.\.\//.test(cmdContent) }
|
||||||
|
]
|
||||||
|
|
||||||
|
const score = checks.filter(c => c.pass).length / checks.length * 100
|
||||||
|
return { command: cmd, checks, score }
|
||||||
|
})
|
||||||
|
|
||||||
|
const avgScore = cmdChecks.reduce((sum, c) => sum + c.score, 0) / cmdChecks.length
|
||||||
|
commandQuality[name] = { status: avgScore >= 80 ? 'PASS' : 'PARTIAL', checks: cmdChecks, score: avgScore }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Step 4: Quality Scoring
|
### Step 4: Quality Scoring
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -101,7 +141,8 @@ const scores = {
|
|||||||
skill_md: skillScore,
|
skill_md: skillScore,
|
||||||
roles_avg: Object.values(roleResults).reduce((sum, r) => sum + r.score, 0) / Object.keys(roleResults).length,
|
roles_avg: Object.values(roleResults).reduce((sum, r) => sum + r.score, 0) / Object.keys(roleResults).length,
|
||||||
integration: integration.overall === 'PASS' ? 100 : 50,
|
integration: integration.overall === 'PASS' ? 100 : 50,
|
||||||
consistency: checkConsistency()
|
consistency: checkConsistency(),
|
||||||
|
command_quality: Object.values(commandQuality).reduce((sum, c) => sum + c.score, 0) / Math.max(Object.keys(commandQuality).length, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkConsistency() {
|
function checkConsistency() {
|
||||||
|
|||||||
@@ -23,21 +23,21 @@ Quality assessment criteria for generated team command .md files.
|
|||||||
| 40% | Missing critical sections |
|
| 40% | Missing critical sections |
|
||||||
| 0% | Skeleton only |
|
| 0% | Skeleton only |
|
||||||
|
|
||||||
**Required Sections Checklist:**
|
**Required Sections Checklist (role.md files):**
|
||||||
- [ ] YAML front matter with `group: team`
|
- [ ] Role Identity (name, responsibility, communication)
|
||||||
- [ ] Overview with core capabilities
|
|
||||||
- [ ] Role Definition (name, responsibility, communication)
|
|
||||||
- [ ] Message Bus section with team_msg examples
|
- [ ] Message Bus section with team_msg examples
|
||||||
- [ ] Message Types table
|
- [ ] Message Types table
|
||||||
- [ ] Execution Process overview diagram
|
- [ ] Toolbox section (Available Commands, Subagent Capabilities, CLI Capabilities)
|
||||||
- [ ] Phase 1: Task Discovery implementation
|
- [ ] Phase 1: Task Discovery implementation
|
||||||
- [ ] Phase 2: Context Loading implementation
|
- [ ] Phase 2: Context Loading / delegation to commands
|
||||||
- [ ] Phase 3: Core Work implementation
|
- [ ] Phase 3: Core Work / delegation to commands
|
||||||
- [ ] Phase 4: Validation/Summary implementation
|
- [ ] Phase 4: Validation/Summary / delegation to commands
|
||||||
- [ ] Phase 5: Report + Loop implementation
|
- [ ] Phase 5: Report + Loop implementation
|
||||||
- [ ] Error Handling table
|
- [ ] Error Handling table
|
||||||
- [ ] Code examples in all phases
|
- [ ] Code examples in all phases
|
||||||
|
|
||||||
|
> **Note**: For `commands/*.md` file quality criteria, see [Command File Quality Standards](#command-file-quality-standards) below.
|
||||||
|
|
||||||
### 2. Pattern Compliance (25%)
|
### 2. Pattern Compliance (25%)
|
||||||
|
|
||||||
| Score | Criteria |
|
| Score | Criteria |
|
||||||
@@ -124,3 +124,48 @@ Quality assessment criteria for generated team command .md files.
|
|||||||
- Additional message type examples
|
- Additional message type examples
|
||||||
- Session file structure documentation
|
- Session file structure documentation
|
||||||
- CLI integration examples
|
- CLI integration examples
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Command File Quality Standards
|
||||||
|
|
||||||
|
Quality assessment criteria for generated command `.md` files in `roles/{name}/commands/`.
|
||||||
|
|
||||||
|
### 5. Command File Quality (Applies to folder-based roles)
|
||||||
|
|
||||||
|
| Score | Criteria |
|
||||||
|
|-------|----------|
|
||||||
|
| 100% | All 4 dimensions pass, all command files self-contained |
|
||||||
|
| 80% | 3/4 dimensions pass, minor gaps in one area |
|
||||||
|
| 60% | 2/4 dimensions pass, some cross-references or missing sections |
|
||||||
|
| 40% | Missing required sections or broken references |
|
||||||
|
| 0% | No command files or non-functional |
|
||||||
|
|
||||||
|
#### Dimension 1: Structural Completeness
|
||||||
|
|
||||||
|
Each command file MUST contain:
|
||||||
|
- [ ] `## When to Use` - Trigger conditions
|
||||||
|
- [ ] `## Strategy` with `### Delegation Mode` (Subagent Fan-out / CLI Fan-out / Sequential Delegation / Direct)
|
||||||
|
- [ ] `## Execution Steps` with numbered steps and code blocks
|
||||||
|
- [ ] `## Error Handling` table with Scenario/Resolution
|
||||||
|
|
||||||
|
#### Dimension 2: Self-Containment
|
||||||
|
|
||||||
|
- [ ] No `Ref:` or cross-references to other command files
|
||||||
|
- [ ] No imports or dependencies on sibling commands
|
||||||
|
- [ ] All context loaded within the command (task, plan, files)
|
||||||
|
- [ ] Any subagent can `Read()` the command and execute independently
|
||||||
|
|
||||||
|
#### Dimension 3: Toolbox Consistency
|
||||||
|
|
||||||
|
- [ ] Every command listed in role.md Toolbox has a corresponding file in `commands/`
|
||||||
|
- [ ] Every file in `commands/` is listed in role.md Toolbox
|
||||||
|
- [ ] Phase mapping in Toolbox matches command's `## When to Use` phase reference
|
||||||
|
- [ ] Delegation mode in command matches role's subagent/CLI capabilities
|
||||||
|
|
||||||
|
#### Dimension 4: Pattern Compliance
|
||||||
|
|
||||||
|
- [ ] Pre-built command patterns (explore, analyze, implement, validate, review, dispatch, monitor) follow templates/role-command-template.md
|
||||||
|
- [ ] Custom commands follow the template skeleton structure
|
||||||
|
- [ ] Delegation mode is appropriate for the command's complexity
|
||||||
|
- [ ] Output format is structured and parseable by the calling role.md
|
||||||
|
|||||||
@@ -470,3 +470,101 @@ When designing a new team command, verify:
|
|||||||
- [ ] Timeout/fallback behavior specified
|
- [ ] Timeout/fallback behavior specified
|
||||||
- [ ] Pattern-specific message types registered
|
- [ ] Pattern-specific message types registered
|
||||||
- [ ] Coordinator aware of pattern (can route messages accordingly)
|
- [ ] Coordinator aware of pattern (can route messages accordingly)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pattern 9: Parallel Subagent Orchestration
|
||||||
|
|
||||||
|
Roles that need to perform complex, multi-perspective work can delegate to subagents or CLI tools rather than executing everything inline. This pattern defines three delegation modes and context management rules.
|
||||||
|
|
||||||
|
### Delegation Modes
|
||||||
|
|
||||||
|
#### Mode A: Subagent Fan-out
|
||||||
|
|
||||||
|
Launch multiple Task agents in parallel for independent work streams.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Launch 2-4 parallel agents for different perspectives
|
||||||
|
const agents = [
|
||||||
|
Task({
|
||||||
|
subagent_type: "cli-explore-agent",
|
||||||
|
run_in_background: false,
|
||||||
|
description: "Explore angle 1",
|
||||||
|
prompt: `Analyze from perspective 1: ${taskDescription}`
|
||||||
|
}),
|
||||||
|
Task({
|
||||||
|
subagent_type: "cli-explore-agent",
|
||||||
|
run_in_background: false,
|
||||||
|
description: "Explore angle 2",
|
||||||
|
prompt: `Analyze from perspective 2: ${taskDescription}`
|
||||||
|
})
|
||||||
|
]
|
||||||
|
// Aggregate results after all complete
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use**: Multi-angle exploration, parallel code analysis, independent subtask execution.
|
||||||
|
|
||||||
|
#### Mode B: CLI Fan-out
|
||||||
|
|
||||||
|
Launch multiple `ccw cli` calls for multi-perspective analysis.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Parallel CLI calls for different analysis angles
|
||||||
|
Bash(`ccw cli -p "PURPOSE: Analyze from security angle..." --tool gemini --mode analysis`, { run_in_background: true })
|
||||||
|
Bash(`ccw cli -p "PURPOSE: Analyze from performance angle..." --tool gemini --mode analysis`, { run_in_background: true })
|
||||||
|
// Wait for all CLI results, then synthesize
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use**: Multi-dimensional code review, architecture analysis, security + performance audits.
|
||||||
|
|
||||||
|
#### Mode C: Sequential Delegation
|
||||||
|
|
||||||
|
Delegate a single heavy task to a specialized agent.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Task({
|
||||||
|
subagent_type: "code-developer",
|
||||||
|
run_in_background: false,
|
||||||
|
description: "Implement complex feature",
|
||||||
|
prompt: `## Goal\n${plan.summary}\n\n## Tasks\n${taskDetails}`
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use**: Complex implementation, test-fix cycles, large-scope refactoring.
|
||||||
|
|
||||||
|
### Context Management Hierarchy
|
||||||
|
|
||||||
|
| Level | Location | Context Size | Use Case |
|
||||||
|
|-------|----------|-------------|----------|
|
||||||
|
| Small | role.md inline | < 200 lines | Simple logic, direct execution |
|
||||||
|
| Medium | commands/*.md | 200-500 lines | Structured delegation with strategy |
|
||||||
|
| Large | Subagent prompt | Unlimited | Full autonomous execution |
|
||||||
|
|
||||||
|
**Rule**: role.md Phase 1/5 are always inline (standardized). Phases 2-4 either inline (small) or delegate to commands (medium/large).
|
||||||
|
|
||||||
|
### Command File Extraction Criteria
|
||||||
|
|
||||||
|
Extract a phase into a command file when ANY of these conditions are met:
|
||||||
|
|
||||||
|
1. **Subagent delegation**: Phase launches Task() agents
|
||||||
|
2. **CLI fan-out**: Phase runs parallel `ccw cli` calls
|
||||||
|
3. **Complex strategy**: Phase has >3 conditional branches
|
||||||
|
4. **Reusable logic**: Same logic used by multiple roles
|
||||||
|
|
||||||
|
If none apply, keep the phase inline in role.md.
|
||||||
|
|
||||||
|
### Relationship to Other Patterns
|
||||||
|
|
||||||
|
- **Pattern 5 (Complexity-Adaptive)**: Pattern 9 provides the delegation mechanisms that Pattern 5 routes to. Low complexity → inline, Medium → CLI agent, High → Subagent fan-out.
|
||||||
|
- **CP-3 (Parallel Fan-out)**: Pattern 9 Mode A/B are the implementation mechanisms for CP-3 at the role level.
|
||||||
|
- **Pattern 4 (Five-Phase)**: Pattern 9 does NOT replace the 5-phase structure. It provides delegation options WITHIN phases 2-4.
|
||||||
|
|
||||||
|
### Checklist
|
||||||
|
|
||||||
|
- [ ] Delegation mode selected based on task characteristics
|
||||||
|
- [ ] Context management level appropriate (small/medium/large)
|
||||||
|
- [ ] Command files extracted only when criteria met
|
||||||
|
- [ ] Subagent prompts include mandatory first steps (read project config)
|
||||||
|
- [ ] CLI fan-out uses `--mode analysis` by default
|
||||||
|
- [ ] Results aggregated after parallel completion
|
||||||
|
- [ ] Error handling covers agent/CLI failure with fallback
|
||||||
|
|||||||
@@ -0,0 +1,725 @@
|
|||||||
|
# Role Command Template
|
||||||
|
|
||||||
|
Template for generating command files in `roles/{role-name}/commands/{command}.md`.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
| Phase | Usage |
|
||||||
|
|-------|-------|
|
||||||
|
| Phase 0 | Read to understand command file structure |
|
||||||
|
| Phase 3 | Apply with role-specific content |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: {{command_name}}
|
||||||
|
|
||||||
|
> {{command_description}}
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
{{when_to_use_description}}
|
||||||
|
|
||||||
|
**Trigger conditions**:
|
||||||
|
{{#each triggers}}
|
||||||
|
- {{this}}
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: {{delegation_mode}}
|
||||||
|
|
||||||
|
{{#if delegation_mode_subagent}}
|
||||||
|
**Subagent Type**: `{{subagent_type}}`
|
||||||
|
**Parallel Count**: {{parallel_count}} (1-4)
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if delegation_mode_cli}}
|
||||||
|
**CLI Tool**: `{{cli_tool}}`
|
||||||
|
**CLI Mode**: `{{cli_mode}}`
|
||||||
|
**Parallel Perspectives**: {{cli_perspectives}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if delegation_mode_sequential}}
|
||||||
|
**Agent Type**: `{{agent_type}}`
|
||||||
|
**Delegation Scope**: {{delegation_scope}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
### Decision Logic
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
{{decision_logic}}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
{{context_preparation_code}}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
{{execution_code}}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
{{result_processing_code}}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
{{output_format}}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
{{#each error_handlers}}
|
||||||
|
| {{this.scenario}} | {{this.resolution}} |
|
||||||
|
{{/each}}
|
||||||
|
| Agent/CLI failure | Retry once, then fallback to inline execution |
|
||||||
|
| Timeout (>5 min) | Report partial results, notify coordinator |
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7 Pre-built Command Patterns
|
||||||
|
|
||||||
|
### 1. explore.md (Multi-angle Exploration)
|
||||||
|
|
||||||
|
**Delegation Mode**: Subagent Fan-out
|
||||||
|
**Source Pattern**: team-lifecycle planner Phase 2
|
||||||
|
**Maps to**: Orchestration roles
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: explore
|
||||||
|
|
||||||
|
> Multi-angle codebase exploration using parallel cli-explore-agent instances.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 2 of Orchestration roles
|
||||||
|
- Task requires understanding existing code patterns
|
||||||
|
- Multiple exploration angles needed (architecture, patterns, dependencies)
|
||||||
|
|
||||||
|
**Trigger conditions**:
|
||||||
|
- New feature planning
|
||||||
|
- Codebase unfamiliar to the agent
|
||||||
|
- Cross-module impact analysis
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: Subagent Fan-out
|
||||||
|
**Subagent Type**: `cli-explore-agent`
|
||||||
|
**Parallel Count**: 2-4 (based on complexity)
|
||||||
|
|
||||||
|
### Decision Logic
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const angles = []
|
||||||
|
if (/architect|structure|design/.test(task.description)) angles.push("architecture")
|
||||||
|
if (/pattern|convention|style/.test(task.description)) angles.push("patterns")
|
||||||
|
if (/depend|import|module/.test(task.description)) angles.push("dependencies")
|
||||||
|
if (/test|spec|coverage/.test(task.description)) angles.push("testing")
|
||||||
|
if (angles.length === 0) angles.push("general", "patterns")
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const taskDescription = task.description
|
||||||
|
const projectRoot = Bash(\`git rev-parse --show-toplevel\`).trim()
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Launch parallel exploration agents (1 per angle)
|
||||||
|
for (const angle of angles) {
|
||||||
|
Task({
|
||||||
|
subagent_type: "cli-explore-agent",
|
||||||
|
run_in_background: false,
|
||||||
|
description: \`Explore: \${angle}\`,
|
||||||
|
prompt: \`Explore the codebase from the perspective of \${angle}.
|
||||||
|
Focus on: \${taskDescription}
|
||||||
|
Project root: \${projectRoot}
|
||||||
|
|
||||||
|
Report findings as structured markdown with file references.\`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Aggregate exploration results
|
||||||
|
const aggregated = {
|
||||||
|
angles_explored: angles,
|
||||||
|
key_findings: [], // merge from all agents
|
||||||
|
relevant_files: [], // deduplicate across agents
|
||||||
|
patterns_found: []
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
## Exploration Results
|
||||||
|
|
||||||
|
### Angles Explored: [list]
|
||||||
|
|
||||||
|
### Key Findings
|
||||||
|
- [finding with file:line reference]
|
||||||
|
|
||||||
|
### Relevant Files
|
||||||
|
- [file path with relevance note]
|
||||||
|
|
||||||
|
### Patterns Found
|
||||||
|
- [pattern name: description]
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| Agent returns no results | Retry with broader search scope |
|
||||||
|
| Agent timeout | Use partial results, note incomplete angles |
|
||||||
|
| Project root not found | Fall back to current directory |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. analyze.md (Multi-perspective Analysis)
|
||||||
|
|
||||||
|
**Delegation Mode**: CLI Fan-out
|
||||||
|
**Source Pattern**: analyze-with-file Phase 2
|
||||||
|
**Maps to**: Read-only analysis roles
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: analyze
|
||||||
|
|
||||||
|
> Multi-perspective code analysis using parallel ccw cli calls.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 3 of Read-only analysis roles
|
||||||
|
- Multiple analysis dimensions needed (security, performance, quality)
|
||||||
|
- Deep analysis beyond inline capability
|
||||||
|
|
||||||
|
**Trigger conditions**:
|
||||||
|
- Code review with specific focus areas
|
||||||
|
- Security/performance audit
|
||||||
|
- Architecture assessment
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: CLI Fan-out
|
||||||
|
**CLI Tool**: `gemini` (primary), `codex` (secondary)
|
||||||
|
**CLI Mode**: `analysis`
|
||||||
|
**Parallel Perspectives**: 2-4
|
||||||
|
|
||||||
|
### Decision Logic
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const perspectives = []
|
||||||
|
if (/security|auth|inject|xss/.test(task.description)) perspectives.push("security")
|
||||||
|
if (/performance|speed|optimize|memory/.test(task.description)) perspectives.push("performance")
|
||||||
|
if (/quality|clean|maintain|debt/.test(task.description)) perspectives.push("code-quality")
|
||||||
|
if (/architect|pattern|structure/.test(task.description)) perspectives.push("architecture")
|
||||||
|
if (perspectives.length === 0) perspectives.push("code-quality", "architecture")
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const targetFiles = Bash(\`git diff --name-only HEAD~1 2>/dev/null || git diff --name-only --cached\`)
|
||||||
|
.split('\\n').filter(Boolean)
|
||||||
|
const fileContext = targetFiles.map(f => \`@\${f}\`).join(' ')
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
for (const perspective of perspectives) {
|
||||||
|
Bash(\`ccw cli -p "PURPOSE: Analyze code from \${perspective} perspective
|
||||||
|
TASK: Review changes in: \${targetFiles.join(', ')}
|
||||||
|
MODE: analysis
|
||||||
|
CONTEXT: \${fileContext}
|
||||||
|
EXPECTED: Findings with severity, file:line references, remediation
|
||||||
|
CONSTRAINTS: Focus on \${perspective}" --tool gemini --mode analysis\`, { run_in_background: true })
|
||||||
|
}
|
||||||
|
// Wait for all CLI results
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Aggregate findings across all perspectives
|
||||||
|
const findings = { critical: [], high: [], medium: [], low: [] }
|
||||||
|
// Merge, deduplicate, prioritize
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
## Analysis Results
|
||||||
|
|
||||||
|
### Perspectives Analyzed: [list]
|
||||||
|
|
||||||
|
### Findings by Severity
|
||||||
|
#### Critical
|
||||||
|
- [finding with file:line]
|
||||||
|
#### High
|
||||||
|
- [finding]
|
||||||
|
...
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| CLI tool unavailable | Fall back to secondary tool (codex) |
|
||||||
|
| CLI returns empty | Retry with broader scope |
|
||||||
|
| Too many findings | Prioritize critical/high, summarize medium/low |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. implement.md (Code Implementation)
|
||||||
|
|
||||||
|
**Delegation Mode**: Sequential Delegation
|
||||||
|
**Source Pattern**: team-lifecycle executor Phase 3
|
||||||
|
**Maps to**: Code generation roles
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: implement
|
||||||
|
|
||||||
|
> Code implementation via code-developer subagent delegation with batch routing.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 3 of Code generation roles
|
||||||
|
- Implementation involves >2 files or complex logic
|
||||||
|
- Plan tasks available with file specifications
|
||||||
|
|
||||||
|
**Trigger conditions**:
|
||||||
|
- Plan approved and tasks defined
|
||||||
|
- Multi-file implementation needed
|
||||||
|
- Complex logic requiring specialized agent
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: Sequential Delegation (with batch routing)
|
||||||
|
**Agent Type**: `code-developer`
|
||||||
|
**Delegation Scope**: Per-batch (group related tasks)
|
||||||
|
|
||||||
|
### Decision Logic
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const taskCount = planTasks.length
|
||||||
|
if (taskCount <= 2) {
|
||||||
|
// Direct: inline Edit/Write
|
||||||
|
mode = "direct"
|
||||||
|
} else if (taskCount <= 5) {
|
||||||
|
// Single agent: one code-developer for all
|
||||||
|
mode = "single-agent"
|
||||||
|
} else {
|
||||||
|
// Batch: group by module, one agent per batch
|
||||||
|
mode = "batch-agent"
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const plan = JSON.parse(Read(planPath))
|
||||||
|
const planTasks = plan.task_ids.map(id =>
|
||||||
|
JSON.parse(Read(\`\${planDir}/.task/\${id}.json\`))
|
||||||
|
)
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
if (mode === "direct") {
|
||||||
|
for (const pt of planTasks) {
|
||||||
|
for (const f of (pt.files || [])) {
|
||||||
|
Read(f.path)
|
||||||
|
Edit({ file_path: f.path, old_string: "...", new_string: "..." })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const batches = mode === "batch-agent"
|
||||||
|
? groupByModule(planTasks)
|
||||||
|
: [planTasks]
|
||||||
|
|
||||||
|
for (const batch of batches) {
|
||||||
|
Task({
|
||||||
|
subagent_type: "code-developer",
|
||||||
|
run_in_background: false,
|
||||||
|
description: \`Implement \${batch.length} tasks\`,
|
||||||
|
prompt: \`## Goal\\n\${plan.summary}\\n\\n## Tasks\\n\${
|
||||||
|
batch.map(t => \`### \${t.title}\\n\${t.description}\`).join('\\n\\n')
|
||||||
|
}\\n\\nComplete each task according to its convergence criteria.\`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const changedFiles = Bash(\`git diff --name-only\`).split('\\n').filter(Boolean)
|
||||||
|
const syntaxClean = !Bash(\`tsc --noEmit 2>&1 || true\`).includes('error TS')
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
## Implementation Results
|
||||||
|
|
||||||
|
### Changed Files: [count]
|
||||||
|
- [file path]
|
||||||
|
|
||||||
|
### Syntax Check: PASS/FAIL
|
||||||
|
### Tasks Completed: [count]/[total]
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| Plan file not found | Notify coordinator, request plan path |
|
||||||
|
| Agent fails on task | Retry once, then mark task as blocked |
|
||||||
|
| Syntax errors after impl | Attempt auto-fix, report if unresolved |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. validate.md (Test-Fix Cycle)
|
||||||
|
|
||||||
|
**Delegation Mode**: Sequential Delegation
|
||||||
|
**Source Pattern**: team-lifecycle tester
|
||||||
|
**Maps to**: Validation roles
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: validate
|
||||||
|
|
||||||
|
> Iterative test-fix cycle with max iteration control.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 3 of Validation roles
|
||||||
|
- After implementation, before review
|
||||||
|
- Automated test suite available
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: Sequential Delegation
|
||||||
|
**Agent Type**: `code-developer` (for fix iterations)
|
||||||
|
**Max Iterations**: 5
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const testCommand = detectTestCommand() // npm test, pytest, etc.
|
||||||
|
const changedFiles = Bash(\`git diff --name-only\`).split('\\n').filter(Boolean)
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
let iteration = 0
|
||||||
|
const MAX_ITERATIONS = 5
|
||||||
|
let lastResult = null
|
||||||
|
|
||||||
|
while (iteration < MAX_ITERATIONS) {
|
||||||
|
lastResult = Bash(\`\${testCommand} 2>&1 || true\`)
|
||||||
|
const passed = !lastResult.includes('FAIL') && !lastResult.includes('Error')
|
||||||
|
|
||||||
|
if (passed) break
|
||||||
|
|
||||||
|
// 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}\\n\\nFix the failing tests. Changed files: \${changedFiles.join(', ')}\`
|
||||||
|
})
|
||||||
|
|
||||||
|
iteration++
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const result = {
|
||||||
|
iterations: iteration,
|
||||||
|
passed: iteration < MAX_ITERATIONS,
|
||||||
|
lastOutput: lastResult
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| No test command found | Notify coordinator |
|
||||||
|
| Max iterations exceeded | Report failures, suggest manual intervention |
|
||||||
|
| Test environment broken | Report environment issue |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. review.md (Multi-dimensional Review)
|
||||||
|
|
||||||
|
**Delegation Mode**: CLI Fan-out
|
||||||
|
**Source Pattern**: team-lifecycle reviewer
|
||||||
|
**Maps to**: Read-only analysis roles
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: review
|
||||||
|
|
||||||
|
> 4-dimensional code review with optional codex review integration.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 3 of Read-only analysis roles (reviewer type)
|
||||||
|
- After implementation and testing
|
||||||
|
- Quality gate before delivery
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: CLI Fan-out
|
||||||
|
**CLI Tool**: `gemini` + optional `codex` (review mode)
|
||||||
|
**Dimensions**: correctness, completeness, maintainability, requirement-fit
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Dimension 1-3: Parallel CLI analysis
|
||||||
|
const dimensions = ["correctness", "completeness", "maintainability"]
|
||||||
|
for (const dim of dimensions) {
|
||||||
|
Bash(\`ccw cli -p "PURPOSE: Review code for \${dim}
|
||||||
|
TASK: Evaluate changes against \${dim} criteria
|
||||||
|
MODE: analysis
|
||||||
|
CONTEXT: @\${changedFiles.join(' @')}
|
||||||
|
EXPECTED: Findings with severity and file:line references" --tool gemini --mode analysis\`, { run_in_background: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dimension 4: Optional codex review
|
||||||
|
Bash(\`ccw cli --tool codex --mode review --uncommitted\`, { run_in_background: true })
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| Codex unavailable | Skip dimension 4, report 3-dimension review |
|
||||||
|
| No changed files | Review full scope of plan files |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. dispatch.md (Task Distribution)
|
||||||
|
|
||||||
|
**Delegation Mode**: N/A (Coordinator-only)
|
||||||
|
**Source Pattern**: auto-parallel + CP-3
|
||||||
|
**Maps to**: Coordinator role
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: dispatch
|
||||||
|
|
||||||
|
> Task chain creation with dependency management for coordinator.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 3 of Coordinator role
|
||||||
|
- After requirement clarification
|
||||||
|
- When creating and assigning tasks to teammates
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: Direct (no delegation - coordinator acts directly)
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const config = TEAM_CONFIG
|
||||||
|
const pipeline = config.pipeline
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const taskIds = {}
|
||||||
|
|
||||||
|
for (const stage of pipeline.stages) {
|
||||||
|
const blockedByIds = stage.blockedBy.map(dep => taskIds[dep]).filter(Boolean)
|
||||||
|
|
||||||
|
TaskCreate({
|
||||||
|
subject: \`\${stage.name}-001: \${stage.role} work\`,
|
||||||
|
description: taskDescription,
|
||||||
|
activeForm: \`\${stage.name} 进行中\`
|
||||||
|
})
|
||||||
|
|
||||||
|
// Record task ID
|
||||||
|
taskIds[stage.name] = newTaskId
|
||||||
|
|
||||||
|
// Set owner and dependencies
|
||||||
|
TaskUpdate({
|
||||||
|
taskId: newTaskId,
|
||||||
|
owner: stage.role,
|
||||||
|
addBlockedBy: blockedByIds
|
||||||
|
})
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 3: Result Processing
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Verify task chain created correctly
|
||||||
|
const allTasks = TaskList()
|
||||||
|
const chainValid = pipeline.stages.every(s => taskIds[s.name])
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| Task creation fails | Retry, then report to user |
|
||||||
|
| Dependency cycle detected | Flatten dependencies, warn |
|
||||||
|
| Role not spawned yet | Queue task, spawn role first |
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. monitor.md (Progress Monitoring)
|
||||||
|
|
||||||
|
**Delegation Mode**: N/A (Coordinator-only)
|
||||||
|
**Source Pattern**: coordinate.md Phase 4
|
||||||
|
**Maps to**: Coordinator role
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Command: monitor
|
||||||
|
|
||||||
|
> Message bus polling and coordination loop for coordinator.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Phase 4 of Coordinator role
|
||||||
|
- After task dispatch
|
||||||
|
- Continuous monitoring until all tasks complete
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
### Delegation Mode
|
||||||
|
|
||||||
|
**Mode**: Direct (coordinator polls and routes)
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1: Context Preparation
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
const routingTable = {}
|
||||||
|
for (const role of config.worker_roles) {
|
||||||
|
const resultType = role.message_types.find(mt =>
|
||||||
|
!mt.type.includes('error') && !mt.type.includes('progress')
|
||||||
|
)
|
||||||
|
routingTable[resultType?.type || \`\${role.name}_complete\`] = {
|
||||||
|
role: role.name,
|
||||||
|
action: "Mark task completed, check downstream dependencies"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
routingTable["error"] = { role: "*", action: "Assess severity, retry or escalate" }
|
||||||
|
routingTable["fix_required"] = { role: "*", action: "Create fix task for executor" }
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Step 2: Execute Strategy
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// Coordination loop
|
||||||
|
let allComplete = false
|
||||||
|
while (!allComplete) {
|
||||||
|
// Poll message bus
|
||||||
|
const messages = mcp__ccw-tools__team_msg({
|
||||||
|
operation: "list",
|
||||||
|
team: teamName,
|
||||||
|
last: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
// Route each message
|
||||||
|
for (const msg of messages) {
|
||||||
|
const handler = routingTable[msg.type]
|
||||||
|
if (handler) {
|
||||||
|
// Execute handler action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check completion
|
||||||
|
const tasks = TaskList()
|
||||||
|
allComplete = tasks.filter(t =>
|
||||||
|
t.owner !== 'coordinator' && t.status !== 'completed'
|
||||||
|
).length === 0
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Scenario | Resolution |
|
||||||
|
|----------|------------|
|
||||||
|
| Message bus unavailable | Fall back to TaskList polling |
|
||||||
|
| Teammate unresponsive | Send follow-up, 2x → respawn |
|
||||||
|
| Deadlock detected | Identify cycle, break with manual unblock |
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Variable Reference
|
||||||
|
|
||||||
|
| Variable | Source | Description |
|
||||||
|
|----------|--------|-------------|
|
||||||
|
| `{{command_name}}` | Command identifier | e.g., "explore", "analyze" |
|
||||||
|
| `{{command_description}}` | One-line description | What this command does |
|
||||||
|
| `{{delegation_mode}}` | Mode selection | "Subagent Fan-out", "CLI Fan-out", "Sequential Delegation", "Direct" |
|
||||||
|
| `{{when_to_use_description}}` | Usage context | When to invoke this command |
|
||||||
|
| `{{triggers}}` | Trigger conditions | List of conditions |
|
||||||
|
| `{{decision_logic}}` | Strategy selection code | JavaScript decision code |
|
||||||
|
| `{{context_preparation_code}}` | Context setup | JavaScript setup code |
|
||||||
|
| `{{execution_code}}` | Core execution | JavaScript execution code |
|
||||||
|
| `{{result_processing_code}}` | Result aggregation | JavaScript result code |
|
||||||
|
| `{{output_format}}` | Expected output structure | Markdown format spec |
|
||||||
|
| `{{error_handlers}}` | Error handling entries | Array of {scenario, resolution} |
|
||||||
|
|
||||||
|
## Self-Containment Rules
|
||||||
|
|
||||||
|
1. **No cross-command references**: Each command.md must be executable independently
|
||||||
|
2. **Include all imports**: List all required context (files, configs) in Step 1
|
||||||
|
3. **Complete error handling**: Every command handles its own failures
|
||||||
|
4. **Explicit output format**: Define what the command produces
|
||||||
|
5. **Strategy declaration**: State delegation mode and decision logic upfront
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Role File Template
|
# Role File Template
|
||||||
|
|
||||||
Template for generating per-role execution detail files in `roles/{role-name}.md`.
|
Template for generating per-role execution detail files in `roles/{role-name}/role.md`.
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
@@ -24,6 +24,24 @@ Template for generating per-role execution detail files in `roles/{role-name}.md
|
|||||||
- **Task Prefix**: `{{task_prefix}}-*`
|
- **Task Prefix**: `{{task_prefix}}-*`
|
||||||
- **Responsibility**: {{responsibility_type}}
|
- **Responsibility**: {{responsibility_type}}
|
||||||
- **Communication**: SendMessage to coordinator only
|
- **Communication**: SendMessage to coordinator only
|
||||||
|
- **Output Tag**: `[{{role_name}}]`
|
||||||
|
|
||||||
|
## Role Boundaries
|
||||||
|
|
||||||
|
### MUST
|
||||||
|
|
||||||
|
- 仅处理 `{{task_prefix}}-*` 前缀的任务
|
||||||
|
- 所有输出(SendMessage、team_msg、日志)必须带 `[{{role_name}}]` 标识
|
||||||
|
- 仅通过 SendMessage 与 coordinator 通信
|
||||||
|
- 严格在 {{responsibility_type}} 职责范围内工作
|
||||||
|
|
||||||
|
### MUST NOT
|
||||||
|
|
||||||
|
- ❌ 执行其他角色职责范围内的工作
|
||||||
|
- ❌ 直接与其他 worker 角色通信(必须经过 coordinator)
|
||||||
|
- ❌ 为其他角色创建任务(TaskCreate 是 coordinator 专属)
|
||||||
|
- ❌ 修改不属于本角色职责的文件或资源
|
||||||
|
- ❌ 在输出中省略 `[{{role_name}}]` 标识
|
||||||
|
|
||||||
## Message Types
|
## Message Types
|
||||||
|
|
||||||
@@ -33,6 +51,36 @@ Template for generating per-role execution detail files in `roles/{role-name}.md
|
|||||||
| `{{this.type}}` | {{../role_name}} → coordinator | {{this.trigger}} | {{this.description}} |
|
| `{{this.type}}` | {{../role_name}} → coordinator | {{this.trigger}} | {{this.description}} |
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
|
## Toolbox
|
||||||
|
|
||||||
|
### Available Commands
|
||||||
|
|
||||||
|
| Command | File | Phase | Description |
|
||||||
|
|---------|------|-------|-------------|
|
||||||
|
{{#each commands}}
|
||||||
|
| `{{this.name}}` | [commands/{{this.name}}.md](commands/{{this.name}}.md) | Phase {{this.phase}} | {{this.description}} |
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
{{#if has_no_commands}}
|
||||||
|
> No command files — all phases execute inline.
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
### Subagent Capabilities
|
||||||
|
|
||||||
|
| Agent Type | Used By | Purpose |
|
||||||
|
|------------|---------|---------|
|
||||||
|
{{#each subagents}}
|
||||||
|
| `{{this.type}}` | {{this.used_by}} | {{this.purpose}} |
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
### CLI Capabilities
|
||||||
|
|
||||||
|
| CLI Tool | Mode | Used By | Purpose |
|
||||||
|
|----------|------|---------|---------|
|
||||||
|
{{#each cli_tools}}
|
||||||
|
| `{{this.tool}}` | {{this.mode}} | {{this.used_by}} | {{this.purpose}} |
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
## Execution (5-Phase)
|
## Execution (5-Phase)
|
||||||
|
|
||||||
### Phase 1: Task Discovery
|
### Phase 1: Task Discovery
|
||||||
@@ -54,33 +102,75 @@ TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
|||||||
|
|
||||||
### Phase 2: {{phase2_name}}
|
### Phase 2: {{phase2_name}}
|
||||||
|
|
||||||
|
{{#if phase2_command}}
|
||||||
|
\`\`\`javascript
|
||||||
|
// Delegate to command file
|
||||||
|
try {
|
||||||
|
const commandContent = Read("commands/{{phase2_command}}.md")
|
||||||
|
// Execute strategy defined in command file
|
||||||
|
} catch {
|
||||||
|
// Fallback: inline execution
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
**Command**: [commands/{{phase2_command}}.md](commands/{{phase2_command}}.md)
|
||||||
|
{{else}}
|
||||||
{{phase2_content}}
|
{{phase2_content}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
### Phase 3: {{phase3_name}}
|
### Phase 3: {{phase3_name}}
|
||||||
|
|
||||||
|
{{#if phase3_command}}
|
||||||
|
\`\`\`javascript
|
||||||
|
// Delegate to command file
|
||||||
|
try {
|
||||||
|
const commandContent = Read("commands/{{phase3_command}}.md")
|
||||||
|
// Execute strategy defined in command file
|
||||||
|
} catch {
|
||||||
|
// Fallback: inline execution
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
**Command**: [commands/{{phase3_command}}.md](commands/{{phase3_command}}.md)
|
||||||
|
{{else}}
|
||||||
{{phase3_content}}
|
{{phase3_content}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
### Phase 4: {{phase4_name}}
|
### Phase 4: {{phase4_name}}
|
||||||
|
|
||||||
|
{{#if phase4_command}}
|
||||||
|
\`\`\`javascript
|
||||||
|
// Delegate to command file
|
||||||
|
try {
|
||||||
|
const commandContent = Read("commands/{{phase4_command}}.md")
|
||||||
|
// Execute strategy defined in command file
|
||||||
|
} catch {
|
||||||
|
// Fallback: inline execution
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
**Command**: [commands/{{phase4_command}}.md](commands/{{phase4_command}}.md)
|
||||||
|
{{else}}
|
||||||
{{phase4_content}}
|
{{phase4_content}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
### Phase 5: Report to Coordinator
|
### Phase 5: Report to Coordinator
|
||||||
|
|
||||||
\`\`\`javascript
|
\`\`\`javascript
|
||||||
// Log message before SendMessage
|
// Log message before SendMessage — 所有输出必须带 [{{role_name}}] 标识
|
||||||
mcp__ccw-tools__team_msg({
|
mcp__ccw-tools__team_msg({
|
||||||
operation: "log",
|
operation: "log",
|
||||||
team: teamName,
|
team: teamName,
|
||||||
from: "{{role_name}}",
|
from: "{{role_name}}",
|
||||||
to: "coordinator",
|
to: "coordinator",
|
||||||
type: "{{primary_message_type}}",
|
type: "{{primary_message_type}}",
|
||||||
summary: \`{{task_prefix}} complete: \${task.subject}\`
|
summary: \`[{{role_name}}] {{task_prefix}} complete: \${task.subject}\`
|
||||||
})
|
})
|
||||||
|
|
||||||
SendMessage({
|
SendMessage({
|
||||||
type: "message",
|
type: "message",
|
||||||
recipient: "coordinator",
|
recipient: "coordinator",
|
||||||
content: \`## {{display_name}} Results
|
content: \`## [{{role_name}}] {{display_name}} Results
|
||||||
|
|
||||||
**Task**: \${task.subject}
|
**Task**: \${task.subject}
|
||||||
**Status**: \${resultStatus}
|
**Status**: \${resultStatus}
|
||||||
@@ -90,7 +180,7 @@ SendMessage({
|
|||||||
|
|
||||||
### Details
|
### Details
|
||||||
\${resultDetails}\`,
|
\${resultDetails}\`,
|
||||||
summary: \`{{task_prefix}} complete\`
|
summary: \`[{{role_name}}] {{task_prefix}} complete\`
|
||||||
})
|
})
|
||||||
|
|
||||||
// Mark task completed
|
// Mark task completed
|
||||||
@@ -115,6 +205,9 @@ if (nextTasks.length > 0) {
|
|||||||
|----------|------------|
|
|----------|------------|
|
||||||
| No {{task_prefix}}-* tasks available | Idle, wait for coordinator assignment |
|
| No {{task_prefix}}-* tasks available | Idle, wait for coordinator assignment |
|
||||||
| Context/Plan file not found | Notify coordinator, request location |
|
| Context/Plan file not found | Notify coordinator, request location |
|
||||||
|
{{#if has_commands}}
|
||||||
|
| Command file not found | Fall back to inline execution |
|
||||||
|
{{/if}}
|
||||||
{{#if adaptive_routing}}
|
{{#if adaptive_routing}}
|
||||||
| Sub-agent failure | Retry once, then fallback to direct execution |
|
| Sub-agent failure | Retry once, then fallback to direct execution |
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -270,6 +363,26 @@ Team coordinator. Orchestrates the pipeline: requirement clarification → task
|
|||||||
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
|
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
|
||||||
- **Responsibility**: Orchestration
|
- **Responsibility**: Orchestration
|
||||||
- **Communication**: SendMessage to all teammates
|
- **Communication**: SendMessage to all teammates
|
||||||
|
- **Output Tag**: `[coordinator]`
|
||||||
|
|
||||||
|
## Role Boundaries
|
||||||
|
|
||||||
|
### MUST
|
||||||
|
|
||||||
|
- 所有输出(SendMessage、team_msg、日志)必须带 `[coordinator]` 标识
|
||||||
|
- 仅负责需求澄清、任务创建/分发、进度监控、结果汇报
|
||||||
|
- 通过 TaskCreate 创建任务并分配给 worker 角色
|
||||||
|
- 通过消息总线监控 worker 进度并路由消息
|
||||||
|
|
||||||
|
### MUST NOT
|
||||||
|
|
||||||
|
- ❌ **直接执行任何业务任务**(代码编写、分析、测试、审查等)
|
||||||
|
- ❌ 直接调用 code-developer、cli-explore-agent 等实现类 subagent
|
||||||
|
- ❌ 直接修改源代码或生成产物文件
|
||||||
|
- ❌ 绕过 worker 角色自行完成应委派的工作
|
||||||
|
- ❌ 在输出中省略 `[coordinator]` 标识
|
||||||
|
|
||||||
|
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
|
||||||
|
|
||||||
## Execution
|
## Execution
|
||||||
|
|
||||||
@@ -331,3 +444,11 @@ Summarize results. AskUserQuestion for next requirement or shutdown.
|
|||||||
| `{{message_types}}` | config.message_types | Array of message types |
|
| `{{message_types}}` | config.message_types | Array of message types |
|
||||||
| `{{primary_message_type}}` | config.message_types[0].type | Primary type |
|
| `{{primary_message_type}}` | config.message_types[0].type | Primary type |
|
||||||
| `{{adaptive_routing}}` | config.adaptive_routing | Boolean |
|
| `{{adaptive_routing}}` | config.adaptive_routing | Boolean |
|
||||||
|
| `{{commands}}` | config.commands | Array of command definitions |
|
||||||
|
| `{{has_commands}}` | config.commands.length > 0 | Boolean: has extracted commands |
|
||||||
|
| `{{has_no_commands}}` | config.commands.length === 0 | Boolean: all phases inline |
|
||||||
|
| `{{subagents}}` | config.subagents | Array of subagent capabilities |
|
||||||
|
| `{{cli_tools}}` | config.cli_tools | Array of CLI tool capabilities |
|
||||||
|
| `{{phase2_command}}` | config.phase2_command | Command name for Phase 2 (if extracted) |
|
||||||
|
| `{{phase3_command}}` | config.phase3_command | Command name for Phase 3 (if extracted) |
|
||||||
|
| `{{phase4_command}}` | config.phase4_command | Command name for Phase 4 (if extracted) |
|
||||||
|
|||||||
@@ -40,6 +40,24 @@ Unified team skill. All team members invoke this skill with `--role=xxx` to rout
|
|||||||
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
└──────────┘ └──────────┘ └──────────┘ └──────────┘
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
|
## Command Architecture
|
||||||
|
|
||||||
|
Each role is organized as a folder with a `role.md` orchestrator and optional `commands/` for delegation:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
roles/
|
||||||
|
{{#each roles}}
|
||||||
|
├── {{this.name}}/
|
||||||
|
│ ├── role.md # Orchestrator (Phase 1/5 inline, Phase 2-4 delegate)
|
||||||
|
│ └── commands/ # Optional: extracted command files
|
||||||
|
│ └── *.md # Self-contained command modules
|
||||||
|
{{/each}}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
**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.
|
||||||
|
|
||||||
|
**Command files** are self-contained: each includes Strategy, Execution Steps, and Error Handling. Any subagent can `Read()` a command file and execute it independently.
|
||||||
|
|
||||||
## Role Router
|
## Role Router
|
||||||
|
|
||||||
### Input Parsing
|
### Input Parsing
|
||||||
@@ -65,7 +83,7 @@ const teamName = "{{team_name}}"
|
|||||||
\`\`\`javascript
|
\`\`\`javascript
|
||||||
const VALID_ROLES = {
|
const VALID_ROLES = {
|
||||||
{{#each roles}}
|
{{#each roles}}
|
||||||
"{{this.name}}": { file: "roles/{{this.name}}.md", prefix: "{{this.task_prefix}}" },
|
"{{this.name}}": { file: "roles/{{this.name}}/role.md", prefix: "{{this.task_prefix}}" },
|
||||||
{{/each}}
|
{{/each}}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,11 +101,51 @@ Read(VALID_ROLES[role].file)
|
|||||||
| Role | Task Prefix | Responsibility | Role File |
|
| Role | Task Prefix | Responsibility | Role File |
|
||||||
|------|-------------|----------------|-----------|
|
|------|-------------|----------------|-----------|
|
||||||
{{#each roles}}
|
{{#each roles}}
|
||||||
| `{{this.name}}` | {{this.task_prefix}}-* | {{this.responsibility}} | [roles/{{this.name}}.md](roles/{{this.name}}.md) |
|
| `{{this.name}}` | {{this.task_prefix}}-* | {{this.responsibility}} | [roles/{{this.name}}/role.md](roles/{{this.name}}/role.md) |
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
## Shared Infrastructure
|
## Shared Infrastructure
|
||||||
|
|
||||||
|
### Role Isolation Rules
|
||||||
|
|
||||||
|
**核心原则**: 每个角色仅能执行自己职责范围内的工作。
|
||||||
|
|
||||||
|
#### Output Tagging(强制)
|
||||||
|
|
||||||
|
所有角色的输出必须带 `[role_name]` 标识前缀:
|
||||||
|
|
||||||
|
\`\`\`javascript
|
||||||
|
// SendMessage — content 和 summary 都必须带标识
|
||||||
|
SendMessage({
|
||||||
|
content: \`## [\\${role}] ...\`,
|
||||||
|
summary: \`[\\${role}] ...\`
|
||||||
|
})
|
||||||
|
|
||||||
|
// team_msg — summary 必须带标识
|
||||||
|
mcp__ccw-tools__team_msg({
|
||||||
|
summary: \`[\\${role}] ...\`
|
||||||
|
})
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
#### Coordinator 隔离
|
||||||
|
|
||||||
|
| 允许 | 禁止 |
|
||||||
|
|------|------|
|
||||||
|
| 需求澄清 (AskUserQuestion) | ❌ 直接编写/修改代码 |
|
||||||
|
| 创建任务链 (TaskCreate) | ❌ 调用实现类 subagent (code-developer 等) |
|
||||||
|
| 分发任务给 worker | ❌ 直接执行分析/测试/审查 |
|
||||||
|
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成任务 |
|
||||||
|
| 汇报结果给用户 | ❌ 修改源代码或产物文件 |
|
||||||
|
|
||||||
|
#### Worker 隔离
|
||||||
|
|
||||||
|
| 允许 | 禁止 |
|
||||||
|
|------|------|
|
||||||
|
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
|
||||||
|
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
|
||||||
|
| 使用 Toolbox 中声明的工具 | ❌ 为其他角色创建任务 (TaskCreate) |
|
||||||
|
| 委派给 commands/ 中的命令 | ❌ 修改不属于本职责的资源 |
|
||||||
|
|
||||||
### Team Configuration
|
### Team Configuration
|
||||||
|
|
||||||
\`\`\`javascript
|
\`\`\`javascript
|
||||||
@@ -149,9 +207,9 @@ TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
|||||||
|
|
||||||
// Phase 2-4: Role-specific (see roles/{role}.md)
|
// Phase 2-4: Role-specific (see roles/{role}.md)
|
||||||
|
|
||||||
// Phase 5: Report + Loop
|
// Phase 5: Report + Loop — 所有输出必须带 [role] 标识
|
||||||
mcp__ccw-tools__team_msg({ operation: "log", team: "{{team_name}}", from: role, to: "coordinator", type: "...", summary: "..." })
|
mcp__ccw-tools__team_msg({ operation: "log", team: "{{team_name}}", from: role, to: "coordinator", type: "...", summary: \`[\${role}] ...\` })
|
||||||
SendMessage({ type: "message", recipient: "coordinator", content: "...", summary: "..." })
|
SendMessage({ type: "message", recipient: "coordinator", content: \`## [\${role}] ...\`, summary: \`[\${role}] ...\` })
|
||||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||||
// Check for next task → back to Phase 1
|
// Check for next task → back to Phase 1
|
||||||
\`\`\`
|
\`\`\`
|
||||||
@@ -182,13 +240,19 @@ Task({
|
|||||||
当前需求: \${taskDescription}
|
当前需求: \${taskDescription}
|
||||||
约束: \${constraints}
|
约束: \${constraints}
|
||||||
|
|
||||||
|
## 角色准则(强制)
|
||||||
|
- 你只能处理 {{this.task_prefix}}-* 前缀的任务,不得执行其他角色的工作
|
||||||
|
- 所有输出(SendMessage、team_msg)必须带 [{{this.name}}] 标识前缀
|
||||||
|
- 仅与 coordinator 通信,不得直接联系其他 worker
|
||||||
|
- 不得使用 TaskCreate 为其他角色创建任务
|
||||||
|
|
||||||
## 消息总线(必须)
|
## 消息总线(必须)
|
||||||
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
|
||||||
|
|
||||||
工作流程:
|
工作流程:
|
||||||
1. TaskList → 找到 {{this.task_prefix}}-* 任务
|
1. TaskList → 找到 {{this.task_prefix}}-* 任务
|
||||||
2. Skill(skill="team-{{../team_name}}", args="--role={{this.name}}") 执行
|
2. Skill(skill="team-{{../team_name}}", args="--role={{this.name}}") 执行
|
||||||
3. team_msg log + SendMessage 结果给 coordinator
|
3. team_msg log + SendMessage 结果给 coordinator(带 [{{this.name}}] 标识)
|
||||||
4. TaskUpdate completed → 检查下一个任务\`
|
4. TaskUpdate completed → 检查下一个任务\`
|
||||||
})
|
})
|
||||||
{{/each}}
|
{{/each}}
|
||||||
@@ -200,7 +264,8 @@ Task({
|
|||||||
|----------|------------|
|
|----------|------------|
|
||||||
| Unknown --role value | Error with available role list |
|
| Unknown --role value | Error with available role list |
|
||||||
| Missing --role arg | Error with usage hint |
|
| Missing --role arg | Error with usage hint |
|
||||||
| Role file not found | Error with expected path |
|
| Role file not found | Error with expected path (roles/{name}/role.md) |
|
||||||
|
| Command file not found | Fall back to inline execution in role.md |
|
||||||
| Task prefix conflict | Log warning, proceed |
|
| Task prefix conflict | Log warning, proceed |
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,21 @@ import {
|
|||||||
GripVertical,
|
GripVertical,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { useSessionManagerStore, selectGroups, selectSessionManagerActiveTerminalId } from '@/stores';
|
import { useSessionManagerStore, selectGroups, selectSessionManagerActiveTerminalId, selectTerminalMetas } from '@/stores';
|
||||||
import { useCliSessionStore } from '@/stores/cliSessionStore';
|
import { useCliSessionStore } from '@/stores/cliSessionStore';
|
||||||
|
import { useTerminalGridStore, selectTerminalGridPanes } from '@/stores/terminalGridStore';
|
||||||
import { Badge } from '@/components/ui/Badge';
|
import { Badge } from '@/components/ui/Badge';
|
||||||
|
import type { TerminalStatus } from '@/types/terminal-dashboard';
|
||||||
|
|
||||||
|
// ========== Status Dot Styles ==========
|
||||||
|
|
||||||
|
const statusDotStyles: Record<TerminalStatus, string> = {
|
||||||
|
active: 'bg-green-500',
|
||||||
|
idle: 'bg-gray-400',
|
||||||
|
error: 'bg-red-500',
|
||||||
|
paused: 'bg-yellow-500',
|
||||||
|
resuming: 'bg-blue-400 animate-pulse',
|
||||||
|
};
|
||||||
|
|
||||||
// ========== SessionGroupTree Component ==========
|
// ========== SessionGroupTree Component ==========
|
||||||
|
|
||||||
@@ -32,11 +44,17 @@ export function SessionGroupTree() {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const groups = useSessionManagerStore(selectGroups);
|
const groups = useSessionManagerStore(selectGroups);
|
||||||
const activeTerminalId = useSessionManagerStore(selectSessionManagerActiveTerminalId);
|
const activeTerminalId = useSessionManagerStore(selectSessionManagerActiveTerminalId);
|
||||||
|
const terminalMetas = useSessionManagerStore(selectTerminalMetas);
|
||||||
const createGroup = useSessionManagerStore((s) => s.createGroup);
|
const createGroup = useSessionManagerStore((s) => s.createGroup);
|
||||||
const moveSessionToGroup = useSessionManagerStore((s) => s.moveSessionToGroup);
|
const moveSessionToGroup = useSessionManagerStore((s) => s.moveSessionToGroup);
|
||||||
const setActiveTerminal = useSessionManagerStore((s) => s.setActiveTerminal);
|
const setActiveTerminal = useSessionManagerStore((s) => s.setActiveTerminal);
|
||||||
const sessions = useCliSessionStore((s) => s.sessions);
|
const sessions = useCliSessionStore((s) => s.sessions);
|
||||||
|
|
||||||
|
// Grid store for pane management
|
||||||
|
const panes = useTerminalGridStore(selectTerminalGridPanes);
|
||||||
|
const assignSession = useTerminalGridStore((s) => s.assignSession);
|
||||||
|
const setFocused = useTerminalGridStore((s) => s.setFocused);
|
||||||
|
|
||||||
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
|
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
const toggleGroup = useCallback((groupId: string) => {
|
const toggleGroup = useCallback((groupId: string) => {
|
||||||
@@ -58,9 +76,28 @@ export function SessionGroupTree() {
|
|||||||
|
|
||||||
const handleSessionClick = useCallback(
|
const handleSessionClick = useCallback(
|
||||||
(sessionId: string) => {
|
(sessionId: string) => {
|
||||||
|
// Set active terminal in session manager
|
||||||
setActiveTerminal(sessionId);
|
setActiveTerminal(sessionId);
|
||||||
|
|
||||||
|
// Find pane that already has this session, or switch focused pane
|
||||||
|
const paneWithSession = Object.entries(panes).find(
|
||||||
|
([, pane]) => pane.sessionId === sessionId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (paneWithSession) {
|
||||||
|
// Focus the pane that has this session
|
||||||
|
setFocused(paneWithSession[0]);
|
||||||
|
} else {
|
||||||
|
// Find focused pane or first pane, and assign session to it
|
||||||
|
const focusedPaneId = useTerminalGridStore.getState().focusedPaneId;
|
||||||
|
const targetPaneId = focusedPaneId || Object.keys(panes)[0];
|
||||||
|
if (targetPaneId) {
|
||||||
|
assignSession(targetPaneId, sessionId);
|
||||||
|
setFocused(targetPaneId);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[setActiveTerminal]
|
[setActiveTerminal, panes, setFocused, assignSession]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
@@ -168,38 +205,47 @@ export function SessionGroupTree() {
|
|||||||
{formatMessage({ id: 'terminalDashboard.sessionTree.emptyGroup' })}
|
{formatMessage({ id: 'terminalDashboard.sessionTree.emptyGroup' })}
|
||||||
</p>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
group.sessionIds.map((sessionId, index) => (
|
group.sessionIds.map((sessionId, index) => {
|
||||||
<Draggable
|
const meta = terminalMetas[sessionId];
|
||||||
key={sessionId}
|
const sessionStatus: TerminalStatus = meta?.status ?? 'idle';
|
||||||
draggableId={sessionId}
|
return (
|
||||||
index={index}
|
<Draggable
|
||||||
>
|
key={sessionId}
|
||||||
{(dragProvided, dragSnapshot) => (
|
draggableId={sessionId}
|
||||||
<div
|
index={index}
|
||||||
ref={dragProvided.innerRef}
|
>
|
||||||
{...dragProvided.draggableProps}
|
{(dragProvided, dragSnapshot) => (
|
||||||
className={cn(
|
<div
|
||||||
'flex items-center gap-1.5 mx-1 px-2 py-1.5 rounded-sm cursor-pointer',
|
ref={dragProvided.innerRef}
|
||||||
'hover:bg-muted/50 transition-colors text-sm',
|
{...dragProvided.draggableProps}
|
||||||
activeTerminalId === sessionId && 'bg-primary/10 text-primary',
|
className={cn(
|
||||||
dragSnapshot.isDragging && 'bg-muted shadow-md'
|
'flex items-center gap-1.5 mx-1 px-2 py-1.5 rounded-sm cursor-pointer',
|
||||||
)}
|
'hover:bg-muted/50 transition-colors text-sm',
|
||||||
onClick={() => handleSessionClick(sessionId)}
|
activeTerminalId === sessionId && 'bg-primary/10 text-primary',
|
||||||
>
|
dragSnapshot.isDragging && 'bg-muted shadow-md'
|
||||||
<span
|
)}
|
||||||
{...dragProvided.dragHandleProps}
|
onClick={() => handleSessionClick(sessionId)}
|
||||||
className="text-muted-foreground/50 hover:text-muted-foreground shrink-0"
|
|
||||||
>
|
>
|
||||||
<GripVertical className="w-3 h-3" />
|
<span
|
||||||
</span>
|
{...dragProvided.dragHandleProps}
|
||||||
<Terminal className="w-3.5 h-3.5 text-muted-foreground shrink-0" />
|
className="text-muted-foreground/50 hover:text-muted-foreground shrink-0"
|
||||||
<span className="flex-1 truncate text-xs">
|
>
|
||||||
{sessionNames[sessionId] ?? sessionId}
|
<GripVertical className="w-3 h-3" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
{/* Status indicator dot */}
|
||||||
)}
|
<span
|
||||||
</Draggable>
|
className={cn('w-2 h-2 rounded-full shrink-0', statusDotStyles[sessionStatus])}
|
||||||
))
|
title={sessionStatus}
|
||||||
|
/>
|
||||||
|
<Terminal className="w-3.5 h-3.5 text-muted-foreground shrink-0" />
|
||||||
|
<span className="flex-1 truncate text-xs">
|
||||||
|
{sessionNames[sessionId] ?? sessionId}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// Single terminal pane = PaneToolbar + TerminalInstance.
|
// Single terminal pane = PaneToolbar + TerminalInstance.
|
||||||
// Renders within the TerminalGrid recursive layout.
|
// Renders within the TerminalGrid recursive layout.
|
||||||
|
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import {
|
import {
|
||||||
SplitSquareHorizontal,
|
SplitSquareHorizontal,
|
||||||
@@ -14,6 +14,10 @@ import {
|
|||||||
X,
|
X,
|
||||||
Terminal,
|
Terminal,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
|
RotateCcw,
|
||||||
|
Pause,
|
||||||
|
Play,
|
||||||
|
Loader2,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { TerminalInstance } from './TerminalInstance';
|
import { TerminalInstance } from './TerminalInstance';
|
||||||
@@ -76,6 +80,15 @@ export function TerminalPane({ paneId }: TerminalPaneProps) {
|
|||||||
const terminalMetas = useSessionManagerStore(selectTerminalMetas);
|
const terminalMetas = useSessionManagerStore(selectTerminalMetas);
|
||||||
const sessions = useCliSessionStore((s) => s.sessions);
|
const sessions = useCliSessionStore((s) => s.sessions);
|
||||||
|
|
||||||
|
// Session lifecycle actions
|
||||||
|
const pauseSession = useSessionManagerStore((s) => s.pauseSession);
|
||||||
|
const resumeSession = useSessionManagerStore((s) => s.resumeSession);
|
||||||
|
const restartSession = useSessionManagerStore((s) => s.restartSession);
|
||||||
|
|
||||||
|
// Action loading states
|
||||||
|
const [isRestarting, setIsRestarting] = useState(false);
|
||||||
|
const [isTogglingPause, setIsTogglingPause] = useState(false);
|
||||||
|
|
||||||
// Association chain for linked issue badge
|
// Association chain for linked issue badge
|
||||||
const associationChain = useIssueQueueIntegrationStore(selectAssociationChain);
|
const associationChain = useIssueQueueIntegrationStore(selectAssociationChain);
|
||||||
const linkedIssueId = useMemo(() => {
|
const linkedIssueId = useMemo(() => {
|
||||||
@@ -133,6 +146,34 @@ export function TerminalPane({ paneId }: TerminalPaneProps) {
|
|||||||
}
|
}
|
||||||
}, [paneId, sessionId, assignSession]);
|
}, [paneId, sessionId, assignSession]);
|
||||||
|
|
||||||
|
const handleRestart = useCallback(async () => {
|
||||||
|
if (!sessionId || isRestarting) return;
|
||||||
|
setIsRestarting(true);
|
||||||
|
try {
|
||||||
|
await restartSession(sessionId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[TerminalPane] Restart failed:', error);
|
||||||
|
} finally {
|
||||||
|
setIsRestarting(false);
|
||||||
|
}
|
||||||
|
}, [sessionId, isRestarting, restartSession]);
|
||||||
|
|
||||||
|
const handleTogglePause = useCallback(async () => {
|
||||||
|
if (!sessionId || isTogglingPause) return;
|
||||||
|
setIsTogglingPause(true);
|
||||||
|
try {
|
||||||
|
if (status === 'paused') {
|
||||||
|
await resumeSession(sessionId);
|
||||||
|
} else if (status === 'active' || status === 'idle') {
|
||||||
|
await pauseSession(sessionId);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[TerminalPane] Toggle pause failed:', error);
|
||||||
|
} finally {
|
||||||
|
setIsTogglingPause(false);
|
||||||
|
}
|
||||||
|
}, [sessionId, isTogglingPause, status, pauseSession, resumeSession]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -197,13 +238,58 @@ export function TerminalPane({ paneId }: TerminalPaneProps) {
|
|||||||
<SplitSquareVertical className="w-3.5 h-3.5" />
|
<SplitSquareVertical className="w-3.5 h-3.5" />
|
||||||
</button>
|
</button>
|
||||||
{sessionId && (
|
{sessionId && (
|
||||||
<button
|
<>
|
||||||
onClick={handleClear}
|
{/* Restart button */}
|
||||||
className="p-1 rounded hover:bg-muted transition-colors text-muted-foreground hover:text-foreground"
|
<button
|
||||||
title={formatMessage({ id: 'terminalDashboard.pane.clearTerminal' })}
|
onClick={handleRestart}
|
||||||
>
|
disabled={isRestarting}
|
||||||
<Eraser className="w-3.5 h-3.5" />
|
className={cn(
|
||||||
</button>
|
'p-1 rounded hover:bg-muted transition-colors',
|
||||||
|
isRestarting ? 'text-muted-foreground/50' : 'text-muted-foreground hover:text-foreground'
|
||||||
|
)}
|
||||||
|
title={formatMessage({ id: 'terminalDashboard.pane.restart' })}
|
||||||
|
>
|
||||||
|
{isRestarting ? (
|
||||||
|
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<RotateCcw className="w-3.5 h-3.5" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
{/* Pause/Resume toggle button */}
|
||||||
|
<button
|
||||||
|
onClick={handleTogglePause}
|
||||||
|
disabled={isTogglingPause || status === 'resuming'}
|
||||||
|
className={cn(
|
||||||
|
'p-1 rounded hover:bg-muted transition-colors',
|
||||||
|
isTogglingPause || status === 'resuming'
|
||||||
|
? 'text-muted-foreground/50'
|
||||||
|
: status === 'paused'
|
||||||
|
? 'text-yellow-500 hover:text-yellow-600'
|
||||||
|
: 'text-muted-foreground hover:text-foreground'
|
||||||
|
)}
|
||||||
|
title={formatMessage({
|
||||||
|
id: status === 'paused'
|
||||||
|
? 'terminalDashboard.pane.resume'
|
||||||
|
: 'terminalDashboard.pane.pause',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{isTogglingPause || status === 'resuming' ? (
|
||||||
|
<Loader2 className="w-3.5 h-3.5 animate-spin" />
|
||||||
|
) : status === 'paused' ? (
|
||||||
|
<Play className="w-3.5 h-3.5" />
|
||||||
|
) : (
|
||||||
|
<Pause className="w-3.5 h-3.5" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
{/* Clear terminal button */}
|
||||||
|
<button
|
||||||
|
onClick={handleClear}
|
||||||
|
className="p-1 rounded hover:bg-muted transition-colors text-muted-foreground hover:text-foreground"
|
||||||
|
title={formatMessage({ id: 'terminalDashboard.pane.clearTerminal' })}
|
||||||
|
>
|
||||||
|
<Eraser className="w-3.5 h-3.5" />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{alertCount > 0 && (
|
{alertCount > 0 && (
|
||||||
<span className="flex items-center gap-0.5 px-1 text-destructive">
|
<span className="flex items-center gap-0.5 px-1 text-destructive">
|
||||||
|
|||||||
@@ -88,7 +88,10 @@
|
|||||||
"splitVertical": "Split Down",
|
"splitVertical": "Split Down",
|
||||||
"clearTerminal": "Clear Terminal",
|
"clearTerminal": "Clear Terminal",
|
||||||
"closePane": "Close Pane",
|
"closePane": "Close Pane",
|
||||||
"linkedIssue": "Linked Issue"
|
"linkedIssue": "Linked Issue",
|
||||||
|
"restart": "Restart Session",
|
||||||
|
"pause": "Pause Session",
|
||||||
|
"resume": "Resume Session"
|
||||||
},
|
},
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
"noTabs": "No terminal sessions"
|
"noTabs": "No terminal sessions"
|
||||||
|
|||||||
@@ -88,7 +88,10 @@
|
|||||||
"splitVertical": "向下分割",
|
"splitVertical": "向下分割",
|
||||||
"clearTerminal": "清屏",
|
"clearTerminal": "清屏",
|
||||||
"closePane": "关闭窗格",
|
"closePane": "关闭窗格",
|
||||||
"linkedIssue": "关联问题"
|
"linkedIssue": "关联问题",
|
||||||
|
"restart": "重启会话",
|
||||||
|
"pause": "暂停会话",
|
||||||
|
"resume": "恢复会话"
|
||||||
},
|
},
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
"noTabs": "暂无终端会话"
|
"noTabs": "暂无终端会话"
|
||||||
|
|||||||
Reference in New Issue
Block a user