Что такое спека (ТЗ) внутри системы
Внутри системы спека (ТЗ) называется «спека» (от англ. specification; привычное
«техническое задание», ТЗ, — тот же термин), а в коде — артефакт с типом kind=spec.
Технически это запись в базе artifacts-service с телом (текст задания) и набором полей:
| Поле | Что значит |
|---|---|
kind = spec | это именно спека (ТЗ), а не задача, результат и т.п. |
status | где спека (ТЗ) в жизни: черновик → на проверке → одобрено / отклонено |
body | сам текст спеки (ТЗ) — что нужно сделать |
base_sha | версия кода, от которой «пляшет» работа (конкретный коммит) — подробно ниже |
parent_id | из какой задачи эта спека (ТЗ) родилась |
base_sha — от какой версии кода «отталкиваемся»
base_sha — это конкретный коммит репозитория, на который опирается спека (ТЗ).
Смысл простой: код меняется каждый день, и спека (ТЗ) всегда написана под какую-то конкретную
версию кода. Чтобы работа была предсказуемой, запоминают именно этот коммит — и DEV-AGENT
стартует от него, а не от «самого свежего состояния на сейчас».
«Отталкиваться от коммита» на практике значит: перед работой DEV-AGENT берёт снимок репозитория ровно на этом коммите — и весь его труд (чтение файлов, правки, коммиты) происходит относительно этой версии. То есть база, от которой DEV-AGENT пляшет, зафиксирована и не «уплывает» из-под него.
Зачем это нужно — пример
Представьте репозиторий, где код постоянно меняется:
понедельник: коммит aaa1111 — SPEC-AGENT читает код и пишет спеку (ТЗ):
«добавь функцию export_report в модуль reports.py»,
запоминает base_sha = aaa1111
вторник: в main влили чужой рефакторинг → коммит bbb2222,
файл reports.py переименован в reporting.py
среда: запускается DEV-AGENT
Если бы base_sha не было, DEV-AGENT в среду взял бы свежий код (bbb2222): файла
reports.py там уже нет, задание «добавь функцию в reports.py» не сходится с реальностью,
DEV-AGENT буксует или делает не то.
С base_sha = aaa1111 DEV-AGENT стартует со снимка понедельника: файл на месте, задание выполнимо ровно так, как его задумал автор спеки (ТЗ).
base_sha или он не похож на коммит, пайплайн останавливается с ошибкой,
а не берёт «что-нибудь свежее» наугад.Откуда спека (ТЗ) берётся
Есть два пути, и какой сработает — зависит от того, с чем пришла задача в workflow:
Путь 1. Спека (ТЗ) уже готова
В workflow приходит сразу spec_id — номер готовой одобренной спеки (ТЗ). Она уже прошла проверку, и дальше сразу запускается DEV-AGENT (агент-разработчик, программа, а не ЧЕЛОВЕК): он начинает работу по готовой спеке (ТЗ).
Путь 2. Спеку (ТЗ) надо сделать
В workflow приходит task_id (номер задачи). Тогда система сама запускает SPEC-AGENT, чтобы он написал спеку (ТЗ) с нуля.
Как SPEC-AGENT пишет спеку (ТЗ) — путь 2
- Workflow получает task_id и видит: «спеки (ТЗ) ещё нет, надо сделать».
- Workflow запускает шаг
SPEC_STEP— диспатчит SPEC-AGENT в Nomad. - SPEC-AGENT получает пакет задачи (историю, подзадачи, срезы, тесткейсы — всё, что уже есть о задаче).
- SPEC-AGENT через MCP-инструмент artifacts создаёт артефакт
specв статусе draft (черновик). - В тело ложатся версии источников; отдельно записывается
base_sha— коммит, от которого работаем. - SPEC-AGENT пишет в свой результат ссылку на созданную спеку (
spec_id) и завершается. - Workflow читает
spec_idиз результата и отправляет спеку (ТЗ) на проверку ЧЕЛОВЕК.
# workflows.py — первый шаг пути «надо сделать спеку (ТЗ)»
run(spec_id, task_id=""):
if task_id: # спеки (ТЗ) ещё нет
результат = запустить_шаг(SPEC_STEP) # SPEC-AGENT пишет черновик
spec_id = вытащить_id_из(результат)
пройти_Gate_спеки(spec_id) # человек проверяет (см. ниже)
Как спека (ТЗ) «живёт»: статусы
У спеки (ТЗ) конечный набор статусов, и переходы строго контролируются:
- draft — черновик. Только что его создал SPEC-AGENT.
- pending_review — отправлена на проверку ЧЕЛОВЕК (workflow делает submit от имени SPEC-AGENT).
- approved — ЧЕЛОВЕК одобрил. Только теперь по спеке (ТЗ) можно работать.
- rejected — ЧЕЛОВЕК вернул с замечаниями. Спека (ТЗ) отправляется на переделку, рождается новая версия.
rejected как есть. SPEC-AGENT создаёт новый артефакт-черновик.
Так всегда видно историю: какая версия была отклонена и почему.Кто и как проверяет спеку (ТЗ)
Проверяет ЧЕЛОВЕК. Механика — две вещи, которые работают вместе:
1. Решение — через artifacts-service
Человек жмёт «одобрить» / «вернуть» в интерфейсе, и система меняет статус спеки (ТЗ) через REST: POST /status (decide_transition, роль human).
Код не верит сигналу на слово: после «стука» он сам перечитывает реальный статус спеки (ТЗ) через artifacts-service. Так решение никогда не расходится с тем, что реально хранится в базе.
человек → POST /status (approved/rejected) # решает artifacts-service
человек → сигнал human_verdict(feedback) # будит workflow
workflow → перечитывает статус спеки (ТЗ) # проверяет сам, не на слово
Что происходит после вердикта
Одобрено ✅
- Workflow запоминает одобренную спеку (ТЗ).
- Узнаёт
base_sha— с какого коммита работать. - Запускает DEV-AGENT: тело спеки (ТЗ) попадает в его задание как основной текст.
- Дальше — обычные шаги разработки (см. разбор workflows.py).
Вернули с замечаниями 🔁
- Workflow берёт текст замечаний и добавляет его в задание SPEC-AGENT: «Ревьюер вернул спеку (ТЗ): …».
- SPEC-AGENT переделывает и создаёт новый черновик.
- Новый черновик снова отправляется ЧЕЛОВЕК на проверку. Цикл повторяется.
Слишком много возвратов ⛔
Всему есть предел — MAX_REWORK = 2. После двух возвратов workflow больше не гоняет
SPEC-AGENT по кругу, а помечает исход как escalated («нужен ЧЕЛОВЕК»): система честно
говорит «сама не справляюсь, реши руками», а не молча крутит цикл вечно.
if rework_count >= MAX_REWORK: # MAX_REWORK = 2
return {"status": "escalated", "failed_step": "spec-review",
"reason": "spec rework ceiling reached: max_rework=2"}
Каналы: откуда и куда
Если собрать всё путешествие спеки (ТЗ) по каналам, получается такая карта:
| Канал | Кто говорит | Что передаёт |
|---|---|---|
| Task-пакет | система → SPEC-AGENT | исходники задачи: история, подзадачи, срезы, тесткейсы |
| MCP artifacts | SPEC-AGENT → artifacts-service | создание артефакта spec (draft, body, base_sha) |
| result.json | SPEC-AGENT → workflow | ссылка на созданную спеку (spec_id) |
| activity submit | workflow → artifacts-service | draft → pending_review |
| REST POST /status | ЧЕЛОВЕК → artifacts-service | approved / rejected (решение) |
| signal human_verdict | система → workflow | «проснись», плюс текст замечаний при возврате |
| REST чтение статуса | workflow → artifacts-service | проверка «а что там реально лежит» |
| Task-промпт DEV-AGENT | workflow → DEV-AGENT | тело одобренной спеки (ТЗ) + base_sha для работы |
Итог: спека (ТЗ) в одной картинке
- Пришла задача без спеки (ТЗ) → workflow запускает SPEC-AGENT.
- SPEC-AGENT создаёт черновик (артефакт spec) через MCP artifacts.
- Черновик уходит ЧЕЛОВЕК на проверку (pending_review).
- Одобрил → спека (ТЗ) едет к DEV-AGENT (тело в промпт, base_sha — точка старта).
- Вернул → SPEC-AGENT переделывает с учётом замечаний; максимум 2 раза, дальше — эскалация ЧЕЛОВЕК.