Артефакты и комментарии¶
Артефакт — неизменяемая запись о результате работы: отчёт, коммит, документ, транскрипт прогона. Комментарий — реплика в треде задачи для координации, с сохранением истории правок. Статья описывает обе сущности, их правила и API, хранение файлов артефактов в хранилище объектов и реестр типов артефактов, и объясняет, что куда класть. Она нужна разработчикам харнессов и интеграций и операторам, читающим результаты агентов.
Что куда класть¶
| Что | Куда | Почему |
|---|---|---|
| Результат работы (отчёт, коммит, файл, сводка run'а) | Artifact | Неизменяем, привязан к run и задаче, доступен как evidence и в контексте следующих runs |
| Обсуждение, вопрос, пояснение к передаче | Comment | Координация между людьми и агентами; автор — из credential |
| Состояние для продолжения работы | Checkpoint run'а | Явное операционное состояние для рестарта (см. Исполнение) |
| Запись о вызове инструмента | Run action | Лёгкий аудит, вне журнала событий |
| Файл результата (документ, PDF, архив) | Содержимое артефакта: PUT /artifact-contents, затем артефакт с contentRef |
Байты лежат в хранилище объектов ядра; база хранит ссылку, размер и контрольную сумму, не blob'ы |
| Файл, который уже живёт в другой системе | Внешнее хранилище + uri артефакта |
Ядро хранит только ссылку |
Ни в комментарии, ни в артефакты — секреты
Ни prompts, ни сырые транскрипты, ни credentials не место в комментариях.
Для транскрипта есть отдельный вид артефакта с ограничением размера и
редакцией — transcript.
Артефакты¶
Модель¶
| Поле | Описание |
|---|---|
id |
Идентификатор |
type |
Вид артефакта, строка 1–200 символов; словарь открытый, зарегистрированные виды проверяются (см. Типы артефактов) |
name |
Имя, 1–500 символов; для файла — имя, под которым он отдаётся |
taskId, runId, workspaceId |
Привязки (все необязательны) |
uri |
Ссылка на содержимое во внешнем хранилище (до 2000 символов) |
content |
Небольшой JSON-документ с содержимым |
metadata |
JSON-метаданные: то, что читатель хочет знать до открытия |
supersedesArtifactId |
Предыдущая ревизия, которую заменяет эта |
contentState |
Содержимое в хранилище: none (его нет — ссылка или JSON), stored (лежит), purged (удалено администратором) |
sizeBytes, mediaType, sha256 |
Размер, media type и SHA-256 содержимого; null у артефакта без содержимого, после удаления сохраняются как след |
typeVersion |
Версия зарегистрированного типа, по которой артефакт проверен; null у незарегистрированного вида |
createdByPrincipalId, createdAt |
Автор и время |
Артефакт сдаётся в одной из трёх форм: ссылка (uri), небольшой JSON
(content) или файл в хранилище ядра (contentRef). contentRef
исключает uri и content.
Артефакты только создаются и читаются: изменения и удаления записи в API нет. Новая версия результата — новый артефакт со ссылкой на предыдущий. Удалить можно только байты содержимого, и только администратору (см. Удаление содержимого).
Создание¶
curl -s -X POST "$CP/artifacts" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"type": "report",
"name": "Отчёт о нагрузке за неделю",
"runId": "<run-id>",
"uri": "https://files.example.com/reports/load-week-38.pdf",
"content": {"summary": "p95 вырос на 12% в пиковые часы"},
"metadata": {"format": "pdf", "pages": 14}
}'
Правила:
- право
artifacts.write— решается на задаче артефакта; артефакт без задачи — на его workspace, без обоих — на уровне tenant'а; - если передан
runIdбезtask, задача берётся из run; если переданы оба и run принадлежит другой задаче —422 artifact_mismatch; - для дочернего run проверяется, что
artifacts.writeвходит в его потолок прав (см. дочерние runs в Исполнении); supersedesArtifactIdдолжен существовать в tenant'е (404);- пустые
typeилиname—422 invalid_type/422 invalid_name; contentRefвместе сuriилиcontent—422 invalid_artifact_content;- если
typeзарегистрирован в tenant'е, артефакт проверяется по последней версии типа (см. Типы артефактов); - общий лимит тела запроса —
CP_MAX_BODY_BYTES(1 МиБ по умолчанию): файлы загружайте отдельно (см. Содержимое в хранилище).
Ревизии¶
flowchart LR
A1["artifact v1<br/>type: report"] --> A2["artifact v2<br/>supersedesArtifactId = v1"] --> A3["artifact v3<br/>supersedesArtifactId = v2"]
Ревизия — отдельный артефакт с supersedesArtifactId. Исходный артефакт
остаётся нетронутым: аудит видит, что было опубликовано и когда.
Чтение¶
curl -s "$CP/artifacts?taskId=<task-id>&type=commit" -H "Authorization: Bearer $TOKEN"
curl -s "$CP/artifacts/<artifact-id>" -H "Authorization: Bearer $TOKEN"
GET /artifacts (artifacts.read) принимает фильтры taskId, runId,
workspaceId, type и пагинацию limit / cursor; новые — первыми.
GET /artifacts/{id} проверяет artifacts.read на задаче артефакта.
Параметр ?forTask=<ref> читает артефакт как вход задачи-получателя:
достаточно tasks.read на задаче-получателе, если артефакт сейчас — один из
её разрешённых входов (см. Входы и выходы).
Иначе действует обычная проверка на задаче артефакта; чужой tenant — 404.
Артефакты прошлых runs задачи также приходят в Run Context
(GET /runs/{id}/context) — так следующий исполнитель видит, что уже
сделано (см. Контекст задачи и память).
Виды артефактов¶
Словарь type открытый: ядро не интерпретирует содержимое. Вид, который
tenant зарегистрировал в реестре типов артефактов,
проверяется при записи; любой другой принимается без проверки. Компоненты
платформы используют такие виды (все — незарегистрированные):
type |
Кто публикует | Содержимое |
|---|---|---|
commit |
Runner, работающий в репозитории | uri коммита, metadata: branch, commit, workspaceKey, published (попала ли ветка во внешний git) |
transcript |
Адаптеры кодовых агентов | Ограниченная лента прогона, схема agent-transcript/1 |
skill_result |
Ядро, при успешном вызове Skill с задачей | content.output — выход Skill; автор — инициатор вызова |
report |
Пример-исполнитель runner'а и интеграции | Произвольный отчёт |
document |
Консоль платформы при прикреплении файла | uri вида platform://documents/<id> — ссылка на документ хранилища платформы |
verification |
Ядро, когда пройдена стадия проверки задачи | Итог проверок (см. Цели, приёмка и evidence) |
Собственные интеграции могут вводить свои виды — выберите стабильные имена
и документируйте их metadata, чтобы на них можно было ссылаться, например,
в выражениях исходов approval ($.task.artifact[<type>].metadata.<field>,
см. Approvals).
Транскрипт прогона¶
Артефакт transcript — один JSON-документ agent-transcript/1, который
адаптер кодового агента публикует в конце run'а:
- размер ограничен 512 КиБ, тексты отдельных записей и результаты инструментов обрезаются;
- каждая строка проходит редакцию локальных путей и credential-подобных значений;
- скрытые рассуждения модели считаются, но не сохраняются;
- если документ всё равно не проходит проверку переносимости, он
публикуется без текста (
"withheld": true), только со счётчиками.
metadata транскрипта содержит schema, harnessType, число записей,
вызовов инструментов и ошибок, модель и расход токенов, если известны. Вызовы
инструментов параллельно пишутся run actions вида tool.<имя>. Подробности
и настройки — в Трассе прогонов.
Артефакт как evidence¶
Артефакт можно указать фактом в evidence задачи:
{"kind": "artifact", "artifactId": "…", "check": "tests"}. Ядро проверит,
что артефакт существует в tenant'е. См.
Цели, приёмка и evidence.
Содержимое в хранилище¶
Файл результата — спецификацию, PDF-заключение, архив — ядро хранит само: в S3-совместимом хранилище объектов (в поставке — MinIO контура, см. Хранилище объектов). База держит только запись артефакта со ссылкой, размером, media type и SHA-256; байты в PostgreSQL и в памяти процесса не лежат. Хранилище наружу не публикуется: байты входят и выходят только через API ядра.
Сдача файла — два шага:
sequenceDiagram
participant C as Клиент
participant CP as Control Plane
participant S as Хранилище объектов
C->>CP: PUT /artifact-contents (байты, Content-Type)
CP->>S: объект tenants/<tenant-id>/sha256/<hex>
CP-->>C: 201 {contentRef, sizeBytes, mediaType, sha256, expiresAt}
C->>CP: POST /artifacts {type, name, task, contentRef, metadata}
CP-->>C: 201 артефакт, contentState = stored
Если хранилище не настроено (CP_S3_ENDPOINT_URL пуст) или недоступно,
маршруты содержимого отвечают 503 content_store_unavailable. Остальное
продолжает работать: артефакты-ссылки и JSON-артефакты создаются и
читаются как обычно.
Загрузка: PUT /artifact-contents¶
Тело запроса — сырые байты файла, не JSON и не multipart. Заголовок
Content-Type обязателен и задаёт media type содержимого.
curl -s -X PUT "$CP/artifact-contents" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/pdf" \
--data-binary @review.pdf
{
"contentRef": "cref_<upload-id>",
"sizeBytes": 184320,
"mediaType": "application/pdf",
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"expiresAt": "2026-01-16T10:00:00Z"
}
Правила:
- право
artifacts.write(без привязки к задаче: задача проверяется, когда на загрузку сошлётся артефакт); Content-Typeотсутствует или не похож наtype/subtype—400 invalid_request; базовый тип приводится к нижнему регистру, параметры (; charset=utf-8) сохраняются;- предел размера —
CP_ARTIFACT_MAX_BYTES(100 МиБ по умолчанию); для этого маршрута он заменяет общийCP_MAX_BODY_BYTES. Больше —413 request_too_large. Тело пишется во временный файл на диске с подсчётом SHA-256 и в память целиком не попадает; - объекты адресуются содержимым внутри tenant'а: одинаковые байты,
загруженные дважды, хранятся одним объектом, но каждая загрузка получает
свой
contentRef.
Кому принадлежит contentRef. Ссылка действует только для principal'а,
который загружал, и только в его tenant'е. Чужая, несуществующая, искажённая
или истёкшая ссылка даёт одинаковый ответ 422 content_ref_not_found:
знание контрольной суммы или чужой ссылки не позволяет сослаться на чужие
байты.
Сколько живёт. Загрузка ждёт артефакта CP_ARTIFACT_UPLOAD_TTL_SECONDS
(24 часа по умолчанию), срок — в expiresAt. Пока срок не вышел, на одну
загрузку могут сослаться несколько артефактов. Worker удаляет загрузки, на
которые до истечения срока не сослался ни один артефакт, и объекты, которые
больше никому не нужны.
Запись артефакта с содержимым¶
curl -s -X POST "$CP/artifacts" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"type": "review-report",
"name": "review.pdf",
"task": "<task-id>",
"contentRef": "cref_<upload-id>",
"metadata": {"reviewer": "alice@example.com"}
}'
В ответе — contentState: "stored" и sizeBytes, mediaType, sha256
загрузки. name — имя, под которым файл будет отдаваться при скачивании.
Чтение содержимого: GET /artifacts/{id}/content¶
curl -s "$CP/artifacts/<artifact-id>/content" \
-H "Authorization: Bearer $TOKEN" -o review.pdf
# как вход задачи-получателя
curl -s "$CP/artifacts/<artifact-id>/content?forTask=<task-ref>" \
-H "Authorization: Bearer $TOKEN" -o review.pdf
Авторизация та же, что у GET /artifacts/{id}: artifacts.read на задаче
артефакта (на workspace, если задачи нет; на tenant'е, если нет и его) или,
с ?forTask=, tasks.read на задаче-получателе, если артефакт — её
разрешённый вход. Исполнитель следующего шага получает вход, даже не имея
права на задачу предыдущего: вход ему выдан потому, что его объявил тип его
задачи.
Байты отдаются потоком с заголовками:
| Заголовок | Значение |
|---|---|
Content-Type |
mediaType артефакта |
Content-Length |
размер |
Content-Disposition |
attachment; filename*=UTF-8''<name> для активного содержимого (text/html, application/xhtml+xml, image/svg+xml, text/xml, application/xml, text/javascript, application/javascript и любой +xml), иначе inline с тем же filename* |
ETag |
"sha256:<hex>" |
X-Content-Type-Options |
nosniff |
Cache-Control |
private, no-store |
| Ответ | Когда |
|---|---|
200 |
Байты |
403 permission_denied |
Нет права ни на задаче артефакта, ни как на вход |
404 |
Артефакта нет в tenant'е или задача forTask не найдена |
404 content_not_found |
У артефакта нет содержимого (contentState = none) |
410 content_purged |
Содержимое удалено администратором |
503 content_store_unavailable |
Хранилище не настроено, недоступно или объекта в нём нет |
Каждая выдача пишет событие artifact.content_read: кто, какой артефакт,
для какой задачи (forTaskId, если выдано как вход) и в каком run
читающего. Событие фиксируется до отправки первого байта; выдача, которую
хранилище не смогло обслужить, события не оставляет.
Удаление содержимого¶
Содержимое хранится бессрочно: закрытие или отмена задачи его не трогает.
Удалить байты может только администратор tenant'а (право admin); запись
артефакта остаётся:
curl -s -X POST "$CP/artifacts/<artifact-id>:purge-content" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"reason": "Персональные данные попали в отчёт по ошибке"}'
reasonобязателен, 1–2000 символов; в событие попадает очищенным от секретов и обрезанным до 1000 символов;- артефакт получает
contentState = purged;sizeBytes,mediaTypeиsha256сохраняются как след; - объект удаляется из хранилища, только если на те же байты не ссылаются другие артефакты с содержимым и неистёкшие загрузки tenant'а;
- повтор на уже удалённом —
200с той же записью, без нового события; артефакт без содержимого —409 content_not_stored; - объект удаляется до фиксации транзакции: если хранилище недоступно,
ответ —
503 content_store_unavailable, запись остаётсяstored.
Событие — artifact.content_purged с полем objectDeleted: удалён ли
объект или он ещё нужен другим артефактам.
MCP-инструменты¶
cp_create_artifactпринимаетfile— путь к локальному файлу. Инструмент сам загружает его (PUT /artifact-contents) и создаёт артефакт текущей задачи и run с полученнымcontentRef.nameпо умолчанию — имя файла,media_typeпо умолчанию угадывается по расширению (иначеapplication/octet-stream).fileисключаетuriиcontent.cp_get_artifact_contentскачивает содержимое артефакта в локальный файл и возвращает путь.path— куда писать (по умолчанию временный каталог вне рабочей копии),for_task— задача-получатель (по умолчанию текущая). Текстовое содержимое до 64 КиБ дополнительно возвращается строкойtext.
Типы артефактов¶
Тип артефакта — объект каталога tenant'а, как тип задачи: ключ, JSON Schema
для metadata, допустимые media types содержимого и потолок размера. Ядро не
знает, что тип означает, — кода под тип нет. Типы нужны, чтобы артефакты
одного вида были однородны и чтобы на них могли ссылаться входы и выходы
типов задач (см. Входы и выходы).
Модель¶
| Поле | Описание |
|---|---|
key |
^[a-z0-9][a-z0-9_-]*$, 1–63 символа; совпадает с type артефакта |
version |
Выдаёт сервер: следующая после максимальной для ключа |
displayName |
1–200 символов |
description |
До 2000 символов |
metadataSchema |
JSON Schema для metadata артефакта, до 16 КиБ; по умолчанию {} — любой объект |
mediaTypes |
1–50 элементов: type/subtype, type/* или */*; приводятся к нижнему регистру, повторы убираются |
maxBytes |
Потолок размера содержимого, от 1 до CP_ARTIFACT_MAX_BYTES; не указан — CP_ARTIFACT_MAX_BYTES на момент создания версии |
status |
active |
Версии¶
Версия неизменяема. POST /artifact-types с существующим ключом
создаёт следующую версию, а не правит текущую. Маршрута депрецирования у
типов артефактов нет. Артефакт всегда проверяется по последней версии
ключа (наибольшей по номеру) и запоминает её в typeVersion.
Адресация по ключу, как в поле type артефакта:
GET /artifact-types/{key}— последняя версия;GET /artifact-types/{key}@{version}— точная версия.
curl -s -X POST "$CP/artifact-types" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"key": "review-report",
"displayName": "Заключение проверки",
"mediaTypes": ["application/pdf"],
"maxBytes": 10485760,
"metadataSchema": {
"type": "object",
"required": ["reviewer"],
"properties": {"reviewer": {"type": "string"}}
}
}'
curl -s "$CP/artifact-types/review-report@1" -H "Authorization: Bearer $TOKEN"
Ошибки публикации — 422 invalid_artifact_type с details.field
(metadataSchema, mediaTypes, mediaTypes[<i>], maxBytes); причина отказа
схемы — в details.reason и details.cause.
Проверка артефакта¶
Если type артефакта зарегистрирован в tenant'е, POST /artifacts
проверяет его по последней версии типа:
| Что | Ошибка |
|---|---|
metadata по metadataSchema |
422 invalid_artifact_metadata, нарушения — в details.errors |
mediaType содержимого по mediaTypes (без параметров и без учёта регистра: text/markdown; charset=utf-8 — это text/markdown) |
422 media_type_not_allowed, в details — mediaType и allowed |
sizeBytes содержимого по maxBytes |
422 artifact_too_large, в details — sizeBytes и maxBytes |
Media type и размер есть только у содержимого из contentRef: ссылка и
JSON-артефакт зарегистрированного типа проверяются только по metadata.
Незарегистрированные виды (commit, report, transcript,
skill_result, verification и любые другие) принимаются без проверки,
typeVersion = null. Артефакты, которые пишет само ядро, не проверяются.
API реестра¶
| Метод | Путь | Право |
|---|---|---|
POST |
/artifact-types |
artifact_types.manage |
GET |
/artifact-types?key=&status= |
artifact_types.read |
GET |
/artifact-types/{key} |
artifact_types.read |
GET |
/artifact-types/{key}@{version} |
artifact_types.read |
Список — новые первыми, пагинация limit / cursor. В пакетах каталога тип
артефакта объявляется видом ArtifactType (см.
Пакеты каталога).
API артефактов¶
| Метод | Путь | Право |
|---|---|---|
PUT |
/artifact-contents |
artifacts.write |
POST |
/artifacts |
artifacts.write на задаче артефакта |
GET |
/artifacts/{id} |
artifacts.read на задаче артефакта или tasks.read на задаче forTask |
GET |
/artifacts/{id}/content |
как GET /artifacts/{id} |
POST |
/artifacts/{id}:purge-content |
admin |
Коды ошибок артефактов¶
| Код | HTTP | Когда |
|---|---|---|
invalid_request |
400 | PUT /artifact-contents без корректного Content-Type |
request_too_large |
413 | Файл больше CP_ARTIFACT_MAX_BYTES |
content_store_unavailable |
503 | Хранилище не настроено, недоступно или потеряло объект |
invalid_artifact_content |
422 | contentRef вместе с uri или content |
content_ref_not_found |
422 | contentRef не является живой загрузкой этого principal'а |
invalid_artifact_metadata |
422 | metadata не проходит metadataSchema типа |
media_type_not_allowed |
422 | Media type содержимого не входит в mediaTypes типа |
artifact_too_large |
422 | Содержимое больше maxBytes типа |
invalid_artifact_type |
422 | Ошибка в определении типа артефакта |
content_not_found |
404 | У артефакта нет содержимого |
content_purged |
410 | Содержимое удалено администратором |
content_not_stored |
409 | :purge-content у артефакта без содержимого |
Комментарии к задаче¶
Комментарий — координация: он не несёт полномочий и не заменяет артефакт. Два правила делают тред надёжным:
- автор берётся из credential, а не из тела запроса — реплику агента отличает от реплики человека сама система, без соглашений в тексте;
- правка сохраняет прежний текст: предыдущая версия записывается в append-only историю до того, как новый текст ляжет в комментарий.
Модель¶
| Поле | Описание |
|---|---|
id, taskId |
Комментарий и задача |
authorPrincipalId |
Автор — principal вызывающего |
body |
Текст до 10 000 символов |
runId, artifactId |
Необязательная привязка к run или артефакту той же задачи |
version |
Растёт при каждой правке; ETag: "comment-<version>" |
createdAt, updatedAt, editedAt |
editedAt задан, если комментарий правили |
Добавление¶
curl -s -X POST "$CP/tasks/TASK-000123/comments" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"body": "Миграция проверена на копии базы, можно выкладывать", "runId": "<run-id>"}'
- право
tasks.write; - текст обрезается по краям; пустой —
422 invalid_comment_body, длиннее 10 000 символов —422 payload_too_large; - текст проверяется на секреты —
422 secret_material_rejected; runId/artifactIdчужой задачи —422 comment_mismatch, чужого tenant'а —404;- терминальная задача комментарии принимает: ретроспектива, причина отмены или ссылка на продолжение появляются уже после закрытия работы.
Правка¶
curl -s -X PATCH "$CP/tasks/TASK-000123/comments/<comment-id>" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-H 'If-Match: "comment-1"' \
-d '{"body": "Миграция проверена на копии базы; выкладывать после 18:00"}'
- Править может только автор (
403 not_comment_author). Исключений для администратора нет: переписать чужие слова от чужого имени — подмена авторства. If-Matchобязателен; несовпадение версии —409 version_conflict.- Правка, не меняющая текст, ничего не записывает: ни ревизии, ни новой версии, ни события — повтор запроса не порождает историю.
- Удаления комментариев нет.
История правок¶
{
"items": [
{
"id": "…", "commentId": "…", "taskId": "…",
"version": 1,
"body": "Миграция проверена на копии базы, можно выкладывать",
"authorPrincipalId": "…",
"createdAt": "…",
"supersededAt": "…",
"supersededBy": "…"
}
],
"nextCursor": null
}
Ревизии хранятся в append-only таблице: UPDATE и DELETE запрещены
триггером базы.
Лента¶
GET /tasks/{ref}/comments — единственная выборка, идущая от старых к
новым: тред читают вперёд, и реплика, написанная во время листания,
приезжает на следующей странице. Курсор ленты имеет собственный формат:
курсор другой выборки здесь даёт 422 invalid_cursor.
API комментариев¶
| Метод | Путь | Право |
|---|---|---|
POST |
/tasks/{ref}/comments |
tasks.write |
GET |
/tasks/{ref}/comments |
tasks.read |
GET |
/tasks/{ref}/comments/{id} |
tasks.read (ETag) |
PATCH |
/tasks/{ref}/comments/{id} |
tasks.write, только автор, If-Match |
GET |
/tasks/{ref}/comments/{id}/revisions |
tasks.read |
Комментарий адресуется через свою задачу: обращение к нему через чужую
задачу — 404.
MCP-инструменты: cp_list_comments (чтение), cp_comment,
cp_edit_comment (изменяющие).
События¶
| Событие | Поток | Payload |
|---|---|---|
artifact.created |
артефакта | type, name, taskId, runId, uri, supersedesArtifactId, sizeBytes, mediaType, sha256, contentState, typeVersion — без content и без байтов |
artifact.content_read |
артефакта | artifactId, taskId, forTaskId, runId (run читающего, если есть), sha256, sizeBytes |
artifact.content_purged |
артефакта | artifactId, taskId, sha256, sizeBytes, reason, objectDeleted |
artifact_type.created |
типа артефакта | key, version, mediaTypes, maxBytes, declaresMetadataSchema |
task.comment_added |
задачи | commentId, authorPrincipalId, version, bodyLength, runId, artifactId |
task.comment_edited |
задачи | То же |
События комментариев пишутся в поток задачи, чтобы подписчик видел обсуждение там же, где смены статуса. Текст комментария в журнал не попадает никогда — только длина.
См. также¶
- Исполнение — claims и runs — checkpoints и run actions.
- Типы задач и статусы — входы и выходы типа задачи.
- Пакеты каталога — вид
ArtifactType. - Хранилище объектов (MinIO)
- Трасса прогонов — транскрипт и actions инструментов.
- Цели, приёмка и evidence
- Документы и файлы
- События