Files
ratatoskr-go/internal/worker/prompt.go
ki.sagidullin 2005421739
Some checks failed
CI / test (push) Failing after 1m59s
CI / build-and-package (amd64, linux) (push) Failing after 1m2s
CI / build-and-package (amd64, windows) (push) Successful in 26s
feat(opencode): рабочий serve для dev стартует из папки репозитория; пул покрывает внешним сервером подкаталоги
2026-08-24 19:36:38 +05:00

145 lines
6.2 KiB
Go
Raw 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"
"github.com/kamelion/ratatoskr-go/internal/storage"
)
// 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 .Primary}}
Основной репозиторий (рабочий каталог этой сессии): {{.Primary}}
{{end}}
{{if .Why}}Зачем: {{.Why}}{{end}}
{{if .AC}}Критерии готовности:
{{.AC}}{{end}}
{{if .Steps}}
**Этапы (выполняй по порядку, у каждого свой критерий готовности):**
{{- range .Steps}}
{{.Title}}{{if .AC}} — готово, когда: {{.AC}}{{end}}
{{- end}}
{{end}}
**Инструкции:**
1. Рабочий каталог — сам основной репозиторий ({{.Primary}}): правь файлы в нём прямо, относительными путями (./...).
{{if .Others}} Связанные репозитории задачи лежат рядом, в ../имя_репо/ (здесь cwd — основной репозиторий): меняй их согласованно, если этого требует задача.{{else}} Работа ведётся только в нём — связанных репозиториев у задачи нет.{{end}}
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
// Primary — основной (первый) репозиторий задачи: рабочий каталог сессии
// dev — это именно его папка (сервер opencode стартует из неё).
Primary string
// Others — остальные репозитории задачи (доступны рядом как ../имя_репо/).
Others []string
Why string
AC string
Steps []storage.Step
// 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}
}