Introduce Phase 2 IAM-adjacent schema for versioned workflow definitions, template assets/versions, and workflow_defs permissions seed. Co-authored-by: Cursor <cursoragent@cursor.com>
140 lines
5.4 KiB
Go
140 lines
5.4 KiB
Go
package workflowdef
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"chat-agent-system/internal/projectworkflow"
|
|
"chat-agent-system/internal/storage"
|
|
)
|
|
|
|
func legacySingleStage(key, name, desc, stageKey, taskKey, docType, docTitle, upstream string) CreateDefinitionInput {
|
|
return CreateDefinitionInput{
|
|
Key: key,
|
|
Name: name,
|
|
Description: desc,
|
|
ProductDomain: "medical_device",
|
|
Definition: VersionDefinition{
|
|
SchemaVersion: 1,
|
|
RequiredUpstreamWorkflow: upstream,
|
|
Stages: []StageDef{{
|
|
Key: stageKey, Name: stageKey, Position: 0,
|
|
DocTasks: []DocTaskDef{{
|
|
Key: taskKey, Title: docTitle, Required: true, Blocking: true, DefaultEnabled: true,
|
|
OutputDocType: docType, OutputDocTitle: docTitle,
|
|
TemplateAssetKey: taskKey, TemplateVersion: 1,
|
|
}},
|
|
}},
|
|
},
|
|
}
|
|
}
|
|
|
|
// BootstrapSeeds 幂等导入静态 catalog、首批行业工作流与 templates/docs。
|
|
func BootstrapSeeds(ctx context.Context, pool *pgxpool.Pool, cas *storage.CAS, templatesDir string, publishedBy int64) error {
|
|
if pool == nil || !TablesReady(ctx, pool) {
|
|
return nil
|
|
}
|
|
store := NewStore(pool)
|
|
svc := NewService(pool, cas)
|
|
|
|
if templatesDir == "" {
|
|
templatesDir = "templates/docs"
|
|
}
|
|
entries, err := os.ReadDir(templatesDir)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
for _, ent := range entries {
|
|
if ent.IsDir() || !strings.HasSuffix(strings.ToLower(ent.Name()), ".md") {
|
|
continue
|
|
}
|
|
key := strings.TrimSuffix(ent.Name(), filepath.Ext(ent.Name()))
|
|
data, readErr := os.ReadFile(filepath.Join(templatesDir, ent.Name()))
|
|
if readErr != nil || len(data) == 0 {
|
|
continue
|
|
}
|
|
_, _ = svc.UploadTemplate(ctx, key, ent.Name(), data, ent.Name(), publishedBy)
|
|
}
|
|
|
|
seeds := []CreateDefinitionInput{
|
|
legacySingleStage("main", "商务与研发综合主线", "V0.1 分诊到 V0.6 阶段评审", "main", "main", "main_proposal", "商务研发综合方案", ""),
|
|
legacySingleStage("product_manager", "智能产品经理", "系统需求规格书生成", "system_reqs", "system_reqs", "system_reqs", "系统需求规格书", ""),
|
|
legacySingleStage("test_manager", "智能测试经理", "系统验证方案及计划", "system_test_plan", "test_manager", "system_test_plan", "系统验证方案及计划", "product_manager"),
|
|
medicalDeviceWorkflow(),
|
|
nonMedicalSoftwareWorkflow(),
|
|
}
|
|
for _, seed := range seeds {
|
|
if err := store.UpsertPublishedSeed(ctx, seed, publishedBy); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func medicalDeviceWorkflow() CreateDefinitionInput {
|
|
return CreateDefinitionInput{
|
|
Key: "medical_device_development",
|
|
Name: "医疗器械研发",
|
|
Description: "商务摸底 → 需求策划 → 设计开发 → 验证确认 → 设计转移",
|
|
ProductDomain: "medical_device",
|
|
Definition: VersionDefinition{
|
|
SchemaVersion: 1,
|
|
Stages: []StageDef{
|
|
stage("biz_intake", "商务摸底", 0, doc("intake", "客户需求采集", "intake", "客户需求采集表")),
|
|
stage("req_planning", "需求与法规策划", 1, doc("system_reqs", "系统需求规格书", "system_reqs", "系统需求规格书")),
|
|
stage("design_dev", "设计开发", 2, doc("prelim_design", "初步设计", "prelim_design", "初步设计文档")),
|
|
stage("verification", "设计验证/确认", 3, doc("test_manager", "系统验证方案", "system_test_plan", "系统验证方案及计划")),
|
|
stage("transfer", "设计转移/发布", 4, doc("feasibility_reg", "法规可行性", "feasibility_reg", "法规可行性评估")),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func nonMedicalSoftwareWorkflow() CreateDefinitionInput {
|
|
return CreateDefinitionInput{
|
|
Key: "non_medical_software",
|
|
Name: "非医疗纯软件",
|
|
Description: "机会范围 → 需求 → 架构 → 实现 → 测试验收 → 发布复盘",
|
|
ProductDomain: "non_medical_software",
|
|
Definition: VersionDefinition{
|
|
SchemaVersion: 1,
|
|
Stages: []StageDef{
|
|
stage("opportunity", "机会与范围", 0, doc("intake", "范围说明", "scope_doc", "项目范围说明")),
|
|
stage("requirements", "产品需求", 1, doc("user_requirements", "用户需求", "user_requirements", "用户需求说明")),
|
|
stage("architecture", "架构与计划", 2, doc("feasibility_dev", "技术可行性", "feasibility_dev", "技术可行性分析")),
|
|
stage("implementation", "实现", 3, doc("prelim_design", "架构设计", "architecture_design", "架构设计文档")),
|
|
stage("testing", "测试与验收", 4, doc("test_manager", "测试计划", "test_plan", "测试计划")),
|
|
stage("release", "发布复盘", 5, doc("research", "发布复盘", "release_review", "发布复盘报告")),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func stage(key, name string, pos int, tasks ...DocTaskDef) StageDef {
|
|
return StageDef{Key: key, Name: name, Position: pos, DocTasks: tasks}
|
|
}
|
|
|
|
func doc(key, title, docType, docTitle string) DocTaskDef {
|
|
return DocTaskDef{
|
|
Key: key, Title: title, Required: true, Blocking: true, DefaultEnabled: true,
|
|
TemplateAssetKey: key, TemplateVersion: 1,
|
|
OutputDocType: docType, OutputDocTitle: docTitle,
|
|
}
|
|
}
|
|
|
|
// SeedFromMemoryCatalog 将内存 catalog 转为种子(测试用)。
|
|
func SeedFromMemoryCatalog(cat projectworkflow.Catalog) []CreateDefinitionInput {
|
|
if cat == nil {
|
|
return nil
|
|
}
|
|
out := make([]CreateDefinitionInput, 0)
|
|
for _, d := range cat.List() {
|
|
out = append(out, legacySingleStage(d.Key, d.Name, d.Description, d.StageKey, d.TaskKey, d.OutputDocType, d.OutputDocTitle, d.RequiredUpstreamWorkflow))
|
|
}
|
|
return out
|
|
}
|