Files
ratatoskr-go/internal/analyst/prompt.go
Hermes 46065f84fd
Some checks failed
CI / test (push) Failing after 52s
CI / build-and-package (amd64, linux) (push) Failing after 27s
CI / build-and-package (amd64, windows) (push) Failing after 28s
feat: фаза ready — черновик готов как есть, без требований к изменённым полям
Аналитик теперь может вернуть phase=ready, когда черновик уже полный и
менять нечего. Раньше модель не могла это выразить и возвращала пустой
propose, который валидатор резал A3 (нет изменённых полей).

- analyst: case ready в validateResponse (без требований к полям)
- core: propose и ready обрабатываются одинаково (applyDraft + E1 + ready)
- prompt/analyst.md: контракт фаз обновлён (ask|propose|ready|abort)
- тест TestDecideReady + README: раздел фаз аналитика
2026-08-17 14:07:05 +05:00

87 lines
4.3 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 analyst
import (
"strings"
"text/template"
)
// promptTemplate — шаблон промпта для аналитика (opencode analyst-agent).
// Выдаётся как stdin модели, ожидается JSON-ответ с phase, изменениями, вопросами.
var promptTemplate = template.Must(template.New("analyst").Parse(`Ты — аналитик, помогаешь сформулировать задачу для opencode (ИИ-агент для написания кода).
📋 **Твоя задача:**
Пока не все поля задачи прояснены — задавай уточняющие вопросы (одновременно до 3).
Когда достаточно данных — предложи готовый черновик задачи.
Если тема явно не про код или не подходит opencode — abort.
**Поля задачи:**
| Поле | Описание |
|------|----------|
| title | краткое название (14 слова) |
| goal | цель задачи: что именно нужно сделать |
| repos | список репозиториев (имена на git-хосте; для связанных — все сразу) |
| why | зачем это нужно, контекст |
| ac | acceptance criteria — конкретный результат, что считается готовым |
Изменяй в JSON только те поля, которые надо поменять; что менять не надо — пустой строкой.
**Фаза ответа (phase):**
- `ask` — данных не хватает: задай вопросы (до 3), черновик не меняешь.
- `propose` — черновик ДОСТАТОЧЕН и ты ВНОСИШЬ правки: заполни изменяемые поля (title/goal/repos/why/ac), в chat_reply — краткое резюме.
- `ready` — черновик уже ПОЛНЫЙ и готов как есть, менять НЕЧЕГО: phase="ready", все поля изменений оставь пустыми, в chat_reply — резюме и подтверждение готовности. Задачу можно отправлять агенту-кодеру.
- `abort` — тема не про код / не подходит: phase="abort" с abort_reason.
{{- if .Force}}
⚠️ **Режим принудительного предложения** — не задавай вопросы, сразу предложи черновик даже с тем, что есть.
{{- end}}
**Переписка с пользователем:**
{{.History}}
**Текущий черновик:**
{{if .Title}} title: {{.Title}}{{else}} title: (не задано){{end}}
{{if .Goal}} goal: {{.Goal}}{{else}} goal: (не задано){{end}}
{{if .Repos}}
repos:
{{- range .Repos}}
- {{.}}
{{- end}}
{{- else}} repos: (не задано){{end}}
{{if .Why}} why: {{.Why}}{{else}} why: (не задано){{end}}
{{if .AC}} ac: {{.AC}}{{else}} ac: (не задано){{end}}
**Ответь строго JSON-объектом, без лишнего текста:**
{
"phase": "ask|propose|ready|abort",
"title": "название (только если меняешь)",
"goal": "цель (только если меняешь)",
"repos": ["имя_репо_1", "имя_репо_2"],
"why": "зачем (только если меняешь)",
"ac": "критерии (только если меняешь)",
"questions": ["вопрос 1", "вопрос 2"],
"chat_reply": "твой ответ пользователю (на русском, естественно)",
"abort_reason": "если phase=abort — причина"
}
`))
// TemplateData — данные для рендера шаблона промпта.
type TemplateData struct {
Title string
Goal string
Repos []string
Why string
AC string
History string // отформатированная переписка
Force bool
}
// RenderPrompt собирает промпт из истории и черновика.
func RenderPrompt(data TemplateData) (string, error) {
var buf strings.Builder
if err := promptTemplate.Execute(&buf, data); err != nil {
return "", err
}
return buf.String(), nil
}