feat(squad): 优化质量门禁章节规范化匹配与审核专员预置草稿流转
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -54,8 +54,16 @@ func (q *QualityGate) Validate(wsDir string, taskKey string, content string) (*Q
|
||||
tmplData, err := os.ReadFile(tmplPath)
|
||||
if err == nil {
|
||||
expectedHeadings := extractHeadings(string(tmplData))
|
||||
actualHeadings := extractHeadings(content)
|
||||
for _, h := range expectedHeadings {
|
||||
if !strings.Contains(content, h) {
|
||||
found := false
|
||||
for _, act := range actualHeadings {
|
||||
if strings.Contains(act, h) || strings.Contains(h, act) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found && !strings.Contains(content, h) {
|
||||
report.MissingSections = append(report.MissingSections, h)
|
||||
report.Violations = append(report.Violations, fmt.Sprintf("缺少必填章节: %s", h))
|
||||
report.Score -= 15.0
|
||||
@@ -269,12 +277,43 @@ func extractHeadings(md string) []string {
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if strings.HasPrefix(trimmed, "## ") {
|
||||
headings = append(headings, trimmed)
|
||||
raw := strings.TrimPrefix(trimmed, "## ")
|
||||
clean := cleanHeadingTitle(raw)
|
||||
if clean != "" {
|
||||
headings = append(headings, clean)
|
||||
}
|
||||
}
|
||||
}
|
||||
return headings
|
||||
}
|
||||
|
||||
func cleanHeadingTitle(title string) string {
|
||||
// 去除前缀序号如 "一、", "二、", "1.", "1.1", "(一)" 等
|
||||
t := strings.TrimSpace(title)
|
||||
runes := []rune(t)
|
||||
// 去掉中文序号如 "一、", "二、", "三、", "四、", "五、", "六、", "七、", "八、", "九、", "十、"
|
||||
chineseNums := []string{"一、", "二、", "三、", "四、", "五、", "六、", "七、", "八、", "九、", "十、"}
|
||||
for _, cn := range chineseNums {
|
||||
if strings.HasPrefix(t, cn) {
|
||||
t = strings.TrimPrefix(t, cn)
|
||||
break
|
||||
}
|
||||
}
|
||||
// 去掉数字序号如 "1. ", "1、"
|
||||
for len(runes) > 0 && ((runes[0] >= '0' && runes[0] <= '9') || runes[0] == '.' || runes[0] == '、' || runes[0] == ' ') {
|
||||
t = strings.TrimSpace(string(runes[1:]))
|
||||
runes = []rune(t)
|
||||
}
|
||||
// 去除可能括号后缀
|
||||
if idx := strings.Index(t, "("); idx > 0 {
|
||||
t = strings.TrimSpace(t[:idx])
|
||||
}
|
||||
if idx := strings.Index(t, "("); idx > 0 {
|
||||
t = strings.TrimSpace(t[:idx])
|
||||
}
|
||||
return strings.TrimSpace(t)
|
||||
}
|
||||
|
||||
func computeSHA256(filePath string) (string, error) {
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
|
||||
@@ -348,6 +348,17 @@ func (d *WorkflowDriver) runOneStep(
|
||||
}
|
||||
stepStart := time.Now()
|
||||
|
||||
// 若当前步骤为 leader 审核定稿,且依赖前序专员稿件,先预置 baseline 草稿,供审查与润色
|
||||
if step.Role == "leader" && deliverableName == "output.md" {
|
||||
targetFile := filepath.Join(subDir, deliverableName)
|
||||
if _, err := os.Stat(targetFile); os.IsNotExist(err) && len(step.Needs) > 0 {
|
||||
srcFile := filepath.Join(wsDir, filepath.FromSlash(step.Needs[0]))
|
||||
if srcData, err := os.ReadFile(srcFile); err == nil && len(srcData) > 0 {
|
||||
_ = os.WriteFile(targetFile, srcData, 0o644)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 读取 TASK.md 与 AGENTS.md
|
||||
taskData, _ := os.ReadFile(filepath.Join(subDir, "TASK.md"))
|
||||
agentsData, _ := os.ReadFile(filepath.Join(subDir, "AGENTS.md"))
|
||||
|
||||
Reference in New Issue
Block a user