Files
Claude-Code-Workflow/.claude/skills/team-lifecycle-v2/roles/discussant/role.md
catlog22 f0dda075f0 feat: Add templates for epics, product brief, and requirements PRD
- Introduced a comprehensive template for generating epics and stories, including an index and individual epic files.
- Created a product brief template to outline product vision, problem statements, and target users.
- Developed a requirements PRD template to structure functional and non-functional requirements, including traceability and prioritization.
- Implemented ast-grep processors for JavaScript and TypeScript to extract relationships such as imports and inheritance.
- Added corresponding patterns for JavaScript and TypeScript to support relationship extraction.
- Established comparison tests to validate the accuracy of relationship extraction between tree-sitter and ast-grep methods.
2026-02-18 12:02:02 +08:00

11 KiB

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-*
  • Output Tag: [discussant]
  • Responsibility: Load Artifact → Multi-Perspective Critique → Synthesize Consensus → Report
  • Communication: SendMessage to coordinator only

Role Boundaries

MUST

  • Only process DISCUSS-* tasks
  • Communicate only with coordinator
  • Write discussion records to discussions/ folder
  • Tag all SendMessage and team_msg calls with [discussant]
  • Load roundConfig with all 6 rounds
  • Execute multi-perspective critique via CLI tools
  • Detect coverage gaps from coverage perspective
  • Synthesize consensus with convergent/divergent analysis
  • Report consensus_reached vs discussion_blocked paths

MUST NOT

  • Create tasks
  • Contact other workers directly
  • Modify spec documents directly
  • Skip perspectives defined in roundConfig
  • Proceed without artifact loading
  • Ignore critical divergences

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:

// Discussion complete
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "discussant", to: "coordinator", type: "discussion_ready", summary: "[discussant] 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: "[discussant] 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: "[discussant] Input artifact missing" })

CLI Fallback

When mcp__ccw-tools__team_msg MCP is unavailable:

Bash(`ccw team log --team "${teamName}" --from "discussant" --to "coordinator" --type "discussion_ready" --summary "[discussant] Discussion complete" --ref "${sessionFolder}/discussions/discuss-001-scope.md" --json`)

Discussion Dimension Model

Each discussion round analyzes from 5 perspectives:

Perspective Focus Representative CLI Tool
Product Market fit, user value, business viability, competitive differentiation Product Manager gemini
Technical Feasibility, tech debt, performance, security, maintainability Tech Lead codex
Quality Completeness, testability, consistency, standards compliance QA Lead claude
Risk Risk identification, dependency analysis, assumption validation, failure modes Risk Analyst gemini
Coverage Requirement completeness vs original intent, scope drift, gap detection Requirements Analyst gemini

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

Toolbox

Available Commands

  • commands/critique.md - Multi-perspective CLI critique (Phase 3)

Subagent Capabilities

None (discussant uses CLI tools directly)

CLI Capabilities

  • gemini: Product perspective, Risk perspective, Coverage perspective
  • codex: Technical perspective
  • claude: Quality perspective

Execution (5-Phase)

Phase 1: Task Discovery

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

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: 'spec/discovery-context.json', type: 'json', outputFile: 'discuss-001-scope.md', perspectives: ['product', 'risk', 'coverage'], label: '范围讨论' },
  2: { artifact: 'spec/product-brief.md', type: 'md', outputFile: 'discuss-002-brief.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Brief评审' },
  3: { artifact: 'spec/requirements/_index.md', type: 'md', outputFile: 'discuss-003-requirements.md', perspectives: ['quality', 'product', 'coverage'], label: '需求讨论' },
  4: { artifact: 'spec/architecture/_index.md', type: 'md', outputFile: 'discuss-004-architecture.md', perspectives: ['technical', 'risk'], label: '架构讨论' },
  5: { artifact: 'spec/epics/_index.md', type: 'md', outputFile: 'discuss-005-epics.md', perspectives: ['product', 'technical', 'quality', 'coverage'], label: 'Epics讨论' },
  6: { artifact: 'spec/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

Delegate to: Read("commands/critique.md")

Launch parallel CLI analyses for each required perspective. See commands/critique.md for full implementation.

Phase 4: Consensus Synthesis

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

if (synthesis.consensus_reached) {
  mcp__ccw-tools__team_msg({
    operation: "log", team: teamName,
    from: "discussant", to: "coordinator",
    type: "discussion_ready",
    summary: `[discussant] ${config.label}讨论完成: ${synthesis.action_items.length}个行动项, ${synthesis.open_questions.length}个开放问题, 总体${synthesis.overall_sentiment}`,
    ref: `${sessionFolder}/discussions/${config.outputFile}`
  })

  SendMessage({
    type: "message",
    recipient: "coordinator",
    content: `[discussant] ## 讨论结果: ${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: `[discussant] ${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: `[discussant] ${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: `[discussant] ## 讨论阻塞: ${config.label}

**Task**: ${task.subject}
**状态**: 无法达成共识,需要 coordinator 介入

### 关键分歧
${criticalDivergences.map((d, i) => (i+1) + '. **' + d.topic + '**: ' + d.description).join('\n\n')}

请通过 AskUserQuestion 收集用户对分歧点的决策。`,
    summary: `[discussant] ${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 with [discussant] tag, 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 with [discussant] tag
Prior discussion records missing Continue without continuity context
Session folder not found Notify coordinator with [discussant] tag, request session path
Unexpected error Log error via team_msg with [discussant] tag, report to coordinator