Files
Agent-System/internal/projectworkflow/catalog.go
T
weichenandCursor dba8139d56 feat(workflow): namespace task keys without breaking old instances
Published manifests now use bd_/pm_/tm_/sw_ prefixes so workflows cannot share a doc id. Frozen instances keep the old keys; lookup, templates, and duty checks treat the two names as the same task.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 10:50:25 +00:00

157 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package projectworkflow
import "sync"
// Definition 工作流静态规范与契约定义
type Definition struct {
Key string `json:"key"`
Name string `json:"name"`
Description string `json:"description"`
StageKey string `json:"stage_key"`
TaskKey string `json:"task_key"`
RequiredUpstreamWorkflow string `json:"required_upstream_workflow,omitempty"`
OutputDocType string `json:"output_doc_type"`
OutputDocTitle string `json:"output_doc_title"`
Enabled bool `json:"enabled"`
}
// Catalog 工作流目录接口
type Catalog interface {
Get(workflowKey string) (*Definition, bool)
List() []*Definition
Validate() error
}
type memoryCatalog struct {
mu sync.RWMutex
definitions map[string]*Definition
order []string
}
// NewDefaultCatalog 创建默认工作流目录(医疗四 + 软件自举/交付)
func NewDefaultCatalog() Catalog {
c := &memoryCatalog{
definitions: make(map[string]*Definition),
order: []string{"main", "product_manager", "test_manager", "rdev", "software_bootstrap", "software_delivery"},
}
c.definitions["main"] = &Definition{
Key: "main",
Name: "商务与研发综合主线",
Description: "覆盖从 V0.1 分诊到 V0.6 阶段评审的全流程智能体编排与商务研发主干协同",
StageKey: "main",
TaskKey: "main",
OutputDocType: "main_proposal",
OutputDocTitle: "商务研发综合方案",
Enabled: true,
}
c.definitions["product_manager"] = &Definition{
Key: "product_manager",
Name: "智能产品经理",
Description: "基于用户需求或项目上下文深度提炼,生成高可靠、可追溯的系统需求规格书",
StageKey: "system_reqs",
TaskKey: "system_reqs",
OutputDocType: "system_reqs",
OutputDocTitle: "系统需求规格书",
Enabled: true,
}
c.definitions["test_manager"] = &Definition{
Key: "test_manager",
Name: "智能测试经理",
Description: "依赖产品经理已批准的系统需求规格书,生成全覆盖、满足法规要求的系统验证方案及计划",
StageKey: "system_test_plan",
TaskKey: "test_manager",
RequiredUpstreamWorkflow: "product_manager",
OutputDocType: "system_test_plan",
OutputDocTitle: "系统验证方案及计划",
Enabled: true,
}
c.definitions["rdev"] = &Definition{
Key: "rdev",
Name: "研发设计控制流程",
Description: "ISO 13485 设计控制:13 阶段 / 60 受控文档(DHF/DMR)",
StageKey: "RD01_planning",
TaskKey: "rd_proposal",
OutputDocType: "rd_proposal",
OutputDocTitle: "项目建议书",
Enabled: true,
}
c.definitions["software_bootstrap"] = &Definition{
Key: "software_bootstrap",
Name: "软件项目自举流程",
Description: "S0–S4:章程、现状、需求、架构、风险、路线与就绪评审",
StageKey: "S0_boundary",
TaskKey: "sw_software_charter",
OutputDocType: "sw_software_charter",
OutputDocTitle: "项目章程",
Enabled: true,
}
c.definitions["software_delivery"] = &Definition{
Key: "software_delivery",
Name: "软件交付迭代流程",
Description: "D0–D4:变更定义、实施证据、验证、发布与复盘",
StageKey: "D0_change_definition",
TaskKey: "sw_change_brief",
OutputDocType: "sw_change_brief",
OutputDocTitle: "变更简报",
Enabled: true,
}
return c
}
// WorkflowKeysForProductDomain returns the catalog keys to mount at create time.
// Empty domain keeps the full catalog (legacy medical create).
func WorkflowKeysForProductDomain(domain string) []string {
switch domain {
case "non_medical_software":
return []string{"software_bootstrap", "software_delivery"}
case "medical_device":
return []string{"main", "product_manager", "test_manager", "rdev"}
default:
return nil
}
}
func (c *memoryCatalog) Get(workflowKey string) (*Definition, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
d, ok := c.definitions[workflowKey]
if !ok {
return nil, false
}
cpy := *d
return &cpy, true
}
func (c *memoryCatalog) List() []*Definition {
c.mu.RLock()
defer c.mu.RUnlock()
list := make([]*Definition, 0, len(c.order))
for _, key := range c.order {
if d, ok := c.definitions[key]; ok {
cpy := *d
list = append(list, &cpy)
}
}
return list
}
func (c *memoryCatalog) Validate() error {
c.mu.RLock()
defer c.mu.RUnlock()
for _, def := range c.definitions {
if def.RequiredUpstreamWorkflow != "" {
if _, ok := c.definitions[def.RequiredUpstreamWorkflow]; !ok {
return ErrWorkflowNotFound
}
}
}
return nil
}