feat(workflow): Phase 4 智能产品经理工作流、系统需求规格书与质量门禁

This commit is contained in:
WeiCHEN
2026-09-10 23:48:40 +08:00
parent 0961e180a3
commit 9d33b1c804
6 changed files with 453 additions and 2 deletions
+48 -2
View File
@@ -187,9 +187,55 @@ func (s *Service) ExecuteTask(ctx context.Context, req TaskRunRequest) (*TaskRun
})
}
// 自动补充知识库检索 (如针对 research、feasibility_reg、cleanroom_spec、prelim_design 等阶段)
// 针对 system_reqs(智能产品经理):若未显式提供 materials,自动抽取项目事实黑板/集体上下文为需求输入
if req.TaskKey == "system_reqs" && len(materials) == 0 && s.ctxMgr != nil && req.ProjectID > 0 {
coll, err := s.ctxMgr.GetProjectContext(ctx, req.ProjectID)
if err == nil && coll != nil {
var b strings.Builder
customer := coll.BlackboardFacts["customer_name"]
if customer == "" {
customer = req.CustomerName
}
device := coll.BlackboardFacts["device_type"]
if device == "" {
device = req.DeviceType
}
intendedUse := coll.BlackboardFacts["intended_use"]
if intendedUse == "" {
intendedUse = req.IntendedUse
}
targetMarket := coll.BlackboardFacts["target_market"]
if targetMarket == "" {
targetMarket = req.TargetMarket
}
b.WriteString(fmt.Sprintf("# 项目需求背景事实与上下文输入\n\n- 项目名称: %s\n- 客户名称: %s\n- 产品类型: %s\n- 预期用途: %s\n- 目标市场: %s\n\n",
coll.ProjectName, customer, device, intendedUse, targetMarket))
if len(coll.BlackboardFacts) > 0 {
b.WriteString("## 已提取项目事实与技术参数\n")
for k, v := range coll.BlackboardFacts {
b.WriteString(fmt.Sprintf("- %s: %s\n", k, v))
}
b.WriteString("\n")
}
if len(coll.MilestoneDecisions) > 0 {
b.WriteString("## 关键里程碑与团队决策\n")
for _, d := range coll.MilestoneDecisions {
b.WriteString(fmt.Sprintf("- [%s] %s: %s\n", d.UserName, d.ActivityType, d.Title))
}
b.WriteString("\n")
}
materials = append(materials, squad.MaterialItem{
Filename: "project_requirements_context.md",
Content: []byte(b.String()),
})
}
}
// 自动补充知识库检索 (如针对 research、feasibility_reg、cleanroom_spec、prelim_design、system_reqs、test_manager 等阶段)
hits := req.KnowledgeHits
if len(hits) == 0 && (req.TaskKey == "research" || req.TaskKey == "feasibility_reg" || req.TaskKey == "cleanroom_spec" || req.TaskKey == "prelim_design") {
if len(hits) == 0 && (req.TaskKey == "research" || req.TaskKey == "feasibility_reg" || req.TaskKey == "cleanroom_spec" || req.TaskKey == "prelim_design" || req.TaskKey == "system_reqs" || req.TaskKey == "test_manager") {
device := req.DeviceType
if device == "" && req.Fields != nil {
device = req.Fields["device_type"]
+41
View File
@@ -4,6 +4,7 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"os"
@@ -104,6 +105,46 @@ func (q *QualityGate) Validate(wsDir string, taskKey string, content string) (*Q
}
}
// 5. 智能产品经理工作流:系统需求规格书检查
if taskKey == "system_reqs" {
if !strings.Contains(content, "REQ-") && !strings.Contains(content, "SYS-REQ") {
report.Violations = append(report.Violations, "系统需求规格书缺少规范的需求编号(如 REQ-01 / SYS-REQ-01)")
report.Score -= 20.0
report.Passed = false
}
hasVerification := strings.Contains(content, "测试") || strings.Contains(content, "分析") ||
strings.Contains(content, "审查") || strings.Contains(content, "演示") ||
strings.Contains(content, "检验") || strings.Contains(content, "检") || strings.Contains(content, "测")
if !hasVerification {
report.Violations = append(report.Violations, "系统需求清单缺少验证方式字段(测试/分析/审查/演示)")
report.Score -= 15.0
report.Passed = false
}
}
// 6. 智能测试经理工作流:系统验证方案及计划检查
if taskKey == "test_manager" {
if !strings.Contains(content, "TC-") && !strings.Contains(content, "TEST-") {
report.Violations = append(report.Violations, "系统验证方案缺少规范的测试用例编号(如 TC-01 / TEST-01)")
report.Score -= 20.0
report.Passed = false
}
if !strings.Contains(content, "REQ-") {
report.Violations = append(report.Violations, "系统验证方案缺少对上游系统需求编号(REQ-)的追溯覆盖")
report.Score -= 15.0
report.Passed = false
}
tcPath := filepath.Join(wsDir, "artifacts", "test_cases.json")
if tcData, err := os.ReadFile(tcPath); err == nil && len(tcData) > 0 {
var dummy any
if err := json.Unmarshal(tcData, &dummy); err != nil {
report.Violations = append(report.Violations, "artifacts/test_cases.json 不是合法的 JSON 格式")
report.Score -= 10.0
report.Passed = false
}
}
}
if report.Score < 0 {
report.Score = 0
}
+70
View File
@@ -131,3 +131,73 @@ func TestQualityGate_AutoRepair(t *testing.T) {
t.Errorf("expected non-nil quality report")
}
}
func TestQualityGate_SystemReqsAndTestManager(t *testing.T) {
tmpDir := t.TempDir()
engine := squad.NewWorkspaceEngine()
gate := squad.NewQualityGate()
// 1. 测试 system_reqs
ws1, err := engine.PrepareWorkspace(squad.WorkspacePrepareRequest{
WorkDir: filepath.Join(tmpDir, "ws_reqs"),
TaskKey: "system_reqs",
StageTitle: "系统需求规格书",
ProjectName: "医疗监护仪",
TemplateContent: "# 系统需求规格书\n\n## 1. 结论\n\n## 2. 系统需求清单\n",
})
if err != nil {
t.Fatalf("PrepareWorkspace failed: %v", err)
}
// 缺少需求编号和验证方式
badReqContent := "# 系统需求规格书\n\n## 1. 结论\n结论完整\n\n## 2. 系统需求清单\n系统应支持心率采集。\n"
rep1, err := gate.Validate(ws1.WorkDir, "system_reqs", badReqContent)
if err != nil {
t.Fatalf("Validate failed: %v", err)
}
if rep1.Passed {
t.Errorf("expected system_reqs missing REQ- and verification to fail")
}
// 合规文本
goodReqContent := "# 系统需求规格书\n\n## 1. 结论\n结论完整\n\n## 2. 系统需求清单\n| REQ-01 | 系统应支持心率监测,测量误差不超过 ±2bpm | 测试 | 高 |\n"
rep2, err := gate.Validate(ws1.WorkDir, "system_reqs", goodReqContent)
if err != nil {
t.Fatalf("Validate failed: %v", err)
}
if !rep2.Passed {
t.Errorf("expected compliant system_reqs to pass, got violations: %v", rep2.Violations)
}
// 2. 测试 test_manager
ws2, err := engine.PrepareWorkspace(squad.WorkspacePrepareRequest{
WorkDir: filepath.Join(tmpDir, "ws_test"),
TaskKey: "test_manager",
StageTitle: "系统验证方案及计划",
ProjectName: "医疗监护仪",
TemplateContent: "# 系统验证方案及计划\n\n## 1. 结论\n\n## 2. 用例与验证规程\n",
})
if err != nil {
t.Fatalf("PrepareWorkspace failed: %v", err)
}
// 缺少用例和上游追溯
badTestContent := "# 系统验证方案及计划\n\n## 1. 结论\n结论\n\n## 2. 用例与验证规程\n验证功能正常。\n"
rep3, err := gate.Validate(ws2.WorkDir, "test_manager", badTestContent)
if err != nil {
t.Fatalf("Validate failed: %v", err)
}
if rep3.Passed {
t.Errorf("expected test_manager missing TC- and REQ- to fail")
}
// 合规文本
goodTestContent := "# 系统验证方案及计划\n\n## 1. 结论\n结论\n\n## 2. 用例与验证规程\n| TC-01 | 验证心率测量精度 | 追溯 REQ-01 | 判定准则误差 <= ±2bpm | 通过 |\n"
rep4, err := gate.Validate(ws2.WorkDir, "test_manager", goodTestContent)
if err != nil {
t.Fatalf("Validate failed: %v", err)
}
if !rep4.Passed {
t.Errorf("expected compliant test_manager to pass, got violations: %v", rep4.Violations)
}
}
+2
View File
@@ -127,6 +127,8 @@ var SupportedTasks = []TaskMeta{
{Key: "feasibility_dev", Title: "设计开发可行性评估", ArtifactTitle: "设计开发可行性评估报告", Description: "工程化差距、技术路线与系统架构可行性推导"},
{Key: "feasibility_reg", Title: "注册路径可行性评估", ArtifactTitle: "注册路径可行性评估报告", Description: "分类建议、临床评价策略与主要标准检测规划"},
{Key: "user_requirements", Title: "用户需求表", ArtifactTitle: "用户需求表", Description: "用户角色画像与可追溯需求条目清单"},
{Key: "system_reqs", Title: "系统需求规格书", ArtifactTitle: "系统需求规格书", Description: "智能产品经理深度提炼,输出系统需求规格书及工程追溯"},
{Key: "test_manager", Title: "系统验证方案及计划", ArtifactTitle: "系统验证方案及计划", Description: "智能测试经理基于系统需求生成系统测试方案与测试用例"},
{Key: "prelim_design", Title: "系统初步设计方案", ArtifactTitle: "系统初步设计方案", Description: "子系统架构边界、数据接口与Mermaid上下文流向"},
{Key: "cdo_quote", Title: "CDO报价单", ArtifactTitle: "CDO报价单(含定价核算 Excel)", Description: "基于公司定价模型的工时拆解、成本核算与法定说明"},
}
+230
View File
@@ -645,6 +645,102 @@ func DefaultSquadAgents(taskKey string) []AgentSpec {
ForbiddenActions: []string{"严禁代用户做商业拍板"},
},
}
case "system_reqs":
return []AgentSpec{
{
Role: "organizer",
Name: "需求梳理专员",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"用户需求抽取", "产品定位基线对齐", "UR需求池建立"},
ForbiddenActions: []string{"严禁随意篡改原始用户需求"},
},
{
Role: "engineer",
Name: "系统工程架构师",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"系统需求分解", "验证方式定义", "接口定义", "requirements.json 导出"},
ForbiddenActions: []string{"严禁遗漏验证方式", "严禁需求编号重复"},
},
{
Role: "regulatory",
Name: "法规合规审查专员",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"医疗器械强标比对", "适用性与理由论证"},
ForbiddenActions: []string{"严禁引用虚构标准号"},
},
{
Role: "writer",
Name: "系统需求文档编制专员",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"严格按 system_reqs.md 模板成文", "正文结构完整", "填满追溯表"},
ForbiddenActions: []string{"严禁残留占位符", "严禁写不做展开"},
},
{
Role: "leader",
Name: "智能产品经理主管",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"系统需求规格书终审", "追溯一致性把关", "质量门禁验收"},
ForbiddenActions: []string{"严禁放行未覆盖验证方式的需求"},
},
}
case "test_manager":
return []AgentSpec{
{
Role: "organizer",
Name: "需求追溯分析员",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"上游系统需求解析", "需求全集锁定", "追溯关系初始化"},
ForbiddenActions: []string{"严禁遗漏任一条上游需求"},
},
{
Role: "engineer",
Name: "系统测试工程师",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"系统验证用例设计", "判据与接受准则", "test_cases.json 导出"},
ForbiddenActions: []string{"严禁测试方法泛化为仅写标准号", "严禁无判定准则"},
},
{
Role: "regulatory",
Name: "试验标准审查员",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"检验方法符合性评估", "检测设备与环境要求审查"},
ForbiddenActions: []string{"严禁使用过期作废标准"},
},
{
Role: "writer",
Name: "系统测试方案编制专员",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"严格按 test_manager.md 模板成文", "用例主表翔实完整"},
ForbiddenActions: []string{"严禁残留占位符", "严禁写不做展开"},
},
{
Role: "leader",
Name: "智能测试经理主管",
Model: "claude-3-7-sonnet",
Tools: []string{"read", "write", "edit"},
BashPermission: "deny",
Responsibilities: []string{"系统验证方案终审", "全覆盖无静默遗漏门禁把关", "质量签署"},
ForbiddenActions: []string{"严禁放行覆盖率不足 100% 的方案"},
},
}
default:
return []AgentSpec{
{
@@ -841,6 +937,140 @@ func DefaultWorkflowSteps(taskKey string) []StepSpec {
},
},
}
case "system_reqs":
return []StepSpec{
{
ID: "step_01_organize",
Role: "organizer",
Title: "解析用户需求并抽取产品功能点",
SubWorkspace: "tasks/01_organize",
Mode: "execute",
Accept: []string{
"抽取用户需求或项目事实黑板中的关键需求条目",
"提取系统功能、非功能指标及环境约束",
"向 blackboard 写入 facts 与 gaps",
},
},
{
ID: "step_02_engineer",
Role: "engineer",
Title: "系统技术规格与性能指标分解",
SubWorkspace: "tasks/02_engineer",
Mode: "execute",
Needs: []string{"tasks/01_organize/output.md"},
Accept: []string{
"定义子系统性能、电气/软件/机械指标与参数",
"规范接口协议与环境要求",
},
},
{
ID: "step_03_regulatory",
Role: "regulatory",
Title: "医疗器械强标比对与合规性论证",
SubWorkspace: "tasks/03_regulatory",
Mode: "execute",
Needs: []string{"tasks/01_organize/output.md"},
Accept: []string{
"审查适用医疗器械强制性标准及条款要求",
"输出安全、可靠性与合规性约束条目",
},
},
{
ID: "step_04_draft",
Role: "writer",
Title: "编制系统需求规格书全文",
SubWorkspace: "tasks/04_draft",
Mode: "execute",
Needs: []string{
"tasks/01_organize/output.md",
"tasks/02_engineer/output.md",
"tasks/03_regulatory/output.md",
},
Accept: []string{
"按 template.md 结构展开,包含系统需求清单与接口要求",
"每条系统需求必须具备明确唯一的 REQ- 编号与验证方式",
"禁止敷衍套话与未替换占位符",
},
},
{
ID: "step_05_review",
Role: "leader",
Title: "终审需求可测性与可追溯性定稿",
SubWorkspace: "tasks/05_review",
Mode: "execute",
Needs: []string{"tasks/04_draft/output.md"},
Accept: []string{
"全面核查需求条目可验证性与无歧义性",
"核查追溯关系完整性并交付终稿",
},
},
}
case "test_manager":
return []StepSpec{
{
ID: "step_01_trace",
Role: "organizer",
Title: "解析上游系统需求并锁定全量追溯矩阵",
SubWorkspace: "tasks/01_trace",
Mode: "execute",
Accept: []string{
"全量读取上游系统需求规格书的所有 REQ- 编号条目",
"建立 100% 覆盖的测试需求追溯矩阵底表",
},
},
{
ID: "step_02_cases",
Role: "engineer",
Title: "设计系统测试用例与判定准则",
SubWorkspace: "tasks/02_cases",
Mode: "execute",
Needs: []string{"tasks/01_trace/output.md"},
Accept: []string{
"为每条需求设计至少一个具备明确合格判定准则的测试用例 TC-",
"导出 test_cases.json 结构化用例清单至 artifacts/",
},
},
{
ID: "step_03_regulatory",
Role: "regulatory",
Title: "检验规程与检测环境合规审查",
SubWorkspace: "tasks/03_regulatory",
Mode: "execute",
Needs: []string{"tasks/02_cases/output.md"},
Accept: []string{
"核验测试方法与引用的医疗器械检验标准条款一致性",
"审查仪器设备与测试环境要求",
},
},
{
ID: "step_04_draft",
Role: "writer",
Title: "编制系统验证方案及计划全文",
SubWorkspace: "tasks/04_draft",
Mode: "execute",
Needs: []string{
"tasks/01_trace/output.md",
"tasks/02_cases/output.md",
"tasks/03_regulatory/output.md",
},
Accept: []string{
"严格按 test_manager.md 模板生成正式方案文本",
"嵌入测试用例清单与覆盖率统计,严禁遗漏上游需求",
},
},
{
ID: "step_05_review",
Role: "leader",
Title: "全覆盖门禁终审与定稿交付",
SubWorkspace: "tasks/05_review",
Mode: "execute",
Needs: []string{"tasks/04_draft/output.md"},
Accept: []string{
"验证需求覆盖率达到 100%",
"签署验证结论并交付",
},
},
}
default:
return []StepSpec{
{
+62
View File
@@ -0,0 +1,62 @@
# 系统需求规格书(SR)
- 项目:{{project_name}}
- 生成时间:{{generated_at}}
- 快照:{{snapshot_id}}
- 文件编号:RD-SR
- 记录归属:DHF
- 版本:A
- 阶段:03 设计输入
## 结论
{{conclusion}}
## 适用性
- 适用 / 不适用:{{applicability}}
- 不适用理由:{{na_rationale}}
## 产品定位与预期用途
- 产品名称:{{project_name}}
- 适用人群与场景:{{intended_use}}
- 目标市场与监管路径:{{target_market}}
## 系统需求清单
| ID | 需求陈述 | 追溯 UR/UN | 验证方式 | 优先级 |
| --- | --- | --- | --- | --- |
{{system_requirements_table}}
## 接口与环境要求
| 接口类型 | 说明与技术参数 | 协议/物理接口 |
| --- | --- | --- |
{{interface_requirements_table}}
## 追溯关系
| 本文件 ID | 上游(输入/需求) | 下游(输出/验证/确认) |
| --- | --- | --- |
| RD-SR | 用户需求文档 / 项目立项事实上下文 | 系统验证方案及计划 (RD-SVP) |
## 已有材料摘要
{{materials}}
## 待确认清单
{{pending_items}}
## 签署
| 角色 | 姓名 | 结论 | 日期 |
| --- | --- | --- | --- |
| 编制 | {{author_name}} | 已编制 | {{generated_at}} |
| 审核 | {{reviewer_name}} | 待审核 | |
| 批准 | {{approver_name}} | 待批准 | |
## 说明
本文档由智能产品经理小队在任务快照上生成,属于受控设计输入历史记录。后续补充的材料不会静默改变本次版本内容。