worker: add reviewer stage (branch→review→push) with R1-R6 errors
All checks were successful
CI / test (push) Successful in 47s
CI / build-and-package (amd64, linux) (push) Successful in 43s
CI / build-and-package (amd64, windows) (push) Successful in 40s

This commit is contained in:
Hermes
2026-08-16 21:21:21 +05:00
parent 130dc59840
commit 4a6ed57971
8 changed files with 610 additions and 65 deletions

View File

@@ -27,8 +27,9 @@ var devPromptTemplate = template.Must(template.New("dev").Parse(`Ты — dev-а
2. Напиши код, реализующий задачу.
3. Убедись, что все acceptance criteria выполнены.
4. Пользуйся встроенными инструментами opencode (чтение файлов, поиск, редактирование).
5. По окончании верни краткий отчёт о том, что сделано.
`))
5. Работай в feature-ветке {{.Branch}} (уже создана, checkout выполнен). Коммить изменения в эту ветку.
6. По окончании верни краткий отчёт о том, что сделано.
{{if .ReviewFeedback}}{{.ReviewFeedback}}{{end}}`))
// DevPromptData — данные для рендера dev-промпта.
type DevPromptData struct {
@@ -37,6 +38,13 @@ type DevPromptData struct {
Repos []string
Why string
AC string
// ReviewFeedback — замечания ревьюера при повторном прогоне dev
// (не пусто → dev должен исправить именно это).
ReviewFeedback []string
// Branch — имя feature-ветки, в которой ведётся работа (для отчёта).
Branch string
}
// RenderDevPrompt собирает промпт для dev-агента.
@@ -46,4 +54,74 @@ func RenderDevPrompt(data DevPromptData) (string, error) {
return "", err
}
return buf.String(), nil
}
// reviewPromptTemplate — промпт для reviewer-агента.
var reviewPromptTemplate = template.Must(template.New("review").Parse(`Ты — ревьюер в конвейере Ratatoskr. Проверь работу dev-агента в feature-ветке **{{.Branch}}** строго и придирчиво.
**Критерии готовности (AC):**
{{.AC}}
**Полный diff ветки (base...HEAD):**
{{.Diff}}
ПРАВИЛА:
1. Изучи весь diff, а не заголовки. Смотри контекст изменений.
2. Проверяй: безопасность; логические ошибки и баги; соответствие AC; качество кода.
3. SOLID — СТРОГО. Приоритет — минимальная связанность компонентов: зависимость от абстракций, без циклических/лишних зависимостей, single responsibility.
4. Любой критический изъян (security/логика) или нарушение SOLID → passed=false. Это блокирующие.
5. critical_issues и solid_violations клади в свои списки; comments — конкретные, где и как править.
**Верни строго один JSON-объект без markdown-обрамления:**
{
"passed": true|false,
"critical_issues": [],
"solid_violations": [],
"comments": []
}`))
// ReviewPromptData — данные для рендера review-промпта.
type ReviewPromptData struct {
Branch string
AC string
Diff string
}
// RenderReviewPrompt собирает промпт для reviewer-агента.
func RenderReviewPrompt(data ReviewPromptData) (string, error) {
var buf strings.Builder
if err := reviewPromptTemplate.Execute(&buf, data); err != nil {
return "", err
}
return buf.String(), nil
}
// reviewFeedbackText — строка (список), которую dev видит при повторном прогоне
// после не-прохода ревью. Пустые comments → пустая строка.
func reviewFeedbackText(branch string, comments []string) string {
if len(comments) == 0 {
return ""
}
var b strings.Builder
b.WriteString("\n\n⚠ РЕВЬЮ НЕ ПРОЙДЕНО по ветке ")
b.WriteString(branch)
b.WriteString(". Прочитай и исправь каждый пункт, затем закоммить повторно:\n")
for _, c := range comments {
if c == "" {
continue
}
b.WriteString("- ")
b.WriteString(c)
b.WriteString("\n")
}
return b.String()
}
// reviewFeedbackList — то же, но возвращает []string (для DevPromptData.ReviewFeedback).
func reviewFeedbackList(branch string, comments []string) []string {
s := reviewFeedbackText(branch, comments)
if s == "" {
return nil
}
return []string{s}
}