Жизненный цикл артефактов (Artifact Lifecycle): создание агентами, согласование человеком
Дата: 2026-10-15 Статус: предложение Связанные: docs/artifact-registry.md (реестр и тулы чтения), docs/sagas.md (саги), docs/knowledge-evolution.md (паттерн «предложил → человек применил»), docs/inbound-messages.md §7 (синтаксис получателей)
#1. Цель
Разрешить агентам создавать и переиспользовать артефакты между собой, сохранив единственный жёсткий инвариант: в навыки попадают только артефакты, утверждённые человеком.
Целевой сценарий (саги):
Агент-аналитик пишет требование → черновик артефакта (draft)
Отправляет на согласование людям → запрос ревью (in_review)
Люди дорабатывают сами или с агентом → правки черновика, новые круги
Человек утверждает → артефакт (approved)
Сага реализует требование в фичу → раны читают артефакт по saga_id
Артефакт перестаёт быть только «справочником, который загрузил админ», и становится общим рабочим материалом системы — при этом статус «утверждён» всегда означает «конкретный человек ответил за этот документ», а не «документ часто встречается».
В UI согласования рецензент может выделить точный фрагмент и сохранить
примечание, предлагаемую замену, одобрение или отказ по этому фрагменту.
Разметка привязана к номеру версии и остаётся рядом с решением о документе.
Для черновика или утверждённой версии тот же набор разметки можно передать
выбранному агенту проекта: агент получает цитаты и инструкции, создаёт
редакцию через artifact_update и оставляет её на проверку человеку.
#2. Проблематика текущего состояния
- Агенты только читают.
artifact_search/artifact_read— весь агентский инструментарий; создание и правка доступны только людям через API/UI. Рабочие продукты агентов (требования, спеки, отчёты) живут в чатах и файлах песочницы, где их нельзя найти, версионировать и связать с сагой. - Нет жизненного цикла. Любой артефакт в реестре неявно считается авторитетным. Свежезалитый черновник требования ничем не отличается от утверждённого регламента — ни для агента, ни для навыка.
- Нет происхождения. Реестр не знает, кто создал документ: человек или ран агента. Для доверия и аудита это критично: «утверждено» без «кем предложено» не разбирается.
- Нет цикла согласования. Доставить требование человеку на ревью можно только
через
ask_human/send_file— без статуса, без нескольких согласующих, без фиксации решения рядом с документом. - Инвариант «в скилах — только утверждённое» не гарантируется ничем. Манифест навыка сегодня может сослаться на любой id, оказавшийся в реестре.
#3. Основные понятия
#3.1. Статус и версии
Артефакт получает машину состояний на уровне версии (см. §5):
draft— черновик: создан человеком или агентом, редактируем, виден агентам;in_review— стоит на согласовании, редактирование тела блокируется; метаданные свободны от версии (см. ниже)approved— утверждён человеком: иммутабелен, доступен для ссылок из навыков;rejected— вернут с замечаниями: можно доработать и отправить снова;superseded— версия заменена более новой утверждённой того же id.
Правка утверждённой версии невозможна: любое изменение — это новая версия того же id, проходящая цикл заново. Навыки ссылаются на id и всегда резолвятся в последнюю утверждённую версию.
Метаданные свободны от версии. Название, описание, тип (reference/work),
привязка к саге и каталожные теги — не то, что утверждает рецензия: они
правятся на месте в любом статусе (в том числе под согласованием и у
утверждённого), не открывая редакцию и не трогая замок. Версию несут тело и
его хранение: content, provider, external_ref, mime_type — их правка
подчиняется машине состояний ниже. Агентский artifact_update сохраняет
прежние ограничения целиком: approved — отказ, in_review — замок.
#3.2. Происхождение (origin)
origin_type human | agent
origin_user кто из людей (для human)
origin_run какой ран создал (для agent)
Происхождение пишется при создании и не меняется. Согласовывать агентский черновик может только человек; происхождение показывается в UI рядом с кнопкой утверждения — решающий должен видеть, что именно он заверяет.
#3.3. Запрос на согласование (review request)
workspace_artifact_review
id, artifact_id, artifact_version
reviewers TEXT[] -- user:ivanov | org:backend | role:admin | project_owner
mode TEXT -- all (по умолчанию) | any
status TEXT -- open | approved | rejected | cancelled
note TEXT -- комментарий отправителя
requested_by / requested_at
resolved_by / resolved_at / comment
Синтаксис получателей переиспользуется из ask_human (docs/inbound-messages.md
§7): конкретный человек, подразделение, роль. mode=any закрывает согласование
первым ответом (одобрение или отказ), mode=all собирает все решения и
закрывается отказом при первом же «нет».
#3.4. Reference-документы и рабочие продукты (kind)
reference— регламенты, инструкции, чек-листы: то, на что ссылаются навыки;work— требования, спеки, проектные решения: то, что производится и реализуется в сагах.
Один реестр, одна модель доступа; kind разделяет сценарии потребления и
группировку в UI, а не права. Граница проницаема: реализованное и закреплённое
требование может стать reference-документом нового навыка — той же записью с
другим kind после нового круга согласования.
#3.5. Артефакт в саге
workspace_artifact.saga_id TEXT NULL — артефакт, созданный внутри саги,
наследует её идентификатор (сага регистрируется тулом saga_register,
docs/sagas.md). Это не сужает видимость (орго-модель не меняется), но даёт
трассировку: требование → согласование → раны реализации → фича. Обратная связь
идёт через события: каждый ран, читавший артефакт, уже эмитит artifact.read;
сага связывает их в сквозную историю.
#4. Принципы
- Утверждение человеком — единственная дверь в
approved. Не сумма сигналов, не частота использования, не агентское ревью. Явное решение именованного человека. - Статус — ограничитель, а не слагаемое. Черновик можно читать, но нельзя
выдавать за опору:
draft/rejectedникогда не резолвятся для навыков, а в ответе тулов всегда видны. - Агент предлагает — человек утверждает. Тот же контракт, что у
skill_proposeи эволюции агентов: агент делает черновик и запрос ревью, решение и ответственность остаются за человеком. - Иммутабельность утверждённого. Изменение одобренного документа — новая
версия и новый круг согласования; воспроизводимость решений восстанавливается
по
content_hashв событиях чтения (docs/artifact-registry.md §3.2). - Черновики читаемы, но помечены. Переиспользование между агентами —
половина ценности: разработчик читает требование аналитика. Ответ тулов
несёт
statusиversion; системный промпт прямо говорит: draft — это неподтверждённый материал. - Инвариант проверяется сервером. Валидация ссылок в манифесте навыка — на границе API (422), а не в соглашениях между агентами.
#5. Машина состояний
┌──────────────────────────────────────────┐
│ │ edit
▼ │
создание ──► draft ──submit──► in_review ──approve──► approved
(human/agent) ▲ │ │
│ edit │ reject │ новая версия
└──────────────────┘ ▼
draft(v+1)
approved(v) при approve(v+1) ──► superseded(v)
Правила переходов (проверяются в Store, не в клиентах):
draft → draft: правки полей/тела, пересчётcontent_hash(кто угодно с правом записи; каждое изменение — событие аудита);draft → in_review:submit, создаёт review-строку; повторныйsubmitтой же версии идемпотентно возвращает открытый review;in_review → approved: решение по правилуmode(all/any); тело фиксируется,versionстановится указателем «утверждённая»;in_review → rejected/rejected → draft: возврат с комментарием и новый круг доработки — в том числе агентом (artifact_update+ повторныйsubmit);approved → superseded: автоматический переход предыдущей утверждённой версии при утверждении следующей;- правка approved (ребро «новая версия» на диаграмме): новая редакция —
отдельный черновик в таблице версий (migration 0006/0007,
workspace_artifact_version); утверждённая версия ОСТАЁТСЯ живой и обслуживает агентов, навыки и чтение, пока редакция не утверждена. Утверждение атомарно промотирует черновик в живую строку (v+1, approved) и штампует предыдущую версию superseded; отклонение возвращает редакцию в draft. Агентский тулartifact_updateредактирует approved только через явный путь новой редакции:new_version: true→POST /v1/workspace/artifacts/{id}/revisionоткрывает черновик-редакцию (утверждённая версия остаётся живой), после чегоartifact_submitотдаёт её на повторное утверждение — решение остаётся за человеком; прямая правка approved (PUT без флага) по-прежнему 409. - удаление: как сегодня — guard 409, пока на артефакт ссылаются навыки; черновики и rejected удаляются свободно (writer).
#6. Согласование несколькими людьми
- Получатели. Список в синтаксисе
ask_human;org:<unit>раскрывается в активных людей подразделения на момент submit. - Режимы.
all— решение принято, когда все ответили «за» (первое «против» закрывает отказом);any— первого ответа достаточно. - Уведомления. Каждому согласующему — уведомление в его включённые
каналы (та же доставка, что у
ask_human: preferred-канал, затем первый включённый и настроенный, иначе веб-инбокс без уведомления) со ссылкой на страницу артефактов. Реализовано в фазе 1 — текст + ссылка, best-effort, вне цикла запроса. Фаза 2: доставка через human_request (orphan-RunIDartifact-review/<round>) — ответ в чате решает круг (ниже), пост в thread-транспортах становится корнем обсуждения, и тредматчится точно в этот круг даже при нескольких открытых ревью у одного согласующего. - Решение из канала (фаза 2). Первое слово ответа решает:
approve/approved/lgtm/ok/одобрить/одобряю/согласен— за,reject/rejected/отклонить/отклоняю— против; остальная часть ответа становится комментарием. Решение проходит тот же переход стора и те же события/аудит, что и кнопка в UI («via: channel:<тип>» в событии); не-первое слово, «да»/«нет» и прочая неоднозначность круг не закрывают — бот просит ответить по форме. Явная «отмена» закрывает только строку канала (круг остаётся открытым для UI). Решивший не входит в список согласующих — бот отказывает, круг не меняется. Инлайн-кнопки (Telegram inline keyboard, Matrix-виджеты) — отдельная работа по драйверам, вне фазы 2. - Решение по групповой записи. Записи согласующих — синтаксис
ask_human; решение принимается от имени записи (org:core,role:lead,project_owner) любым её участником с активным профилем: решение фиксируется под записью,decided_byназывает конкретного принципала. Один принципал может закрыть несколько записей сразу (свой id + своя роль/подразделение) —mode=allсчитает записи, а не людей. - Доработка в цикле. Человек правит черновик сам (UI) или отвечает
замечанием; агент вносит правки
artifact_updateи повторно отправляет. Круги не ограничены, каждый оставляет review-строку и события. - Анти-спам. Лимит submit-ов на агента в сутки (env
ARTIFACT_SUBMIT_PER_DAY, по умолчанию 10) — как rate-limit intake: защита очереди согласующих от зафлудившего рана. - Напоминания и эскалация (фаза 2). Фоновый свип раз в 5 минут:
открытый круг старше дедлайна (env
ARTIFACT_REVIEW_TIMEOUT, по умолчанию 72ч;0выключает свип) получает одно напоминание согласующим в каналы; ещё через один полный таймаут молчания — эскалация эффективному главе орг-единицы артефакта (снизу вверх: ближайший предок с назначенной головой; неактивная голова пропускается), без единицы/головы — администраторам инсталляции (семантикаproject_owner: у проектов пока нет владельца). Каждый шаг срабатывает один раз на круг (штампыreminded_at/escalated_at— и защита от повтора), событияartifact.review.reminded/artifact.review.escalatedидут в журнал. Решение из UI закрывает строку канала — чат не может решить круг дважды, и наоборот: ответ из канала закрывает круг для UI. - Идемпотентность. Повторный approve/reject того же review — 409 без изменения состояния; решение фиксируется один раз.
#7. Инструменты агента
Новые тулы (ядро ходит в workspace API от service-identity, как artifact_search;
origin фиксируется сервером по RunID):
artifact_create { title, description, content?, mime_type?, kind=work,
saga_id? } → draft
artifact_update { artifact_id, title?, description?, content?, … }
→ только draft/rejected версии
artifact_submit { artifact_id, reviewers[], mode=all, note? }
→ in_review + уведомления
Изменения существующих:
artifact_search— фильтрstatus=(по умолчанию все, как сегодня) иkind=; в выдаче добавляютсяstatus,version,origin_type;artifact_read— в ответеstatusиversion; чтение черновика разрешено (переиспользование), тело помечено статусом в метаданных ответа.
Политика безопасности: три новых тула добавляются в policySafeTools — они не
имеют внешних эффектов (черновик внутри реестра, submit — запрос к людям, не
действие), ровно как ask_human и skill_propose.
Системная секция промпта (рядом со Skills) дополняется: «рабочие продукты создавай как артефакты (kind=work), указывай saga_id; draft — не утверждён: не выдавай его за опору и не ссылайся на него в навыках».
#8. Связь с навыками (инвариант)
PUT /skills/{id}(новая версия манифеста): каждая ссылкаartifacts[]проверяется наstatus=approved; иначе — 422artifact_not_approvedсо списком id и текущих статусов.- Резолюция ссылок (
GET /skills/{id}, digest,skill_inspect) отдаёт только утверждённые версии; артефакт, потерявший approved-версию (сверх редкий случай отката), помечается вskill_inspectпредупреждением, навык не ломается. - Существующие ссылки миграции не касаются: текущие артефакты становятся
approved(v1) — их уже загрузили люди, см. §12 (миграция).
#9. API
POST /v1/workspace/artifacts — создание (status по origin:
human → approved, agent → draft)
PUT /v1/workspace/artifacts/{id} — правка draft/rejected;
approved → 409 + подсказка о новой версии
POST /v1/workspace/artifacts/{id}/submit — { reviewers[], mode, note } → 202
(идемпотентно на версию)
POST /v1/workspace/artifacts/{id}/reviews/{rid}/approve — { comment }
POST /v1/workspace/artifacts/{id}/reviews/{rid}/reject — { comment }
GET /v1/workspace/artifacts?status=&kind=&saga= — фильтры списков
GET /v1/workspace/artifacts/{id}/reviews — история согласований
RBAC: создание/правка — writer (тул агента — service-identity с origin=agent); approve/reject — writer, но не сервисный токен рана (только человек); удаление — operator, как сегодня.
#10. UI
Страница «Артефакты» (уже в основном меню):
- чипы-фильтры статусов (draft / in_review / approved / rejected / superseded) и kind — по образцу bounded-чипов «Входящих», со счётчиками;
- карточка: бейдж статуса, версия, происхождение («создал: агент analyst, ран …» / «создал: ivanov»), сага;
- панель согласования для in_review: список согласующих, режим, кнопки «Утвердить» / «Отклонить» с комментарием; история кругов;
- редактор навыка: выбор артефактов ограничен approved (недоступные — с пояснением);
- уведомление согласующему кликабельно ведёт на карточку артефакта.
#11. Аудит и события
Журнал (outbox, durable — не best-effort, как artifact.read):
artifact.proposed { artifact_id, version, origin, kind, saga_id? }
artifact.updated { artifact_id, version, actor }
artifact.review.requested{ artifact_id, version, reviewers, mode }
artifact.review.approved { artifact_id, version, resolved_by }
artifact.review.rejected { artifact_id, version, resolved_by, comment }
artifact.superseded { artifact_id, from_version, to_version }
API-действия дублируются в access audit (create/update/approve), как сегодня.
#12. Фазы реализации
#Фаза 1 — жизненный цикл и создание агентами (ядро ценности)
Миграция (status/kind/version/origin/saga_id; существующие записи →
approved v1, kind=reference, origin=human — они загружены людьми, это и
есть их утверждение); машина состояний в Store; тулы artifact_create / artifact_update / artifact_submit; статус в artifact_search/read; guard
навыков (422); review-таблица и approve/reject API; события; UI-минимум: чипы
статусов, бейджи, кнопки решения, происхождение. Уведомление согласующим —
текстовое со ссылкой.
#Фаза 2 — согласование в каналах (реализовано)
Обобщение human_requests на запросы вне рана (orphan-RunID
artifact-review/<round>): уведомление согласующему создаёт строку
human_request с выдачами (deliveries) по каналам; ответ в чате согласующего
решает круг тем же переходом стора, что и кнопка в UI (первое слово ответа —
решение, остальное — комментарий). Пост в thread-транспортах закрепляется
как корень обсуждения — тредматчится точно в этот круг. Напоминания по
дедлайну (env ARTIFACT_REVIEW_TIMEOUT, по умолчанию 72ч, 0 выключает) и
эскалация эффективному главе орг-единицы артефакта (без головы/единицы —
админам) после второго таймаута молчания; каждый шаг — один раз на круг.
Настоящие инлайн-кнопки (Telegram/Matrix) — отдельная работа по драйверам.
#Фаза 3 — версии, комплаенс, трассировка
Полная история тел: снапшоты утверждённых версий при открытии новой редакции
и просмотр архивных тел в UI — реализовано (таблица
workspace_artifact_version, эндпоинт GET /artifacts/{id}/versions, блок
«История версий» в карточке). Осталось: восстановление на дату — закрывает
открытый вопрос docs/artifact-registry.md §12; UI-трассировка саги: артефакт
→ круги согласования → раны реализации → итоговый PR/фича; пиннг версии в
манифесте навыка (опционально, для комплаенса); конвертация work → reference
как самостоятельный сценарий.
#13. Критерии готовности
#Фаза 1
- Агент создаёт требование в саге, человек утверждает; второй агент в ране той
же саги читает его через
artifact_readи видитstatus=approved, version=1. - Манифест навыка со ссылкой на draft отклонён: 422
artifact_not_approved. - Правка approved через API — 409; через тула — понятная ошибка агенту.
- Повторный approve того же review — 409, состояние не меняется.
- Все переходы дают события; в трейсе согласование читается как шаги с локализованными строками.
- Существующие до миграции навыки и артефакты работают без изменений.
#Фаза 2
- Согласование закрывается ответом из канала; в UI виден тот же результат (те же решения, события и аудит; событие помечено via: channel:<тип>).
- Просроченный review получает одно напоминание согласующим, а после второго таймаута молчания эскалирует эффективному главе орг-единицы (иначе админам) — по одному разу на круг.
#Фаза 3
- Содержимое любого артефакта восстанавливается на любую дату.
- Страница саги связывает требование → раны → фичу без ручного поиска.
#14. Открытые вопросы
- Ко-редактирование черновиков. Сейчас править draft может любой writer (и любой агент) — это позволяет доработку «с агентом», но не защищает от затирания. Вариант: черновик-владелец + явная передача права.
- Обязательный ревью для человеческих reference-документов в строгих инсталляциях (сейчас создание человеком = утверждение).
- Агентское предварительное ревью (reviewer-агент готовит сводку замечаний до человека) — снижает нагрузку на согласующих, но не заменяет их.
- Пиннг версии в манифесте против always-latest-approved: нужно комплаенс- требование, чтобы выбрать.
- Квоты на размер агентских черновиков (сейчас общий лимит 2 МиБ).
#15. Архитектурные ограничения
- Граница с knowledge: артефакт — документ с телом; знание — утверждение с
доказательной базой. Утверждение артефакта не создаёт knowledge; агент
записывает выводы отдельным
remember. - Утверждение делает документ опорой для навыков, но не «истиной»: достоверность содержимого остаётся на человеке, поставившем подпись.
- Реестр остаётся сквозным ресурсом оргструктуры:
saga_id— трассировка, не права; видимость определяетсяorg_unit_id, как сегодня. - Черновики не попадают в промпты неявно — прогрессивное раскрытие (docs/artifact-registry.md §3.4) не меняется.
- Согласование не блокирует раны: submit — асинхронный запрос к людям, ран
продолжает работу (в отличие от
ask_human), т.к. цикл доработки может занимать дни.