Files
ratatoskr-go/internal/worker/prompt.go
Hermes 4a6ed57971
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
worker: add reviewer stage (branch→review→push) with R1-R6 errors
2026-08-16 21:21:21 +05:00

127 lines
5.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package worker
import (
"strings"
"text/template"
)
// devPromptTemplate — промпт для dev-агента при запуске задачи.
var devPromptTemplate = template.Must(template.New("dev").Parse(`Ты — dev-агент, реализуешь задачу в репозитории(ях).
**Задача:**
{{if .Title}}Название: {{.Title}}{{end}}
{{if .Goal}}Цель: {{.Goal}}{{end}}
{{if .Repos}}
Репозитории (доступны как подпапки текущего каталога):
{{- range .Repos}}
- {{.}}
{{- end}}
{{end}}
{{if .Why}}Зачем: {{.Why}}{{end}}
{{if .AC}}Критерии готовности:
{{.AC}}{{end}}
**Инструкции:**
1. Рабочий каталог — общий корень, в котором лежат все репозитории по именам.
Правь файлы внутри нужного репозитория (./имя_репо/...). Связанные репозитории меняй согласованно.
2. Напиши код, реализующий задачу.
3. Убедись, что все acceptance criteria выполнены.
4. Пользуйся встроенными инструментами opencode (чтение файлов, поиск, редактирование).
5. Работай в feature-ветке {{.Branch}} (уже создана, checkout выполнен). Коммить изменения в эту ветку.
6. По окончании верни краткий отчёт о том, что сделано.
{{if .ReviewFeedback}}{{.ReviewFeedback}}{{end}}`))
// DevPromptData — данные для рендера dev-промпта.
type DevPromptData struct {
Title string
Goal string
Repos []string
Why string
AC string
// ReviewFeedback — замечания ревьюера при повторном прогоне dev
// (не пусто → dev должен исправить именно это).
ReviewFeedback []string
// Branch — имя feature-ветки, в которой ведётся работа (для отчёта).
Branch string
}
// RenderDevPrompt собирает промпт для dev-агента.
func RenderDevPrompt(data DevPromptData) (string, error) {
var buf strings.Builder
if err := devPromptTemplate.Execute(&buf, data); err != nil {
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}
}