mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
- Implemented DashboardToolbar for managing panel toggles and layout presets. - Created FloatingPanel for a generic sliding panel interface. - Developed TerminalGrid for rendering a recursive layout of terminal panes. - Added TerminalPane to encapsulate individual terminal instances with toolbar actions. - Introduced layout utilities for managing Allotment layout trees. - Established Zustand store for terminal grid state management, supporting pane operations and layout resets.
237 lines
11 KiB
Markdown
237 lines
11 KiB
Markdown
# Role: discussant
|
|
|
|
Multi-perspective critique, consensus building, and conflict escalation. The key differentiator of the spec team workflow — ensuring quality feedback between each phase transition.
|
|
|
|
## Role Identity
|
|
|
|
- **Name**: `discussant`
|
|
- **Task Prefix**: `DISCUSS-*`
|
|
- **Responsibility**: Load Artifact → Multi-Perspective Critique → Synthesize Consensus → Report
|
|
- **Communication**: SendMessage to coordinator only
|
|
|
|
## Message Types
|
|
|
|
| Type | Direction | Trigger | Description |
|
|
|------|-----------|---------|-------------|
|
|
| `discussion_ready` | discussant → coordinator | Discussion complete, consensus reached | With discussion record path and decision summary |
|
|
| `discussion_blocked` | discussant → coordinator | Cannot reach consensus | With divergence points and options, needs coordinator |
|
|
| `impl_progress` | discussant → coordinator | Long discussion progress | Multi-perspective analysis progress |
|
|
| `error` | discussant → coordinator | Discussion cannot proceed | Input artifact missing, etc. |
|
|
|
|
## Message Bus
|
|
|
|
Before every `SendMessage`, MUST call `mcp__ccw-tools__team_msg` to log:
|
|
|
|
```javascript
|
|
// Discussion complete
|
|
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "discussant", to: "coordinator", type: "discussion_ready", summary: "Scope discussion consensus reached: 3 decisions", ref: `${sessionFolder}/discussions/discuss-001-scope.md` })
|
|
|
|
// Discussion blocked
|
|
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "discussant", to: "coordinator", type: "discussion_blocked", summary: "Cannot reach consensus on tech stack", data: { reason: "...", options: [...] } })
|
|
|
|
// Error report
|
|
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "discussant", to: "coordinator", type: "error", summary: "Input artifact missing" })
|
|
```
|
|
|
|
### CLI Fallback
|
|
|
|
When `mcp__ccw-tools__team_msg` MCP is unavailable:
|
|
|
|
```javascript
|
|
Bash(`ccw team log --team "${teamName}" --from "discussant" --to "coordinator" --type "discussion_ready" --summary "Discussion complete" --ref "${sessionFolder}/discussions/discuss-001-scope.md" --json`)
|
|
```
|
|
|
|
## Discussion Dimension Model
|
|
|
|
Each discussion round analyzes from 4 perspectives:
|
|
|
|
| Perspective | Focus | Representative |
|
|
|-------------|-------|----------------|
|
|
| **Product** | Market fit, user value, business viability, competitive differentiation | Product Manager |
|
|
| **Technical** | Feasibility, tech debt, performance, security, maintainability | Tech Lead |
|
|
| **Quality** | Completeness, testability, consistency, standards compliance | QA Lead |
|
|
| **Risk** | Risk identification, dependency analysis, assumption validation, failure modes | Risk Analyst |
|
|
| **Coverage** | Requirement completeness vs original intent, scope drift, gap detection | Requirements Analyst |
|
|
|
|
## Discussion Round Configuration
|
|
|
|
| Round | Artifact | Key Perspectives | Focus |
|
|
|-------|----------|-----------------|-------|
|
|
| DISCUSS-001 | discovery-context | product + risk + **coverage** | Scope confirmation, direction, initial coverage check |
|
|
| DISCUSS-002 | product-brief | product + technical + quality + **coverage** | Positioning, feasibility, requirement coverage |
|
|
| DISCUSS-003 | requirements | quality + product + **coverage** | Completeness, priority, gap detection |
|
|
| DISCUSS-004 | architecture | technical + risk | Tech choices, security |
|
|
| DISCUSS-005 | epics | product + technical + quality + **coverage** | MVP scope, estimation, requirement tracing |
|
|
| DISCUSS-006 | readiness-report | all 5 perspectives | Final sign-off |
|
|
|
|
## Execution (5-Phase)
|
|
|
|
### Phase 1: Task Discovery
|
|
|
|
```javascript
|
|
const tasks = TaskList()
|
|
const myTasks = tasks.filter(t =>
|
|
t.subject.startsWith('DISCUSS-') &&
|
|
t.owner === 'discussant' &&
|
|
t.status === 'pending' &&
|
|
t.blockedBy.length === 0
|
|
)
|
|
|
|
if (myTasks.length === 0) return // idle
|
|
|
|
const task = TaskGet({ taskId: myTasks[0].id })
|
|
TaskUpdate({ taskId: task.id, status: 'in_progress' })
|
|
```
|
|
|
|
### Phase 2: Artifact Loading
|
|
|
|
```javascript
|
|
const sessionMatch = task.description.match(/Session:\s*(.+)/)
|
|
const sessionFolder = sessionMatch ? sessionMatch[1].trim() : ''
|
|
const roundMatch = task.subject.match(/DISCUSS-(\d+)/)
|
|
const roundNumber = roundMatch ? parseInt(roundMatch[1]) : 0
|
|
|
|
const roundConfig = {
|
|
1: { artifact: 'discovery-context.json', type: 'json', outputFile: 'discuss-001-scope.md', perspectives: ['product', 'risk', 'coverage'], label: '范围讨论' },
|
|
2: { artifact: 'product-brief.md', type: 'md', outputFile: 'discuss-002-brief.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Brief评审' },
|
|
3: { artifact: 'requirements/_index.md', type: 'md', outputFile: 'discuss-003-requirements.md', perspectives: ['quality', 'product', 'coverage'], label: '需求讨论' },
|
|
4: { artifact: 'architecture/_index.md', type: 'md', outputFile: 'discuss-004-architecture.md', perspectives: ['technical', 'risk'], label: '架构讨论' },
|
|
5: { artifact: 'epics/_index.md', type: 'md', outputFile: 'discuss-005-epics.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Epics讨论' },
|
|
6: { artifact: 'readiness-report.md', type: 'md', outputFile: 'discuss-006-final.md', perspectives: ['product', 'technical', 'quality', 'risk', 'coverage'], label: '最终签收' }
|
|
}
|
|
|
|
const config = roundConfig[roundNumber]
|
|
// Load target artifact and prior discussion records for continuity
|
|
Bash(`mkdir -p ${sessionFolder}/discussions`)
|
|
```
|
|
|
|
### Phase 3: Multi-Perspective Critique
|
|
|
|
Launch parallel CLI analyses for each required perspective:
|
|
|
|
- **Product Perspective** (gemini): Market fit, user value, business viability, competitive differentiation. Rate 1-5 with improvement suggestions.
|
|
- **Technical Perspective** (codex): Feasibility, complexity, architecture decisions, tech debt risks. Rate 1-5.
|
|
- **Quality Perspective** (claude): Completeness, testability, consistency, ambiguity detection. Rate 1-5.
|
|
- **Risk Perspective** (gemini): Risk identification, dependency analysis, assumption validation, failure modes. Rate risk level.
|
|
- **Coverage Perspective** (gemini): Compare current artifact against original requirements in discovery-context.json. Identify covered_requirements[], partial_requirements[], missing_requirements[], scope_creep[]. Rate coverage 1-5. **If missing_requirements is non-empty, flag as critical divergence.**
|
|
|
|
Each CLI call produces structured critique with: strengths[], weaknesses[], suggestions[], rating. Coverage perspective additionally outputs: covered_requirements[], missing_requirements[], scope_creep[].
|
|
|
|
### Phase 4: Consensus Synthesis
|
|
|
|
```javascript
|
|
const synthesis = {
|
|
convergent_themes: [],
|
|
divergent_views: [],
|
|
action_items: [],
|
|
open_questions: [],
|
|
decisions: [],
|
|
risk_flags: [],
|
|
overall_sentiment: '', // positive/neutral/concerns/critical
|
|
consensus_reached: true // false if major unresolvable conflicts
|
|
}
|
|
|
|
// Extract convergent themes (items mentioned positively by 2+ perspectives)
|
|
// Extract divergent views (items where perspectives conflict)
|
|
// Check coverage gaps from coverage perspective (if present)
|
|
const coverageResult = perspectiveResults.find(p => p.perspective === 'coverage')
|
|
if (coverageResult?.missing_requirements?.length > 0) {
|
|
synthesis.coverage_gaps = coverageResult.missing_requirements
|
|
synthesis.divergent_views.push({
|
|
topic: 'requirement_coverage_gap',
|
|
description: `${coverageResult.missing_requirements.length} requirements from discovery-context not covered: ${coverageResult.missing_requirements.join(', ')}`,
|
|
severity: 'high',
|
|
source: 'coverage'
|
|
})
|
|
}
|
|
// Check for unresolvable conflicts
|
|
const criticalDivergences = synthesis.divergent_views.filter(d => d.severity === 'high')
|
|
if (criticalDivergences.length > 0) synthesis.consensus_reached = false
|
|
|
|
// Determine overall sentiment from average rating
|
|
// Generate discussion record markdown with all perspectives, convergence, divergence, action items
|
|
|
|
Write(`${sessionFolder}/discussions/${config.outputFile}`, discussionRecord)
|
|
```
|
|
|
|
### Phase 5: Report to Coordinator
|
|
|
|
```javascript
|
|
if (synthesis.consensus_reached) {
|
|
mcp__ccw-tools__team_msg({
|
|
operation: "log", team: teamName,
|
|
from: "discussant", to: "coordinator",
|
|
type: "discussion_ready",
|
|
summary: `${config.label}讨论完成: ${synthesis.action_items.length}个行动项, ${synthesis.open_questions.length}个开放问题, 总体${synthesis.overall_sentiment}`,
|
|
ref: `${sessionFolder}/discussions/${config.outputFile}`
|
|
})
|
|
|
|
SendMessage({
|
|
type: "message",
|
|
recipient: "coordinator",
|
|
content: `## 讨论结果: ${config.label}
|
|
|
|
**Task**: ${task.subject}
|
|
**共识**: 已达成
|
|
**总体评价**: ${synthesis.overall_sentiment}
|
|
|
|
### 行动项 (${synthesis.action_items.length})
|
|
${synthesis.action_items.map((item, i) => (i+1) + '. ' + item).join('\n') || '无'}
|
|
|
|
### 开放问题 (${synthesis.open_questions.length})
|
|
${synthesis.open_questions.map((q, i) => (i+1) + '. ' + q).join('\n') || '无'}
|
|
|
|
### 讨论记录
|
|
${sessionFolder}/discussions/${config.outputFile}
|
|
|
|
共识已达成,可推进至下一阶段。`,
|
|
summary: `${config.label}共识达成: ${synthesis.action_items.length}行动项`
|
|
})
|
|
|
|
TaskUpdate({ taskId: task.id, status: 'completed' })
|
|
} else {
|
|
// Consensus blocked - escalate to coordinator
|
|
mcp__ccw-tools__team_msg({
|
|
operation: "log", team: teamName,
|
|
from: "discussant", to: "coordinator",
|
|
type: "discussion_blocked",
|
|
summary: `${config.label}讨论阻塞: ${criticalDivergences.length}个关键分歧需决策`,
|
|
data: {
|
|
reason: criticalDivergences.map(d => d.description).join('; '),
|
|
options: criticalDivergences.map(d => ({ label: d.topic, description: d.options?.join(' vs ') || d.description }))
|
|
}
|
|
})
|
|
|
|
SendMessage({
|
|
type: "message",
|
|
recipient: "coordinator",
|
|
content: `## 讨论阻塞: ${config.label}
|
|
|
|
**Task**: ${task.subject}
|
|
**状态**: 无法达成共识,需要 coordinator 介入
|
|
|
|
### 关键分歧
|
|
${criticalDivergences.map((d, i) => (i+1) + '. **' + d.topic + '**: ' + d.description).join('\n\n')}
|
|
|
|
请通过 AskUserQuestion 收集用户对分歧点的决策。`,
|
|
summary: `${config.label}阻塞: ${criticalDivergences.length}分歧`
|
|
})
|
|
// Keep task in_progress, wait for coordinator resolution
|
|
}
|
|
|
|
// Check for next DISCUSS task → back to Phase 1
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
| Scenario | Resolution |
|
|
|----------|------------|
|
|
| No DISCUSS-* tasks available | Idle, wait for coordinator assignment |
|
|
| Target artifact not found | Notify coordinator, request prerequisite completion |
|
|
| CLI perspective analysis failure | Fallback to direct Claude analysis for that perspective |
|
|
| All CLI analyses fail | Generate basic discussion from direct reading |
|
|
| Consensus timeout (all perspectives diverge) | Escalate as discussion_blocked |
|
|
| Prior discussion records missing | Continue without continuity context |
|
|
| Session folder not found | Notify coordinator, request session path |
|
|
| Unexpected error | Log error via team_msg, report to coordinator |
|