mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-27 09:13:07 +08:00
feat(spec-generator): add Phase 1.5 requirement expansion & clarification
Insert interactive requirement discussion stage between Discovery and Product Brief to address missing requirement depth analysis. Phase 1.5 uses Gemini CLI for gap analysis, supports multi-round interactive discussion (max 5 rounds), and outputs refined-requirements.json as high-quality input for downstream phases. Compatible with -y auto mode.
This commit is contained in:
@@ -11,21 +11,23 @@ Structured specification document generator producing a complete specification p
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
Phase 0: Specification Study (Read specs/ + templates/ - mandatory prerequisite)
|
||||
|
|
||||
Phase 1: Discovery -> spec-config.json + discovery-context.json
|
||||
|
|
||||
Phase 2: Product Brief -> product-brief.md (multi-CLI parallel analysis)
|
||||
|
|
||||
Phase 3: Requirements (PRD) -> requirements/ (_index.md + REQ-*.md + NFR-*.md)
|
||||
|
|
||||
Phase 4: Architecture -> architecture/ (_index.md + ADR-*.md, multi-CLI review)
|
||||
|
|
||||
Phase 5: Epics & Stories -> epics/ (_index.md + EPIC-*.md)
|
||||
|
|
||||
Phase 6: Readiness Check -> readiness-report.md + spec-summary.md
|
||||
|
|
||||
Handoff to execution workflows
|
||||
Phase 0: Specification Study (Read specs/ + templates/ - mandatory prerequisite)
|
||||
|
|
||||
Phase 1: Discovery -> spec-config.json + discovery-context.json
|
||||
|
|
||||
Phase 1.5: Req Expansion -> refined-requirements.json (interactive discussion + CLI gap analysis)
|
||||
| (-y auto mode: auto-expansion, skip interaction)
|
||||
Phase 2: Product Brief -> product-brief.md (multi-CLI parallel analysis)
|
||||
|
|
||||
Phase 3: Requirements (PRD) -> requirements/ (_index.md + REQ-*.md + NFR-*.md)
|
||||
|
|
||||
Phase 4: Architecture -> architecture/ (_index.md + ADR-*.md, multi-CLI review)
|
||||
|
|
||||
Phase 5: Epics & Stories -> epics/ (_index.md + EPIC-*.md)
|
||||
|
|
||||
Phase 6: Readiness Check -> readiness-report.md + spec-summary.md
|
||||
|
|
||||
Handoff to execution workflows
|
||||
```
|
||||
|
||||
## Key Design Principles
|
||||
@@ -79,6 +81,16 @@ Phase 1: Discovery & Seed Analysis
|
||||
|- User confirmation (interactive, -y skips)
|
||||
|- Output: spec-config.json, discovery-context.json (optional)
|
||||
|
||||
Phase 1.5: Requirement Expansion & Clarification
|
||||
|- Ref: phases/01-5-requirement-clarification.md
|
||||
|- CLI gap analysis: completeness scoring, missing dimensions detection
|
||||
|- Multi-round interactive discussion (max 5 rounds)
|
||||
| |- Round 1: present gap analysis + expansion suggestions
|
||||
| |- Round N: follow-up refinement based on user responses
|
||||
|- User final confirmation of requirements
|
||||
|- Auto mode (-y): CLI auto-expansion without interaction
|
||||
|- Output: refined-requirements.json
|
||||
|
||||
Phase 2: Product Brief
|
||||
|- Ref: phases/02-product-brief.md
|
||||
|- 3 parallel CLI analyses: Product (Gemini) + Technical (Codex) + User (Claude)
|
||||
@@ -148,6 +160,7 @@ Bash(`mkdir -p "${workDir}"`);
|
||||
.workflow/.spec/SPEC-{slug}-{YYYY-MM-DD}/
|
||||
├── spec-config.json # Session configuration + phase state
|
||||
├── discovery-context.json # Codebase exploration results (optional)
|
||||
├── refined-requirements.json # Phase 1.5: Confirmed requirements after discussion
|
||||
├── product-brief.md # Phase 2: Product brief
|
||||
├── requirements/ # Phase 3: Detailed PRD (directory)
|
||||
│ ├── _index.md # Summary, MoSCoW table, traceability, links
|
||||
@@ -184,8 +197,10 @@ Bash(`mkdir -p "${workDir}"`);
|
||||
"dimensions": []
|
||||
},
|
||||
"has_codebase": false,
|
||||
"refined_requirements_file": "refined-requirements.json",
|
||||
"phasesCompleted": [
|
||||
{ "phase": 1, "name": "discovery", "output_file": "spec-config.json", "completed_at": "ISO8601" },
|
||||
{ "phase": 1.5, "name": "requirement-clarification", "output_file": "refined-requirements.json", "discussion_rounds": 2, "completed_at": "ISO8601" },
|
||||
{ "phase": 3, "name": "requirements", "output_dir": "requirements/", "output_index": "requirements/_index.md", "file_count": 8, "completed_at": "ISO8601" }
|
||||
]
|
||||
}
|
||||
@@ -211,6 +226,12 @@ Bash(`mkdir -p "${workDir}"`);
|
||||
| [phases/01-discovery.md](phases/01-discovery.md) | Seed analysis and session setup | Phase start |
|
||||
| [specs/document-standards.md](specs/document-standards.md) | Frontmatter format for spec-config.json | Config generation |
|
||||
|
||||
### Phase 1.5: Requirement Expansion & Clarification
|
||||
| Document | Purpose | When to Use |
|
||||
|----------|---------|-------------|
|
||||
| [phases/01-5-requirement-clarification.md](phases/01-5-requirement-clarification.md) | Interactive requirement discussion workflow | Phase start |
|
||||
| [specs/quality-gates.md](specs/quality-gates.md) | Quality criteria for refined requirements | Validation |
|
||||
|
||||
### Phase 2: Product Brief
|
||||
| Document | Purpose | When to Use |
|
||||
|----------|---------|-------------|
|
||||
@@ -254,6 +275,9 @@ Bash(`mkdir -p "${workDir}"`);
|
||||
|-------|-------|-----------|--------|
|
||||
| Phase 1 | Empty input | Yes | Error and exit |
|
||||
| Phase 1 | CLI seed analysis fails | No | Use basic parsing fallback |
|
||||
| Phase 1.5 | Gap analysis CLI fails | No | Skip to user questions with basic prompts |
|
||||
| Phase 1.5 | User skips discussion | No | Proceed with seed_analysis as-is |
|
||||
| Phase 1.5 | Max rounds reached (5) | No | Force confirmation with current state |
|
||||
| Phase 2 | Single CLI perspective fails | No | Continue with available perspectives |
|
||||
| Phase 2 | All CLI calls fail | No | Generate basic brief from seed analysis |
|
||||
| Phase 3 | Gemini CLI fails | No | Use codex fallback |
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
# Phase 1.5: Requirement Expansion & Clarification
|
||||
|
||||
在进入正式文档生成前,通过多轮交互讨论对原始需求进行深度挖掘、扩展和确认。
|
||||
|
||||
## Objective
|
||||
|
||||
- 识别原始需求中的模糊点、遗漏和潜在风险
|
||||
- 通过 CLI 辅助分析需求完整性,生成深度探测问题
|
||||
- 支持多轮交互讨论,逐步细化需求
|
||||
- 生成经用户确认的 `refined-requirements.json` 作为后续阶段的高质量输入
|
||||
|
||||
## Input
|
||||
|
||||
- Dependency: `{workDir}/spec-config.json` (Phase 1 output)
|
||||
- Optional: `{workDir}/discovery-context.json` (codebase context)
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Load Phase 1 Context
|
||||
|
||||
```javascript
|
||||
const specConfig = JSON.parse(Read(`${workDir}/spec-config.json`));
|
||||
const { seed_analysis, seed_input, focus_areas, has_codebase, depth } = specConfig;
|
||||
|
||||
let discoveryContext = null;
|
||||
if (has_codebase) {
|
||||
try {
|
||||
discoveryContext = JSON.parse(Read(`${workDir}/discovery-context.json`));
|
||||
} catch (e) { /* proceed without */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: CLI Gap Analysis & Question Generation
|
||||
|
||||
调用 Gemini CLI 分析原始需求的完整性,识别模糊点并生成探测问题。
|
||||
|
||||
```javascript
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: 深度分析用户的初始需求,识别模糊点、遗漏和需要澄清的领域。
|
||||
Success: 生成 3-5 个高质量的探测问题,覆盖功能范围、边界条件、非功能性需求、用户场景等维度。
|
||||
|
||||
ORIGINAL SEED INPUT:
|
||||
${seed_input}
|
||||
|
||||
SEED ANALYSIS:
|
||||
${JSON.stringify(seed_analysis, null, 2)}
|
||||
|
||||
FOCUS AREAS: ${focus_areas.join(', ')}
|
||||
${discoveryContext ? `
|
||||
CODEBASE CONTEXT:
|
||||
- Existing patterns: ${discoveryContext.existing_patterns?.slice(0,5).join(', ') || 'none'}
|
||||
- Tech stack: ${JSON.stringify(discoveryContext.tech_stack || {})}
|
||||
` : ''}
|
||||
|
||||
TASK:
|
||||
1. 评估当前需求描述的完整性(1-10 分,列出缺失维度)
|
||||
2. 识别 3-5 个关键模糊区域,每个区域包含:
|
||||
- 模糊点描述(为什么不清楚)
|
||||
- 1-2 个开放式探测问题
|
||||
- 1-2 个扩展建议(基于领域最佳实践)
|
||||
3. 检查以下维度是否有遗漏:
|
||||
- 功能范围边界(什么在范围内/外?)
|
||||
- 核心用户场景和流程
|
||||
- 非功能性需求(性能、安全、可用性、可扩展性)
|
||||
- 集成点和外部依赖
|
||||
- 数据模型和存储需求
|
||||
- 错误处理和异常场景
|
||||
4. 基于领域经验提供需求扩展建议
|
||||
|
||||
MODE: analysis
|
||||
EXPECTED: JSON output:
|
||||
{
|
||||
\"completeness_score\": 7,
|
||||
\"missing_dimensions\": [\"Performance requirements\", \"Error handling\"],
|
||||
\"clarification_areas\": [
|
||||
{
|
||||
\"area\": \"Scope boundary\",
|
||||
\"rationale\": \"Input does not clarify...\",
|
||||
\"questions\": [\"Question 1?\", \"Question 2?\"],
|
||||
\"suggestions\": [\"Suggestion 1\", \"Suggestion 2\"]
|
||||
}
|
||||
],
|
||||
\"expansion_recommendations\": [
|
||||
{
|
||||
\"category\": \"Non-functional\",
|
||||
\"recommendation\": \"Consider adding...\",
|
||||
\"priority\": \"high|medium|low\"
|
||||
}
|
||||
]
|
||||
}
|
||||
CONSTRAINTS: 问题必须是开放式的,建议必须具体可执行,使用用户输入的语言
|
||||
" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
});
|
||||
// Wait for CLI result before continuing
|
||||
```
|
||||
|
||||
解析 CLI 输出为结构化数据:
|
||||
```javascript
|
||||
const gapAnalysis = {
|
||||
completeness_score: 0,
|
||||
missing_dimensions: [],
|
||||
clarification_areas: [],
|
||||
expansion_recommendations: []
|
||||
};
|
||||
// Parse from CLI output
|
||||
```
|
||||
|
||||
### Step 3: Interactive Discussion Loop
|
||||
|
||||
核心多轮交互循环。每轮:展示分析结果 → 用户回应 → 更新需求状态 → 判断是否继续。
|
||||
|
||||
```javascript
|
||||
// Initialize requirement state
|
||||
let requirementState = {
|
||||
problem_statement: seed_analysis.problem_statement,
|
||||
target_users: seed_analysis.target_users,
|
||||
domain: seed_analysis.domain,
|
||||
constraints: seed_analysis.constraints,
|
||||
confirmed_features: [],
|
||||
non_functional_requirements: [],
|
||||
boundary_conditions: [],
|
||||
integration_points: [],
|
||||
key_assumptions: [],
|
||||
discussion_rounds: 0
|
||||
};
|
||||
|
||||
let discussionLog = [];
|
||||
let userSatisfied = false;
|
||||
|
||||
// === Round 1: Present gap analysis results ===
|
||||
// Display completeness_score, clarification_areas, expansion_recommendations
|
||||
// Then ask user to respond
|
||||
|
||||
while (!userSatisfied && requirementState.discussion_rounds < 5) {
|
||||
requirementState.discussion_rounds++;
|
||||
|
||||
if (requirementState.discussion_rounds === 1) {
|
||||
// --- First round: present initial gap analysis ---
|
||||
// Format questions and suggestions from gapAnalysis for display
|
||||
// Present as a structured summary to the user
|
||||
|
||||
AskUserQuestion({
|
||||
questions: [
|
||||
{
|
||||
question: buildDiscussionPrompt(gapAnalysis, requirementState),
|
||||
header: "Req Expand",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "I'll answer", description: "I have answers/feedback to provide (type in 'Other')" },
|
||||
{ label: "Accept all suggestions", description: "Accept all expansion recommendations as-is" },
|
||||
{ label: "Skip to generation", description: "Requirements are clear enough, proceed directly" }
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
} else {
|
||||
// --- Subsequent rounds: refine based on user feedback ---
|
||||
// Call CLI with accumulated context for follow-up analysis
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: 基于用户最新回应,更新需求理解,识别剩余模糊点。
|
||||
|
||||
CURRENT REQUIREMENT STATE:
|
||||
${JSON.stringify(requirementState, null, 2)}
|
||||
|
||||
DISCUSSION HISTORY:
|
||||
${JSON.stringify(discussionLog, null, 2)}
|
||||
|
||||
USER'S LATEST RESPONSE:
|
||||
${lastUserResponse}
|
||||
|
||||
TASK:
|
||||
1. 将用户回应整合到需求状态中
|
||||
2. 识别 1-3 个仍需澄清或可扩展的领域
|
||||
3. 生成后续问题(如有必要)
|
||||
4. 如果需求已充分,输出最终需求摘要
|
||||
|
||||
MODE: analysis
|
||||
EXPECTED: JSON output:
|
||||
{
|
||||
\"updated_fields\": { /* fields to merge into requirementState */ },
|
||||
\"status\": \"need_more_discussion\" | \"ready_for_confirmation\",
|
||||
\"follow_up\": {
|
||||
\"remaining_areas\": [{\"area\": \"...\", \"questions\": [\"...\"]}],
|
||||
\"summary\": \"...\"
|
||||
}
|
||||
}
|
||||
CONSTRAINTS: 避免重复已回答的问题,聚焦未覆盖的领域
|
||||
" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
});
|
||||
// Wait for CLI result, parse and continue
|
||||
|
||||
// If status === "ready_for_confirmation", break to confirmation step
|
||||
// If status === "need_more_discussion", present follow-up questions
|
||||
|
||||
AskUserQuestion({
|
||||
questions: [
|
||||
{
|
||||
question: buildFollowUpPrompt(followUpAnalysis, requirementState),
|
||||
header: "Follow-up",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "I'll answer", description: "I have more feedback (type in 'Other')" },
|
||||
{ label: "Looks good", description: "Requirements are sufficiently clear now" },
|
||||
{ label: "Accept suggestions", description: "Accept remaining suggestions" }
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// Process user response
|
||||
// - "Skip to generation" / "Looks good" → userSatisfied = true
|
||||
// - "Accept all suggestions" → merge suggestions into requirementState, userSatisfied = true
|
||||
// - "I'll answer" (with Other text) → record in discussionLog, continue loop
|
||||
// - User selects Other with custom text → parse and record
|
||||
|
||||
discussionLog.push({
|
||||
round: requirementState.discussion_rounds,
|
||||
agent_prompt: currentPrompt,
|
||||
user_response: userResponse,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### Helper: Build Discussion Prompt
|
||||
|
||||
```javascript
|
||||
function buildDiscussionPrompt(gapAnalysis, state) {
|
||||
let prompt = `## Requirement Analysis Results\n\n`;
|
||||
prompt += `**Completeness Score**: ${gapAnalysis.completeness_score}/10\n`;
|
||||
|
||||
if (gapAnalysis.missing_dimensions.length > 0) {
|
||||
prompt += `**Missing Dimensions**: ${gapAnalysis.missing_dimensions.join(', ')}\n\n`;
|
||||
}
|
||||
|
||||
prompt += `### Key Questions\n\n`;
|
||||
gapAnalysis.clarification_areas.forEach((area, i) => {
|
||||
prompt += `**${i+1}. ${area.area}**\n`;
|
||||
prompt += ` ${area.rationale}\n`;
|
||||
area.questions.forEach(q => { prompt += ` - ${q}\n`; });
|
||||
if (area.suggestions.length > 0) {
|
||||
prompt += ` Suggestions: ${area.suggestions.join('; ')}\n`;
|
||||
}
|
||||
prompt += `\n`;
|
||||
});
|
||||
|
||||
if (gapAnalysis.expansion_recommendations.length > 0) {
|
||||
prompt += `### Expansion Recommendations\n\n`;
|
||||
gapAnalysis.expansion_recommendations.forEach(rec => {
|
||||
prompt += `- [${rec.priority}] **${rec.category}**: ${rec.recommendation}\n`;
|
||||
});
|
||||
}
|
||||
|
||||
prompt += `\nPlease answer the questions above, or choose an option below.`;
|
||||
return prompt;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Auto Mode Handling
|
||||
|
||||
```javascript
|
||||
if (autoMode) {
|
||||
// Skip interactive discussion
|
||||
// CLI generates default requirement expansion based on seed_analysis
|
||||
Bash({
|
||||
command: `ccw cli -p "PURPOSE: 基于种子分析自动生成需求扩展,无需用户交互。
|
||||
|
||||
SEED ANALYSIS:
|
||||
${JSON.stringify(seed_analysis, null, 2)}
|
||||
|
||||
SEED INPUT: ${seed_input}
|
||||
DEPTH: ${depth}
|
||||
${discoveryContext ? `CODEBASE: ${JSON.stringify(discoveryContext.tech_stack || {})}` : ''}
|
||||
|
||||
TASK:
|
||||
1. 基于领域最佳实践,自动扩展功能需求清单
|
||||
2. 推断合理的非功能性需求
|
||||
3. 识别明显的边界条件
|
||||
4. 列出关键假设
|
||||
|
||||
MODE: analysis
|
||||
EXPECTED: JSON output matching refined-requirements.json schema
|
||||
CONSTRAINTS: 保守推断,只添加高置信度的扩展
|
||||
" --tool gemini --mode analysis`,
|
||||
run_in_background: true
|
||||
});
|
||||
// Parse output directly into refined-requirements.json
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Generate Requirement Confirmation Summary
|
||||
|
||||
在写入文件前,向用户展示最终的需求确认摘要(非 auto mode)。
|
||||
|
||||
```javascript
|
||||
if (!autoMode) {
|
||||
// Build confirmation summary from requirementState
|
||||
const summary = buildConfirmationSummary(requirementState);
|
||||
|
||||
AskUserQuestion({
|
||||
questions: [
|
||||
{
|
||||
question: `## Requirement Confirmation\n\n${summary}\n\nConfirm and proceed to specification generation?`,
|
||||
header: "Confirm",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Confirm & proceed", description: "Requirements confirmed, start spec generation" },
|
||||
{ label: "Need adjustments", description: "Go back and refine further" }
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// If "Need adjustments" → loop back to Step 3
|
||||
// If "Confirm & proceed" → continue to Step 6
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6: Write refined-requirements.json
|
||||
|
||||
```javascript
|
||||
const refinedRequirements = {
|
||||
session_id: specConfig.session_id,
|
||||
phase: "1.5",
|
||||
generated_at: new Date().toISOString(),
|
||||
source: autoMode ? "auto-expansion" : "interactive-discussion",
|
||||
discussion_rounds: requirementState.discussion_rounds,
|
||||
|
||||
// Core requirement content
|
||||
clarified_problem_statement: requirementState.problem_statement,
|
||||
confirmed_target_users: requirementState.target_users.map(u =>
|
||||
typeof u === 'string' ? { name: u, needs: [], pain_points: [] } : u
|
||||
),
|
||||
confirmed_domain: requirementState.domain,
|
||||
|
||||
confirmed_features: requirementState.confirmed_features.map(f => ({
|
||||
name: f.name,
|
||||
description: f.description,
|
||||
acceptance_criteria: f.acceptance_criteria || [],
|
||||
edge_cases: f.edge_cases || [],
|
||||
priority: f.priority || "unset"
|
||||
})),
|
||||
|
||||
non_functional_requirements: requirementState.non_functional_requirements.map(nfr => ({
|
||||
type: nfr.type, // Performance, Security, Usability, Scalability, etc.
|
||||
details: nfr.details,
|
||||
measurable_criteria: nfr.measurable_criteria || ""
|
||||
})),
|
||||
|
||||
boundary_conditions: {
|
||||
in_scope: requirementState.boundary_conditions.filter(b => b.scope === 'in'),
|
||||
out_of_scope: requirementState.boundary_conditions.filter(b => b.scope === 'out'),
|
||||
constraints: requirementState.constraints
|
||||
},
|
||||
|
||||
integration_points: requirementState.integration_points,
|
||||
key_assumptions: requirementState.key_assumptions,
|
||||
|
||||
// Traceability
|
||||
discussion_log: autoMode ? [] : discussionLog
|
||||
};
|
||||
|
||||
Write(`${workDir}/refined-requirements.json`, JSON.stringify(refinedRequirements, null, 2));
|
||||
```
|
||||
|
||||
### Step 7: Update spec-config.json
|
||||
|
||||
```javascript
|
||||
specConfig.refined_requirements_file = "refined-requirements.json";
|
||||
specConfig.phasesCompleted.push({
|
||||
phase: 1.5,
|
||||
name: "requirement-clarification",
|
||||
output_file: "refined-requirements.json",
|
||||
discussion_rounds: requirementState.discussion_rounds,
|
||||
completed_at: new Date().toISOString()
|
||||
});
|
||||
|
||||
Write(`${workDir}/spec-config.json`, JSON.stringify(specConfig, null, 2));
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
- **File**: `refined-requirements.json`
|
||||
- **Format**: JSON
|
||||
- **Updated**: `spec-config.json` (added `refined_requirements_file` field and phase 1.5 to `phasesCompleted`)
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- [ ] Problem statement refined (>= 30 characters, more specific than seed)
|
||||
- [ ] At least 2 confirmed features with descriptions
|
||||
- [ ] At least 1 non-functional requirement identified
|
||||
- [ ] Boundary conditions defined (in-scope + out-of-scope)
|
||||
- [ ] Key assumptions listed (>= 1)
|
||||
- [ ] Discussion rounds recorded (>= 1 in interactive mode)
|
||||
- [ ] User explicitly confirmed requirements (non-auto mode)
|
||||
- [ ] `refined-requirements.json` written with valid JSON
|
||||
- [ ] `spec-config.json` updated with phase 1.5 completion
|
||||
|
||||
## Next Phase
|
||||
|
||||
Proceed to [Phase 2: Product Brief](02-product-brief.md). Phase 2 should load `refined-requirements.json` as primary input instead of relying solely on `spec-config.json.seed_analysis`.
|
||||
@@ -13,6 +13,7 @@ Generate a product brief through multi-perspective CLI analysis, establishing "w
|
||||
## Input
|
||||
|
||||
- Dependency: `{workDir}/spec-config.json`
|
||||
- Primary: `{workDir}/refined-requirements.json` (Phase 1.5 output, preferred over raw seed_analysis)
|
||||
- Optional: `{workDir}/discovery-context.json`
|
||||
- Config: `{workDir}/spec-config.json`
|
||||
- Template: `templates/product-brief.md`
|
||||
@@ -25,6 +26,14 @@ Generate a product brief through multi-perspective CLI analysis, establishing "w
|
||||
const specConfig = JSON.parse(Read(`${workDir}/spec-config.json`));
|
||||
const { seed_analysis, seed_input, has_codebase, depth, focus_areas } = specConfig;
|
||||
|
||||
// Load refined requirements (Phase 1.5 output) - preferred over raw seed_analysis
|
||||
let refinedReqs = null;
|
||||
try {
|
||||
refinedReqs = JSON.parse(Read(`${workDir}/refined-requirements.json`));
|
||||
} catch (e) {
|
||||
// No refined requirements, fall back to seed_analysis
|
||||
}
|
||||
|
||||
let discoveryContext = null;
|
||||
if (has_codebase) {
|
||||
try {
|
||||
@@ -35,13 +44,25 @@ if (has_codebase) {
|
||||
}
|
||||
|
||||
// Build shared context string for CLI prompts
|
||||
// Prefer refined requirements over raw seed_analysis
|
||||
const problem = refinedReqs?.clarified_problem_statement || seed_analysis.problem_statement;
|
||||
const users = refinedReqs?.confirmed_target_users?.map(u => u.name || u).join(', ')
|
||||
|| seed_analysis.target_users.join(', ');
|
||||
const domain = refinedReqs?.confirmed_domain || seed_analysis.domain;
|
||||
const constraints = refinedReqs?.boundary_conditions?.constraints?.join(', ')
|
||||
|| seed_analysis.constraints.join(', ');
|
||||
const features = refinedReqs?.confirmed_features?.map(f => f.name).join(', ') || '';
|
||||
const nfrs = refinedReqs?.non_functional_requirements?.map(n => `${n.type}: ${n.details}`).join('; ') || '';
|
||||
|
||||
const sharedContext = `
|
||||
SEED: ${seed_input}
|
||||
PROBLEM: ${seed_analysis.problem_statement}
|
||||
TARGET USERS: ${seed_analysis.target_users.join(', ')}
|
||||
DOMAIN: ${seed_analysis.domain}
|
||||
CONSTRAINTS: ${seed_analysis.constraints.join(', ')}
|
||||
PROBLEM: ${problem}
|
||||
TARGET USERS: ${users}
|
||||
DOMAIN: ${domain}
|
||||
CONSTRAINTS: ${constraints}
|
||||
FOCUS AREAS: ${focus_areas.join(', ')}
|
||||
${features ? `CONFIRMED FEATURES: ${features}` : ''}
|
||||
${nfrs ? `NON-FUNCTIONAL REQUIREMENTS: ${nfrs}` : ''}
|
||||
${discoveryContext ? `
|
||||
CODEBASE CONTEXT:
|
||||
- Existing patterns: ${discoveryContext.existing_patterns?.slice(0,5).join(', ') || 'none'}
|
||||
|
||||
@@ -81,6 +81,7 @@ Examples:
|
||||
|------|-------|-------------|
|
||||
| `spec-config.json` | 1 | Session configuration and state |
|
||||
| `discovery-context.json` | 1 | Codebase exploration results (optional) |
|
||||
| `refined-requirements.json` | 1.5 | Confirmed requirements after discussion |
|
||||
| `product-brief.md` | 2 | Product brief document |
|
||||
| `requirements.md` | 3 | PRD document |
|
||||
| `architecture.md` | 4 | Architecture decisions document |
|
||||
@@ -168,6 +169,7 @@ Derived from [REQ-001](requirements.md#req-001).
|
||||
"dimensions": ["string array - 3-5 exploration dimensions"]
|
||||
},
|
||||
"has_codebase": "boolean",
|
||||
"refined_requirements_file": "string (optional) - path to refined-requirements.json",
|
||||
"phasesCompleted": [
|
||||
{
|
||||
"phase": "number (1-6)",
|
||||
@@ -181,6 +183,60 @@ Derived from [REQ-001](requirements.md#req-001).
|
||||
|
||||
---
|
||||
|
||||
## refined-requirements.json Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "string (required) - matches spec-config.json",
|
||||
"phase": "1.5",
|
||||
"generated_at": "ISO8601 (required)",
|
||||
"source": "interactive-discussion|auto-expansion (required)",
|
||||
"discussion_rounds": "number (required) - 0 for auto mode",
|
||||
"clarified_problem_statement": "string (required) - refined problem statement",
|
||||
"confirmed_target_users": [
|
||||
{
|
||||
"name": "string",
|
||||
"needs": ["string array"],
|
||||
"pain_points": ["string array"]
|
||||
}
|
||||
],
|
||||
"confirmed_domain": "string",
|
||||
"confirmed_features": [
|
||||
{
|
||||
"name": "string",
|
||||
"description": "string",
|
||||
"acceptance_criteria": ["string array"],
|
||||
"edge_cases": ["string array"],
|
||||
"priority": "must|should|could|unset"
|
||||
}
|
||||
],
|
||||
"non_functional_requirements": [
|
||||
{
|
||||
"type": "Performance|Security|Usability|Scalability|Reliability|...",
|
||||
"details": "string",
|
||||
"measurable_criteria": "string (optional)"
|
||||
}
|
||||
],
|
||||
"boundary_conditions": {
|
||||
"in_scope": ["string array"],
|
||||
"out_of_scope": ["string array"],
|
||||
"constraints": ["string array"]
|
||||
},
|
||||
"integration_points": ["string array"],
|
||||
"key_assumptions": ["string array"],
|
||||
"discussion_log": [
|
||||
{
|
||||
"round": "number",
|
||||
"agent_prompt": "string",
|
||||
"user_response": "string",
|
||||
"timestamp": "ISO8601"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
- [ ] Every document starts with valid YAML frontmatter
|
||||
|
||||
@@ -88,6 +88,18 @@ Content provides sufficient detail for execution teams.
|
||||
| Dimensions generated | 3-5 exploration dimensions | Warning |
|
||||
| Constraints listed | >= 0 (can be empty with justification) | Info |
|
||||
|
||||
### Phase 1.5: Requirement Expansion & Clarification
|
||||
|
||||
| Check | Criteria | Severity |
|
||||
|-------|----------|----------|
|
||||
| Problem statement refined | More specific than seed, >= 30 characters | Error |
|
||||
| Confirmed features | >= 2 features with descriptions | Error |
|
||||
| Non-functional requirements | >= 1 identified (performance, security, etc.) | Warning |
|
||||
| Boundary conditions | In-scope and out-of-scope defined | Warning |
|
||||
| Key assumptions | >= 1 assumption listed | Warning |
|
||||
| User confirmation | Explicit user confirmation recorded (non-auto mode) | Info |
|
||||
| Discussion rounds | >= 1 round of interaction (non-auto mode) | Info |
|
||||
|
||||
### Phase 2: Product Brief
|
||||
|
||||
| Check | Criteria | Severity |
|
||||
|
||||
Reference in New Issue
Block a user