---
title: Как работают неизменяемые версии пайплайнов
description: Почему правка пайплайна — всегда новый карв, а не редактирование, и как это делает каждый прошлый прогон воспроизводимым, а каждый откат — перестановкой указателя.
locale: ru
version: 0.2.0
canonical: https://enterium-developer-docs.pages.dev/developers/ru/how-it-works/immutable-pipeline-versions/
---

> Documentation index: https://enterium-developer-docs.pages.dev/developers/llms.txt — every page of this portal has a Markdown twin at <route>.md; the frozen API contract is at https://enterium-developer-docs.pages.dev/developers/api/openapi.json.

**Проблема:** LLM-контент-пайплайн меняется постоянно — промпты, гейты,
порядок шагов. Если код, произведший вчерашнюю тысячу статей, можно
править на месте, ты теряешь ответ на единственный важный при регрессии
качества вопрос: *что именно произвело эту статью?*

Наивный ответ — «посмотри git-историю» — не работает операционно: флот
исполняет не git-историю, а то, что лежит на диске, и «маленький фикс»,
задеплоенный в полдень, молча меняет то, что сделает ночной прогон.

## Слой 1 — версия это директория, а не ref

Каждая версия пайплайна — **полная неизменяемая директория кода**:
`pipelines/{id}/{variant}/{version}/` со своим `manifest.yaml`. После
регистрации директория не редактируется никогда. Правка — сколь угодно
малая — становится **карвом**: байт-копия родительской версии, патч,
регистрация новой версии в каталоге.

```mermaid
flowchart LR
    A[v3.1.16<br/>frozen] -- carve: copy + patch --> B[v3.1.17<br/>frozen]
    B -- carve --> C[v3.1.18<br/>latest]
    A -.rollback target.-> CAT[catalog.yaml<br/>latest pointer]
    C -.-> CAT
```

Манифест — это контракт: диспетчер читает его — шаги, требуемое
окружение, entrypoint'ы — и никогда не заглядывает в код. Старые версии
остаются в списке и остаются запускаемыми.

## Слой 2 — резолюция и пины

Какая версия исполнится, решается в момент диспатча:
**явный запрос → пин контракта → `latest` каталога**. Ночной прод-прогон
дополнительно пинит свои версии Collect/Generate явно, что превращает
промоушен в осознанные два шага: приземлить версию, затем передвинуть
пин. Регрессия, найденная между шагами, не касается флота.

## Слой 3 — что это покупает

- **Форензика.** Каждый прогон записывает свою версию; версия не может
  измениться под ним. «Какой код написал это предложение» имеет точный
  ответ и месяцы спустя.
- **Мгновенный откат.** Передвинь указатель обратно. Без revert-коммитов,
  без редеплоя, без «почти того же».
- **Безопасная параллельность.** Несколько агентов карвят будущие версии,
  пока прод стоит на пине; ничто из их работы не дестабилизирует
  работающий код.
- **Честный A/B.** Две сосуществующие версии каталога можно гнать по
  живым контрактам и сравнивать по выходу — ни одна не движущаяся мишень.

## Компромиссы

Неизменяемость копит директории. Политика ретеншна держит дерево
компактным: выживают версии на живых пинах, `latest` с предшественником и
именованные цели отката; остальное удаляется из дерева явной, одобренной
владельцем очисткой (история остаётся в git, и каждая удалённая версия
оставляет тег для восстановления). Нумерация несёт смысл: новый **мажор**
отмечает архитектурное поколение (для Collect v3.x — векторное
ранжирование; v2.x — по ключевым словам — остаётся аварийным фолбэком).

## Пощупать за две минуты

Возьми поверхность каталога и текущие пины через API — или просто прочти
машинный манифест этой сборки документации: та же философия применена к
этим страницам — `versions.json` + `manifest.json` с content-хэшами в
корне портала.
