package main import ( "regexp" "strings" ) var emptySection = regexp.MustCompile(`(?i)^(none|nothing|n/a|-|—)\.?$`) // cleanReport drops everything before the first "## " heading and every section that has no // content or only "None". It returns "" when the answer has no heading at all. func cleanReport(answer string) string { var out []string var heading string var body []string started := false flush := func() { if heading == "" { return } var content []string for _, l := range body { if t := strings.TrimSpace(l); t != "" { content = append(content, t) } } if len(content) == 0 || (len(content) == 1 && emptySection.MatchString(content[0])) { heading, body = "", nil return } out = append(out, heading) out = append(out, body...) heading, body = "", nil } for _, line := range strings.Split(strings.ReplaceAll(answer, "\r\n", "\n"), "\n") { if strings.HasPrefix(line, "## ") { flush() started = true heading = line continue } if started { body = append(body, line) } } flush() return strings.TrimSpace(strings.Join(out, "\n")) } func hasHeading(report, prefix string) bool { for _, line := range strings.Split(report, "\n") { if strings.HasPrefix(line, prefix) { return true } } return false } var verdictLine = regexp.MustCompile(`(?i)^verdict:\s*(request[-_ ]changes|comment|approve)\s*$`) // splitVerdict takes the agent's explicit verdict, its last non-empty line "Verdict: ", // off the answer. The verdict is "" when the line is missing, which later reads as a plain comment. func splitVerdict(answer string) (rest, verdict string) { lines := strings.Split(strings.TrimRight(strings.ReplaceAll(answer, "\r\n", "\n"), " \t\n"), "\n") if len(lines) == 0 { return answer, "" } m := verdictLine.FindStringSubmatch(strings.TrimSpace(lines[len(lines)-1])) if m == nil { return answer, "" } return strings.Join(lines[:len(lines)-1], "\n"), strings.ToLower(strings.NewReplacer("_", "-", " ", "-").Replace(m[1])) } // Gitea's review events. Gitea stores any other value as a pending review only its author sees. const ( eventApproved = "APPROVED" eventRequestChanges = "REQUEST_CHANGES" eventComment = "COMMENT" ) // reviewEvent maps the agent's verdict to the Gitea review event. Changes are requested and // comments posted as the agent said; an approval is only honoured for a non-empty change whose // report holds no red or yellow section, and anything else is a comment. func reviewEvent(verdict, report string, nonEmptyChange bool) string { switch verdict { case "request-changes": return eventRequestChanges case "approve": if nonEmptyChange && !hasHeading(report, "## 🔴") && !hasHeading(report, "## 🟡") { return eventApproved } } return eventComment }