diff --git a/.claude/skills/team-skill-designer/SKILL.md b/.claude/skills/team-skill-designer/SKILL.md index 041346d1..2b871214 100644 --- a/.claude/skills/team-skill-designer/SKILL.md +++ b/.claude/skills/team-skill-designer/SKILL.md @@ -46,11 +46,21 @@ Meta-skill for creating unified team skills where all team members invoke ONE sk .claude/skills/team-{name}/ ├── SKILL.md → Skill(skill="team-{name}", args="--role=xxx") ├── roles/ -│ ├── coordinator.md -│ ├── planner.md -│ ├── executor.md -│ ├── tester.md -│ └── reviewer.md +│ ├── coordinator/ +│ │ ├── role.md # Orchestrator +│ │ └── commands/ # Modular command files +│ ├── planner/ +│ │ ├── role.md +│ │ └── commands/ +│ ├── executor/ +│ │ ├── role.md +│ │ └── commands/ +│ ├── tester/ +│ │ ├── role.md +│ │ └── commands/ +│ └── reviewer/ +│ ├── role.md +│ └── commands/ └── specs/ └── team-config.json ``` @@ -70,15 +80,25 @@ Task({ ├── SKILL.md # Role router + shared infrastructure │ ├─ Frontmatter │ ├─ 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) │ ├─ Coordinator Spawn Template │ └─ Error Handling -├── roles/ # Role-specific execution detail -│ ├── coordinator.md # Orchestration logic -│ ├── {role-1}.md # First worker role -│ ├── {role-2}.md # Second worker role -│ └── ... +├── roles/ # Role-specific execution detail (folder-based) +│ ├── coordinator/ +│ │ ├── role.md # Orchestrator (Phase 1/5 inline, Phase 2-4 delegate) +│ │ └── 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 └── team-config.json ``` @@ -91,7 +111,7 @@ SKILL.md parses `$ARGUMENTS` to extract `--role`: ``` Input: Skill(skill="team-{name}", args="--role=planner") ↓ Parse --role=planner - ↓ Read roles/planner.md + ↓ Read roles/planner/role.md ↓ Execute planner-specific 5-phase logic ``` @@ -107,11 +127,13 @@ SKILL.md defines ONCE, all roles inherit: ### Pattern 3: Role Files = Full Execution Detail -Each `roles/{role}.md` contains: -- Role-specific 5-phase implementation +Each `roles/{role}/role.md` contains: +- 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 task prefix - 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 @@ -124,9 +146,9 @@ Phase 1 collects ALL roles at once (not one at a time): 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/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 | |----------|---------| -| [templates/skill-router-template.md](templates/skill-router-template.md) | Generated SKILL.md template with role router | -| [templates/role-template.md](templates/role-template.md) | Generated role file template | +| [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 with Toolbox + command delegation | +| [templates/role-command-template.md](templates/role-command-template.md) | Command file template with 7 pre-built patterns | ### Existing Reference @@ -188,8 +211,9 @@ Phase 2: Pattern Analysis Phase 3: Skill Package Generation -> Ref: phases/03-skill-generation.md - - Generate SKILL.md (role router + shared infrastructure) - - Generate roles/*.md (per-role execution detail) + - Generate SKILL.md (role router + command architecture + shared infrastructure) + - Generate roles/{name}/role.md (per-role orchestrator with Toolbox) + - Generate roles/{name}/commands/*.md (modular command files) - Generate specs/team-config.json - Output: .claude/skills/team-{name}/ complete package @@ -238,8 +262,15 @@ Bash(`mkdir -p "${workDir}"`); └── preview/ # Phase 3 output (preview before delivery) ├── SKILL.md ├── roles/ - │ ├── coordinator.md - │ └── {role-N}.md + │ ├── coordinator/ + │ │ ├── role.md + │ │ └── commands/ + │ │ ├── dispatch.md + │ │ └── monitor.md + │ └── {role-N}/ + │ ├── role.md + │ └── commands/ + │ └── *.md └── specs/ └── team-config.json @@ -247,8 +278,12 @@ Final delivery: .claude/skills/team-{name}/ ├── SKILL.md ├── roles/ -│ ├── coordinator.md -│ └── ... +│ ├── coordinator/ +│ │ ├── role.md +│ │ └── commands/ +│ └── {role-N}/ +│ ├── role.md +│ └── commands/ └── specs/ └── team-config.json ``` @@ -281,5 +316,7 @@ Final delivery: |-------|----------| | Generated SKILL.md missing router | Check templates/skill-router-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 | | Quality score below threshold | Review specs/quality-standards.md | diff --git a/.claude/skills/team-skill-designer/phases/01-requirements-collection.md b/.claude/skills/team-skill-designer/phases/01-requirements-collection.md index 8365b783..3d7482c7 100644 --- a/.claude/skills/team-skill-designer/phases/01-requirements-collection.md +++ b/.claude/skills/team-skill-designer/phases/01-requirements-collection.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 - 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 -- Define pipeline (task chain order) +- Build pipeline from inferred roles - Generate team-config.json ## Input @@ -17,7 +17,7 @@ Collect team definition and ALL role definitions in one pass. ## Execution Steps -### Step 1: Team Basic Information +### Step 1: Team Name + Task Description ```javascript const teamInfo = await AskUserQuestion({ @@ -28,29 +28,30 @@ const teamInfo = await AskUserQuestion({ multiSelect: false, options: [ { label: "自定义", description: "输入自定义团队名称" }, - { label: "dev", description: "开发团队(plan/execute/test/review)" }, - { label: "spec", description: "规格文档团队(analyst/writer/reviewer/discuss)" }, + { label: "dev", description: "通用开发团队" }, + { label: "spec", description: "规格文档团队" }, { label: "security", description: "安全审计团队" } ] }, { - question: "团队使用什么 pipeline 模型?", - header: "Pipeline", + question: "这个团队的核心任务是什么?(描述目标场景,系统将自动推断所需角色)", + header: "Task Desc", multiSelect: false, options: [ - { label: "Standard (Recommended)", description: "PLAN → IMPL → TEST + REVIEW(标准开发流水线)" }, - { label: "Document Chain", description: "RESEARCH → DRAFT → DISCUSS → REVIEW(文档工作流)" }, - { label: "Custom", description: "自定义 pipeline" } + { label: "自定义", description: "输入具体任务描述,如:实现新功能并确保质量" }, + { label: "全栈开发", description: "需求分析 → 规划 → 编码 → 测试 → 审查" }, + { label: "代码审查与重构", description: "代码分析 → 问题发现 → 重构实施 → 验证" }, + { label: "文档编写", description: "调研 → 讨论 → 撰写 → 审校" } ] } ] }) ``` -### Step 2: Role Definitions (Batch) +### Step 2: Role Inference (Task-Driven) ```javascript -// Always include coordinator +// Coordinator 始终存在 const roles = [{ name: "coordinator", responsibility_type: "Orchestration", @@ -58,50 +59,124 @@ const roles = [{ 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")) { - // Pre-fill standard development roles - roles.push( - { 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" }, - { name: "reviewer", responsibility_type: "Read-only analysis", task_prefix: "REVIEW", description: "Multi-dimensional code review" } - ) -} else if (pipelineType.includes("Document")) { - roles.push( - { name: "analyst", responsibility_type: "Orchestration", task_prefix: "RESEARCH", description: "Seed analysis, codebase exploration, context collection" }, - { name: "writer", responsibility_type: "Code generation", task_prefix: "DRAFT", description: "Document drafting following templates" }, - { 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" } - ) -} else { - // Custom: ask user for each role +const ROLE_SIGNALS = { + planner: { + signals: /规划|计划|设计|架构|plan|design|architect|分析需求|探索|explore/i, + role: { name: "planner", responsibility_type: "Orchestration", task_prefix: "PLAN", description: "Code exploration and implementation planning" } + }, + executor: { + 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" } + }, + tester: { + signals: /测试|验证|质量|test|verify|validate|QA|回归|regression|修复|fix|bug/i, + role: { name: "tester", responsibility_type: "Validation", task_prefix: "TEST", description: "Test execution and fix cycles" } + }, + reviewer: { + signals: /审查|审核|review|audit|检查|inspect|代码质量|code quality/i, + role: { name: "reviewer", responsibility_type: "Read-only analysis", task_prefix: "REVIEW", description: "Multi-dimensional code review" } + }, + 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 -// 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: [ { - question: "是否需要自定义角色?(默认角色已根据 pipeline 预填充)", - header: "Customize", + question: `根据任务描述,推断出以下角色:\n${rolesSummary}\n\n是否需要调整?`, + header: "Confirm", multiSelect: false, options: [ - { label: "使用默认 (Recommended)", description: "直接使用预填充的角色定义" }, - { label: "添加角色", description: "在默认基础上添加新角色" }, - { label: "修改角色", description: "修改默认角色定义" }, - { label: "从零开始", description: "清空默认,逐个定义角色" } + { label: "确认使用 (Recommended)", description: "使用推断的角色组合" }, + { label: "添加角色", description: "在推断结果基础上添加角色" }, + { label: "移除角色", description: "移除某些不需要的角色" }, + { label: "重新描述", description: "重新输入任务描述,重新推断" } ] } ] }) -if (customization["Customize"].includes("添加角色")) { +if (confirmation["Confirm"].includes("添加角色")) { const newRole = await AskUserQuestion({ questions: [ { @@ -196,39 +271,118 @@ roles[0].message_types = [ ] ``` -### Step 5: Pipeline Definition +### Step 4b: Toolbox Inference (Per Role) ```javascript -// Build pipeline from roles and their task chain positions -function buildPipeline(roles, pipelineType) { - if (pipelineType.includes("Standard")) { - return { - stages: [ - { name: "PLAN", role: "planner", blockedBy: [] }, - { name: "IMPL", role: "executor", blockedBy: ["PLAN"] }, - { name: "TEST", role: "tester", blockedBy: ["IMPL"] }, - { name: "REVIEW", role: "reviewer", blockedBy: ["IMPL"] } - ], - diagram: "需求 → [PLAN: planner] → coordinator 审批 → [IMPL: executor] → [TEST + REVIEW: tester/reviewer] → 汇报" - } +// Infer commands, subagents, and CLI tools based on responsibility type +const toolboxMap = { + "Read-only analysis": { + commands: ["review", "analyze"], + subagents: [], + cli_tools: [ + { tool: "gemini", mode: "analysis", purpose: "Multi-perspective code analysis" }, + { tool: "codex", mode: "review", purpose: "Git-aware code review" } + ], + phase_commands: { phase2: null, phase3: "analyze", phase4: null } + }, + "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 diff --git a/.claude/skills/team-skill-designer/phases/02-pattern-analysis.md b/.claude/skills/team-skill-designer/phases/02-pattern-analysis.md index 34268743..072c896a 100644 --- a/.claude/skills/team-skill-designer/phases/02-pattern-analysis.md +++ b/.claude/skills/team-skill-designer/phases/02-pattern-analysis.md @@ -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 ```javascript @@ -191,6 +218,15 @@ const analysis = { role_router: "Parse --role from $ARGUMENTS → dispatch to roles/{role}.md", shared_infrastructure: "Message bus + task lifecycle defined once in SKILL.md", 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 + })) } } diff --git a/.claude/skills/team-skill-designer/phases/03-skill-generation.md b/.claude/skills/team-skill-designer/phases/03-skill-generation.md index 25ede7a6..0381c58c 100644 --- a/.claude/skills/team-skill-designer/phases/03-skill-generation.md +++ b/.claude/skills/team-skill-designer/phases/03-skill-generation.md @@ -1,19 +1,19 @@ # 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 - Generate SKILL.md with role router and shared infrastructure -- Generate roles/coordinator.md -- Generate roles/{worker-role}.md for each worker role +- Generate roles/coordinator/role.md + commands/ +- Generate roles/{worker-role}/role.md + commands/ for each worker role - Generate specs/team-config.json - All files written to preview directory first ## Input - 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) ## 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 routerTemplate = Read(`${skillDir}/templates/skill-router-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` -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) @@ -37,11 +39,11 @@ This is the unified entry point. All roles invoke this skill with `--role=xxx`. ```javascript 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') 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') const messageBusTable = config.worker_roles.map(r => @@ -328,10 +330,20 @@ AskUserQuestion({ | 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. @@ -620,7 +632,126 @@ ${role.adaptive_routing ? '| Sub-agent failure | Retry once, fallback to direct | 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/` - **Files**: - - `preview/SKILL.md` - Role router + shared infrastructure - - `preview/roles/coordinator.md` - Coordinator execution - - `preview/roles/{role}.md` - Per-worker role execution + - `preview/SKILL.md` - Role router + shared infrastructure + command architecture + - `preview/roles/coordinator/role.md` - Coordinator orchestrator + - `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 ## 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 coordinator spawn template -- [ ] Every role has a file in roles/ -- [ ] Every role file has 5-phase execution -- [ ] Every role file has message types table -- [ ] Every role file has error handling +- [ ] Every role has a folder in roles/ with role.md +- [ ] Every role.md has 5-phase execution (Phase 1/5 inline, Phase 2-4 delegate or inline) +- [ ] Every role.md has Toolbox section (commands, subagents, cli_tools) +- [ ] 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 ## Next Phase diff --git a/.claude/skills/team-skill-designer/phases/04-integration-verification.md b/.claude/skills/team-skill-designer/phases/04-integration-verification.md index a96bc7c7..7314956c 100644 --- a/.claude/skills/team-skill-designer/phases/04-integration-verification.md +++ b/.claude/skills/team-skill-designer/phases/04-integration-verification.md @@ -27,7 +27,7 @@ const skillMd = Read(`${previewDir}/SKILL.md`) const roleFiles = {} for (const role of config.roles) { try { - roleFiles[role.name] = Read(`${previewDir}/roles/${role.name}.md`) + roleFiles[role.name] = Read(`${previewDir}/roles/${role.name}/role.md`) } catch { roleFiles[role.name] = null } @@ -40,7 +40,7 @@ for (const role of config.roles) { const routerChecks = config.roles.map(role => { const hasRouterEntry = skillMd.includes(`"${role.name}"`) const hasRoleFile = roleFiles[role.name] !== null - const hasRoleLink = skillMd.includes(`roles/${role.name}.md`) + const hasRoleLink = skillMd.includes(`roles/${role.name}/role.md`) return { 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 ```javascript @@ -134,7 +170,8 @@ const overallStatus = [ ...routerChecks.map(c => c.status), prefixCheck.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' const report = { @@ -145,7 +182,8 @@ const report = { prefix_uniqueness: prefixCheck, message_types: msgChecks, spawn_template: spawnChecks, - pattern_compliance: patternChecks + pattern_compliance: patternChecks, + command_files: commandChecks }, overall: overallStatus, file_count: { diff --git a/.claude/skills/team-skill-designer/phases/05-validation.md b/.claude/skills/team-skill-designer/phases/05-validation.md index 9ea83a5d..b1fdac65 100644 --- a/.claude/skills/team-skill-designer/phases/05-validation.md +++ b/.claude/skills/team-skill-designer/phases/05-validation.md @@ -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 ```javascript @@ -101,7 +141,8 @@ const scores = { skill_md: skillScore, roles_avg: Object.values(roleResults).reduce((sum, r) => sum + r.score, 0) / Object.keys(roleResults).length, 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() { diff --git a/.claude/skills/team-skill-designer/specs/quality-standards.md b/.claude/skills/team-skill-designer/specs/quality-standards.md index e75a188f..968fd153 100644 --- a/.claude/skills/team-skill-designer/specs/quality-standards.md +++ b/.claude/skills/team-skill-designer/specs/quality-standards.md @@ -23,21 +23,21 @@ Quality assessment criteria for generated team command .md files. | 40% | Missing critical sections | | 0% | Skeleton only | -**Required Sections Checklist:** -- [ ] YAML front matter with `group: team` -- [ ] Overview with core capabilities -- [ ] Role Definition (name, responsibility, communication) +**Required Sections Checklist (role.md files):** +- [ ] Role Identity (name, responsibility, communication) - [ ] Message Bus section with team_msg examples - [ ] Message Types table -- [ ] Execution Process overview diagram +- [ ] Toolbox section (Available Commands, Subagent Capabilities, CLI Capabilities) - [ ] Phase 1: Task Discovery implementation -- [ ] Phase 2: Context Loading implementation -- [ ] Phase 3: Core Work implementation -- [ ] Phase 4: Validation/Summary implementation +- [ ] Phase 2: Context Loading / delegation to commands +- [ ] Phase 3: Core Work / delegation to commands +- [ ] Phase 4: Validation/Summary / delegation to commands - [ ] Phase 5: Report + Loop implementation - [ ] Error Handling table - [ ] 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%) | Score | Criteria | @@ -124,3 +124,48 @@ Quality assessment criteria for generated team command .md files. - Additional message type examples - Session file structure documentation - 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 diff --git a/.claude/skills/team-skill-designer/specs/team-design-patterns.md b/.claude/skills/team-skill-designer/specs/team-design-patterns.md index e51d4785..4c5dddf6 100644 --- a/.claude/skills/team-skill-designer/specs/team-design-patterns.md +++ b/.claude/skills/team-skill-designer/specs/team-design-patterns.md @@ -470,3 +470,101 @@ When designing a new team command, verify: - [ ] Timeout/fallback behavior specified - [ ] Pattern-specific message types registered - [ ] 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 diff --git a/.claude/skills/team-skill-designer/templates/role-command-template.md b/.claude/skills/team-skill-designer/templates/role-command-template.md new file mode 100644 index 00000000..4af22f4c --- /dev/null +++ b/.claude/skills/team-skill-designer/templates/role-command-template.md @@ -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 diff --git a/.claude/skills/team-skill-designer/templates/role-template.md b/.claude/skills/team-skill-designer/templates/role-template.md index 0ada69b3..3bfaf9dd 100644 --- a/.claude/skills/team-skill-designer/templates/role-template.md +++ b/.claude/skills/team-skill-designer/templates/role-template.md @@ -1,6 +1,6 @@ # 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 @@ -24,6 +24,24 @@ Template for generating per-role execution detail files in `roles/{role-name}.md - **Task Prefix**: `{{task_prefix}}-*` - **Responsibility**: {{responsibility_type}} - **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 @@ -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}} | {{/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) ### Phase 1: Task Discovery @@ -54,33 +102,75 @@ TaskUpdate({ taskId: task.id, status: 'in_progress' }) ### 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}} +{{/if}} ### 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}} +{{/if}} ### 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}} +{{/if}} ### Phase 5: Report to Coordinator \`\`\`javascript -// Log message before SendMessage +// Log message before SendMessage — 所有输出必须带 [{{role_name}}] 标识 mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "{{role_name}}", to: "coordinator", type: "{{primary_message_type}}", - summary: \`{{task_prefix}} complete: \${task.subject}\` + summary: \`[{{role_name}}] {{task_prefix}} complete: \${task.subject}\` }) SendMessage({ type: "message", recipient: "coordinator", - content: \`## {{display_name}} Results + content: \`## [{{role_name}}] {{display_name}} Results **Task**: \${task.subject} **Status**: \${resultStatus} @@ -90,7 +180,7 @@ SendMessage({ ### Details \${resultDetails}\`, - summary: \`{{task_prefix}} complete\` + summary: \`[{{role_name}}] {{task_prefix}} complete\` }) // Mark task completed @@ -115,6 +205,9 @@ if (nextTasks.length > 0) { |----------|------------| | No {{task_prefix}}-* tasks available | Idle, wait for coordinator assignment | | 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}} | Sub-agent failure | Retry once, then fallback to direct execution | {{/if}} @@ -270,6 +363,26 @@ Team coordinator. Orchestrates the pipeline: requirement clarification → task - **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them) - **Responsibility**: Orchestration - **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 @@ -331,3 +444,11 @@ Summarize results. AskUserQuestion for next requirement or shutdown. | `{{message_types}}` | config.message_types | Array of message types | | `{{primary_message_type}}` | config.message_types[0].type | Primary type | | `{{adaptive_routing}}` | config.adaptive_routing | Boolean | +| `{{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) | diff --git a/.claude/skills/team-skill-designer/templates/skill-router-template.md b/.claude/skills/team-skill-designer/templates/skill-router-template.md index 5518a6cc..334eeaf2 100644 --- a/.claude/skills/team-skill-designer/templates/skill-router-template.md +++ b/.claude/skills/team-skill-designer/templates/skill-router-template.md @@ -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 ### Input Parsing @@ -65,7 +83,7 @@ const teamName = "{{team_name}}" \`\`\`javascript const VALID_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}} } @@ -83,11 +101,51 @@ Read(VALID_ROLES[role].file) | Role | Task Prefix | Responsibility | Role File | |------|-------------|----------------|-----------| {{#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}} ## 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 \`\`\`javascript @@ -149,9 +207,9 @@ TaskUpdate({ taskId: task.id, status: 'in_progress' }) // Phase 2-4: Role-specific (see roles/{role}.md) -// Phase 5: Report + Loop -mcp__ccw-tools__team_msg({ operation: "log", team: "{{team_name}}", from: role, to: "coordinator", type: "...", summary: "..." }) -SendMessage({ type: "message", recipient: "coordinator", content: "...", summary: "..." }) +// Phase 5: Report + Loop — 所有输出必须带 [role] 标识 +mcp__ccw-tools__team_msg({ operation: "log", team: "{{team_name}}", from: role, to: "coordinator", type: "...", summary: \`[\${role}] ...\` }) +SendMessage({ type: "message", recipient: "coordinator", content: \`## [\${role}] ...\`, summary: \`[\${role}] ...\` }) TaskUpdate({ taskId: task.id, status: 'completed' }) // Check for next task → back to Phase 1 \`\`\` @@ -182,13 +240,19 @@ Task({ 当前需求: \${taskDescription} 约束: \${constraints} +## 角色准则(强制) +- 你只能处理 {{this.task_prefix}}-* 前缀的任务,不得执行其他角色的工作 +- 所有输出(SendMessage、team_msg)必须带 [{{this.name}}] 标识前缀 +- 仅与 coordinator 通信,不得直接联系其他 worker +- 不得使用 TaskCreate 为其他角色创建任务 + ## 消息总线(必须) 每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。 工作流程: 1. TaskList → 找到 {{this.task_prefix}}-* 任务 2. Skill(skill="team-{{../team_name}}", args="--role={{this.name}}") 执行 -3. team_msg log + SendMessage 结果给 coordinator +3. team_msg log + SendMessage 结果给 coordinator(带 [{{this.name}}] 标识) 4. TaskUpdate completed → 检查下一个任务\` }) {{/each}} @@ -200,7 +264,8 @@ Task({ |----------|------------| | Unknown --role value | Error with available role list | | 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 | ``` diff --git a/ccw/frontend/src/components/terminal-dashboard/SessionGroupTree.tsx b/ccw/frontend/src/components/terminal-dashboard/SessionGroupTree.tsx index dd189d41..adf23f39 100644 --- a/ccw/frontend/src/components/terminal-dashboard/SessionGroupTree.tsx +++ b/ccw/frontend/src/components/terminal-dashboard/SessionGroupTree.tsx @@ -22,9 +22,21 @@ import { GripVertical, } from 'lucide-react'; import { cn } from '@/lib/utils'; -import { useSessionManagerStore, selectGroups, selectSessionManagerActiveTerminalId } from '@/stores'; +import { useSessionManagerStore, selectGroups, selectSessionManagerActiveTerminalId, selectTerminalMetas } from '@/stores'; import { useCliSessionStore } from '@/stores/cliSessionStore'; +import { useTerminalGridStore, selectTerminalGridPanes } from '@/stores/terminalGridStore'; import { Badge } from '@/components/ui/Badge'; +import type { TerminalStatus } from '@/types/terminal-dashboard'; + +// ========== Status Dot Styles ========== + +const statusDotStyles: Record = { + active: 'bg-green-500', + idle: 'bg-gray-400', + error: 'bg-red-500', + paused: 'bg-yellow-500', + resuming: 'bg-blue-400 animate-pulse', +}; // ========== SessionGroupTree Component ========== @@ -32,11 +44,17 @@ export function SessionGroupTree() { const { formatMessage } = useIntl(); const groups = useSessionManagerStore(selectGroups); const activeTerminalId = useSessionManagerStore(selectSessionManagerActiveTerminalId); + const terminalMetas = useSessionManagerStore(selectTerminalMetas); const createGroup = useSessionManagerStore((s) => s.createGroup); const moveSessionToGroup = useSessionManagerStore((s) => s.moveSessionToGroup); const setActiveTerminal = useSessionManagerStore((s) => s.setActiveTerminal); 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>(new Set()); const toggleGroup = useCallback((groupId: string) => { @@ -58,9 +76,28 @@ export function SessionGroupTree() { const handleSessionClick = useCallback( (sessionId: string) => { + // Set active terminal in session manager 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( @@ -168,38 +205,47 @@ export function SessionGroupTree() { {formatMessage({ id: 'terminalDashboard.sessionTree.emptyGroup' })}

) : ( - group.sessionIds.map((sessionId, index) => ( - - {(dragProvided, dragSnapshot) => ( -
handleSessionClick(sessionId)} - > - { + const meta = terminalMetas[sessionId]; + const sessionStatus: TerminalStatus = meta?.status ?? 'idle'; + return ( + + {(dragProvided, dragSnapshot) => ( +
handleSessionClick(sessionId)} > - - - - - {sessionNames[sessionId] ?? sessionId} - -
- )} -
- )) + + + + {/* Status indicator dot */} + + + + {sessionNames[sessionId] ?? sessionId} + +
+ )} +
+ ); + }) )} {provided.placeholder} diff --git a/ccw/frontend/src/components/terminal-dashboard/TerminalPane.tsx b/ccw/frontend/src/components/terminal-dashboard/TerminalPane.tsx index 374d26c3..7cd867d8 100644 --- a/ccw/frontend/src/components/terminal-dashboard/TerminalPane.tsx +++ b/ccw/frontend/src/components/terminal-dashboard/TerminalPane.tsx @@ -4,7 +4,7 @@ // Single terminal pane = PaneToolbar + TerminalInstance. // Renders within the TerminalGrid recursive layout. -import { useCallback, useMemo } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; import { SplitSquareHorizontal, @@ -14,6 +14,10 @@ import { X, Terminal, ChevronDown, + RotateCcw, + Pause, + Play, + Loader2, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { TerminalInstance } from './TerminalInstance'; @@ -76,6 +80,15 @@ export function TerminalPane({ paneId }: TerminalPaneProps) { const terminalMetas = useSessionManagerStore(selectTerminalMetas); 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 const associationChain = useIssueQueueIntegrationStore(selectAssociationChain); const linkedIssueId = useMemo(() => { @@ -133,6 +146,34 @@ export function TerminalPane({ paneId }: TerminalPaneProps) { } }, [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 (
{sessionId && ( - + <> + {/* Restart button */} + + {/* Pause/Resume toggle button */} + + {/* Clear terminal button */} + + )} {alertCount > 0 && ( diff --git a/ccw/frontend/src/locales/en/terminal-dashboard.json b/ccw/frontend/src/locales/en/terminal-dashboard.json index 2616c5d6..03b00ce1 100644 --- a/ccw/frontend/src/locales/en/terminal-dashboard.json +++ b/ccw/frontend/src/locales/en/terminal-dashboard.json @@ -88,7 +88,10 @@ "splitVertical": "Split Down", "clearTerminal": "Clear Terminal", "closePane": "Close Pane", - "linkedIssue": "Linked Issue" + "linkedIssue": "Linked Issue", + "restart": "Restart Session", + "pause": "Pause Session", + "resume": "Resume Session" }, "tabBar": { "noTabs": "No terminal sessions" diff --git a/ccw/frontend/src/locales/zh/terminal-dashboard.json b/ccw/frontend/src/locales/zh/terminal-dashboard.json index db627e40..5157b444 100644 --- a/ccw/frontend/src/locales/zh/terminal-dashboard.json +++ b/ccw/frontend/src/locales/zh/terminal-dashboard.json @@ -88,7 +88,10 @@ "splitVertical": "向下分割", "clearTerminal": "清屏", "closePane": "关闭窗格", - "linkedIssue": "关联问题" + "linkedIssue": "关联问题", + "restart": "重启会话", + "pause": "暂停会话", + "resume": "恢复会话" }, "tabBar": { "noTabs": "暂无终端会话"