mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-06 16:31:12 +08:00
feat: Add coordinator commands and role specifications for UI design team
- Implemented the 'monitor' command for coordinator role to handle monitoring events, task completion, and pipeline management. - Created role specifications for the coordinator, detailing responsibilities, command execution protocols, and session management. - Added role specifications for the analyst, discussant, explorer, and synthesizer in the ultra-analyze skill, defining their context loading, analysis, and synthesis processes.
This commit is contained in:
@@ -51,10 +51,10 @@ function buildPipeline(pipelineMode) {
|
||||
```javascript
|
||||
// Session directory already created in Phase 2
|
||||
// Write pipeline config to shared memory
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
|
||||
sharedMemory.pipeline_mode = pipelineMode
|
||||
sharedMemory.pipeline_stages = buildPipeline(pipelineMode).map(s => `${s.prefix}-${s.suffix}`)
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(sharedMemory, null, 2))
|
||||
```
|
||||
|
||||
### Step 2: Create Task Chain
|
||||
@@ -110,16 +110,14 @@ const chainValid = chainTasks.length === pipeline.length
|
||||
|
||||
if (!chainValid) {
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
to: "user", type: "error",
|
||||
summary: `[coordinator] Task chain incomplete: ${chainTasks.length}/${pipeline.length}`
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "error",
|
||||
})
|
||||
}
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName, from: "coordinator",
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
to: "all", type: "dispatch_ready",
|
||||
summary: `[coordinator] Task chain created: ${pipeline.map(s => `${s.prefix}-${s.suffix}`).join(' -> ')} (mode: ${pipelineMode})`
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ const STAGE_WORKER_MAP = {
|
||||
### Step 1: Context Preparation
|
||||
|
||||
```javascript
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
const sharedMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
|
||||
|
||||
// Get pipeline tasks in creation order (= dependency order)
|
||||
const allTasks = TaskList()
|
||||
@@ -55,9 +55,8 @@ for (const stageTask of pipelineTasks) {
|
||||
|
||||
if (!workerConfig) {
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: sessionId // MUST be session ID (e.g., RC-xxx-date), NOT team name, from: "coordinator",
|
||||
to: "user", type: "error",
|
||||
summary: `[coordinator] Unknown stage prefix: ${stagePrefix}, skipping`
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "error",
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -66,9 +65,8 @@ for (const stageTask of pipelineTasks) {
|
||||
TaskUpdate({ taskId: stageTask.id, status: 'in_progress' })
|
||||
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: sessionId // MUST be session ID (e.g., RC-xxx-date), NOT team name, from: "coordinator",
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
to: workerConfig.role, type: "stage_transition",
|
||||
summary: `[coordinator] Starting stage: ${stageTask.subject} -> ${workerConfig.role}`
|
||||
})
|
||||
|
||||
// 3. Build worker arguments
|
||||
@@ -86,19 +84,17 @@ for (const stageTask of pipelineTasks) {
|
||||
if (action === 'skip') continue
|
||||
} else {
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: sessionId // MUST be session ID (e.g., RC-xxx-date), NOT team name, from: "coordinator",
|
||||
to: "user", type: "stage_transition",
|
||||
summary: `[coordinator] Stage complete: ${stageTask.subject}`
|
||||
operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "stage_transition",
|
||||
})
|
||||
}
|
||||
|
||||
// 6. Post-stage: After SCAN check findings
|
||||
if (stagePrefix === 'SCAN') {
|
||||
const mem = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
const mem = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
|
||||
if ((mem.findings_count || 0) === 0) {
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: sessionId // MUST be session ID (e.g., RC-xxx-date), NOT team name, from: "coordinator",
|
||||
to: "user", type: "pipeline_complete",
|
||||
summary: `[coordinator] 0 findings. Code is clean. Skipping review/fix.` })
|
||||
mcp__ccw-tools__team_msg({ operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "pipeline_complete",
|
||||
for (const r of pipelineTasks.slice(pipelineTasks.indexOf(stageTask) + 1))
|
||||
TaskUpdate({ taskId: r.id, status: 'deleted' })
|
||||
break
|
||||
@@ -107,7 +103,7 @@ for (const stageTask of pipelineTasks) {
|
||||
|
||||
// 7. Post-stage: After REV confirm fix scope
|
||||
if (stagePrefix === 'REV' && pipelineMode === 'full') {
|
||||
const mem = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
const mem = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
|
||||
|
||||
if (!autoYes) {
|
||||
const conf = AskUserQuestion({ questions: [{
|
||||
@@ -126,7 +122,7 @@ for (const stageTask of pipelineTasks) {
|
||||
break
|
||||
}
|
||||
mem.fix_scope = conf["Fix Confirmation"] === "Fix critical/high only" ? 'critical,high' : 'all'
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(mem, null, 2))
|
||||
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(mem, null, 2))
|
||||
}
|
||||
|
||||
Write(`${sessionFolder}/fix/fix-manifest.json`, JSON.stringify({
|
||||
@@ -163,9 +159,8 @@ function buildWorkerArgs(stageTask, workerConfig) {
|
||||
```javascript
|
||||
function handleStageFailure(stageTask, taskState, workerConfig, autoYes) {
|
||||
if (autoYes) {
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: sessionId // MUST be session ID (e.g., RC-xxx-date), NOT team name, from: "coordinator",
|
||||
to: "user", type: "error",
|
||||
summary: `[coordinator] [auto] ${stageTask.subject} incomplete, skipping` })
|
||||
mcp__ccw-tools__team_msg({ operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "error",
|
||||
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
|
||||
return 'skip'
|
||||
}
|
||||
@@ -191,9 +186,8 @@ function handleStageFailure(stageTask, taskState, workerConfig, autoYes) {
|
||||
TaskUpdate({ taskId: stageTask.id, status: 'deleted' })
|
||||
return 'skip'
|
||||
} else {
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: sessionId // MUST be session ID (e.g., RC-xxx-date), NOT team name, from: "coordinator",
|
||||
to: "user", type: "error",
|
||||
summary: `[coordinator] User aborted at: ${stageTask.subject}` })
|
||||
mcp__ccw-tools__team_msg({ operation: "log", session_id: sessionId, from: "coordinator",
|
||||
type: "error",
|
||||
return 'abort'
|
||||
}
|
||||
}
|
||||
@@ -202,10 +196,10 @@ function handleStageFailure(stageTask, taskState, workerConfig, autoYes) {
|
||||
### Step 3: Finalize
|
||||
|
||||
```javascript
|
||||
const finalMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
|
||||
const finalMemory = JSON.parse(Read(`${sessionFolder}/.msg/meta.json`))
|
||||
finalMemory.pipeline_status = 'complete'
|
||||
finalMemory.completed_at = new Date().toISOString()
|
||||
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(finalMemory, null, 2))
|
||||
Write(`${sessionFolder}/.msg/meta.json`, JSON.stringify(finalMemory, null, 2))
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -32,18 +32,56 @@ Code review team coordinator. Orchestrates the scan-review-fix pipeline (CP-1 Li
|
||||
|
||||
---
|
||||
|
||||
## Command Execution Protocol
|
||||
|
||||
When coordinator needs to execute a command (dispatch, monitor):
|
||||
|
||||
1. **Read the command file**: `roles/coordinator/commands/<command-name>.md`
|
||||
2. **Follow the workflow** defined in the command file (Phase 2-4 structure)
|
||||
3. **Commands are inline execution guides** -- NOT separate agents or subprocesses
|
||||
4. **Execute synchronously** -- complete the command workflow before proceeding
|
||||
|
||||
Example:
|
||||
```
|
||||
Phase 3 needs task dispatch
|
||||
-> Read roles/coordinator/commands/dispatch.md
|
||||
-> Execute Phase 2 (Context Loading)
|
||||
-> Execute Phase 3 (Task Chain Creation)
|
||||
-> Execute Phase 4 (Validation)
|
||||
-> Continue to Phase 4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Entry Router
|
||||
|
||||
When coordinator is invoked, first detect the invocation type:
|
||||
When coordinator is invoked, detect invocation type:
|
||||
|
||||
| Detection | Condition | Handler |
|
||||
|-----------|-----------|---------|
|
||||
| Worker callback | Message contains `[scanner]`, `[reviewer]`, or `[fixer]` tag | -> handleCallback: auto-advance pipeline |
|
||||
| Status check | Arguments contain "check" or "status" | -> handleCheck: output execution graph, no advancement |
|
||||
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume: check worker states, advance pipeline |
|
||||
| New session | None of the above | -> Phase 1 (Parse Arguments) |
|
||||
| Worker callback | Message contains role tag [scanner], [reviewer], [fixer] | -> handleCallback |
|
||||
| Status check | Arguments contain "check" or "status" | -> handleCheck |
|
||||
| Manual resume | Arguments contain "resume" or "continue" | -> handleResume |
|
||||
| Pipeline complete | All tasks have status "completed" | -> handleComplete |
|
||||
| Interrupted session | Active/paused session exists | -> Phase 0 (Session Resume Check) |
|
||||
| New session | None of above | -> Phase 1 (Parse Arguments) |
|
||||
|
||||
For callback/check/resume: load `commands/monitor.md` and execute the appropriate handler, then STOP.
|
||||
For callback/check/resume/complete: load `commands/monitor.md` and execute matched handler, then STOP.
|
||||
|
||||
### Router Implementation
|
||||
|
||||
1. **Load session context** (if exists):
|
||||
- Scan `.workflow/.team-review/RC-*/.msg/meta.json` for active/paused sessions
|
||||
- If found, extract session folder path, status, and pipeline mode
|
||||
|
||||
2. **Parse $ARGUMENTS** for detection keywords:
|
||||
- Check for role name tags in message content
|
||||
- Check for "check", "status", "resume", "continue" keywords
|
||||
|
||||
3. **Route to handler**:
|
||||
- For monitor handlers: Read `commands/monitor.md`, execute matched handler, STOP
|
||||
- For Phase 0: Execute Session Resume Check
|
||||
- For Phase 1: Execute Parse Arguments below
|
||||
|
||||
---
|
||||
|
||||
@@ -86,18 +124,16 @@ Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <session-id>, // MUST be session ID (e.g., RC-xxx-date), NOT team name. Extract from Session: field in task description.
|
||||
session_id: <session-id>,
|
||||
from: "coordinator",
|
||||
to: "user",
|
||||
type: "dispatch_ready",
|
||||
summary: "[coordinator] Task chain created, pipeline ready"
|
||||
type: "dispatch_ready"
|
||||
})
|
||||
```
|
||||
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <session-id> --from coordinator --to user --type dispatch_ready --summary \"[coordinator] Task chain created\" --json")
|
||||
Bash("ccw team log --session-id <session-id> --from coordinator --type dispatch_ready --json")
|
||||
```
|
||||
|
||||
---
|
||||
@@ -156,10 +192,12 @@ Bash("ccw team log --team <session-id> --from coordinator --to user --type dispa
|
||||
│ ├── decisions.md
|
||||
│ ├── conventions.md
|
||||
│ └── issues.md
|
||||
└── shared-memory.json
|
||||
├── .msg/
|
||||
│ ├── messages.jsonl
|
||||
│ └── meta.json
|
||||
```
|
||||
|
||||
3. Initialize shared-memory.json with: workflow_id, mode, target, dimensions, auto flag
|
||||
3. Initialize .msg/meta.json with: workflow_id, mode, target, dimensions, auto flag
|
||||
|
||||
**Success**: Session folder created, shared memory initialized.
|
||||
|
||||
|
||||
@@ -139,9 +139,8 @@ if (isQuickPath) {
|
||||
results_so_far:{fixed:results.fixed.length, failed:results.failed.length}
|
||||
}, null, 2))
|
||||
|
||||
mcp__ccw-tools__team_msg({ operation:"log", team:"team-review", from:"fixer",
|
||||
mcp__ccw-tools__team_msg({ operation:"log", session_id: sessionId, from:"fixer",
|
||||
to:"coordinator", type:"fix_progress",
|
||||
summary:`[fixer] Group ${gid}: ${results.fixed.length} fixed, ${results.failed.length} failed` })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -172,9 +172,8 @@ const fixPlan = {
|
||||
Bash(`mkdir -p "${sessionFolder}/fix"`)
|
||||
Write(`${sessionFolder}/fix/fix-plan.json`, JSON.stringify(fixPlan, null, 2))
|
||||
|
||||
mcp__ccw-tools__team_msg({ operation:"log", team:"team-review", from:"fixer",
|
||||
mcp__ccw-tools__team_msg({ operation:"log", session_id: sessionId, from:"fixer",
|
||||
to:"coordinator", type:"fix_progress",
|
||||
summary:`[fixer] Fix plan: ${totalGroups} groups, ${totalFindings} findings, path=${isQuickPath ? 'quick' : 'standard'}` })
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -67,11 +67,9 @@ Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <session-id>, // MUST be session ID (e.g., RC-xxx-date), NOT team name. Extract from Session: field in task description.
|
||||
session_id: <session-id>,
|
||||
from: "fixer",
|
||||
to: "coordinator",
|
||||
type: "fix_complete",
|
||||
summary: "[fixer] Fix: <fixed>/<total> (<rate>%)",
|
||||
ref: "<session-folder>/fix/fix-summary.json"
|
||||
})
|
||||
```
|
||||
@@ -79,7 +77,7 @@ mcp__ccw-tools__team_msg({
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <session-id> --from fixer --to coordinator --type fix_complete --summary \"[fixer] Fix complete\" --ref <path> --json")
|
||||
Bash("ccw team log --session-id <session-id> --from fixer --type fix_complete --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
@@ -214,7 +212,7 @@ Delegate to `commands/execute-fixes.md`.
|
||||
|
||||
1. Generate fix-summary.json with: fix_id, fix_date, scope, total, fixed, failed, skipped, fix_rate, verification results
|
||||
2. Generate fix-summary.md (human-readable)
|
||||
3. Update shared-memory.json with fix results
|
||||
3. Update .msg/meta.json with fix results
|
||||
4. Log via team_msg with `[fixer]` prefix
|
||||
5. SendMessage to coordinator
|
||||
6. TaskUpdate completed
|
||||
|
||||
@@ -66,11 +66,9 @@ Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <session-id>, // MUST be session ID (e.g., RC-xxx-date), NOT team name. Extract from Session: field in task description.
|
||||
session_id: <session-id>,
|
||||
from: "reviewer",
|
||||
to: "coordinator",
|
||||
type: "review_complete",
|
||||
summary: "[reviewer] Review complete: <count> findings (<severity-summary>)",
|
||||
ref: "<session-folder>/review/review-report.json"
|
||||
})
|
||||
```
|
||||
@@ -78,7 +76,7 @@ mcp__ccw-tools__team_msg({
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <session-id> --from reviewer --to coordinator --type review_complete --summary \"[reviewer] Review complete\" --ref <path> --json")
|
||||
Bash("ccw team log --session-id <session-id> --from reviewer --type review_complete --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
@@ -200,7 +198,7 @@ Delegate to `commands/generate-report.md`.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. Update shared-memory.json with review results summary
|
||||
1. Update .msg/meta.json with review results summary
|
||||
2. Build top findings summary (critical/high, max 8)
|
||||
3. Log via team_msg with `[reviewer]` prefix
|
||||
4. SendMessage to coordinator
|
||||
|
||||
@@ -67,11 +67,9 @@ Before every SendMessage, log via `mcp__ccw-tools__team_msg`:
|
||||
```
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log",
|
||||
team: <session-id>, // MUST be session ID (e.g., RC-xxx-date), NOT team name. Extract from Session: field in task description.
|
||||
session_id: <session-id>,
|
||||
from: "scanner",
|
||||
to: "coordinator",
|
||||
type: "scan_complete",
|
||||
summary: "[scanner] Scan complete: <count> findings (<dimension-summary>)",
|
||||
ref: "<session-folder>/scan/scan-results.json"
|
||||
})
|
||||
```
|
||||
@@ -79,7 +77,7 @@ mcp__ccw-tools__team_msg({
|
||||
**CLI fallback** (when MCP unavailable):
|
||||
|
||||
```
|
||||
Bash("ccw team log --team <session-id> --from scanner --to coordinator --type scan_complete --summary \"[scanner] Scan complete\" --ref <path> --json")
|
||||
Bash("ccw team log --session-id <session-id> --from scanner --type scan_complete --ref <path> --json")
|
||||
```
|
||||
|
||||
---
|
||||
@@ -222,7 +220,7 @@ If no source files found -> report empty, complete task cleanly.
|
||||
|
||||
**Workflow**:
|
||||
|
||||
1. Update shared-memory.json with scan results summary
|
||||
1. Update .msg/meta.json with scan results summary
|
||||
2. Build top findings summary (critical/high, max 10)
|
||||
3. Log via team_msg with `[scanner]` prefix
|
||||
4. SendMessage to coordinator
|
||||
|
||||
Reference in New Issue
Block a user