127 lines
5.2 KiB
Go
127 lines
5.2 KiB
Go
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}
|
||
} |