package workflowdef import ( "os" "path/filepath" "runtime" "strings" "testing" ) func TestRDevManifestCompleteness(t *testing.T) { def, err := LoadManifestDefinition("rdev.v2.json") if err != nil { t.Fatal(err) } normalizeManifestDefinition(&def) res := ValidateDefinitionV2(def, nil, nil) if !res.Valid { t.Fatalf("rdev v2 invalid: %+v", res.Issues) } keys := make([]string, 0, 60) for _, st := range def.Stages { for _, dt := range st.DocTasks { keys = append(keys, dt.Key) } } if len(keys) != 60 { t.Fatalf("want 60 doc tasks, got %d", len(keys)) } if len(def.Stages) != 13 { t.Fatalf("want 13 stages, got %d", len(def.Stages)) } existing := map[string]struct{}{ "intake": {}, "research": {}, "feasibility_dev": {}, "feasibility_reg": {}, "user_requirements": {}, "system_reqs": {}, "test_manager": {}, "prelim_design": {}, "cdo_quote": {}, } _, thisFile, _, _ := runtime.Caller(0) repoRoot := filepath.Clean(filepath.Join(filepath.Dir(thisFile), "../..")) templatesDir := filepath.Join(repoRoot, "templates", "docs") for _, key := range keys { if !strings.HasPrefix(key, "rd_") { t.Fatalf("rdev task key must use rd_ prefix: %s", key) } if _, clash := existing[key]; clash { t.Fatalf("rdev key %s intersects existing task keys", key) } path := filepath.Join(templatesDir, key+".md") b, err := os.ReadFile(path) if err != nil { t.Fatalf("template missing for %s: %v", key, err) } if len(strings.TrimSpace(string(b))) == 0 { t.Fatalf("template empty: %s", key) } } last := filepath.Join(templatesDir, "rd_design_validation_report.md") b, err := os.ReadFile(last) if err != nil { t.Fatal(err) } if !strings.Contains(string(b), "签署") { t.Fatal("rd_design_validation_report.md must contain 签署") } }