生成项目建议书 now resolves to rd_proposal. Longer titles win, so 系统设计方案 is not mistaken for the shorter business-stage phrase, and an explicit generate command is no longer swallowed by a progress question. Co-authored-by: Cursor <cursoragent@cursor.com>
448 lines
17 KiB
Go
448 lines
17 KiB
Go
package squad
|
|
|
|
import (
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// RDevArtifactKind 研发文档产物类别(对齐参考项目 artifact_kind)。
|
|
type RDevArtifactKind string
|
|
|
|
const (
|
|
RDevKindDocument RDevArtifactKind = "document"
|
|
RDevKindReviewMinutes RDevArtifactKind = "review_minutes"
|
|
RDevKindUploadIndex RDevArtifactKind = "upload_index"
|
|
)
|
|
|
|
// RDevTaskMeta rdev 任务目录项。
|
|
type RDevTaskMeta struct {
|
|
Key string
|
|
Title string
|
|
Phase string
|
|
PhaseTitle string
|
|
Kind RDevArtifactKind
|
|
DocCode string
|
|
Skippable bool
|
|
StageKey string
|
|
Hint string
|
|
SkipHint string
|
|
Aliases []string
|
|
}
|
|
|
|
// RDevCatalog 60 项研发设计控制任务(SSOT 来源:refs rdev.yaml → rd_ 前缀)。
|
|
var RDevCatalog = []RDevTaskMeta{
|
|
{
|
|
Key: "rd_proposal", Title: "项目建议书", Phase: "01",
|
|
PhaseTitle: "策划", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-PROPOSAL", Skippable: false, StageKey: "RD01_planning",
|
|
},
|
|
{
|
|
Key: "rd_design_plan", Title: "设计开发计划任务书", Phase: "01",
|
|
PhaseTitle: "策划", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-DESIGN-PLAN", Skippable: false, StageKey: "RD01_planning",
|
|
},
|
|
{
|
|
Key: "rd_planning_review", Title: "设计和开发策划评审记录", Phase: "02",
|
|
PhaseTitle: "策划评审", Kind: RDevArtifactKind("review_minutes"),
|
|
DocCode: "RD-PLAN-REV", Skippable: false, StageKey: "RD02_planning_review",
|
|
},
|
|
{
|
|
Key: "rd_user_needs", Title: "用户需求规格书", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-UN", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_regs_stds", Title: "法规和标准清单", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-REGS", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_adverse_events", Title: "同类产品不良事件信息", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-AE", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_system_reqs", Title: "系统需求规格书", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SR", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_risk_plan", Title: "风险管理计划", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-RISK-PLAN", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_hazard_analysis", Title: "安全性问题清单及可能危险分析表", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-HAZARD", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_sw_plan", Title: "软件开发计划", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-PLAN", Skippable: true, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_sw_reqs", Title: "软件需求规格书", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-REQ", Skippable: true, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_sw_config", Title: "软件配置及维护计划", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-CFG", Skippable: true, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_design_input_spec", Title: "设计输入规格书", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-DI-SPEC", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_design_input_list", Title: "设计输入清单", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-DI-LIST", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_system_design", Title: "系统设计方案", Phase: "03",
|
|
PhaseTitle: "设计输入", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SYS-DES", Skippable: false, StageKey: "RD03_design_input",
|
|
},
|
|
{
|
|
Key: "rd_req_review", Title: "需求评审记录", Phase: "04",
|
|
PhaseTitle: "需求评审", Kind: RDevArtifactKind("review_minutes"),
|
|
DocCode: "RD-REQ-REV", Skippable: false, StageKey: "RD04_requirements_review",
|
|
},
|
|
{
|
|
Key: "rd_input_phase_review", Title: "设计开发评审记录(阶段3和4)", Phase: "05",
|
|
PhaseTitle: "输入阶段评审", Kind: RDevArtifactKind("review_minutes"),
|
|
DocCode: "RD-IN-REV", Skippable: false, StageKey: "RD05_input_phase_review",
|
|
},
|
|
{
|
|
Key: "rd_drawings_3d", Title: "2D图纸和3D模型", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-DWG", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_product_bom", Title: "产品BOM", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-BOM", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_ee_bom", Title: "电子电气BOM", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-EE-BOM", Skippable: true, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_pcba", Title: "PCBA原理图及Layout", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-PCBA", Skippable: true, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_electrical_sys", Title: "系统电气设计图", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-ELEC", Skippable: true, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_sw_arch", Title: "软件概要设计方案", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-ARCH", Skippable: true, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_sw_ui", Title: "软件UI设计文档", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-UI", Skippable: true, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_purchase_spec", Title: "采购技术规范", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-PUR", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_process_flow", Title: "工艺流程图及作业指导", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-PROC", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_packaging", Title: "包装图纸和设计要求", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-PACK", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_ifu", Title: "产品使用说明书", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-IFU", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_incoming_iqc", Title: "原材料进货检验规范", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-IQC", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_ipqc", Title: "生产过程检验规范", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-IPQC", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_fqc", Title: "成品检验规范", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-FQC", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_tech_req", Title: "产品技术要求", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-TECH", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_risk_report", Title: "风险管理报告", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-RISK-RPT", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_design_output_list", Title: "设计输出清单", Phase: "06",
|
|
PhaseTitle: "设计输出", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-DO-LIST", Skippable: false, StageKey: "RD06_design_output",
|
|
},
|
|
{
|
|
Key: "rd_output_review", Title: "设计开发评审记录(阶段6)", Phase: "07",
|
|
PhaseTitle: "输出评审", Kind: RDevArtifactKind("review_minutes"),
|
|
DocCode: "RD-OUT-REV", Skippable: false, StageKey: "RD07_output_review",
|
|
},
|
|
{
|
|
Key: "rd_prototype_photos", Title: "样机照片", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-PHOTO", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_design_vv", Title: "设计验证方案", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-VV", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_shelf_life", Title: "货架寿命方案", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SHELF", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_lifetime", Title: "产品使用期限研究方案", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-LIFE", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_biocompatibility", Title: "生物学检测方案", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-BIO", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_cleaning", Title: "清洁消毒验证方案", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-CLEAN", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_emc_safety", Title: "EMC及安规摸底报告", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("upload_index"),
|
|
DocCode: "RD-EMC", Skippable: true, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_risk_report_v", Title: "风险管理报告(验证阶段)", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-RISK-V", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_sw_release", Title: "软件发布清单", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-REL", Skippable: true, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_sw_unit_test", Title: "软件单元测试报告", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-UT", Skippable: true, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_sw_sys_test", Title: "软件系统测试报告", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-ST", Skippable: true, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_qualified_suppliers", Title: "合格供方名录", Phase: "08",
|
|
PhaseTitle: "验证", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SUP", Skippable: false, StageKey: "RD08_verification",
|
|
},
|
|
{
|
|
Key: "rd_verification_review", Title: "设计开发评审记录(验证阶段)", Phase: "09",
|
|
PhaseTitle: "验证评审", Kind: RDevArtifactKind("review_minutes"),
|
|
DocCode: "RD-VER-REV", Skippable: false, StageKey: "RD09_verification_review",
|
|
},
|
|
{
|
|
Key: "rd_dmr_list", Title: "DMR文件清单", Phase: "10",
|
|
PhaseTitle: "转换", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-DMR-LIST", Skippable: false, StageKey: "RD10_transfer",
|
|
},
|
|
{
|
|
Key: "rd_pack_ship", Title: "包装运输方案", Phase: "10",
|
|
PhaseTitle: "转换", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SHIP", Skippable: false, StageKey: "RD10_transfer",
|
|
},
|
|
{
|
|
Key: "rd_risk_report_t", Title: "风险管理报告(转换阶段)", Phase: "10",
|
|
PhaseTitle: "转换", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-RISK-T", Skippable: false, StageKey: "RD10_transfer",
|
|
},
|
|
{
|
|
Key: "rd_transfer_review", Title: "设计开发评审记录(转换阶段)", Phase: "11",
|
|
PhaseTitle: "转换评审", Kind: RDevArtifactKind("review_minutes"),
|
|
DocCode: "RD-XFER-REV", Skippable: false, StageKey: "RD11_transfer_review",
|
|
},
|
|
{
|
|
Key: "rd_validation_plan", Title: "设计确认方案", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-VAL-PLAN", Skippable: false, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_use_error", Title: "使用错误评估报告", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-USE-ERR", Skippable: false, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_animal_study", Title: "动物试验方案", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-ANIMAL", Skippable: true, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_sw_quality", Title: "软件质量测试报告", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-SW-QA", Skippable: true, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_clinical", Title: "临床试验报告", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-CLIN", Skippable: true, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_risk_report_val", Title: "风险管理报告(确认阶段)", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-RISK-VAL", Skippable: false, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_user_test", Title: "用户测试报告", Phase: "12",
|
|
PhaseTitle: "确认", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-USER-T", Skippable: false, StageKey: "RD12_validation",
|
|
},
|
|
{
|
|
Key: "rd_design_validation_report", Title: "设计确认报告", Phase: "13",
|
|
PhaseTitle: "设计确认报告", Kind: RDevArtifactKind("document"),
|
|
DocCode: "RD-VAL-RPT", Skippable: false, StageKey: "RD13_validation_report",
|
|
},
|
|
}
|
|
|
|
var (
|
|
rdevCatalogByKey map[string]RDevTaskMeta
|
|
rdevCatalogByAlias map[string]string
|
|
)
|
|
|
|
func init() {
|
|
rdevCatalogByKey = make(map[string]RDevTaskMeta, len(RDevCatalog))
|
|
rdevCatalogByAlias = make(map[string]string)
|
|
for i := range RDevCatalog {
|
|
if h, ok := rdevStageHints[RDevCatalog[i].Key]; ok {
|
|
RDevCatalog[i].Hint = h.Hint
|
|
RDevCatalog[i].SkipHint = h.SkipHint
|
|
RDevCatalog[i].Aliases = append([]string(nil), h.Aliases...)
|
|
}
|
|
rdevCatalogByKey[RDevCatalog[i].Key] = RDevCatalog[i]
|
|
for _, alias := range RDevCatalog[i].Aliases {
|
|
rdevCatalogByAlias[alias] = RDevCatalog[i].Key
|
|
}
|
|
}
|
|
}
|
|
|
|
// RDevTriggerPhrase 对话里用来点名研发任务的标题或别名。
|
|
type RDevTriggerPhrase struct {
|
|
Text string
|
|
TaskKey string
|
|
}
|
|
|
|
// RDevTriggerPhrases 返回可用于「生成/出」匹配的研发文档名。
|
|
// 过短的英文缩写不进入,避免 UN/BOM 这类记号命中无关句子。
|
|
func RDevTriggerPhrases() []RDevTriggerPhrase {
|
|
seen := map[string]string{}
|
|
var out []RDevTriggerPhrase
|
|
add := func(text, key string) {
|
|
text = strings.TrimSpace(text)
|
|
if text == "" || rdevTriggerAliasUnsafe(text) {
|
|
return
|
|
}
|
|
if prev, ok := seen[text]; ok && prev != key {
|
|
return
|
|
}
|
|
if _, ok := seen[text]; ok {
|
|
return
|
|
}
|
|
seen[text] = key
|
|
out = append(out, RDevTriggerPhrase{Text: text, TaskKey: key})
|
|
}
|
|
for _, item := range RDevCatalog {
|
|
add(item.Title, item.Key)
|
|
for _, alias := range item.Aliases {
|
|
add(alias, item.Key)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func rdevTriggerAliasUnsafe(text string) bool {
|
|
if utf8.RuneCountInString(text) < 2 {
|
|
return true
|
|
}
|
|
for _, r := range text {
|
|
if r > 127 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
func LookupRDevTask(taskKey string) (RDevTaskMeta, bool) {
|
|
if t, ok := rdevCatalogByKey[taskKey]; ok {
|
|
return t, true
|
|
}
|
|
if key, ok := rdevCatalogByAlias[strings.TrimSpace(taskKey)]; ok {
|
|
t, found := rdevCatalogByKey[key]
|
|
return t, found
|
|
}
|
|
return RDevTaskMeta{}, false
|
|
}
|
|
|
|
// RDevNeedsRegulatory 是否注入法规专员步骤。未声明复杂度时保持任务名单,避免已有运行突然少一步。
|
|
func RDevNeedsRegulatory(taskKey string) bool {
|
|
return RDevNeedsRegulatoryAt(taskKey, "")
|
|
}
|
|
|
|
// RDevNeedsRegulatoryAt 在任务名单之上再看 complexity_tier。
|
|
// high 与未声明走名单;medium 与 low 不注入。对齐参考项目 when: complexity_tier=high。
|
|
func RDevNeedsRegulatoryAt(taskKey, tier string) bool {
|
|
switch strings.ToLower(strings.TrimSpace(tier)) {
|
|
case "medium", "low":
|
|
return false
|
|
}
|
|
switch taskKey {
|
|
case "rd_sw_plan", "rd_sw_reqs", "rd_sw_config", "rd_sw_arch", "rd_sw_ui",
|
|
"rd_sw_release", "rd_sw_unit_test", "rd_sw_sys_test", "rd_sw_quality",
|
|
"rd_regs_stds", "rd_adverse_events", "rd_biocompatibility", "rd_clinical", "rd_animal_study",
|
|
"rd_risk_plan", "rd_hazard_analysis", "rd_risk_report", "rd_risk_report_v",
|
|
"rd_risk_report_t", "rd_risk_report_val", "rd_emc_safety":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// rdevSupportedTasks 将目录转为 SupportedTasks 片段。
|
|
func rdevSupportedTasks() []TaskMeta {
|
|
out := make([]TaskMeta, 0, len(RDevCatalog))
|
|
for _, t := range RDevCatalog {
|
|
out = append(out, TaskMeta{
|
|
Key: t.Key, Title: t.Title, ArtifactTitle: t.Title,
|
|
Description: "研发设计控制文档:" + t.Title,
|
|
})
|
|
}
|
|
return out
|
|
}
|