mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
feat: add spec team commands with structured discussion rounds
Design 5 team commands based on spec-generator skill workflow, introducing multi-perspective discussion rounds between each phase: - spec-coordinate: workflow orchestration + discussion management - spec-analyst: seed analysis + codebase exploration (RESEARCH-*) - spec-writer: 4-type document generation (DRAFT-*) - spec-reviewer: 4-dimension quality scoring (QUALITY-*) - spec-discuss: multi-perspective critique + consensus building (DISCUSS-*)
This commit is contained in:
481
.claude/commands/team/spec-writer.md
Normal file
481
.claude/commands/team/spec-writer.md
Normal file
@@ -0,0 +1,481 @@
|
||||
---
|
||||
name: spec-writer
|
||||
description: Team spec writer - 产品简报/需求文档/架构文档/史诗故事撰写、模板驱动文档生成
|
||||
argument-hint: ""
|
||||
allowed-tools: SendMessage(*), TaskUpdate(*), TaskList(*), TaskGet(*), TodoWrite(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*), Task(*)
|
||||
group: team
|
||||
---
|
||||
|
||||
# Team Spec Writer Command (/team:spec-writer)
|
||||
|
||||
## Overview
|
||||
|
||||
Team spec-writer role command. Operates as a teammate within a Spec Team, responsible for generating all specification documents. Maps to spec-generator Phases 2-5 (Product Brief, Requirements, Architecture, Epics & Stories).
|
||||
|
||||
**Core capabilities:**
|
||||
- Task discovery from shared team task list (DRAFT-* tasks)
|
||||
- Complexity-adaptive writing (Low → direct, Medium/High → multi-CLI analysis)
|
||||
- Multi-perspective document generation (产品/技术/用户 parallel analysis)
|
||||
- Template-driven output following spec-generator document standards
|
||||
- Discussion feedback incorporation for iterative refinement
|
||||
|
||||
## Role Definition
|
||||
|
||||
**Name**: `spec-writer`
|
||||
**Responsibility**: Load Context → Generate Document → Incorporate Feedback → Report
|
||||
**Communication**: SendMessage to coordinator only
|
||||
|
||||
## 消息总线
|
||||
|
||||
每次 SendMessage **前**,必须调用 `mcp__ccw-tools__team_msg` 记录消息:
|
||||
|
||||
```javascript
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "spec-writer", to: "coordinator", type: "<type>", summary: "<摘要>", ref: "<文件路径>" })
|
||||
```
|
||||
|
||||
### 支持的 Message Types
|
||||
|
||||
| Type | 方向 | 触发时机 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `draft_ready` | spec-writer → coordinator | 文档撰写完成 | 附带文档路径和类型 |
|
||||
| `draft_revision` | spec-writer → coordinator | 文档修订后重新提交 | 说明修改内容 |
|
||||
| `impl_progress` | spec-writer → coordinator | 长时间撰写进展 | 多文档阶段进度 |
|
||||
| `error` | spec-writer → coordinator | 遇到不可恢复错误 | 模板缺失、上下文不足等 |
|
||||
|
||||
### 调用示例
|
||||
|
||||
```javascript
|
||||
// 文档就绪
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "spec-writer", to: "coordinator", type: "draft_ready", summary: "Product Brief 完成: 8个章节, 3视角合成", ref: ".workflow/.spec-team/session/product-brief.md" })
|
||||
|
||||
// 文档修订
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "spec-writer", to: "coordinator", type: "draft_revision", summary: "PRD 已按讨论反馈修订: 新增2个NFR, 调整3个优先级" })
|
||||
|
||||
// 错误上报
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "spec-writer", to: "coordinator", type: "error", summary: "缺少 discovery-context.json, 无法生成 Product Brief" })
|
||||
```
|
||||
|
||||
## Execution Process
|
||||
|
||||
```
|
||||
Phase 1: Task Discovery
|
||||
├─ TaskList to find unblocked DRAFT-* tasks
|
||||
├─ TaskGet to read full task details
|
||||
└─ TaskUpdate to mark in_progress
|
||||
|
||||
Phase 2: Context & Discussion Loading
|
||||
├─ Read session config (spec-config.json)
|
||||
├─ Read relevant prior documents and discussion records
|
||||
├─ Determine document type from task subject (Brief/PRD/Architecture/Epics)
|
||||
└─ Load discussion feedback (discuss-*.md)
|
||||
|
||||
Phase 3: Document Generation (type-specific)
|
||||
├─ DRAFT-001: Product Brief (multi-CLI parallel analysis)
|
||||
├─ DRAFT-002: Requirements/PRD (functional + non-functional + MoSCoW)
|
||||
├─ DRAFT-003: Architecture (ADRs + tech stack + diagrams)
|
||||
└─ DRAFT-004: Epics & Stories (decomposition + dependencies + MVP)
|
||||
|
||||
Phase 4: Self-Validation
|
||||
├─ Check all template sections populated
|
||||
├─ Verify cross-references to prior documents
|
||||
└─ Validate YAML frontmatter completeness
|
||||
|
||||
Phase 5: Report to Coordinator
|
||||
├─ team_msg log + SendMessage document summary
|
||||
├─ TaskUpdate completed
|
||||
└─ Check for next DRAFT-* task
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Phase 1: Task Discovery
|
||||
|
||||
```javascript
|
||||
// Find assigned DRAFT-* tasks
|
||||
const tasks = TaskList()
|
||||
const myTasks = tasks.filter(t =>
|
||||
t.subject.startsWith('DRAFT-') &&
|
||||
t.owner === 'spec-writer' &&
|
||||
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: Context & Discussion Loading
|
||||
|
||||
```javascript
|
||||
// Extract session folder from task description
|
||||
const sessionMatch = task.description.match(/Session:\s*(.+)/)
|
||||
const sessionFolder = sessionMatch ? sessionMatch[1].trim() : ''
|
||||
|
||||
// Load session config
|
||||
let specConfig = null
|
||||
try { specConfig = JSON.parse(Read(`${sessionFolder}/spec-config.json`)) } catch {}
|
||||
|
||||
// Determine document type from task subject
|
||||
const docType = task.subject.includes('Product Brief') ? 'product-brief'
|
||||
: task.subject.includes('Requirements') || task.subject.includes('PRD') ? 'requirements'
|
||||
: task.subject.includes('Architecture') ? 'architecture'
|
||||
: task.subject.includes('Epics') ? 'epics'
|
||||
: 'unknown'
|
||||
|
||||
// Load discussion feedback (from preceding DISCUSS task)
|
||||
const discussionFiles = {
|
||||
'product-brief': 'discussions/discuss-001-scope.md',
|
||||
'requirements': 'discussions/discuss-002-brief.md',
|
||||
'architecture': 'discussions/discuss-003-requirements.md',
|
||||
'epics': 'discussions/discuss-004-architecture.md'
|
||||
}
|
||||
let discussionFeedback = null
|
||||
try {
|
||||
discussionFeedback = Read(`${sessionFolder}/${discussionFiles[docType]}`)
|
||||
} catch {}
|
||||
|
||||
// Load prior documents
|
||||
const priorDocs = {}
|
||||
if (docType !== 'product-brief') {
|
||||
try { priorDocs.discoveryContext = Read(`${sessionFolder}/discovery-context.json`) } catch {}
|
||||
}
|
||||
if (docType === 'requirements' || docType === 'architecture' || docType === 'epics') {
|
||||
try { priorDocs.productBrief = Read(`${sessionFolder}/product-brief.md`) } catch {}
|
||||
}
|
||||
if (docType === 'architecture' || docType === 'epics') {
|
||||
try { priorDocs.requirementsIndex = Read(`${sessionFolder}/requirements/_index.md`) } catch {}
|
||||
}
|
||||
if (docType === 'epics') {
|
||||
try { priorDocs.architectureIndex = Read(`${sessionFolder}/architecture/_index.md`) } catch {}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: Document Generation
|
||||
|
||||
```javascript
|
||||
// Route to specific generation logic based on document type
|
||||
switch (docType) {
|
||||
case 'product-brief':
|
||||
await generateProductBrief(sessionFolder, specConfig, discussionFeedback)
|
||||
break
|
||||
case 'requirements':
|
||||
await generateRequirements(sessionFolder, specConfig, priorDocs, discussionFeedback)
|
||||
break
|
||||
case 'architecture':
|
||||
await generateArchitecture(sessionFolder, specConfig, priorDocs, discussionFeedback)
|
||||
break
|
||||
case 'epics':
|
||||
await generateEpics(sessionFolder, specConfig, priorDocs, discussionFeedback)
|
||||
break
|
||||
}
|
||||
```
|
||||
|
||||
#### DRAFT-001: Product Brief (Multi-Perspective Analysis)
|
||||
|
||||
```javascript
|
||||
async function generateProductBrief(sessionFolder, config, discussionFeedback) {
|
||||
const discoveryContext = JSON.parse(Read(`${sessionFolder}/discovery-context.json`))
|
||||
const topic = config?.topic || discoveryContext.seed_analysis.problem_statement
|
||||
|
||||
// 进展通知
|
||||
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: "spec-writer", to: "coordinator", type: "impl_progress", summary: "开始 Product Brief 多视角分析 (1/3)" })
|
||||
|
||||
// Launch 3 parallel CLI analyses for multi-perspective synthesis
|
||||
// 1. Product perspective (Gemini)
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Analyze from PRODUCT perspective for specification.
|
||||
TASK: • Market fit analysis • Value proposition • Success criteria • Competitive landscape
|
||||
TOPIC: ${topic}
|
||||
CONTEXT: Discovery findings: ${JSON.stringify(discoveryContext.seed_analysis)}
|
||||
${discussionFeedback ? `DISCUSSION FEEDBACK: ${discussionFeedback}` : ''}
|
||||
EXPECTED: Structured product analysis (vision, problem, goals, scope, constraints)
|
||||
CONSTRAINTS: Focus on product strategy" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// 2. Technical perspective (Codex)
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Analyze from TECHNICAL perspective for specification.
|
||||
TASK: • Technical feasibility • Architecture constraints • Tech stack recommendations • Implementation risks
|
||||
TOPIC: ${topic}
|
||||
CONTEXT: Discovery findings: ${JSON.stringify(discoveryContext.seed_analysis)}
|
||||
${discoveryContext.codebase_context ? `CODEBASE: ${JSON.stringify(discoveryContext.codebase_context)}` : ''}
|
||||
EXPECTED: Technical feasibility assessment
|
||||
CONSTRAINTS: Focus on engineering perspective" --tool codex --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// 3. User perspective (Claude)
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Analyze from USER perspective for specification.
|
||||
TASK: • User personas • User journeys • UX considerations • Accessibility needs
|
||||
TOPIC: ${topic}
|
||||
CONTEXT: Target users: ${JSON.stringify(discoveryContext.seed_analysis.target_users)}
|
||||
EXPECTED: User experience analysis (personas, journeys, pain points)
|
||||
CONSTRAINTS: Focus on end-user perspective" --tool claude --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// Wait for all 3 analyses to complete, then synthesize
|
||||
|
||||
// Generate product-brief.md with YAML frontmatter
|
||||
const brief = `---
|
||||
session_id: ${config.session_id}
|
||||
phase: 2
|
||||
document_type: product-brief
|
||||
status: draft
|
||||
generated_at: ${new Date().toISOString()}
|
||||
version: 1
|
||||
dependencies:
|
||||
- discovery-context.json
|
||||
- discuss-001-scope.md
|
||||
---
|
||||
|
||||
# Product Brief: ${topic}
|
||||
|
||||
## Vision
|
||||
${productPerspective.vision}
|
||||
|
||||
## Problem Statement
|
||||
${discoveryContext.seed_analysis.problem_statement}
|
||||
|
||||
## Target Users
|
||||
${personas.map(p => `### ${p.name}\n- **Role**: ${p.role}\n- **Pain Points**: ${p.painPoints}\n- **Goals**: ${p.goals}`).join('\n\n')}
|
||||
|
||||
## Goals & Success Metrics
|
||||
${productPerspective.goals}
|
||||
|
||||
## Scope
|
||||
### In Scope
|
||||
${productPerspective.inScope}
|
||||
|
||||
### Out of Scope
|
||||
${productPerspective.outOfScope}
|
||||
|
||||
## Technical Feasibility
|
||||
${technicalPerspective.summary}
|
||||
|
||||
## User Experience Considerations
|
||||
${userPerspective.summary}
|
||||
|
||||
## Multi-Perspective Synthesis
|
||||
### Convergent Themes
|
||||
${synthesis.convergent}
|
||||
|
||||
### Divergent Views
|
||||
${synthesis.divergent}
|
||||
|
||||
### Discussion Feedback Integration
|
||||
${discussionFeedback ? discussionFeedback.summary : 'N/A (first draft)'}
|
||||
|
||||
## Constraints
|
||||
${discoveryContext.seed_analysis.constraints.map(c => `- ${c}`).join('\n')}
|
||||
|
||||
## Open Questions
|
||||
${openQuestions.map(q => `- ${q}`).join('\n')}
|
||||
`
|
||||
Write(`${sessionFolder}/product-brief.md`, brief)
|
||||
}
|
||||
```
|
||||
|
||||
#### DRAFT-002: Requirements/PRD
|
||||
|
||||
```javascript
|
||||
async function generateRequirements(sessionFolder, config, priorDocs, discussionFeedback) {
|
||||
// Use Gemini CLI to expand requirements from product brief
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Generate functional and non-functional requirements from Product Brief.
|
||||
TASK:
|
||||
• Extract functional requirements (REQ-NNN format) with user stories and acceptance criteria
|
||||
• Generate non-functional requirements (NFR-{type}-NNN) for Performance/Security/Scalability/Usability
|
||||
• Apply MoSCoW prioritization (Must/Should/Could/Won't)
|
||||
• Create traceability matrix to Product Brief goals
|
||||
CONTEXT: Product Brief: ${priorDocs.productBrief}
|
||||
${discussionFeedback ? `DISCUSSION FEEDBACK: ${discussionFeedback}` : ''}
|
||||
EXPECTED: Structured requirements list in JSON
|
||||
CONSTRAINTS: Each requirement needs ID, title, user story, 2-4 acceptance criteria" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// Generate requirements/ directory structure
|
||||
Bash(`mkdir -p ${sessionFolder}/requirements`)
|
||||
|
||||
// Write _index.md + individual REQ-*.md + NFR-*.md files
|
||||
// Following spec-generator templates/requirements-prd.md format
|
||||
}
|
||||
```
|
||||
|
||||
#### DRAFT-003: Architecture
|
||||
|
||||
```javascript
|
||||
async function generateArchitecture(sessionFolder, config, priorDocs, discussionFeedback) {
|
||||
// Generate architecture via Gemini
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Design system architecture based on requirements.
|
||||
TASK:
|
||||
• Select architecture style with justification
|
||||
• Define core components and responsibilities
|
||||
• Create component interaction diagram (Mermaid)
|
||||
• Choose tech stack (languages, frameworks, databases, infrastructure)
|
||||
• Generate 2-4 ADRs with alternatives and pros/cons
|
||||
• Design data model (Mermaid erDiagram)
|
||||
• Define security architecture
|
||||
CONTEXT: Requirements: ${priorDocs.requirementsIndex}
|
||||
Product Brief: ${priorDocs.productBrief}
|
||||
${discussionFeedback ? `DISCUSSION FEEDBACK: ${discussionFeedback}` : ''}
|
||||
EXPECTED: Complete architecture document
|
||||
CONSTRAINTS: Include ADRs with alternatives" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// Challenge architecture via Codex
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Challenge and review proposed architecture.
|
||||
TASK: • Review ADR alternatives • Identify bottlenecks • Assess security gaps • Rate quality (1-5)
|
||||
CONTEXT: [architecture output from above]
|
||||
EXPECTED: Architecture review with ratings" --tool codex --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// Generate architecture/ directory
|
||||
Bash(`mkdir -p ${sessionFolder}/architecture`)
|
||||
|
||||
// Write _index.md + ADR-*.md files
|
||||
}
|
||||
```
|
||||
|
||||
#### DRAFT-004: Epics & Stories
|
||||
|
||||
```javascript
|
||||
async function generateEpics(sessionFolder, config, priorDocs, discussionFeedback) {
|
||||
// Decompose via Gemini
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: Decompose requirements into Epics and Stories.
|
||||
TASK:
|
||||
• Group 3-7 logical Epics by domain or user journey
|
||||
• Generate 2-5 Stories per Epic (user story format)
|
||||
• Create cross-Epic dependency map (Mermaid)
|
||||
• Define MVP scope with done criteria
|
||||
• Recommend execution order
|
||||
CONTEXT: Requirements: ${priorDocs.requirementsIndex}
|
||||
Architecture: ${priorDocs.architectureIndex}
|
||||
Product Brief: ${priorDocs.productBrief}
|
||||
${discussionFeedback ? `DISCUSSION FEEDBACK: ${discussionFeedback}` : ''}
|
||||
EXPECTED: Epic/Story decomposition with dependencies
|
||||
CONSTRAINTS: Each story needs AC, size estimate (S/M/L/XL), requirement tracing" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
})
|
||||
|
||||
// Generate epics/ directory
|
||||
Bash(`mkdir -p ${sessionFolder}/epics`)
|
||||
|
||||
// Write _index.md + EPIC-*.md files
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 4: Self-Validation
|
||||
|
||||
```javascript
|
||||
// Validate generated document
|
||||
const validationChecks = {
|
||||
has_frontmatter: false,
|
||||
sections_complete: false,
|
||||
cross_references: false,
|
||||
discussion_integrated: false
|
||||
}
|
||||
|
||||
// Check YAML frontmatter
|
||||
const docContent = Read(`${sessionFolder}/${outputPath}`)
|
||||
validationChecks.has_frontmatter = /^---\n[\s\S]+?\n---/.test(docContent)
|
||||
|
||||
// Check required sections based on doc type
|
||||
const requiredSections = {
|
||||
'product-brief': ['Vision', 'Problem Statement', 'Target Users', 'Goals', 'Scope'],
|
||||
'requirements': ['_index.md', 'REQ-'],
|
||||
'architecture': ['_index.md', 'ADR-'],
|
||||
'epics': ['_index.md', 'EPIC-']
|
||||
}
|
||||
// Verify all sections present
|
||||
|
||||
// Check cross-references to prior documents
|
||||
validationChecks.cross_references = docContent.includes('session_id')
|
||||
|
||||
// Check discussion feedback integration
|
||||
validationChecks.discussion_integrated = !discussionFeedback || docContent.includes('Discussion')
|
||||
|
||||
const allValid = Object.values(validationChecks).every(v => v)
|
||||
```
|
||||
|
||||
### Phase 5: Report to Coordinator
|
||||
|
||||
```javascript
|
||||
const docTypeLabel = {
|
||||
'product-brief': 'Product Brief',
|
||||
'requirements': 'Requirements/PRD',
|
||||
'architecture': 'Architecture Document',
|
||||
'epics': 'Epics & Stories'
|
||||
}
|
||||
|
||||
// Log before SendMessage
|
||||
mcp__ccw-tools__team_msg({
|
||||
operation: "log", team: teamName,
|
||||
from: "spec-writer", to: "coordinator",
|
||||
type: "draft_ready",
|
||||
summary: `${docTypeLabel[docType]} 完成: ${allValid ? '验证通过' : '部分验证失败'}`,
|
||||
ref: `${sessionFolder}/${outputPath}`
|
||||
})
|
||||
|
||||
SendMessage({
|
||||
type: "message",
|
||||
recipient: "coordinator",
|
||||
content: `## 文档撰写结果
|
||||
|
||||
**Task**: ${task.subject}
|
||||
**文档类型**: ${docTypeLabel[docType]}
|
||||
**验证状态**: ${allValid ? 'PASS' : 'PARTIAL'}
|
||||
|
||||
### 文档摘要
|
||||
${documentSummary}
|
||||
|
||||
### 讨论反馈整合
|
||||
${discussionFeedback ? '已整合前序讨论反馈' : '首次撰写(无前序讨论反馈)'}
|
||||
|
||||
### 自验证结果
|
||||
${Object.entries(validationChecks).map(([k, v]) => `- ${k}: ${v ? '✓' : '✗'}`).join('\n')}
|
||||
|
||||
### 输出位置
|
||||
${sessionFolder}/${outputPath}
|
||||
|
||||
文档已就绪,可进入讨论轮次。`,
|
||||
summary: `${docTypeLabel[docType]} 就绪`
|
||||
})
|
||||
|
||||
// Mark task completed
|
||||
TaskUpdate({ taskId: task.id, status: 'completed' })
|
||||
|
||||
// Check for next DRAFT task
|
||||
const nextTasks = TaskList().filter(t =>
|
||||
t.subject.startsWith('DRAFT-') &&
|
||||
t.owner === 'spec-writer' &&
|
||||
t.status === 'pending' &&
|
||||
t.blockedBy.length === 0
|
||||
)
|
||||
|
||||
if (nextTasks.length > 0) {
|
||||
// Continue with next task -> back to Phase 1
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Resolution |
|
||||
|----------|------------|
|
||||
| No DRAFT-* tasks available | Idle, wait for coordinator assignment |
|
||||
| Prior document not found | Notify coordinator, request prerequisite |
|
||||
| CLI analysis failure | Retry with fallback tool, then direct generation |
|
||||
| Template sections incomplete | Generate best-effort, note gaps in report |
|
||||
| Discussion feedback contradicts prior docs | Note conflict in document, flag for next discussion |
|
||||
| Session folder missing | Notify coordinator, request session path |
|
||||
| Unexpected error | Log error via team_msg, report to coordinator |
|
||||
Reference in New Issue
Block a user