Убрать конечные точки в абзацах и перечислениях документации

This commit is contained in:
admin committed 2026-11-11 06:25:43 +00:00
1 parent 15f541e9e4
commit 4eb5180d99
20 files changed
+267 -267

No files matched your search

+5 -5
View File
@@ -1,6 +1,6 @@
# API экземпляров агентов
Общие правила: [conventions.md](conventions.md). Все ресурсы scoped к tenant. Viewer читает разрешённые агенты; operator создаёт и настраивает свои, admin — разрешённые tenant-агенты.
Общие правила: [conventions.md](conventions.md). Все ресурсы scoped к tenant. Viewer читает разрешённые агенты; operator создаёт и настраивает свои, admin — разрешённые tenant-агенты
| Метод и путь | Запрос | Ответ | Поведение |
|---|---|---|---|
@@ -14,11 +14,11 @@
| POST /v1/agents/{id}/upgrade | targetTemplateVersionId, config, connections; If-Match | 200 AgentRevision | Новая ревизия, старые Run не меняются |
| DELETE /v1/agents/{id} | If-Match | 202 operationId | Архивирует; активные Run требуют отдельной отмены |
Agent: id, tenantId, ownerId, name, currentRevision, archivedAt?, createdAt. AgentRevision: id, agentId, revision, templateVersionId, configSchemaDigest, config, connections, createdAt. Connections — map логического имени на connectionId, без секретов.
Agent: id, tenantId, ownerId, name, currentRevision, archivedAt?, createdAt. AgentRevision: id, agentId, revision, templateVersionId, configSchemaDigest, config, connections, createdAt. Connections — map логического имени на connectionId, без секретов
ValidationResult: valid:boolean, errors:[{path, code, message}], effectiveConfig. При семантически невалидной конфигурации endpoint validate возвращает 200 valid=false; endpoints сохранения возвращают 422. Ссылки на чужие подключения не раскрываются в errors.
ValidationResult: valid:boolean, errors:[{path, code, message}], effectiveConfig. При семантически невалидной конфигурации endpoint validate возвращает 200 valid=false; endpoints сохранения возвращают 422. Ссылки на чужие подключения не раскрываются в errors
UpgradePreview: fromVersionId, toVersionId, changes:[{path, kind}], validation, addedPermissions. Preview не разрешает новые доступы автоматически. Принятие upgrade заново проверяет rights и policy.
UpgradePreview: fromVersionId, toVersionId, changes:[{path, kind}], validation, addedPermissions. Preview не разрешает новые доступы автоматически. Принятие upgrade заново проверяет rights и policy
## Пример создания
@@ -28,4 +28,4 @@ UpgradePreview: fromVersionId, toVersionId, changes:[{path, kind}], validation,
## Подключения
GET /v1/connections возвращает Page<ConnectionSummary> с cursor и limit, без credentials. Подключения создаются через provider authorization flow; единый контракт и защищённая передача API key описаны в [Provider API](provider-api.md). DELETE /v1/connections/{id} отзывает платформенный доступ и при возможности выполняет revoke у провайдера. Повторное использование в новом Run после отзыва запрещено.
GET /v1/connections возвращает Page<ConnectionSummary> с cursor и limit, без credentials. Подключения создаются через provider authorization flow; единый контракт и защищённая передача API key описаны в [Provider API](provider-api.md). DELETE /v1/connections/{id} отзывает платформенный доступ и при возможности выполняет revoke у провайдера. Повторное использование в новом Run после отзыва запрещено
+6 -6
View File
@@ -1,6 +1,6 @@
# API каталога
Общие правила: [conventions.md](conventions.md). Автор публикации — publisher соответствующего tenant. Читатель видит public или разрешённые tenant/private пакеты.
Общие правила: [conventions.md](conventions.md). Автор публикации — publisher соответствующего tenant. Читатель видит public или разрешённые tenant/private пакеты
| Метод и путь | Запрос | Ответ | Доступ / особые ошибки |
|---|---|---|---|
@@ -20,13 +20,13 @@
## Формы
Package: id, tenantId, kind (harness/plugin/skill/template), name, description, visibility (public/tenant/private), ownerId, createdAt, revision.
Package: id, tenantId, kind (harness/plugin/skill/template), name, description, visibility (public/tenant/private), ownerId, createdAt, revision
VersionDraft: id, packageId, version, manifest, status=draft. PackageVersion: те же идентификаторы, artifactRef, artifactDigest, schemaDigest?, publishedAt. VersionPolicy хранится отдельно: status, reason?, revision. Поле version не разрешает перезапись содержимого.
VersionDraft: id, packageId, version, manifest, status=draft. PackageVersion: те же идентификаторы, artifactRef, artifactDigest, schemaDigest?, publishedAt. VersionPolicy хранится отдельно: status, reason?, revision. Поле version не разрешает перезапись содержимого
Resolution: resolutionId, templateVersionId, packages:[{packageVersionId, kind, digest, artifactRef}], configSchemaDigest, requiredCapabilities, requiredPermissions. environment: os, architecture, protocolVersion, availableCapabilities. Resolution не содержит credentials и не обещает бессрочное право скачать заблокированный пакет.
Resolution: resolutionId, templateVersionId, packages:[{packageVersionId, kind, digest, artifactRef}], configSchemaDigest, requiredCapabilities, requiredPermissions. environment: os, architecture, protocolVersion, availableCapabilities. Resolution не содержит credentials и не обещает бессрочное право скачать заблокированный пакет
ConfigBundle: schema (JSON Schema), defaults (object), uiSchema (object|null), schemaDigest. UI schema необязательна. OCI upload использует стандартный registry API с ограниченным токеном; upload ручка для него выдаёт registry reference и scope, а не S3 URL.
ConfigBundle: schema (JSON Schema), defaults (object), uiSchema (object|null), schemaDigest. UI schema необязательна. OCI upload использует стандартный registry API с ограниченным токеном; upload ручка для него выдаёт registry reference и scope, а не S3 URL
## Пример resolve
@@ -34,4 +34,4 @@ ConfigBundle: schema (JSON Schema), defaults (object), uiSchema (object|null), s
{"templateVersionId":"version_company_1","environment":{"os":"linux","architecture":"amd64","protocolVersion":"1","availableCapabilities":["oci-v1","cancel-v1"]}}
```
Публикация возвращает успех только после проверки артефакта. Если загрузка завершилась, а запрос publish потерялся, повтор с тем же ключом безопасен. Удаление пакета, на который ссылаются сохранённые запуски, не входит в MVP; вместо него используются deprecated/blocked.
Публикация возвращает успех только после проверки артефакта. Если загрузка завершилась, а запрос publish потерялся, повтор с тем же ключом безопасен. Удаление пакета, на который ссылаются сохранённые запуски, не входит в MVP; вместо него используются deprecated/blocked
+7 -7
View File
@@ -1,12 +1,12 @@
# Общие правила API v1
Это проектируемые публичные контракты Invest Harness. Базовый путь /v1; JSON UTF-8; HTTPS обязателен. Внутренние API движка не являются публичным контрактом.
Это проектируемые публичные контракты Invest Harness. Базовый путь /v1; JSON UTF-8; HTTPS обязателен. Внутренние API движка не являются публичным контрактом
## Типы и ошибки
Id — непрозрачная строка 1–128 символов; Timestamp — RFC3339 UTC; Digest — sha256: и 64 hex-символа; Revision — положительное целое. Денежные суммы задаются integer minor units + currency; CPU в millicores, память и файлы в bytes, интервалы в seconds. Дата расписания содержит отдельно IANA timezone.
Id — непрозрачная строка 1–128 символов; Timestamp — RFC3339 UTC; Digest — sha256: и 64 hex-символа; Revision — положительное целое. Денежные суммы задаются integer minor units + currency; CPU в millicores, память и файлы в bytes, интервалы в seconds. Дата расписания содержит отдельно IANA timezone
Ошибка: {"error":{"code":"CONFIG_INVALID","message":"Настройки не соответствуют схеме","details":[{"path":"/lookbackDays","code":"maximum"}],"requestId":"req_example"}}. Никаких секретов или stack trace в ответе.
Ошибка: {"error":{"code":"CONFIG_INVALID","message":"Настройки не соответствуют схеме","details":[{"path":"/lookbackDays","code":"maximum"}],"requestId":"req_example"}}. Никаких секретов или stack trace в ответе
| HTTP | Значение |
|---|---|
@@ -22,12 +22,12 @@ Id — непрозрачная строка 1–128 символов; Timestamp
## Доступ и повторные запросы
Сессия пользователя или сервисный bearer token. Membership и ресурсный tenant проверяются на каждой операции. Публичное чтение каталога не даёт доступ к приватным зависимостям. Cookie-мутации требуют CSRF-защиты. Запросы публикации, запуска, retry и resume требуют Idempotency-Key; область ключа tenant + principal + method + path. Hash тела связывается с ключом; другое тело → 409. Результат хранится минимум 7 дней, а уникальность attemptId и schedule occurrence действует независимо от TTL ключа.
Сессия пользователя или сервисный bearer token. Membership и ресурсный tenant проверяются на каждой операции. Публичное чтение каталога не даёт доступ к приватным зависимостям. Cookie-мутации требуют CSRF-защиты. Запросы публикации, запуска, retry и resume требуют Idempotency-Key; область ключа tenant + principal + method + path. Hash тела связывается с ключом; другое тело → 409. Результат хранится минимум 7 дней, а уникальность attemptId и schedule occurrence действует независимо от TTL ключа
PATCH/PUT изменяемых ресурсов требуют If-Match, ответ содержит ETag. Списки: limit 1..100, непрозрачный cursor, ответ {items:[], nextCursor:null}. Cursor фиксирует сортировку createdAt,id и фильтры, не заменяет авторизацию. DELETE с асинхронной очисткой возвращает 202 и operationId.
PATCH/PUT изменяемых ресурсов требуют If-Match, ответ содержит ETag. Списки: limit 1..100, непрозрачный cursor, ответ {items:[], nextCursor:null}. Cursor фиксирует сортировку createdAt,id и фильтры, не заменяет авторизацию. DELETE с асинхронной очисткой возвращает 202 и operationId
## События и файлы
SSE endpoint принимает Last-Event-ID; SSE cursor монотонен в пределах Run и назначается сервером, отдельно от runner eventId. После retention слишком старый cursor возвращает 410 с указанием получить snapshot. Повторные runner events дедуплицируются по attemptId + eventId. SSE data содержит RunEvent, а transport id — серверный cursor; клиент хранит cursor для reconnect. SSE не является источником истины о состоянии: GET Run возвращает канонический snapshot.
SSE endpoint принимает Last-Event-ID; SSE cursor монотонен в пределах Run и назначается сервером, отдельно от runner eventId. После retention слишком старый cursor возвращает 410 с указанием получить snapshot. Повторные runner events дедуплицируются по attemptId + eventId. SSE data содержит RunEvent, а transport id — серверный cursor; клиент хранит cursor для reconnect. SSE не является источником истины о состоянии: GET Run возвращает канонический snapshot
Binary upload выполняется по scoped grant. Он содержит uploadId, url, expiresAt, maxBytes, requiredHeaders; постоянные записи хранят artifactId, не подписанный URL. Grant не считается подтверждением загрузки: finalize проверяет размер, digest и объект. По умолчанию ошибки не повторяются автоматически, кроме явных transient ошибок с ограниченным backoff и jitter.
Binary upload выполняется по scoped grant. Он содержит uploadId, url, expiresAt, maxBytes, requiredHeaders; постоянные записи хранят artifactId, не подписанный URL. Grant не считается подтверждением загрузки: finalize проверяет размер, digest и объект. По умолчанию ошибки не повторяются автоматически, кроме явных transient ошибок с ограниченным backoff и jitter
+13 -13
View File
@@ -1,12 +1,12 @@
# Runner Protocol v1
Новый контракт Invest Harness для заменяемых исполнителей. Стандартный движок подключается адаптером; он не обязан понимать этот API напрямую. ExecutionSpec одинаков для удалённой и локальной реализации.
Новый контракт Invest Harness для заменяемых исполнителей. Стандартный движок подключается адаптером; он не обязан понимать этот API напрямую. ExecutionSpec одинаков для удалённой и локальной реализации
## Регистрация
Admin создаёт POST /v1/runner-pools/{poolId}/registration-grants с {expiresInSeconds:600}; ответ 201 {grant, expiresAt}. Grant одноразовый, не журналируется. Runner вызывает POST /v1/runners/register с {grant, name, protocolVersion:"1", capabilities}; ответ 201 {runnerId, poolId, credential, expiresAt}. Долгоживущая идентичность хранится в защищённом хранилище исполнителя; credential обновляется через POST /v1/runners/{id}/credentials/rotate с текущей идентичностью и отзывается через DELETE /v1/runners/{id} администратором.
Admin создаёт POST /v1/runner-pools/{poolId}/registration-grants с {expiresInSeconds:600}; ответ 201 {grant, expiresAt}. Grant одноразовый, не журналируется. Runner вызывает POST /v1/runners/register с {grant, name, protocolVersion:"1", capabilities}; ответ 201 {runnerId, poolId, credential, expiresAt}. Долгоживущая идентичность хранится в защищённом хранилище исполнителя; credential обновляется через POST /v1/runners/{id}/credentials/rotate с текущей идентичностью и отзывается через DELETE /v1/runners/{id} администратором
Capabilities: os, architecture, executionKinds:["oci"], features:["cancel-v1"], maxConcurrency. checkpoint-v1 и input-v1 опциональны. Профиль пула задаёт доверенную изоляцию и квоты отдельно от заявления capabilities.
Capabilities: os, architecture, executionKinds:["oci"], features:["cancel-v1"], maxConcurrency. checkpoint-v1 и input-v1 опциональны. Профиль пула задаёт доверенную изоляцию и квоты отдельно от заявления capabilities
## Выполнение
@@ -20,28 +20,28 @@ Capabilities: os, architecture, executionKinds:["oci"], features:["cancel-v1"],
| POST /v1/attempts/{id}/complete | leaseEpoch, completionId, outcome, resultManifest?, error? | 200 Attempt |
| POST /v1/attempts/{id}/suspend | leaseEpoch, checkpointArtifactId, inputRequest | 200 Run |
Assignment: attemptId, runId, leaseEpoch, leaseUntil, executionSpec, attemptContext, executionToken, tokenExpiresAt. См. [схему](../contracts/runner-assignment.schema.json). Execution token scoped к Attempt. Запрос claim authenticated идентичностью Runner; последующие операции — execution token. Назначение создаётся сервером атомарно; один claim выдаёт максимум один Attempt, availableSlots не разрешает превысить maxConcurrency пула.
Assignment: attemptId, runId, leaseEpoch, leaseUntil, executionSpec, attemptContext, executionToken, tokenExpiresAt. См. [схему](../contracts/runner-assignment.schema.json). Execution token scoped к Attempt. Запрос claim authenticated идентичностью Runner; последующие операции — execution token. Назначение создаётся сервером атомарно; один claim выдаёт максимум один Attempt, availableSlots не разрешает превысить maxConcurrency пула
Outcome: succeeded/failed/cancelled. Success требует ResultManifest и сохранённых объектов, даже если artifacts пуст. Error: code, message, retryableHint; решение о retry принимает платформа. Complete повторяется с тем же completionId и телом; другой payload после terminal state → 409. Поздние heartbeat и события с прежним epoch → 409 LEASE_EXPIRED. Повтор уже принятого complete с тем же completionId и телом возвращает сохранённый ответ даже после истечения lease, но никогда не меняет состояние. Для этого replay допускается с действующей идентичностью назначенного Runner; новый terminal report с устаревшим epoch запрещён. События могут доставляться повторно; уникальны по attemptId + eventId.
Outcome: succeeded/failed/cancelled. Success требует ResultManifest и сохранённых объектов, даже если artifacts пуст. Error: code, message, retryableHint; решение о retry принимает платформа. Complete повторяется с тем же completionId и телом; другой payload после terminal state → 409. Поздние heartbeat и события с прежним epoch → 409 LEASE_EXPIRED. Повтор уже принятого complete с тем же completionId и телом возвращает сохранённый ответ даже после истечения lease, но никогда не меняет состояние. Для этого replay допускается с действующей идентичностью назначенного Runner; новый terminal report с устаревшим epoch запрещён. События могут доставляться повторно; уникальны по attemptId + eventId
Suspend допустим только для checkpoint-v1 + input-v1. InputRequest: id, schema, prompt, expiresAt. Платформа принимает checkpoint, переводит Run в waiting_input, отзывает lease; новый Attempt получает checkpointRef и проверенный ответ в AttemptContext, отдельно от ExecutionSpec. Без checkpoint протокол не обещает сохранение памяти процесса.
Suspend допустим только для checkpoint-v1 + input-v1. InputRequest: id, schema, prompt, expiresAt. Платформа принимает checkpoint, переводит Run в waiting_input, отзывает lease; новый Attempt получает checkpointRef и проверенный ответ в AttemptContext, отдельно от ExecutionSpec. Без checkpoint протокол не обещает сохранение памяти процесса
## Локальный процесс
Адаптер materialize-ит immutable ExecutionSpec в /input/execution.json, входные файлы — read-only /input/files; вывод — /output. Разрешённые secrets передаются отдельным каналом и не сериализуются в spec. Entrypoint — массив аргументов, не shell-строка. События JSONL поступают через отдельный pipe или файл адаптера, stdout/stderr считаются логами. Адаптер читает /output/result.json и загружает разрешённые артефакты; ссылки вне /output и symlink traversal запрещены.
Адаптер materialize-ит immutable ExecutionSpec в /input/execution.json, входные файлы — read-only /input/files; вывод — /output. Разрешённые secrets передаются отдельным каналом и не сериализуются в spec. Entrypoint — массив аргументов, не shell-строка. События JSONL поступают через отдельный pipe или файл адаптера, stdout/stderr считаются логами. Адаптер читает /output/result.json и загружает разрешённые артефакты; ссылки вне /output и symlink traversal запрещены
Соглашение путей относится к стандартному OCI-адаптеру. Другой Runner может реализовать иной транспорт при сохранении семантики ExecutionSpec и результатов. Локальный offline Runner не вызывает облачные claim/heartbeat, но ведёт эквивалентное локальное состояние.
Соглашение путей относится к стандартному OCI-адаптеру. Другой Runner может реализовать иной транспорт при сохранении семантики ExecutionSpec и результатов. Локальный offline Runner не вызывает облачные claim/heartbeat, но ведёт эквивалентное локальное состояние
## Минимальная проверка совместимости
Runner обязан показать: корректный success; failure; отказ при несовместимом spec; отмену; тайм-аут; повтор complete без дублей; отказ с просроченным lease; изоляцию файлов между задачами; корректный upload digest; отсутствие secrets в событиях. Resume проверяется только при соответствующей capability. Managed и customer-managed пулы отображаются раздельно.
Runner обязан показать: корректный success; failure; отказ при несовместимом spec; отмену; тайм-аут; повтор complete без дублей; отказ с просроченным lease; изоляцию файлов между задачами; корректный upload digest; отсутствие secrets в событиях. Resume проверяется только при соответствующей capability. Managed и customer-managed пулы отображаются раздельно
## Восстановление потерянного ответа
claimRequestId уникален в пределах runnerId. Повтор claim с тем же ID и телом возвращает то же назначение (или исходный 204), не занимает новый слот. Дедупликация хранится 24 часа; перед повторным получением работы после reconnect Runner вызывает GET /v1/runners/{id}/assignments (200 {items:[Assignment]}) со своей идентичностью. Endpoint возвращает только активные назначения этого Runner и перевыпускает их короткие токены. Если lease уже утрачен, старую работу прекращают; восстановление не продлевает истёкший lease.
claimRequestId уникален в пределах runnerId. Повтор claim с тем же ID и телом возвращает то же назначение (или исходный 204), не занимает новый слот. Дедупликация хранится 24 часа; перед повторным получением работы после reconnect Runner вызывает GET /v1/runners/{id}/assignments (200 {items:[Assignment]}) со своей идентичностью. Endpoint возвращает только активные назначения этого Runner и перевыпускает их короткие токены. Если lease уже утрачен, старую работу прекращают; восстановление не продлевает истёкший lease
Heartbeat продлевает lease и executionToken не дальше deadlineAt. Complete ID и хеш тела сохраняются до удаления Run. Sequence монотонен внутри потока событий; heartbeat/started имеют отдельный счётчик controlSequence (поле sequence в этих запросах), чтобы доставка логов не блокировала lease. Повтор с тем же номером и другим телом — 409. Конфликт события по eventId либо sequence также даёт 409. Клиент сериализует control-запросы.
Heartbeat продлевает lease и executionToken не дальше deadlineAt. Complete ID и хеш тела сохраняются до удаления Run. Sequence монотонен внутри потока событий; heartbeat/started имеют отдельный счётчик controlSequence (поле sequence в этих запросах), чтобы доставка логов не блокировала lease. Повтор с тем же номером и другим телом — 409. Конфликт события по eventId либо sequence также даёт 409. Клиент сериализует control-запросы
ResultManifest валидируется по [схеме](../contracts/result-manifest.schema.json), а output — дополнительно по outputSchemaRef шаблона. InputRequest schema использует тот же ограниченный профиль, что формы настроек. Событие input_requested информационное; только успешный suspend меняет состояние.
ResultManifest валидируется по [схеме](../contracts/result-manifest.schema.json), а output — дополнительно по outputSchemaRef шаблона. InputRequest schema использует тот же ограниченный профиль, что формы настроек. Событие input_requested информационное; только успешный suspend меняет состояние
Повтор claim не возобновляет утраченную аренду: если сохранённое назначение уже неактивно, сервер возвращает 409 ASSIGNMENT_EXPIRED. Перед запуском из повторного ответа Runner проверяет leaseUntil по серверному времени. ClaimRequestId с иным телом возвращает 409. Поля runId в Assignment и вложенном ExecutionSpec должны совпадать; server validator проверяет это отдельно от JSON Schema.
Повтор claim не возобновляет утраченную аренду: если сохранённое назначение уже неактивно, сервер возвращает 409 ASSIGNMENT_EXPIRED. Перед запуском из повторного ответа Runner проверяет leaseUntil по серверному времени. ClaimRequestId с иным телом возвращает 409. Поля runId в Assignment и вложенном ExecutionSpec должны совпадать; server validator проверяет это отдельно от JSON Schema
+9 -9
View File
@@ -1,6 +1,6 @@
# Provider API v1
Platform identity и provider identity независимы. Все операции требуют текущего actor и tenant; запрос к provider mode допускается только если матрица разрешает local/on_prem/managed_remote. Provider broker — модуль Platform API для управляемых credentials, локальный аналог — sidecar; provider plugin вызывается в изолированном host, а не внутри API-процесса.
Platform identity и provider identity независимы. Все операции требуют текущего actor и tenant; запрос к provider mode допускается только если матрица разрешает local/on_prem/managed_remote. Provider broker — модуль Platform API для управляемых credentials, локальный аналог — sidecar; provider plugin вызывается в изолированном host, а не внутри API-процесса
| Метод и путь | Запрос | Ответ |
|---|---|---|
@@ -14,22 +14,22 @@ Platform identity и provider identity независимы. Все операц
| GET /v1/connections/{id}/models | cursor, limit | 200 Page<ModelDescriptor> |
| DELETE /v1/connections/{id} | — | 204 после платформенного revoke; remote revoke best effort с аудитом |
ProviderDescriptor: id, pluginVersionId, methods:[{id, kind:api_key/oauth_pkce/device_code/official_client, allowedPlacements, status:enabled/gated/unsupported, reason?}], capabilitiesRevision. methodId определяется provider adapter; браузер не выбирает произвольный OAuth endpoint.
ProviderDescriptor: id, pluginVersionId, methods:[{id, kind:api_key/oauth_pkce/device_code/official_client, allowedPlacements, status:enabled/gated/unsupported, reason?}], capabilitiesRevision. methodId определяется provider adapter; браузер не выбирает произвольный OAuth endpoint
AuthFlow: id, providerId, methodId, status:pending/connected/failed/expired/cancelled, expiresAt, action:{type:open_url/device_code/local_client, url?, userCode?, intervalSeconds?}, connectionId?. PKCE verifier, refresh token и client secret не возвращаются клиенту. returnRoute — относительный allowlisted путь. API-key создаётся через защищённый POST /v1/connections, описанный ниже, не через GET callback.
AuthFlow: id, providerId, methodId, status:pending/connected/failed/expired/cancelled, expiresAt, action:{type:open_url/device_code/local_client, url?, userCode?, intervalSeconds?}, connectionId?. PKCE verifier, refresh token и client secret не возвращаются клиенту. returnRoute — относительный allowlisted путь. API-key создаётся через защищённый POST /v1/connections, описанный ниже, не через GET callback
ConnectionSummary: id, tenantId, ownerId, providerId, pluginVersionId, authMode, placement, bindingId?, status:active/reauth_required/revoked/error, scopes, accountLabel, expiresAt?, capabilitiesRevision. bindingId для runner_private_store привязывает к одному разрешённому пулу/пользовательскому окружению. Verify не выполняет платный inference без отдельного opt-in; model list не гарантирует entitlement.
ConnectionSummary: id, tenantId, ownerId, providerId, pluginVersionId, authMode, placement, bindingId?, status:active/reauth_required/revoked/error, scopes, accountLabel, expiresAt?, capabilitiesRevision. bindingId для runner_private_store привязывает к одному разрешённому пулу/пользовательскому окружению. Verify не выполняет платный inference без отдельного opt-in; model list не гарантирует entitlement
POST auth flow и verify принимают Idempotency-Key. OAuth callback одноразовый, проверяет state, expiry, actor binding и exact redirect URI; при потере пользовательской сессии завершение требует reauth владельца. Device polling выполняет broker по interval, не каждая открытая вкладка. Authentication errors возвращаются нормализованно без raw provider token response.
POST auth flow и verify принимают Idempotency-Key. OAuth callback одноразовый, проверяет state, expiry, actor binding и exact redirect URI; при потере пользовательской сессии завершение требует reauth владельца. Device polling выполняет broker по interval, не каждая открытая вкладка. Authentication errors возвращаются нормализованно без raw provider token response
## Инференс как внутренний контракт
ProviderInvocation: invocationId, runId, attemptId, connectionId, modelId, request, deadlineAt, capabilityRequirements. Доступ проверяется по executionToken и активному lease. Обёртка DSH нормализует stream events, usageStatus и terminal outcome. Credentials доступны только разрешённому adapter/официальному клиенту; shared глобального аккаунта нет. Внешний provider request id сохраняется для диагностики и дедупликации, если API поддерживает её.
ProviderInvocation: invocationId, runId, attemptId, connectionId, modelId, request, deadlineAt, capabilityRequirements. Доступ проверяется по executionToken и активному lease. Обёртка DSH нормализует stream events, usageStatus и terminal outcome. Credentials доступны только разрешённому adapter/официальному клиенту; shared глобального аккаунта нет. Внешний provider request id сохраняется для диагностики и дедупликации, если API поддерживает её
## Передача API key
POST /v1/connections принимает {providerId, methodId, placement, label, credentialInput?, bindingId?}; ответ 201 ConnectionSummary. Для server_vault credentialInput={apiKey:string} передаётся только в TLS body, исключается из access/error logs, tracing и сохранения idempotency payload; сервер хранит только хеш запроса и зашифрованный ключ. Для local_keychain/runner_private_store ключ принимает локальный broker, облачный API получает только подтверждённый bindingId. Переданный клиентом bindingId проверяется на владельца и proof-of-possession от доверенного broker. API не принимает локальный путь к чужому файлу или произвольный vault URI.
POST /v1/connections принимает {providerId, methodId, placement, label, credentialInput?, bindingId?}; ответ 201 ConnectionSummary. Для server_vault credentialInput={apiKey:string} передаётся только в TLS body, исключается из access/error logs, tracing и сохранения idempotency payload; сервер хранит только хеш запроса и зашифрованный ключ. Для local_keychain/runner_private_store ключ принимает локальный broker, облачный API получает только подтверждённый bindingId. Переданный клиентом bindingId проверяется на владельца и proof-of-possession от доверенного broker. API не принимает локальный путь к чужому файлу или произвольный vault URI
GET /v1/connections принимает cursor/limit и возвращает Page<ConnectionSummary>. ModelDescriptor: id, providerId, displayName, capabilities, contextWindow?, availability:unknown/available/unavailable, checkedAt?. Поля capabilities — набор поддержанных операций (text, tools, image_input, structured_output), а не гарантия доступа к модели по подписке.
GET /v1/connections принимает cursor/limit и возвращает Page<ConnectionSummary>. ModelDescriptor: id, providerId, displayName, capabilities, contextWindow?, availability:unknown/available/unavailable, checkedAt?. Поля capabilities — набор поддержанных операций (text, tools, image_input, structured_output), а не гарантия доступа к модели по подписке
AuthFlow создаётся только для oauth_pkce/device_code/official_client. Callback OAuth использует GET только для провайдеров с query response mode; иной response mode требует отдельного адаптера и conformance. По истечении expiresAt flow больше не может создавать connection. Внешний callback без пользовательской cookie проверяет flow binding, а выдача connection пользователю требует исходную сессию либо повторный вход владельца.
AuthFlow создаётся только для oauth_pkce/device_code/official_client. Callback OAuth использует GET только для провайдеров с query response mode; иной response mode требует отдельного адаптера и conformance. По истечении expiresAt flow больше не может создавать connection. Внешний callback без пользовательской cookie проверяет flow binding, а выдача connection пользователю требует исходную сессию либо повторный вход владельца
+9 -9
View File
@@ -1,6 +1,6 @@
# API запусков и расписаний
Общие правила: [conventions.md](conventions.md). Operator запускает и отменяет доступные ему агенты; viewer читает разрешённые Run. Доступ к самому агенту не заменяет проверку прав на его connections.
Общие правила: [conventions.md](conventions.md). Operator запускает и отменяет доступные ему агенты; viewer читает разрешённые Run. Доступ к самому агенту не заменяет проверку прав на его connections
| Метод и путь | Запрос | Ответ | Особенности |
|---|---|---|---|
@@ -18,11 +18,11 @@
| GET /v1/schedules | cursor, limit | 200 Page<Schedule> | Tenant-scoped |
| DELETE /v1/schedules/{id} | If-Match | 204 | Останавливает будущие, не текущие Run |
Run: id, tenantId, agentId, agentRevisionId, status, specDigest, createdAt, startedAt?, finishedAt?, attemptCount, parentRunId?, error?, resultManifest?, inputRequest?. Полный spec доступен только субъектам с run:read-config; обычный status не содержит конфигурацию.
Run: id, tenantId, agentId, agentRevisionId, status, specDigest, createdAt, startedAt?, finishedAt?, attemptCount, parentRunId?, error?, resultManifest?, inputRequest?. Полный spec доступен только субъектам с run:read-config; обычный status не содержит конфигурацию
Schedule: id, tenantId, agentId, agentRevisionId, cron, timezone, overlapPolicy (skip/queue), misfirePolicy (skip/coalesce), enabled, nextRunAt, revision. Расписание закрепляет agentRevisionId при создании. Новая ревизия применяется только явным PATCH расписания; уже созданные Run не меняются. Cron интерпретируется как пять полей (минута, час, день месяца, месяц, день недели); шаг менее минуты не поддерживается.
Schedule: id, tenantId, agentId, agentRevisionId, cron, timezone, overlapPolicy (skip/queue), misfirePolicy (skip/coalesce), enabled, nextRunAt, revision. Расписание закрепляет agentRevisionId при создании. Новая ревизия применяется только явным PATCH расписания; уже созданные Run не меняются. Cron интерпретируется как пять полей (минута, час, день месяца, месяц, день недели); шаг менее минуты не поддерживается
Limits: cpuMillis, memoryBytes, timeoutSeconds, outputBytes. Пользователь может запросить меньше предела policy; превышение даёт 422, а не скрытое повышение прав. Input — JSON по input schema template. PoolId не даёт доступ к чужому пулу.
Limits: cpuMillis, memoryBytes, timeoutSeconds, outputBytes. Пользователь может запросить меньше предела policy; превышение даёт 422, а не скрытое повышение прав. Input — JSON по input schema template. PoolId не даёт доступ к чужому пулу
## Пример
@@ -30,14 +30,14 @@ Limits: cpuMillis, memoryBytes, timeoutSeconds, outputBytes. Пользоват
{"agentId":"agent_company","agentRevision":1,"input":{"company":"Example Company"},"limits":{"cpuMillis":1000,"memoryBytes":1073741824,"timeoutSeconds":900,"outputBytes":104857600}}
```
Отмена не гарантирует отмену уже совершённого внешнего действия. Reconcile технического статуса выполняет сервис исполнения; пользовательский запрос не переписывает состояние Runner произвольно.
Отмена не гарантирует отмену уже совершённого внешнего действия. Reconcile технического статуса выполняет сервис исполнения; пользовательский запрос не переписывает состояние Runner произвольно
## Семантика расписаний
GET /v1/schedules/{id} возвращает Schedule. POST /v1/schedules/preview принимает cron, timezone, from, count (1–10) и возвращает {occurrences:[UTC timestamp], warnings:[]}; сохранения не выполняет. Pause — PATCH enabled=false, resume — PATCH enabled=true; оба требуют If-Match. Возобновление не догоняет периоды явной паузы.
GET /v1/schedules/{id} возвращает Schedule. POST /v1/schedules/preview принимает cron, timezone, from, count (1–10) и возвращает {occurrences:[UTC timestamp], warnings:[]}; сохранения не выполняет. Pause — PATCH enabled=false, resume — PATCH enabled=true; оба требуют If-Match. Возобновление не догоняет периоды явной паузы
Cron: пять полей; день недели 0–6 (0 — воскресенье); если day-of-month и day-of-week ограничены одновременно, применяется OR. DST: несуществующее локальное время пропускается, двойное — первое вхождение. Обновление tzdata пересчитывает только будущие occurrences; версия tzdata записывается в аудит. Первый релиз не поддерживает jitter и интервалы меньше минуты.
Cron: пять полей; день недели 0–6 (0 — воскресенье); если day-of-month и day-of-week ограничены одновременно, применяется OR. DST: несуществующее локальное время пропускается, двойное — первое вхождение. Обновление tzdata пересчитывает только будущие occurrences; версия tzdata записывается в аудит. Первый релиз не поддерживает jitter и интервалы меньше минуты
Skip отбрасывает occurrence, если у расписания есть нетерминальный Run. Queue допускает один активный и максимум один ожидающий Run; лишние occurrences объединяются с ожидающим. При простое misfirePolicy=coalesce (default) выбирает последний пропущенный occurrence, skip не создаёт Run. Уникальность (scheduleId, scheduledAt) гарантируется БД. Проверка overlap и создание Run выполняются под блокировкой строки Schedule в одной транзакции. Ручные Run не учитываются в overlap, но учитываются в квотах tenant.
Skip отбрасывает occurrence, если у расписания есть нетерминальный Run. Queue допускает один активный и максимум один ожидающий Run; лишние occurrences объединяются с ожидающим. При простое misfirePolicy=coalesce (default) выбирает последний пропущенный occurrence, skip не создаёт Run. Уникальность (scheduleId, scheduledAt) гарантируется БД. Проверка overlap и создание Run выполняются под блокировкой строки Schedule в одной транзакции. Ручные Run не учитываются в overlap, но учитываются в квотах tenant
Отзыв доступа к агенту/connection, блокировка пакета и архивирование агента останавливают расписание с reason, не создавая бесконечную череду failed Run. Любой запуск повторно проверяет права владельца расписания. Локальное расписание требует работающего daemon; перенос в облако отключает прежнего владельца до включения нового.
Отзыв доступа к агенту/connection, блокировка пакета и архивирование агента останавливают расписание с reason, не создавая бесконечную череду failed Run. Любой запуск повторно проверяет права владельца расписания. Локальное расписание требует работающего daemon; перенос в облако отключает прежнего владельца до включения нового
+12 -12
View File
@@ -1,35 +1,35 @@
# Каталог пакетов
Каталог — отдельный Go-сервис со своей PostgreSQL БД. Он владеет метаданными harness, plugin, skill и template. OCI-образы обслуживает registry, архивы — S3. Прямой доступ других сервисов к таблицам каталога запрещён; используется API.
Каталог — отдельный Go-сервис со своей PostgreSQL БД. Он владеет метаданными harness, plugin, skill и template. OCI-образы обслуживает registry, архивы — S3. Прямой доступ других сервисов к таблицам каталога запрещён; используется API
## Пакет и версия
Package содержит id, tenantId, kind, name, description, visibility и ownerId. Имя уникально внутри tenant и kind. PackageVersion содержит version, manifest, artifactDigest, artifactRef, schemaDigest, createdAt и publisherId. Содержимое версии неизменяемо. Отдельная запись VersionPolicy хранит status, reason и changedAt: блокировка не переписывает исходный пакет.
Package содержит id, tenantId, kind, name, description, visibility и ownerId. Имя уникально внутри tenant и kind. PackageVersion содержит version, manifest, artifactDigest, artifactRef, schemaDigest, createdAt и publisherId. Содержимое версии неизменяемо. Отдельная запись VersionPolicy хранит status, reason и changedAt: блокировка не переписывает исходный пакет
Harness описывает поддерживаемый runtime, entrypoint и протокол ввода/вывода. Plugin описывает расширение и совместимость с harness. Skill содержит инструкции, ресурсы и при необходимости скрипты. Template объединяет точные или ограниченные версии зависимостей, инструкции и схему конфигурации. Skill с исполняемым кодом проходит те же проверки, что plugin.
Harness описывает поддерживаемый runtime, entrypoint и протокол ввода/вывода. Plugin описывает расширение и совместимость с harness. Skill содержит инструкции, ресурсы и при необходимости скрипты. Template объединяет точные или ограниченные версии зависимостей, инструкции и схему конфигурации. Skill с исполняемым кодом проходит те же проверки, что plugin
## Публикация
Автор с ролью publisher создаёт draft, получает ограниченный upload grant и загружает артефакт. Для OCI он использует стандартный registry push. Publish проверяет размер, digest, формат манифеста, ссылки внутри архива, схему конфигурации, доступ к зависимостям и отсутствие циклов. Архив не может содержать выходящие за корень пути, абсолютные пути или небезопасные symlink.
Автор с ролью publisher создаёт draft, получает ограниченный upload grant и загружает артефакт. Для OCI он использует стандартный registry push. Publish проверяет размер, digest, формат манифеста, ссылки внутри архива, схему конфигурации, доступ к зависимостям и отсутствие циклов. Архив не может содержать выходящие за корень пути, абсолютные пути или небезопасные symlink
Только после проверки артефакта транзакция публикует версию. Повтор Publish с тем же Idempotency-Key возвращает прежний результат. То же имя версии с другим digest даёт 409. Объекты без опубликованной версии очищаются после 24 часов — исходное значение, настраиваемое администратором.
Только после проверки артефакта транзакция публикует версию. Повтор Publish с тем же Idempotency-Key возвращает прежний результат. То же имя версии с другим digest даёт 409. Объекты без опубликованной версии очищаются после 24 часов — исходное значение, настраиваемое администратором
## Resolve
Resolver принимает templateVersionId и профиль среды. Он строит ацикличный граф зависимостей, проверяет совместимость, выбирает конкретные версии и возвращает lock со всеми digest. Диапазоны версий разрешены на входе публикации шаблона, но не в ExecutionSpec. Конфликт версий возвращается с цепочками зависимостей; молчаливый выбор несовместимого пакета запрещён.
Resolver принимает templateVersionId и профиль среды. Он строит ацикличный граф зависимостей, проверяет совместимость, выбирает конкретные версии и возвращает lock со всеми digest. Диапазоны версий разрешены на входе публикации шаблона, но не в ExecutionSpec. Конфликт версий возвращается с цепочками зависимостей; молчаливый выбор несовместимого пакета запрещён
Доступ проверяется при resolve, выдаче download grant и назначении Attempt. Публичный шаблон не должен требовать недоступную аудитории приватную зависимость. Блокировка версии запрещает новые назначения; для уже работающих Attempt администратор выбирает policy cancel или allow_finish с аудитом.
Доступ проверяется при resolve, выдаче download grant и назначении Attempt. Публичный шаблон не должен требовать недоступную аудитории приватную зависимость. Блокировка версии запрещает новые назначения; для уже работающих Attempt администратор выбирает policy cancel или allow_finish с аудитом
## Обновления и хранение
Обновление шаблона не изменяет существующие AgentRevision. Пользователь получает preview изменений и ошибок валидации. Новая ревизия создаётся только после успешной проверки. В MVP миграция ручная через форму; исполняемые миграции автора не запускаются в браузере.
Обновление шаблона не изменяет существующие AgentRevision. Пользователь получает preview изменений и ошибок валидации. Новая ревизия создаётся только после успешной проверки. В MVP миграция ручная через форму; исполняемые миграции автора не запускаются в браузере
Deprecated версия доступна закреплённым агентам, но скрыта из стандартного выбора. Удаление referenced-версии возвращает 409. Физическая очистка допускается после retention запусков, проверки ссылок и grace period. Immutable артефакты адресуются по digest; signed URL не сохраняется в постоянном lock.
Deprecated версия доступна закреплённым агентам, но скрыта из стандартного выбора. Удаление referenced-версии возвращает 409. Физическая очистка допускается после retention запусков, проверки ссылок и grace period. Immutable артефакты адресуются по digest; signed URL не сохраняется в постоянном lock
API: [catalog-api.md](api/catalog-api.md). Все диаграммы: [design.md](design.md).
API: [catalog-api.md](api/catalog-api.md). Все диаграммы: [design.md](design.md)
## DSH и схемы ввода/вывода
Каталог хранит оригинальный DSH plugin artifact вместе с платформенным manifest envelope. Поля dshCompatibility фиксируют диапазон DSH, runtime, entry module и поддержанный профиль; tested versions и digest находятся в отчёте проверки каталога. Декларация автора не даёт badge совместимости. Плагины с зависимостью от API платформы явно объявляют endpoint и scopes; offline режим может не поддерживаться.
Каталог хранит оригинальный DSH plugin artifact вместе с платформенным manifest envelope. Поля dshCompatibility фиксируют диапазон DSH, runtime, entry module и поддержанный профиль; tested versions и digest находятся в отчёте проверки каталога. Декларация автора не даёт badge совместимости. Плагины с зависимостью от API платформы явно объявляют endpoint и scopes; offline режим может не поддерживаться
Template публикует inputSchemaRef и outputSchemaRef в том же архиве. Resolver включает архив по digest в lock, а API валидирует input до создания Run и output до success. UI схемы относятся к настройкам; дополнительные права не могут выдаваться значениями формы. См. [DSH foundation](dsh-foundation.md) и [плагины](plugins.md).
Template публикует inputSchemaRef и outputSchemaRef в том же архиве. Resolver включает архив по digest в lock, а API валидирует input до создания Run и output до success. UI схемы относятся к настройкам; дополнительные права не могут выдаваться значениями формы. См. [DSH foundation](dsh-foundation.md) и [плагины](plugins.md)
+13 -13
View File
@@ -2,31 +2,31 @@
## Контракт автора
Шаблон содержит config.schema.json, config.defaults.json и необязательную ui.schema.json. JSON Schema описывает данные, UI Schema — только представление. Собственные параметры harness и plugins располагаются в пространствах имён harness и plugins.<packageId>; схема template объединяет их без конфликтов имён.
Шаблон содержит config.schema.json, config.defaults.json и необязательную ui.schema.json. JSON Schema описывает данные, UI Schema — только представление. Собственные параметры harness и plugins располагаются в пространствах имён harness и plugins.<packageId>; схема template объединяет их без конфликтов имён
Базовый диалект — JSON Schema Draft 2020-12. MVP renderer поддерживает object, string, number, integer, boolean, array, enum, required, additionalProperties, minimum/maximum, minLength/maxLength, minItems/maxItems и локальные $ref/$defs. oneOf и условные секции включаются только после проверки renderer и валидатора. Неизвестные UI-компоненты и неподдерживаемые keywords отвергаются при публикации, а не игнорируются. Удалённые $ref запрещены. Ограничиваются размер, вложенность и сложность схемы. На старте запрещены пользовательские regex pattern, пока не реализованы лимиты их выполнения.
Базовый диалект — JSON Schema Draft 2020-12. MVP renderer поддерживает object, string, number, integer, boolean, array, enum, required, additionalProperties, minimum/maximum, minLength/maxLength, minItems/maxItems и локальные $ref/$defs. oneOf и условные секции включаются только после проверки renderer и валидатора. Неизвестные UI-компоненты и неподдерживаемые keywords отвергаются при публикации, а не игнорируются. Удалённые $ref запрещены. Ограничиваются размер, вложенность и сложность схемы. На старте запрещены пользовательские regex pattern, пока не реализованы лимиты их выполнения
## Применение значений
1. Загрузить схему и defaults, закреплённые по digest.
2. Создать конфигурацию из defaults и явных значений пользователя: objects объединяются по ключам, arrays заменяются целиком; null допустим только по схеме и не означает удаление.
3. Проверить итоговую конфигурацию одним согласованным набором правил.
4. Проверить права на подключения и ограничения организации.
5. Сохранить полный результат как новую AgentRevision с schemaDigest.
1. Загрузить схему и defaults, закреплённые по digest
2. Создать конфигурацию из defaults и явных значений пользователя: objects объединяются по ключам, arrays заменяются целиком; null допустим только по схеме и не означает удаление
3. Проверить итоговую конфигурацию одним согласованным набором правил
4. Проверить права на подключения и ограничения организации
5. Сохранить полный результат как новую AgentRevision с schemaDigest
JSON Schema default — аннотация, а не команда валидатору. defaults-файл при публикации обязан соответствовать схеме после объединения с обязательными вводимыми полями; отсутствующие обязательные поля пользователь заполняет до сохранения. Сервер не доверяет клиентской валидации.
JSON Schema default — аннотация, а не команда валидатору. defaults-файл при публикации обязан соответствовать схеме после объединения с обязательными вводимыми полями; отсутствующие обязательные поля пользователь заполняет до сохранения. Сервер не доверяет клиентской валидации
## UI
Web UI: TypeScript, React, JSON Forms; серверный валидатор — совместимая Go-библиотека Draft 2020-12, точная реализация выбирается по общему корпусу контрактных примеров. UI schema использует только встроенные контролы и layout, без JavaScript, HTML и внешних скриптов. Описания отображаются как безопасный текст.
Web UI: TypeScript, React, JSON Forms; серверный валидатор — совместимая Go-библиотека Draft 2020-12, точная реализация выбирается по общему корпусу контрактных примеров. UI schema использует только встроенные контролы и layout, без JavaScript, HTML и внешних скриптов. Описания отображаются как безопасный текст
Поля для подключения к сервису отображают selector ConnectionRef. Секретные значения не входят в JSON конфигурации, defaults, пример или URL. readOnly, writeOnly и скрытие поля в UI не заменяют server-side permission checks. Пользователь не может через config повысить лимит ресурсов, изменить tenantId или разрешить новые сетевые доступы.
Поля для подключения к сервису отображают selector ConnectionRef. Секретные значения не входят в JSON конфигурации, defaults, пример или URL. readOnly, writeOnly и скрытие поля в UI не заменяют server-side permission checks. Пользователь не может через config повысить лимит ресурсов, изменить tenantId или разрешить новые сетевые доступы
## Версии и изменения
PUT конфигурации требует If-Match. При конфликте ревизии сервер возвращает 412. UI показывает различия, пользователь повторно сохраняет результат. Запуск фиксирует agentRevisionId, schemaDigest и effectiveConfig; последующие изменения агента не влияют на Run.
PUT конфигурации требует If-Match. При конфликте ревизии сервер возвращает 412. UI показывает различия, пользователь повторно сохраняет результат. Запуск фиксирует agentRevisionId, schemaDigest и effectiveConfig; последующие изменения агента не влияют на Run
Новая версия шаблона сначала проверяется на копии конфигурации. При несовместимости показываются JSON Pointer путей и сообщения ошибок. Старая ревизия остаётся рабочей до явного обновления. В MVP автоматических исполняемых миграций нет.
Новая версия шаблона сначала проверяется на копии конфигурации. При несовместимости показываются JSON Pointer путей и сообщения ошибок. Старая ревизия остаётся рабочей до явного обновления. В MVP автоматических исполняемых миграций нет
## Источники и пример
@@ -37,4 +37,4 @@ PUT конфигурации требует If-Match. При конфликте
- [Начальные значения](contracts/examples/config.defaults.json)
- [Представление формы](contracts/examples/ui.schema.json)
Ограниченный набор JSON Schema keywords относится к пользовательским формам config/input. Служебные схемы протокола могут использовать allOf/if/then и не передаются renderer. Версия профиля валидатора закрепляется вместе с шаблоном; несовместимая схема отвергается при публикации.
Ограниченный набор JSON Schema keywords относится к пользовательским формам config/input. Служебные схемы протокола могут использовать allOf/if/then и не передаются renderer. Версия профиля валидатора закрепляется вместе с шаблоном; несовместимая схема отвергается при публикации
+21 -21
View File
@@ -1,6 +1,6 @@
# Модель данных
Типы в этой таблице определяют семантику API. JSON Schema ниже задают машиночитаемую основу контракта; дополнительные межресурсные проверки выполняются сервисами.
Типы в этой таблице определяют семантику API. JSON Schema ниже задают машиночитаемую основу контракта; дополнительные межресурсные проверки выполняются сервисами
| Сущность | Ключевые поля | Владелец |
|---|---|---|
@@ -22,31 +22,31 @@
## Инварианты
- Между БД нет внешних ключей: идентификаторы проверяются API. Каждый сервис владеет своими транзакциями и outbox.
- Run ссылается на immutable AgentRevision и ExecutionSpec; повторная проверка прав не изменяет их содержимое.
- Published PackageVersion не перезаписывается. Политика блокировки хранится отдельно.
- Попытка имеет только одного текущего владельца lease; epoch монотонно растёт при новом назначении.
- Terminal report и смена состояния сохраняются одной транзакцией вместе с событием outbox.
- Resource ID не является доказательством доступа. Tenant scope проверяется независимо.
- ConnectionRef никогда не содержит значение секрета.
- Artifact считается готовым после проверки объекта и digest, а не после выдачи upload URL.
- Между БД нет внешних ключей: идентификаторы проверяются API. Каждый сервис владеет своими транзакциями и outbox
- Run ссылается на immutable AgentRevision и ExecutionSpec; повторная проверка прав не изменяет их содержимое
- Published PackageVersion не перезаписывается. Политика блокировки хранится отдельно
- Попытка имеет только одного текущего владельца lease; epoch монотонно растёт при новом назначении
- Terminal report и смена состояния сохраняются одной транзакцией вместе с событием outbox
- Resource ID не является доказательством доступа. Tenant scope проверяется независимо
- ConnectionRef никогда не содержит значение секрета
- Artifact считается готовым после проверки объекта и digest, а не после выдачи upload URL
## Схемы
- [Манифест пакета](package-manifest.schema.json) — общий envelope четырёх видов пакетов.
- [ExecutionSpec](execution-spec.schema.json) — конкретный состав запуска.
- [Событие](run-event.schema.json) — события исполнителя.
- [Пример manifest](examples/template-manifest.json).
- [Пример ExecutionSpec](examples/execution-spec.json).
- [Манифест пакета](package-manifest.schema.json) — общий envelope четырёх видов пакетов
- [ExecutionSpec](execution-spec.schema.json) — конкретный состав запуска
- [Событие](run-event.schema.json) — события исполнителя
- [Пример manifest](examples/template-manifest.json)
- [Пример ExecutionSpec](examples/execution-spec.json)
Id — opaque string. Version — SemVer строка; разрешение диапазонов выполняет resolver до фиксации ExecutionSpec. Digest — SHA-256. Timestamps — RFC3339 UTC. UUID не навязывается публичным контрактом.
Id — opaque string. Version — SemVer строка; разрешение диапазонов выполняет resolver до фиксации ExecutionSpec. Digest — SHA-256. Timestamps — RFC3339 UTC. UUID не навязывается публичным контрактом
Package manifest с kind=template обязан указать harnessVersionId, configSchemaRef и зависимости. Harness обязан указать entrypoint и executionKind. Plugin и skill указывают совместимость supportedHarnesses. Отсутствующая optional capability означает, что возможность недоступна; поле не может быть выведено из названия пакета.
Package manifest с kind=template обязан указать harnessVersionId, configSchemaRef и зависимости. Harness обязан указать entrypoint и executionKind. Plugin и skill указывают совместимость supportedHarnesses. Отсутствующая optional capability означает, что возможность недоступна; поле не может быть выведено из названия пакета
Run, Attempt, Schedule и reservations составляют одну транзакционную область Platform DB. Внешние Execution DB и Catalog DB не принимают бизнес-переходы Run. Подробнее: [исполнение](../execution.md).
Run, Attempt, Schedule и reservations составляют одну транзакционную область Platform DB. Внешние Execution DB и Catalog DB не принимают бизнес-переходы Run. Подробнее: [исполнение](../execution.md)
- [Assignment и AttemptContext](runner-assignment.schema.json): контекст попытки отдельно от неизменяемого spec.
- [ResultManifest](result-manifest.schema.json): результат и проверяемые артефакты.
- [Provider API](../api/provider-api.md): канонический ConnectionSummary; secretBindingRef остаётся серверным полем.
- [Assignment и AttemptContext](runner-assignment.schema.json): контекст попытки отдельно от неизменяемого spec
- [ResultManifest](result-manifest.schema.json): результат и проверяемые артефакты
- [Provider API](../api/provider-api.md): канонический ConnectionSummary; secretBindingRef остаётся серверным полем
inputSchemaRef и outputSchemaRef обязательны для template. Все schemaRef — пути внутри проверенного архива версии; произвольные сетевые $ref запрещены. DSH-плагин указывает dshCompatibility; статус совместимости выставляется каталогом по отдельному отчёту, а не самим автором.
inputSchemaRef и outputSchemaRef обязательны для template. Все schemaRef — пути внутри проверенного архива версии; произвольные сетевые $ref запрещены. DSH-плагин указывает dshCompatibility; статус совместимости выставляется каталогом по отдельному отчёту, а не самим автором
+33 -33
View File
@@ -25,32 +25,32 @@
## Концепция и статус
Invest Harness — платформа агентов для инвестиций. Автор публикует шаблон и его зависимости, пользователь выбирает шаблон, настраивает его через автоматически построенную форму и запускает локально или удалённо. Оба режима используют один формат пакетов и ExecutionSpec. Стандартный агент строится на DSH с собственным интерфейсом и исправленным разделением ядра, конфигурации, credentials и исполнения. Плагины сохраняют совместимость с публичным API DSH в проверенном профиле; другие harness также допускаются.
Invest Harness — платформа агентов для инвестиций. Автор публикует шаблон и его зависимости, пользователь выбирает шаблон, настраивает его через автоматически построенную форму и запускает локально или удалённо. Оба режима используют один формат пакетов и ExecutionSpec. Стандартный агент строится на DSH с собственным интерфейсом и исправленным разделением ядра, конфигурации, credentials и исполнения. Плагины сохраняют совместимость с публичным API DSH в проверенном профиле; другие harness также допускаются
Документ задаёт целевую архитектуру и контракты первой версии. Реализация сервисов пока не входит в этот репозиторий. Выбранные технологии — проектные решения; численные показатели масштабирования — гипотезы до измерений.
Документ задаёт целевую архитектуру и контракты первой версии. Реализация сервисов пока не входит в этот репозиторий. Выбранные технологии — проектные решения; численные показатели масштабирования — гипотезы до измерений
Для платформы содержимое окружения Runner — чёрный ящик. Внутри могут работать агентские цепочки, произвольные программы, разные модели и интеграции. Платформа отвечает за доставку пакетов, доступы, ресурсы, состояния и результаты. Она не задаёт инвестиционную стратегию и не гарантирует корректность финансовых выводов или внешних действий. Способность продолжить работу после сбоя должна быть явно объявлена пакетом.
Для платформы содержимое окружения Runner — чёрный ящик. Внутри могут работать агентские цепочки, произвольные программы, разные модели и интеграции. Платформа отвечает за доставку пакетов, доступы, ресурсы, состояния и результаты. Она не задаёт инвестиционную стратегию и не гарантирует корректность финансовых выводов или внешних действий. Способность продолжить работу после сбоя должна быть явно объявлена пакетом
Локальный запуск уже загруженного публичного пакета не требует облачного аккаунта. Сеть может требоваться модели или инструментам. Публичность описания пакета не означает доступ к пользовательским данным.
Локальный запуск уже загруженного публичного пакета не требует облачного аккаунта. Сеть может требоваться модели или инструментам. Публичность описания пакета не означает доступ к пользовательским данным
## Пользовательские сценарии
1. Автор загружает версию пакета и схемы, проверяет зависимости и публикует версию.
2. Пользователь выбирает шаблон, заполняет форму и подключает разрешённые интеграции. Сохраняется ревизия экземпляра агента.
3. Пользователь запускает агента локально, в управляемом пуле или на своём Runner.
4. Платформа показывает состояние, события, файлы и итог, позволяет отменить запуск.
5. Если harness поддерживает запрос ввода и checkpoint, пользователь может ответить и продолжить выполнение отдельной попыткой.
6. Обновление шаблона создаёт новую ревизию агента после проверки настроек; текущие запуски не меняются.
1. Автор загружает версию пакета и схемы, проверяет зависимости и публикует версию
2. Пользователь выбирает шаблон, заполняет форму и подключает разрешённые интеграции. Сохраняется ревизия экземпляра агента
3. Пользователь запускает агента локально, в управляемом пуле или на своём Runner
4. Платформа показывает состояние, события, файлы и итог, позволяет отменить запуск
5. Если harness поддерживает запрос ввода и checkpoint, пользователь может ответить и продолжить выполнение отдельной попыткой
6. Обновление шаблона создаёт новую ревизию агента после проверки настроек; текущие запуски не меняются
### Пять инвестиционных сценариев
На общем DSH harness создаются пять шаблонов: **START** объясняет инструменты начинающему, **GUARD** проверяет портфель к заданной дате, **GOAL** рассчитывает план накопления, **PULSE** сопоставляет подтверждённые мнения авторов, **PRO** анализирует отчётность. Пользователь настраивает шаблон через JSON Schema Driven UI и выбирает локальный либо удалённый Runner. Финансовые инструменты реализуются плагинами; методика задаётся скиллами.
На общем DSH harness создаются пять шаблонов: **START** объясняет инструменты начинающему, **GUARD** проверяет портфель к заданной дате, **GOAL** рассчитывает план накопления, **PULSE** сопоставляет подтверждённые мнения авторов, **PRO** анализирует отчётность. Пользователь настраивает шаблон через JSON Schema Driven UI и выбирает локальный либо удалённый Runner. Финансовые инструменты реализуются плагинами; методика задаётся скиллами
[Сценарии с настройками, шагами, обработкой ошибок и критериями приёмки](scenarios.md). Они описывают демонстрационные шаблоны с учебным или read-only доступом; конкретные внешние интеграции требуют проверки. Внутренняя логика агента остаётся за границей ответственности платформы.
[Сценарии с настройками, шагами, обработкой ошибок и критериями приёмки](scenarios.md). Они описывают демонстрационные шаблоны с учебным или read-only доступом; конкретные внешние интеграции требуют проверки. Внутренняя логика агента остаётся за границей ответственности платформы
## Архитектура C4
Контейнер в C4 — отдельно запускаемое приложение или хранилище, не обязательно Docker-контейнер. Диаграммы используют нотацию Mermaid с явными типами элементов C4. C3 раскрывает логические модули, а не отдельные микросервисы.
Контейнер в C4 — отдельно запускаемое приложение или хранилище, не обязательно Docker-контейнер. Диаграммы используют нотацию Mermaid с явными типами элементов C4. C3 раскрывает логические модули, а не отдельные микросервисы
### C1 Контекст
@@ -137,9 +137,9 @@ flowchart TB
L -->|Локальные credentials| M
```
Путь X → D обозначает публичный протокол собственной реализации Runner. Стандартный исполнитель соединяется со своим движком через адаптер внутри сервиса исполнения; он не обязан нативно поддерживать этот протокол. Диспетчер остаётся единственным владельцем бизнес-решения о назначении. Нельзя одновременно выдавать один Attempt через обе системы очередей.
Путь X → D обозначает публичный протокол собственной реализации Runner. Стандартный исполнитель соединяется со своим движком через адаптер внутри сервиса исполнения; он не обязан нативно поддерживать этот протокол. Диспетчер остаётся единственным владельцем бизнес-решения о назначении. Нельзя одновременно выдавать один Attempt через обе системы очередей
Gateway логически обслуживает публичные HTTPS-маршруты; внутренние стрелки сокращены. Авторизация выполняется в принимающем сервисе и не заменяется наличием Gateway. Registry на схеме вынесен для наглядности, но может работать в одном процессе с сервисом исполнения. S3 buckets логически отдельны; физический сервис может быть общим.
Gateway логически обслуживает публичные HTTPS-маршруты; внутренние стрелки сокращены. Авторизация выполняется в принимающем сервисе и не заменяется наличием Gateway. Registry на схеме вынесен для наглядности, но может работать в одном процессе с сервисом исполнения. S3 buckets логически отдельны; физический сервис может быть общим
### C3 Каталог
@@ -222,7 +222,7 @@ flowchart TB
| Наблюдаемость | OpenTelemetry, Prometheus, Grafana, Loki | Интеграция; без payload и секретов по умолчанию |
| Начальное развёртывание | Linux, Docker Compose, Nginx | Управление и исполнители на разных машинах |
Runtime внутри harness’а не ограничен языком платформы. Kubernetes — будущая реализация Runner, не зависимость MVP. Kafka и отдельный координатор кластера в MVP не требуются.
Runtime внутри harness’а не ограничен языком платформы. Kubernetes — будущая реализация Runner, не зависимость MVP. Kafka и отдельный координатор кластера в MVP не требуются
## Публикация пакета
@@ -242,11 +242,11 @@ sequenceDiagram
C-->>A: Published version
```
Метаданные опубликованы только после проверки объекта. Незавершённые загрузки убирает сборщик мусора после grace period. Каталог хранит четыре типа пакетов: harness, plugin, skill, template. Версии неизменяемы; блокировка — изменяемая политика доступа поверх версии. Детали: [каталог](catalog.md).
Метаданные опубликованы только после проверки объекта. Незавершённые загрузки убирает сборщик мусора после grace period. Каталог хранит четыре типа пакетов: harness, plugin, skill, template. Версии неизменяемы; блокировка — изменяемая политика доступа поверх версии. Детали: [каталог](catalog.md)
## Настройка через JSON Schema
Автор шаблона задаёт config.schema.json, config.defaults.json и необязательную ui.schema.json. Схемы настроек harness’а и плагинов подключаются шаблоном в отдельные пространства имён. Пользователь меняет значения, не схему автора. Secret-поля содержат ссылки на подключения, а не значения credentials.
Автор шаблона задаёт config.schema.json, config.defaults.json и необязательную ui.schema.json. Схемы настроек harness’а и плагинов подключаются шаблоном в отдельные пространства имён. Пользователь меняет значения, не схему автора. Secret-поля содержат ссылки на подключения, а не значения credentials
```mermaid
sequenceDiagram
@@ -263,7 +263,7 @@ sequenceDiagram
B-->>W: Новая immutable revision
```
Сервер повторно валидирует данные. Скрытое поле формы не является защитой. Defaults применяются отдельным шагом: JSON Schema default не заполняет данные автоматически. [Конфигурация и UI](configuration-ui.md).
Сервер повторно валидирует данные. Скрытое поле формы не является защитой. Defaults применяются отдельным шагом: JSON Schema default не заполняет данные автоматически. [Конфигурация и UI](configuration-ui.md)
## Локальный запуск
@@ -307,7 +307,7 @@ sequenceDiagram
B-->>U: Статус и доступ к файлам
```
Обработка допускает повторную доставку; exactly-once внешних действий не обещается. Отзыв lease блокирует поздние записи в платформу, но не может отменить уже отправленный запрос во внешний сервис. [Исполнение](execution.md).
Обработка допускает повторную доставку; exactly-once внешних действий не обещается. Отзыв lease блокирует поздние записи в платформу, но не может отменить уже отправленный запрос во внешний сервис. [Исполнение](execution.md)
## Авторизация
@@ -330,7 +330,7 @@ sequenceDiagram
T-->>R: Результат без долгоживущего ключа
```
Прямые интеграции разрешаются явно: секрет может потребоваться внутри окружения. В таком режиме runner-owner становится частью границы доверия, а стоимость внешних вызовов нельзя ограничить только платформенным счётчиком. [Доступы и изоляция](security.md).
Прямые интеграции разрешаются явно: секрет может потребоваться внутри окружения. В таком режиме runner-owner становится частью границы доверия, а стоимость внешних вызовов нельзя ограничить только платформенным счётчиком. [Доступы и изоляция](security.md)
## Состояния запуска
@@ -362,7 +362,7 @@ stateDiagram-v2
cancelled --> [*]
```
Переход в waiting_input освобождает исполнителя только после durable checkpoint. Для harness без checkpoint этот режим не предоставляется. При потере lease от собственного Runner результат внешних действий может остаться неизвестным.
Переход в waiting_input освобождает исполнителя только после durable checkpoint. Для harness без checkpoint этот режим не предоставляется. При потере lease от собственного Runner результат внешних действий может остаться неизвестным
## Замена исполнителей
@@ -381,7 +381,7 @@ flowchart TB
P --> L
```
Нативный Runner и адаптер не создают две независимые аренды одного Attempt: платформа хранит lease, адаптер сопоставляет его с executionId движка и подавляет дубликаты. Локальный автономный режим использует тот же ExecutionSpec, но не обязан регистрироваться в облаке. [Протокол Runner](api/executor-api.md).
Нативный Runner и адаптер не создают две независимые аренды одного Attempt: платформа хранит lease, адаптер сопоставляет его с executionId движка и подавляет дубликаты. Локальный автономный режим использует тот же ExecutionSpec, но не обязан регистрироваться в облаке. [Протокол Runner](api/executor-api.md)
## Масштабирование
@@ -398,19 +398,19 @@ flowchart LR
B --> M
```
Ёмкость определяется активными запусками, длительностью и ресурсами; добавление исполнителей ограничено квотами внешних API. Реализации движка с одной активной репликой не масштабируются простым дублированием процесса: сначала проверяются ограничения ядра, затем шардирование по пулам. Формулы, отказы, SLO и retention: [масштабирование](scaling.md).
Ёмкость определяется активными запусками, длительностью и ресурсами; добавление исполнителей ограничено квотами внешних API. Реализации движка с одной активной репликой не масштабируются простым дублированием процесса: сначала проверяются ограничения ядра, затем шардирование по пулам. Формулы, отказы, SLO и retention: [масштабирование](scaling.md)
## MVP и развитие
MVP: четыре типа пакетов; immutable versions; конфигурация через формы; экземпляры агентов; ручной и регулярный запуск; стандартный и локальный Runner; документированный протокол своей реализации; отмена, события и результаты; tenant isolation; registry и buckets; аудит.
MVP: четыре типа пакетов; immutable versions; конфигурация через формы; экземпляры агентов; ручной и регулярный запуск; стандартный и локальный Runner; документированный протокол своей реализации; отмена, события и результаты; tenant isolation; registry и buckets; аудит
Полный MVP достигается поэтапно (P0–P5 ниже), а не одним релизом. Следующий этап: возобновление через checkpoint, пользовательский ввод, автоматическая миграция конфигураций, Kubernetes Runner, автоматическое масштабирование и коммерческий биллинг. Протокол заранее резервирует эти возможности, но UI не предлагает их без подтверждённой capability.
Полный MVP достигается поэтапно (P0–P5 ниже), а не одним релизом. Следующий этап: возобновление через checkpoint, пользовательский ввод, автоматическая миграция конфигураций, Kubernetes Runner, автоматическое масштабирование и коммерческий биллинг. Протокол заранее резервирует эти возможности, но UI не предлагает их без подтверждённой capability
Открытые решения: провайдер KMS и S3, конкретные версии зависимостей, политика модерации публичных пакетов, целевые SLO после нагрузочных измерений, перечень лицензий распространяемых runtime и пакетов. Публичный доступ к этому проекту сам по себе не задаёт лицензию его дальнейшего использования.
Открытые решения: провайдер KMS и S3, конкретные версии зависимостей, политика модерации публичных пакетов, целевые SLO после нагрузочных измерений, перечень лицензий распространяемых runtime и пакетов. Публичный доступ к этому проекту сам по себе не задаёт лицензию его дальнейшего использования
## DSH: интерфейс и внутренняя архитектура
Свой UI показывает шаблоны, настройки, подключения, расписания и результаты. Внутри DSH сохраняются публичные точки подключения плагинов; platform adapter изолирует конфигурацию, credentials, запуск и состояния сессий. Runner остаётся заменяемым, а внутренний agent loop — чёрным ящиком для диспетчера.
Свой UI показывает шаблоны, настройки, подключения, расписания и результаты. Внутри DSH сохраняются публичные точки подключения плагинов; platform adapter изолирует конфигурацию, credentials, запуск и состояния сессий. Runner остаётся заменяемым, а внутренний agent loop — чёрным ящиком для диспетчера
```mermaid
flowchart LR
@@ -432,11 +432,11 @@ flowchart LR
BROKER --> EXT["LLM / официальный клиент / API"]
```
Совместимость подтверждается для конкретных версий DSH, runtime и плагина. Непроверенные пакеты не получают отметку совместимости; зависимость от платформенного API объявляется явно. Детали и исходные источники: [DSH foundation](dsh-foundation.md).
Совместимость подтверждается для конкретных версий DSH, runtime и плагина. Непроверенные пакеты не получают отметку совместимости; зависимость от платформенного API объявляется явно. Детали и исходные источники: [DSH foundation](dsh-foundation.md)
## Плагины и авторизация провайдеров
Первая линейка: provider-claude, provider-codex, provider-xai, provider-generic, recurring-tasks и package-discovery. Provider plugins поддерживают API keys и отдельно разрешённые способы входа в аккаунт. Наличие подписки само по себе не делает её доступной стороннему приложению; неподтверждённые режимы не включаются. Плагин расписаний обращается к единому Scheduler, а discovery ищет пакеты и показывает зависимости/разрешения до установки.
Первая линейка: provider-claude, provider-codex, provider-xai, provider-generic, recurring-tasks и package-discovery. Provider plugins поддерживают API keys и отдельно разрешённые способы входа в аккаунт. Наличие подписки само по себе не делает её доступной стороннему приложению; неподтверждённые режимы не включаются. Плагин расписаний обращается к единому Scheduler, а discovery ищет пакеты и показывает зависимости/разрешения до установки
```mermaid
sequenceDiagram
@@ -455,7 +455,7 @@ sequenceDiagram
B-->>UI: ConnectionSummary без секретов
```
Для official_client авторизация завершается внутри неизменённого клиента; broker получает только статус/binding, не извлекает его tokens. Для API key используется отдельная защищённая передача. Полная матрица и правила: [плагины](plugins.md), [Provider API](api/provider-api.md), [API edge cases](provider-edge-cases.md).
Для official_client авторизация завершается внутри неизменённого клиента; broker получает только статус/binding, не извлекает его tokens. Для API key используется отдельная защищённая передача. Полная матрица и правила: [плагины](plugins.md), [Provider API](api/provider-api.md), [API edge cases](provider-edge-cases.md)
## Режимы приложения и развёртывания
@@ -472,7 +472,7 @@ flowchart TB
ONPREM --> PRIVATE["Runner внутри инфраструктуры клиента"]
```
Desktop выполняет локально через sidecar; mobile/PWA управляют Runner. On-prem означает размещение всей платформы у клиента; свой Runner при облачном API — отдельный режим. Local CLI остаётся самостоятельным способом запуска без обязательной облачной учётки.
Desktop выполняет локально через sidecar; mobile/PWA управляют Runner. On-prem означает размещение всей платформы у клиента; свой Runner при облачном API — отдельный режим. Local CLI остаётся самостоятельным способом запуска без обязательной облачной учётки
## Roadmap и готовность
@@ -487,7 +487,7 @@ Desktop выполняет локально через sidecar; mobile/PWA уп
| P6 | Standalone JS: desktop, mobile, PWA |
| P7 | Расширение API edge cases, нагрузка и эксплуатация |
Проверки ошибок и изоляции входят в каждый этап, а не откладываются до P7. [Roadmap с критериями выхода](roadmap.md). Начинать можно с P0–P2; [результат проверки дизайна](review.md) разделяет принятые решения и оставшиеся проверки реализации.
Проверки ошибок и изоляции входят в каждый этап, а не откладываются до P7. [Roadmap с критериями выхода](roadmap.md). Начинать можно с P0–P2; [результат проверки дизайна](review.md) разделяет принятые решения и оставшиеся проверки реализации
## Подробные спецификации
+9 -9
View File
@@ -2,13 +2,13 @@
## Решение
Invest Harness использует DeepSeek Harness (DSH) как базовый движок агентов. Изменяем интерфейс и внутренние границы, сохраняя публичные контракты плагинов. Это целевой дизайн нашей сборки, а не утверждение, что все необходимые возможности уже реализованы в upstream.
Invest Harness использует DeepSeek Harness (DSH) как базовый движок агентов. Изменяем интерфейс и внутренние границы, сохраняя публичные контракты плагинов. Это целевой дизайн нашей сборки, а не утверждение, что все необходимые возможности уже реализованы в upstream
Исходный ориентир spike — @deepseek-ai/dsh 0.2.2-rc.1, указанный в проверенном манифесте на 11.11.2026. Перед первым runtime-релизом фиксируются исходный commit, версии всех DSH-пакетов, lock зависимостей и digest сборки. Плавающий master не используется в опубликованных harness’ах. Сама версия пакета без проверки целостности недостаточна.
Исходный ориентир spike — @deepseek-ai/dsh 0.2.2-rc.1, указанный в проверенном манифесте на 11.11.2026. Перед первым runtime-релизом фиксируются исходный commit, версии всех DSH-пакетов, lock зависимостей и digest сборки. Плавающий master не используется в опубликованных harness’ах. Сама версия пакета без проверки целостности недостаточна
## Исправления интерфейса
Собственный JS-интерфейс строится вокруг пользователя: каталог → шаблон → настройки → подключения → запуск → результаты. Пользователь не редактирует внутреннюю конфигурацию движка. JSON Schema Driven UI обслуживает настройки harness, plugins и template с одинаковыми сообщениями об ошибках. Экран подключения явно различает API key, вход через аккаунт и локальный официальный клиент. История показывает состояние запуска и попыток, запросы ввода и источник расхода.
Собственный JS-интерфейс строится вокруг пользователя: каталог → шаблон → настройки → подключения → запуск → результаты. Пользователь не редактирует внутреннюю конфигурацию движка. JSON Schema Driven UI обслуживает настройки harness, plugins и template с одинаковыми сообщениями об ошибках. Экран подключения явно различает API key, вход через аккаунт и локальный официальный клиент. История показывает состояние запуска и попыток, запросы ввода и источник расхода
## Исправления архитектуры
@@ -22,18 +22,18 @@ Invest Harness использует DeepSeek Harness (DSH) как базовый
| Контекст | Отдельный workspace и DSH state directory для каждого Agent/Run с явной политикой сохранения | Нет смешения tenant-сессий |
| Обновления | Собственная версия сборки + upstream baseline + compatibility report | Плагин не ломается после незаметного обновления |
В DSH уже есть профили запуска и отдельный headless-режим. Платформенный адаптер нормализует поток событий и результат; он не считает произвольный stderr машинным протоколом. Продолжение сохранённой DSH-сессии требует исходных state files и совместимого workspace; оно не равно переносимому checkpoint без проверенного адаптера.
В DSH уже есть профили запуска и отдельный headless-режим. Платформенный адаптер нормализует поток событий и результат; он не считает произвольный stderr машинным протоколом. Продолжение сохранённой DSH-сессии требует исходных state files и совместимого workspace; оно не равно переносимому checkpoint без проверенного адаптера
## Совместимость с DSH
Плагины реализуют публичные DSH/Cordis interfaces, объявляют peer dependencies и требования к сервисам. Каталог добавляет envelope публикации, не заменяя формат самого DSH-пакета. Наши стандартные плагины должны загружаться в проверенном upstream DSH с теми же public interfaces; платформенные операции требуют настроенного endpoint Invest Harness. При отсутствии endpoint плагин сообщает capability unavailable, не ломая запуск DSH.
Плагины реализуют публичные DSH/Cordis interfaces, объявляют peer dependencies и требования к сервисам. Каталог добавляет envelope публикации, не заменяя формат самого DSH-пакета. Наши стандартные плагины должны загружаться в проверенном upstream DSH с теми же public interfaces; платформенные операции требуют настроенного endpoint Invest Harness. При отсутствии endpoint плагин сообщает capability unavailable, не ломая запуск DSH
Входящая совместимость не означает запуск любого стороннего плагина. Матрица фиксирует DSH version, plugin version, Node version, OS/architecture, permissions и surfaces: headless/web/local. Проверки: load/dispose, регистрация tools, config validation, streaming, cancellation, credential refresh, отсутствие зависимостей от private APIs. Плагин, требующий внутренний UI DSH, получает ui-specific статус и адаптер; он не объявляется автоматически совместимым с новым UI.
Входящая совместимость не означает запуск любого стороннего плагина. Матрица фиксирует DSH version, plugin version, Node version, OS/architecture, permissions и surfaces: headless/web/local. Проверки: load/dispose, регистрация tools, config validation, streaming, cancellation, credential refresh, отсутствие зависимостей от private APIs. Плагин, требующий внутренний UI DSH, получает ui-specific статус и адаптер; он не объявляется автоматически совместимым с новым UI
Несовместимая смена API меняет compatibility profile; resolver отказывает до запуска. Lifecycle адаптации и возможности безопасности остаются частью сборки, а не требуют silent monkey patch каждого плагина.
Несовместимая смена API меняет compatibility profile; resolver отказывает до запуска. Lifecycle адаптации и возможности безопасности остаются частью сборки, а не требуют silent monkey patch каждого плагина
## Основа и ограничения лицензирования
DSH опубликован под MIT; сохраняем copyright и license notices в сборках. Состав сторонних пакетов проверяется для каждого распространяемого образа. Это не определяет лицензию всего Invest Harness и не заменяет условия моделей и провайдеров.
DSH опубликован под MIT; сохраняем copyright и license notices в сборках. Состав сторонних пакетов проверяется для каждого распространяемого образа. Это не определяет лицензию всего Invest Harness и не заменяет условия моделей и провайдеров
Источники: [CLI manifest](https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/apps/cli/package.json), [Headless](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/headless/README.md), [Authorization service](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/credentials/authorization/README.md), [MIT](https://github.com/deepseek-ai/deepseek-harness/blob/master/LICENSE).
Источники: [CLI manifest](https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/apps/cli/package.json), [Headless](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/headless/README.md), [Authorization service](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/credentials/authorization/README.md), [MIT](https://github.com/deepseek-ai/deepseek-harness/blob/master/LICENSE)
+14 -14
View File
@@ -2,42 +2,42 @@
## Граница чёрного ящика
Harness получает ExecutionSpec и разрешённые ресурсы. Его внутренний цикл не управляется платформой. Для участия в платформе пакет предоставляет entrypoint и адаптер событий. Exit code 0 означает успешное завершение процесса, но Run становится succeeded только после проверки ResultManifest и сохранения артефактов. Ошибка финансового рассуждения не определяется статусом процесса.
Harness получает ExecutionSpec и разрешённые ресурсы. Его внутренний цикл не управляется платформой. Для участия в платформе пакет предоставляет entrypoint и адаптер событий. Exit code 0 означает успешное завершение процесса, но Run становится succeeded только после проверки ResultManifest и сохранения артефактов. Ошибка финансового рассуждения не определяется статусом процесса
## Планирование
API в одной транзакции записывает Run, reservation бюджета/места в очереди и outbox. Слот активного исполнения резервируется только при claim. Диспетчер обрабатывает outbox идемпотентно по runId. Resolve выполняется до создания снимка; назначение повторно проверяет block policy и права. Попытка захватывается атомарно с leaseEpoch. Стандартный execution adapter использует runId/attemptId как ключ дедупликации, хранит соответствие с executionId движка и сверяет состояние при неоднозначном ответе.
API в одной транзакции записывает Run, reservation бюджета/места в очереди и outbox. Слот активного исполнения резервируется только при claim. Диспетчер обрабатывает outbox идемпотентно по runId. Resolve выполняется до создания снимка; назначение повторно проверяет block policy и права. Попытка захватывается атомарно с leaseEpoch. Стандартный execution adapter использует runId/attemptId как ключ дедупликации, хранит соответствие с executionId движка и сверяет состояние при неоднозначном ответе
Расписания закрепляют agentRevisionId, IANA timezone, cron expression, nextRunAt и overlapPolicy: skip или queue. Политика misfire: skip либо coalesce (по умолчанию), создающая не более одного запуска за простой. Queue удерживает максимум одно ожидающее срабатывание; следующие объединяются с ним. Уникальный ключ scheduleId + scheduledAt предотвращает дубли. При переходах DST пропущенное локальное время пропускается, повторённое выполняется один раз; scheduledAt фиксируется как UTC instant. Ручной запуск имеет отдельный ключ.
Расписания закрепляют agentRevisionId, IANA timezone, cron expression, nextRunAt и overlapPolicy: skip или queue. Политика misfire: skip либо coalesce (по умолчанию), создающая не более одного запуска за простой. Queue удерживает максимум одно ожидающее срабатывание; следующие объединяются с ним. Уникальный ключ scheduleId + scheduledAt предотвращает дубли. При переходах DST пропущенное локальное время пропускается, повторённое выполняется один раз; scheduledAt фиксируется как UTC instant. Ручной запуск имеет отдельный ключ
## Lease и повторы
Начальные настройки: lease 90 секунд, heartbeat каждые 20 секунд, maxAttempts 3 только для явно retry-safe задач. Важна серверная шкала времени. Каждый heartbeat и terminal report содержит attemptId, leaseEpoch и sequence. Устаревший epoch возвращает 409 и не может изменить состояние Run.
Начальные настройки: lease 90 секунд, heartbeat каждые 20 секунд, maxAttempts 3 только для явно retry-safe задач. Важна серверная шкала времени. Каждый heartbeat и terminal report содержит attemptId, leaseEpoch и sequence. Устаревший epoch возвращает 409 и не может изменить состояние Run
Потеря lease переводит Run в interrupted. Автоповтор разрешён, только если template объявил retrySafe и policy организации позволяет; иначе нужен явный retry пользователя после предупреждения о возможном повторе внешних действий. Checkpoint continuation создаёт новый Attempt того же Run. Retry terminal Run создаёт новый Run с parentRunId и копией настроек и зависимостей, новым runId и specDigest и актуальной проверкой прав.
Потеря lease переводит Run в interrupted. Автоповтор разрешён, только если template объявил retrySafe и policy организации позволяет; иначе нужен явный retry пользователя после предупреждения о возможном повторе внешних действий. Checkpoint continuation создаёт новый Attempt того же Run. Retry terminal Run создаёт новый Run с parentRunId и копией настроек и зависимостей, новым runId и specDigest и актуальной проверкой прав
Fencing защищает записи платформы, но не останавливает старый процесс на недоступной машине и не обеспечивает exactly-once сторонних API. Повторные внешние действия должен защищать сам harness или поддерживающий idempotency key шлюз.
Fencing защищает записи платформы, но не останавливает старый процесс на недоступной машине и не обеспечивает exactly-once сторонних API. Повторные внешние действия должен защищать сам harness или поддерживающий idempotency key шлюз
## Отмена и ожидание
Cancel queued снимает reservation и сразу завершает Run. Cancel running устанавливает cancelling; Runner прекращает процесс и возвращает подтверждение. Для управляемого Runner после grace period выполняется принудительная остановка. Без подтверждения собственного Runner состояние становится interrupted, а не falsely cancelled. Поздний success после принятой отмены не отменяет запрос пользователя.
Cancel queued снимает reservation и сразу завершает Run. Cancel running устанавливает cancelling; Runner прекращает процесс и возвращает подтверждение. Для управляемого Runner после grace period выполняется принудительная остановка. Без подтверждения собственного Runner состояние становится interrupted, а не falsely cancelled. Поздний success после принятой отмены не отменяет запрос пользователя
Waiting_input поддерживается только с capability checkpoint-v1: Runner сохраняет checkpoint, передаёт его digest и input schema, получает подтверждение, затем освобождает lease. Ответ пользователя валидируется, разрешение проверяется заново. Повтор responseId не создаёт ещё одну попытку. Новое продолжение закрепляется за исходным ExecutionSpec.
Waiting_input поддерживается только с capability checkpoint-v1: Runner сохраняет checkpoint, передаёт его digest и input schema, получает подтверждение, затем освобождает lease. Ответ пользователя валидируется, разрешение проверяется заново. Повтор responseId не создаёт ещё одну попытку. Новое продолжение закрепляется за исходным ExecutionSpec
## Локальный режим
Клиент скачивает lock и артефакты, проверяет digest и разрешения, сохраняет ExecutionSpec, запускает локальный Runner. Credentials поступают из OS keychain или выбранного пользователем провайдера. Облачная регистрация не обязательна для кешированных публичных пакетов. Синхронизация результатов с облаком — отдельное явное действие, не поведение по умолчанию.
Клиент скачивает lock и артефакты, проверяет digest и разрешения, сохраняет ExecutionSpec, запускает локальный Runner. Credentials поступают из OS keychain или выбранного пользователем провайдера. Облачная регистрация не обязательна для кешированных публичных пакетов. Синхронизация результатов с облаком — отдельное явное действие, не поведение по умолчанию
## Артефакты
Runner запрашивает upload grant для конкретного Attempt и назначения файла. Grant ограничен размером, сроком и префиксом. ResultManifest содержит artifactId, digest, sizeBytes и mediaType, без произвольных URL. Сервис проверяет существование объектов до terminal success. Логи доставляются отдельно и не являются единственным источником состояния.
Runner запрашивает upload grant для конкретного Attempt и назначения файла. Grant ограничен размером, сроком и префиксом. ResultManifest содержит artifactId, digest, sizeBytes и mediaType, без произвольных URL. Сервис проверяет существование объектов до terminal success. Логи доставляются отдельно и не являются единственным источником состояния
[Runner Protocol](api/executor-api.md) · [Состояния и диаграммы](design.md).
[Runner Protocol](api/executor-api.md) · [Состояния и диаграммы](design.md)
## Владение состоянием и продолжение
Run, Attempt, Schedule, reservations и их outbox находятся в Platform DB. API и диспетчер используют общий модуль переходов состояния и транзакций. Execution DB хранит только техническое соответствие attemptId → executionId и состояние движка, а не второй источник истины Run. Финализация Attempt, Run, освобождение активного слота и outbox атомарны в Platform DB; события движка проходят тот же путь.
Run, Attempt, Schedule, reservations и их outbox находятся в Platform DB. API и диспетчер используют общий модуль переходов состояния и транзакций. Execution DB хранит только техническое соответствие attemptId → executionId и состояние движка, а не второй источник истины Run. Финализация Attempt, Run, освобождение активного слота и outbox атомарны в Platform DB; события движка проходят тот же путь
ExecutionSpec неизменяем на протяжении Run. Checkpoint и ответ пользователя передаются отдельно в AttemptContext внутри Assignment. Deadline фиксируется при первом назначении: timeoutSeconds ограничивает время Run с первого назначения, включая ожидание ввода и последующие очереди; продолжение не обнуляет deadline. Подтверждённая остановка по deadline завершает Run как failed с DEADLINE_EXCEEDED; неподтверждённая — interrupted без автоматического повтора. Истечение inputRequest.expiresAt завершает waiting_input как failed с INPUT_EXPIRED. Ошибка подготовки без внешних эффектов допускает bounded retry внутри preparing до maxAttempts; после исчерпания — failed.
ExecutionSpec неизменяем на протяжении Run. Checkpoint и ответ пользователя передаются отдельно в AttemptContext внутри Assignment. Deadline фиксируется при первом назначении: timeoutSeconds ограничивает время Run с первого назначения, включая ожидание ввода и последующие очереди; продолжение не обнуляет deadline. Подтверждённая остановка по deadline завершает Run как failed с DEADLINE_EXCEEDED; неподтверждённая — interrupted без автоматического повтора. Истечение inputRequest.expiresAt завершает waiting_input как failed с INPUT_EXPIRED. Ошибка подготовки без внешних эффектов допускает bounded retry внутри preparing до maxAttempts; после исчерпания — failed
После принятой отмены автоматический retry запрещён даже при interrupted. Reconciler проверяет deadline, протухшие lease и outbox; изменение статуса выполняется условно по текущему состоянию и epoch.
После принятой отмены автоматический retry запрещён даже при interrupted. Reconciler проверяет deadline, протухшие lease и outbox; изменение статуса выполняется условно по текущему состоянию и epoch
+11 -11
View File
@@ -1,6 +1,6 @@
# Плагины Invest Harness
Плагины совместимы с публичным DSH plugin API в проверенной матрице версий. Harness — движок, template — состав агента, skill — инструкции, plugin — исполняемое расширение. Подключение аккаунта провайдера не является входом в Invest Harness.
Плагины совместимы с публичным DSH plugin API в проверенной матрице версий. Harness — движок, template — состав агента, skill — инструкции, plugin — исполняемое расширение. Подключение аккаунта провайдера не является входом в Invest Harness
## Первая линейка
@@ -13,13 +13,13 @@
| recurring-tasks | Планирование регулярных задач из агента и формы | Сохранённое Schedule, preview ближайших запусков |
| package-discovery | Поиск плагинов, harness’ов, скиллов и шаблонов | Доступные пакеты, совместимость, preview установки |
Это план разработки, а не список уже установленных расширений. Account-based режим включается отдельно для каждой комбинации provider, deploymentMode, integrationPath. Если путь недоступен, UI показывает причину и API-вариант без скрытого переключения способа оплаты.
Это план разработки, а не список уже установленных расширений. Account-based режим включается отдельно для каждой комбинации provider, deploymentMode, integrationPath. Если путь недоступен, UI показывает причину и API-вариант без скрытого переключения способа оплаты
## Авторизация провайдеров
Методы провайдера перечисляет adapter discovery; браузер не получает client secret или refresh token. OAuth flow хранит state, PKCE, nonce где применимо, redirect allowlist, срок и tenant/actor binding. Device flow соблюдает polling interval и slow_down. Отмена и expiry завершают flow. Refresh выполняется single-flight на connectionId с атомарной заменой refresh token. invalid_grant переводит Connection в reauth_required; повторные login попытки не создаются автоматически.
Методы провайдера перечисляет adapter discovery; браузер не получает client secret или refresh token. OAuth flow хранит state, PKCE, nonce где применимо, redirect allowlist, срок и tenant/actor binding. Device flow соблюдает polling interval и slow_down. Отмена и expiry завершают flow. Refresh выполняется single-flight на connectionId с атомарной заменой refresh token. invalid_grant переводит Connection в reauth_required; повторные login попытки не создаются автоматически
Credential placement: local_keychain, runner_private_store или server_vault. Переход между ними требует нового разрешённого связывания; локальная подписка не переносится на hosted Runner неявно. Для official-client-mode provider broker хранит статус и binding, а не извлекает закрытые токены клиента.
Credential placement: local_keychain, runner_private_store или server_vault. Переход между ними требует нового разрешённого связывания; локальная подписка не переносится на hosted Runner неявно. Для official-client-mode provider broker хранит статус и binding, а не извлекает закрытые токены клиента
| Провайдер | Подтверждённая основа | Решение для Invest Harness |
|---|---|---|
@@ -28,22 +28,22 @@ Credential placement: local_keychain, runner_private_store или server_vault.
| xAI | Официальный Grok Build описывает browser/device login и API key | Наличие login у клиента не доказывает доступность произвольного DSH subscription adapter. Remote account mode gated до проверки; API доступен как отдельный режим |
| Другие | Условия и протокол определяет провайдер | Новый адаптер проходит ту же матрицу auth, scopes, quotas, refresh и deployment modes |
Источники, проверенные 11.11.2026: [Claude authentication and credential use](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use), [Codex app-server auth](https://learn.chatgpt.com/docs/app-server), [Sign in with ChatGPT integration](https://developers.openai.com/siwc/token-sharing-open-source/codex-app-server), [Grok Build authentication](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/02-authentication.md).
Источники, проверенные 11.11.2026: [Claude authentication and credential use](https://code.claude.com/docs/en/legal-and-compliance#authentication-and-credential-use), [Codex app-server auth](https://learn.chatgpt.com/docs/app-server), [Sign in with ChatGPT integration](https://developers.openai.com/siwc/token-sharing-open-source/codex-app-server), [Grok Build authentication](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/02-authentication.md)
## Регулярные задачи
Плагин предоставляет preview_schedule, create_schedule, list_schedules, update_schedule, pause_schedule. Перед записью отображает timezone, следующие 5 occurrences, overlap и catch-up policy, ревизию агента и бюджет. Действия выполняются с actor-scoped разрешением schedules:write, не полномочиями администратора.
Плагин предоставляет preview_schedule, create_schedule, list_schedules, update_schedule, pause_schedule. Перед записью отображает timezone, следующие 5 occurrences, overlap и catch-up policy, ревизию агента и бюджет. Действия выполняются с actor-scoped разрешением schedules:write, не полномочиями администратора
В cloud/on-prem единственный владелец времени — диспетчер. Локально тот же модуль расчёта работает в Local Scheduler с локальной БД; закрытое приложение не обещает фоновые запуски без установленного daemon. Расписание принадлежит одному placement. Перенос требует pause старого, handover cursor и activation нового; просто копировать active Schedule нельзя. В MVP blackout/exchange calendars не гарантируются; инвестиционный календарь добавляется отдельным адаптером позже.
В cloud/on-prem единственный владелец времени — диспетчер. Локально тот же модуль расчёта работает в Local Scheduler с локальной БД; закрытое приложение не обещает фоновые запуски без установленного daemon. Расписание принадлежит одному placement. Перенос требует pause старого, handover cursor и activation нового; просто копировать active Schedule нельзя. В MVP blackout/exchange calendars не гарантируются; инвестиционный календарь добавляется отдельным адаптером позже
## Поиск и установка
Tools search_packages, inspect_package, resolve_dependencies, preview_install возвращают только доступные пользователю версии. Выдача включает kind, owner, digest, runtime compatibility, permissions и review status. MVP использует PostgreSQL full-text/trigram поиск, не отдельную поисковую инфраструктуру.
Tools search_packages, inspect_package, resolve_dependencies, preview_install возвращают только доступные пользователю версии. Выдача включает kind, owner, digest, runtime compatibility, permissions и review status. MVP использует PostgreSQL full-text/trigram поиск, не отдельную поисковую инфраструктуру
Описание найденного пакета — данные, не инструкция агенту. Поиск не запускает код. Установка создаёт новую AgentRevision после подтверждения изменения permissions; работающий Run не меняется. Результат resolve ещё раз проверяется при записи ревизии и назначении Runner.
Описание найденного пакета — данные, не инструкция агенту. Поиск не запускает код. Установка создаёт новую AgentRevision после подтверждения изменения permissions; работающий Run не меняется. Результат resolve ещё раз проверяется при записи ревизии и назначении Runner
## Контракт адаптера провайдера
Adapter interface version 1: listAuthMethods, startAuth, pollAuth, cancelAuth, getConnectionStatus, disconnect, listModels, invoke, cancelInvocation. Инференс нормализует текст, tool calls, structured output и usage, сохраняя provider-specific metadata в ограниченном namespace. Capabilities определяют поддержку tools, stream, JSON Schema, images, cancellation и resume. Provider passwords не входят в этот интерфейс.
Adapter interface version 1: listAuthMethods, startAuth, pollAuth, cancelAuth, getConnectionStatus, disconnect, listModels, invoke, cancelInvocation. Инференс нормализует текст, tool calls, structured output и usage, сохраняя provider-specific metadata в ограниченном namespace. Capabilities определяют поддержку tools, stream, JSON Schema, images, cancellation и resume. Provider passwords не входят в этот интерфейс
Подробные ручки: [provider-api.md](api/provider-api.md). Граничные случаи: [provider-edge-cases.md](provider-edge-cases.md).
Подробные ручки: [provider-api.md](api/provider-api.md). Граничные случаи: [provider-edge-cases.md](provider-edge-cases.md)
+2 -2
View File
@@ -1,6 +1,6 @@
# Граничные случаи провайдеров
Эта матрица — обязательные проверки adapter conformance, а не утверждение, что все API одинаковы.
Эта матрица — обязательные проверки adapter conformance, а не утверждение, что все API одинаковы
| Случай | Поведение платформы / адаптера | Проверка |
|---|---|---|
@@ -22,4 +22,4 @@
| Mobile background / sleep | Клиент переподключается по cursor, job живёт на Runner | Закрытие экрана не считается отменой Run |
| API dialect version drift | Закреплённая adapter version, capability probe и контрактные fixtures | Несовместимость отключает конкретный mode |
Каждый новый provider mode сначала проходит fake-provider fixtures без реальных списаний, затем минимальный opt-in live smoke с бюджетом. Артефакты проверки содержат redacted status, timings, capabilities, версии и date; не токены и не полные prompts. Provider mode включается независимо по local/on_prem/managed_remote.
Каждый новый provider mode сначала проходит fake-provider fixtures без реальных списаний, затем минимальный opt-in live smoke с бюджетом. Артефакты проверки содержат redacted status, timings, capabilities, версии и date; не токены и не полные prompts. Provider mode включается независимо по local/on_prem/managed_remote
+4 -4
View File
@@ -1,6 +1,6 @@
# Проверка дизайна перед реализацией
Проверено 11.11.2026. Это проверка согласованности спецификации, не подтверждение работоспособности ещё не созданной платформы. Можно начинать P0–P2; поддержка DSH и account modes требует проверок из roadmap.
Проверено 11.11.2026. Это проверка согласованности спецификации, не подтверждение работоспособности ещё не созданной платформы. Можно начинать P0–P2; поддержка DSH и account modes требует проверок из roadmap
## Исправленные противоречия и пробелы
@@ -31,10 +31,10 @@
| Собственный Runner | P4 до допуска пула | Protocol conformance плюс явное подтверждение владельцем trust policy |
| Нагрузка и восстановление | P7 до эксплуатационных обещаний | Нагрузочный профиль, реальные SLO, restore rehearsal |
Выбор лицензии Invest Harness остаётся решением владельца проекта; публичный репозиторий не заменяет разрешение на распространение. Версии библиотек и deploy images закрепляются в реализации, а не остаются плавающими ссылками из документа.
Выбор лицензии Invest Harness остаётся решением владельца проекта; публичный репозиторий не заменяет разрешение на распространение. Версии библиотек и deploy images закрепляются в реализации, а не остаются плавающими ссылками из документа
## Первый вертикальный срез
Автор публикует DSH harness, один совместимый plugin и template с config/input/output schemas. Пользователь создаёт ревизию через форму, связывает тестовый provider и запускает тот же состав локально и на одном Runner. Сохраняются события и валидный результат. Повтор POST Run и claim не создаёт дубликаты; чужой tenant не читает результат; cancel останавливает процесс; потеря lease запрещает позднюю запись; credentials отсутствуют в snapshot и логах.
Автор публикует DSH harness, один совместимый plugin и template с config/input/output schemas. Пользователь создаёт ревизию через форму, связывает тестовый provider и запускает тот же состав локально и на одном Runner. Сохраняются события и валидный результат. Повтор POST Run и claim не создаёт дубликаты; чужой tenant не читает результат; cancel останавливает процесс; потеря lease запрещает позднюю запись; credentials отсутствуют в snapshot и логах
Машиночитаемые схемы здесь задают основу протокола, но не полный SDK. До реализации endpoint его request/response и ошибки переносятся в OpenAPI и проверяются контрактными fixtures. Проверки JSON Schema не доказывают корректность OAuth, sandbox или финансовых действий внутри harness.
Машиночитаемые схемы здесь задают основу протокола, но не полный SDK. До реализации endpoint его request/response и ошибки переносятся в OpenAPI и проверяются контрактными fixtures. Проверки JSON Schema не доказывают корректность OAuth, sandbox или финансовых действий внутри harness
+5 -5
View File
@@ -1,6 +1,6 @@
# Roadmap Invest Harness
Этапы выражают зависимости и критерии готовности, не календарные обещания. Названия компонентов и схемы всей системы находятся в [основной диздоке](design.md).
Этапы выражают зависимости и критерии готовности, не календарные обещания. Названия компонентов и схемы всей системы находятся в [основной диздоке](design.md)
| Этап | Результат | Критерий выхода |
|---|---|---|
@@ -13,14 +13,14 @@
| P6 Standalone JS app | Общий TypeScript/React UI: PWA, desktop shell, mobile shell | Desktop через Electron и локальный sidecar; mobile через Capacitor как клиент Runner; безопасный IPC, deep links, login/cancel/reconnect |
| P7 API edge cases и эксплуатация | Provider conformance, нагрузка, отказоустойчивость, observability | Выполнена матрица edge cases, лимиты подтверждены измерениями; Kubernetes Runner только после потребности и отдельной проверки |
Edge cases не откладываются целиком до P7: auth/stream/retry проверки являются gate каждого провайдера уже на P5. P7 расширяет сочетания и нагрузку. Работа над UI и provider spikes может идти параллельно после P0, но publication gate не пропускается.
Edge cases не откладываются целиком до P7: auth/stream/retry проверки являются gate каждого провайдера уже на P5. P7 расширяет сочетания и нагрузку. Работа над UI и provider spikes может идти параллельно после P0, но publication gate не пропускается
## Standalone не означает одинаковый runtime везде
Desktop UI общается с локальным Go sidecar и DSH Node runtime через ограниченный IPC. Node integration в renderer выключена; изоляция контекста включена. Mobile и PWA управляют удалённым или доступным on-prem Runner; Docker и полный DSH на телефоне не обещаются. Offline mobile — кеш каталога/черновиков, не выполнение произвольного harness. Локальное выполнение на мобильном устройстве требует отдельного capability и будущего runtime.
Desktop UI общается с локальным Go sidecar и DSH Node runtime через ограниченный IPC. Node integration в renderer выключена; изоляция контекста включена. Mobile и PWA управляют удалённым или доступным on-prem Runner; Docker и полный DSH на телефоне не обещаются. Offline mobile — кеш каталога/черновиков, не выполнение произвольного harness. Локальное выполнение на мобильном устройстве требует отдельного capability и будущего runtime
On-prem control plane размещается у клиента. Собственный Runner, подключённый к облачному control plane, — другой режим и сам по себе не является on-prem установкой всей платформы.
On-prem control plane размещается у клиента. Собственный Runner, подключённый к облачному control plane, — другой режим и сам по себе не является on-prem установкой всей платформы
## Готовность к началу реализации
Можно начинать P0–P2 по текущим контрактам. Нельзя объявлять готовыми универсальную DSH-совместимость, перенос сессии между средами и вход по подписке любого провайдера до выполнения соответствующих gate. Функциональность без подтверждённого mode не блокирует API-key путь и базовую платформу.
Можно начинать P0–P2 по текущим контрактам. Нельзя объявлять готовыми универсальную DSH-совместимость, перенос сессии между средами и вход по подписке любого провайдера до выполнения соответствующих gate. Функциональность без подтверждённого mode не блокирует API-key путь и базовую платформу
+12 -12
View File
@@ -2,15 +2,15 @@
## Модель нагрузки
Число аккаунтов не определяет ёмкость. Измеряем arrival rate λ, среднюю и p95 длительность T, CPU и память Attempt, размер образа, объём логов, количество внешних запросов и число одновременных подключений. Раздельные классы: короткие интерактивные задачи, длинные фоновые, периодические и сборка пакетов.
Число аккаунтов не определяет ёмкость. Измеряем arrival rate λ, среднюю и p95 длительность T, CPU и память Attempt, размер образа, объём логов, количество внешних запросов и число одновременных подключений. Раздельные классы: короткие интерактивные задачи, длинные фоновые, периодические и сборка пакетов
По Little’s law среднее число активных задач L = λ × T. Для целевой загрузки слотов ρ начальная оценка slots ≥ λ × T / ρ. Пример-гипотеза: 120 запусков/мин, 180 секунд на запуск, ρ=0.7 → около 515 слотов. Это не 515 серверов: число слотов на узле ограничено одновременно CPU, RAM, диском и квотами API. Хвосты длительности требуют нагрузочного измерения, а не подстановки p95 в доказательство SLO.
По Little’s law среднее число активных задач L = λ × T. Для целевой загрузки слотов ρ начальная оценка slots ≥ λ × T / ρ. Пример-гипотеза: 120 запусков/мин, 180 секунд на запуск, ρ=0.7 → около 515 слотов. Это не 515 серверов: число слотов на узле ограничено одновременно CPU, RAM, диском и квотами API. Хвосты длительности требуют нагрузочного измерения, а не подстановки p95 в доказательство SLO
## Очереди и backpressure
Admission control при создании Run резервирует место в очереди и бюджет; tenant concurrency резервируется атомарно при назначении Attempt. Weighted fair scheduling чередует tenants; внутри tenant приоритет + возраст. Ограничены queue depth и max queue age. При превышении пользователь получает 429 с Retry-After либо явный queued status по принятой policy. Бесконечного скрытого backlog быть не должно.
Admission control при создании Run резервирует место в очереди и бюджет; tenant concurrency резервируется атомарно при назначении Attempt. Weighted fair scheduling чередует tenants; внутри tenant приоритет + возраст. Ограничены queue depth и max queue age. При превышении пользователь получает 429 с Retry-After либо явный queued status по принятой policy. Бесконечного скрытого backlog быть не должно
Учитываем лимиты внешних API, токены/мин, соединения и доступность источников. Шлюз контролирует свои вызовы. Для прямых вызовов Runner платформа гарантирует только ресурсные/временные лимиты, а финансовый предел зависит от провайдера credentials.
Учитываем лимиты внешних API, токены/мин, соединения и доступность источников. Шлюз контролирует свои вызовы. Для прямых вызовов Runner платформа гарантирует только ресурсные/временные лимиты, а финансовый предел зависит от провайдера credentials
## Масштабирование компонентов
@@ -23,13 +23,13 @@ Admission control при создании Run резервирует место
| PostgreSQL | Индексы, bounded pagination, архивирование; read replicas для допустимо устаревших чтений | Назначения и авторизация читаются из актуального источника |
| S3 / registry | Прямые scoped grants, кеш по digest, лимит параллельных загрузок | Bandwidth, egress, cache isolation |
Горячие индексы: Run(tenantId, createdAt, id), Run(status, nextEligibleAt, id), Attempt(poolId, leaseUntil), Package(tenantId, kind, name), уникальный PackageVersion(packageId, version). Большие события и логи не хранятся целиком в строке Run.
Горячие индексы: Run(tenantId, createdAt, id), Run(status, nextEligibleAt, id), Attempt(poolId, leaseUntil), Package(tenantId, kind, name), уникальный PackageVersion(packageId, version). Большие события и логи не хранятся целиком в строке Run
## Прогрев и масштабирование исполнителей
Managed pool хранит небольшой warm reserve. Scale-out — по времени ожидания совместимых задач, scale-in — после drain: новые задания не выдаются, активные завершаются. Кеш неизменяемых образов по digest экономит загрузки. Приватные образы и архивы не выдаются другому tenant без проверки доступа. Garbage collection кеша использует размер и last-used; pinned active layers не удаляются.
Managed pool хранит небольшой warm reserve. Scale-out — по времени ожидания совместимых задач, scale-in — после drain: новые задания не выдаются, активные завершаются. Кеш неизменяемых образов по digest экономит загрузки. Приватные образы и архивы не выдаются другому tenant без проверки доступа. Garbage collection кеша использует размер и last-used; pinned active layers не удаляются
Собственный пул имеет независимые лимиты и SLA владельца. Недоступность такого пула не переносит задание автоматически в управляемый: credentials и политика размещения могут запрещать перенос.
Собственный пул имеет независимые лимиты и SLA владельца. Недоступность такого пула не переносит задание автоматически в управляемый: credentials и политика размещения могут запрещать перенос
## Отказы
@@ -45,14 +45,14 @@ Managed pool хранит небольшой warm reserve. Scale-out — по в
## Retention и восстановление
Исходные настраиваемые значения: orphan uploads 24 часа; debug-логи 14 дней; результаты 30 дней; аудит 180 дней. Это проектные значения, а не юридические обязательства. Активные Run и checkpoints защищены от очистки. Образы удаляются только после проверки ссылок, grace period и доступности backup.
Исходные настраиваемые значения: orphan uploads 24 часа; debug-логи 14 дней; результаты 30 дней; аудит 180 дней. Это проектные значения, а не юридические обязательства. Активные Run и checkpoints защищены от очистки. Образы удаляются только после проверки ссылок, grace period и доступности backup
Backup включает БД, объекты, ключевые конфигурации и возможность восстановления ключей шифрования. Проверяется согласованное восстановление metadata → digest → object. Цели для первой проверки: RPO 1 час, RTO 4 часа, без обещания до rehearsal.
Backup включает БД, объекты, ключевые конфигурации и возможность восстановления ключей шифрования. Проверяется согласованное восстановление metadata → digest → object. Цели для первой проверки: RPO 1 час, RTO 4 часа, без обещания до rehearsal
## Метрики и проверка
Предлагаемые цели пилота: p95 control API <500 мс без внешних вызовов; p95 queue wait <30 секунд при нагрузке в пределах квоты и доступном пуле. Время выполнения чёрного ящика не включается в API SLO. Следим за queue age, interrupted rate, attempts/run, event lag, orphan bytes, cache hit, SQL saturation и стоимостью на Run.
Предлагаемые цели пилота: p95 control API <500 мс без внешних вызовов; p95 queue wait <30 секунд при нагрузке в пределах квоты и доступном пуле. Время выполнения чёрного ящика не включается в API SLO. Следим за queue age, interrupted rate, attempts/run, event lag, orphan bytes, cache hit, SQL saturation и стоимостью на Run
Нагрузочные сценарии: равномерный поток, массовый scheduled burst без jitter (MVP), один шумный tenant, недоступный внешний API, перезапуск dispatcher, потеря Runner, медленный S3, дубли terminal reports. Отдельно проверяем отсутствие чужих артефактов и credentials. Jitter расписаний оценивается будущим экспериментом.
Нагрузочные сценарии: равномерный поток, массовый scheduled burst без jitter (MVP), один шумный tenant, недоступный внешний API, перезапуск dispatcher, потеря Runner, медленный S3, дубли terminal reports. Отдельно проверяем отсутствие чужих артефактов и credentials. Jitter расписаний оценивается будущим экспериментом
Стоимость = вычисления + хранение + egress + управляемые вызовы моделей. Цена прямых сторонних вызовов может быть неизвестна. Биллинг не строится исключительно на недоверенных отчётах пользовательского Runner.
Стоимость = вычисления + хранение + egress + управляемые вызовы моделей. Цена прямых сторонних вызовов может быть неизвестна. Биллинг не строится исключительно на недоверенных отчётах пользовательского Runner
+63 -63
View File
@@ -1,8 +1,8 @@
# Пять демонстрационных сценариев
Сценарии адаптированы из предоставленной аналитической работы «Finance Harness», версия 1.0 от 11.11.2026, раздел 3 (страницы 4–5), с учётом технической модели на странице 11. Это требования к демонстрации Invest Harness, а не описание готовых интеграций или подтверждённых продуктовых эффектов.
Сценарии адаптированы из предоставленной аналитической работы «Finance Harness», версия 1.0 от 11.11.2026, раздел 3 (страницы 4–5), с учётом технической модели на странице 11. Это требования к демонстрации Invest Harness, а не описание готовых интеграций или подтверждённых продуктовых эффектов
В исследовании профили называются harness. В [терминах платформы](design.md) START, GUARD, GOAL, PULSE и PRO — пять **шаблонов агента** на общей DSH-базе: каждый закрепляет harness, плагины, скиллы, правила ответа и JSON Schema настроек. Отдельный движок для каждого сценария не нужен. Пользователь создаёт из шаблона свой экземпляр агента.
В исследовании профили называются harness. В [терминах платформы](design.md) START, GUARD, GOAL, PULSE и PRO — пять **шаблонов агента** на общей DSH-базе: каждый закрепляет harness, плагины, скиллы, правила ответа и JSON Schema настроек. Отдельный движок для каждого сценария не нужен. Пользователь создаёт из шаблона свой экземпляр агента
| Шаблон | Запрос пользователя | Результат | Демонстрируемая возможность |
|---|---|---|---|
@@ -14,127 +14,127 @@
## Общие условия демонстрации
Пользователь выбирает шаблон в каталоге, настраивает форму, связывает разрешённые connections и выбирает локальное или удалённое исполнение. Провайдер модели выбирается независимо от сценария: API key либо доступный для этой среды account mode из [матрицы плагинов](plugins.md). Наличие подписки не гарантирует доступность интеграции.
Пользователь выбирает шаблон в каталоге, настраивает форму, связывает разрешённые connections и выбирает локальное или удалённое исполнение. Провайдер модели выбирается независимо от сценария: API key либо доступный для этой среды account mode из [матрицы плагинов](plugins.md). Наличие подписки не гарантирует доступность интеграции
В каждом сценарии ниже названия инструментов и финансовых плагинов — проектируемые возможности. Плагины объявляют доступы, а шаблоны закрепляют версии и скиллы. Минимальная демонстрация работает с подготовленными документами и снимками данных; доступ к брокерскому аккаунту, Пульсу и платным источникам не считается уже полученным.
В каждом сценарии ниже названия инструментов и финансовых плагинов — проектируемые возможности. Плагины объявляют доступы, а шаблоны закрепляют версии и скиллы. Минимальная демонстрация работает с подготовленными документами и снимками данных; доступ к брокерскому аккаунту, Пульсу и платным источникам не считается уже полученным
Для этих пяти демонстрационных шаблонов используются учебные либо read-only подключения без отправки торговых поручений. Это граница конкретных шаблонов; платформа по-прежнему рассматривает внутреннюю логику Runner как чёрный ящик. Скилл описывает метод работы, но ограничения доступа обеспечивает runtime и политика инструментов.
Для этих пяти демонстрационных шаблонов используются учебные либо read-only подключения без отправки торговых поручений. Это граница конкретных шаблонов; платформа по-прежнему рассматривает внутреннюю логику Runner как чёрный ящик. Скилл описывает метод работы, но ограничения доступа обеспечивает runtime и политика инструментов
Настройки ниже — содержимое config schema шаблона; вопрос, документ и снимок портфеля — вход конкретного Run. Секреты хранятся в connections, а не в форме. Смена профиля не переносит контекст автоматически: пользователь явно передаёт выбранный снимок или параметры цели новому агенту; права проверяются повторно. Общая неограниченная память между агентами не требуется.
Настройки ниже — содержимое config schema шаблона; вопрос, документ и снимок портфеля — вход конкретного Run. Секреты хранятся в connections, а не в форме. Смена профиля не переносит контекст автоматически: пользователь явно передаёт выбранный снимок или параметры цели новому агенту; права проверяются повторно. Общая неограниченная память между агентами не требуется
## 1. START — «Мой первый портфель»
**Пользователь и цель.** Начинающий инвестор хочет понять инструменты и смысл показателей до принятия собственного решения. Пример запроса: «Объясни разницу между вкладом и облигацией из этого примера простыми словами».
**Пользователь и цель.** Начинающий инвестор хочет понять инструменты и смысл показателей до принятия собственного решения. Пример запроса: «Объясни разницу между вкладом и облигацией из этого примера простыми словами»
**Состав.** DSH harness; плагины словаря, рыночных справочников и симулятора портфеля (`glossary`, `market_data`, `portfolio_simulator`); скилл объяснения финансовых понятий. Брокерское подключение не требуется.
**Состав.** DSH harness; плагины словаря, рыночных справочников и симулятора портфеля (`glossary`, `market_data`, `portfolio_simulator`); скилл объяснения финансовых понятий. Брокерское подключение не требуется
**Настройки формы.** `knowledgeLevel` — начальный/базовый; `explanationDepth` — кратко/подробно; `showGlossary` и `includeQuiz` — переключатели; `virtualCapital` — положительная сумма с валютой. Это параметры объяснения и симуляции, а не присвоение пользователю инвестиционной стратегии.
**Настройки формы.** `knowledgeLevel` — начальный/базовый; `explanationDepth` — кратко/подробно; `showGlossary` и `includeQuiz` — переключатели; `virtualCapital` — положительная сумма с валютой. Это параметры объяснения и симуляции, а не присвоение пользователю инвестиционной стратегии
**Ход сценария.**
1. Пользователь выбирает START, задаёт уровень объяснения и виртуальный капитал, сохраняет ревизию.
2. Передаёт вопрос и выбирает инструменты из демонстрационного набора.
3. Агент получает определения и характеристики из разрешённых источников, отделяет известные условия от допущений.
4. Симулятор строит учебный пример; агент объясняет результаты и при включённой настройке добавляет вопрос для самопроверки.
5. Пользователь меняет глубину объяснения через форму и запускает новый Run с теми же входными данными.
1. Пользователь выбирает START, задаёт уровень объяснения и виртуальный капитал, сохраняет ревизию
2. Передаёт вопрос и выбирает инструменты из демонстрационного набора
3. Агент получает определения и характеристики из разрешённых источников, отделяет известные условия от допущений
4. Симулятор строит учебный пример; агент объясняет результаты и при включённой настройке добавляет вопрос для самопроверки
5. Пользователь меняет глубину объяснения через форму и запускает новый Run с теми же входными данными
**Результат.** Сравнение инструментов, расшифровка терминов, учебный пример и ссылки на использованные материалы. Краткий и подробный режимы сохраняют одни и те же исходные факты.
**Результат.** Сравнение инструментов, расшифровка терминов, учебный пример и ссылки на использованные материалы. Краткий и подробный режимы сохраняют одни и те же исходные факты
**Если данных не хватает.** Агент обозначает отсутствующие характеристики и предлагает дополнить вход. Недоступность источника не заменяется выдуманным значением. Учебная цена или доходность явно помечается как условная.
**Если данных не хватает.** Агент обозначает отсутствующие характеристики и предлагает дополнить вход. Недоступность источника не заменяется выдуманным значением. Учебная цена или доходность явно помечается как условная
**Критерий приёмки.** Форма меняет стиль и детализацию ответа без редактирования prompt пользователем; расчёты симулятора воспроизводимы; отсутствуют инструменты размещения поручений. Минимальный запуск — локально с кешированным учебным набором; модель может требовать сеть.
**Критерий приёмки.** Форма меняет стиль и детализацию ответа без редактирования prompt пользователем; расчёты симулятора воспроизводимы; отсутствуют инструменты размещения поручений. Минимальный запуск — локально с кешированным учебным набором; модель может требовать сеть
## 2. GUARD — «Сохранить деньги»
**Пользователь и цель.** Инвестору нужны деньги к определённой дате. Он хочет увидеть концентрацию, сроки и неопределённость ликвидности своего портфеля. Пример: «Мне нужны деньги через девять месяцев. Какие позиции требуют внимания?».
**Пользователь и цель.** Инвестору нужны деньги к определённой дате. Он хочет увидеть концентрацию, сроки и неопределённость ликвидности своего портфеля. Пример: «Мне нужны деньги через девять месяцев. Какие позиции требуют внимания?»
**Состав.** DSH harness; плагины чтения портфеля, метаданных облигаций и сценарного расчёта (`portfolio_read`, `bond_metadata`, `rate_scenario`, `issuer_risk`), при регулярном запуске — `recurring-tasks`; скилл аудита портфеля.
**Состав.** DSH harness; плагины чтения портфеля, метаданных облигаций и сценарного расчёта (`portfolio_read`, `bond_metadata`, `rate_scenario`, `issuer_risk`), при регулярном запуске — `recurring-tasks`; скилл аудита портфеля
**Настройки формы.** `targetDate`, `requiredAmount`, `baseCurrency`, `maxDataAgeHours`, включение сценариев изменения ставки. Параметры стресс-сценария задаются явно. Расписание настраивается отдельной формой платформы с timezone, preview, overlap и misfire policy.
**Настройки формы.** `targetDate`, `requiredAmount`, `baseCurrency`, `maxDataAgeHours`, включение сценариев изменения ставки. Параметры стресс-сценария задаются явно. Расписание настраивается отдельной формой платформы с timezone, preview, overlap и misfire policy
**Ход сценария.**
1. Пользователь выбирает GUARD и загружает снимок портфеля либо подключает доступный read-only источник.
2. Задаёт дату потребности в деньгах и сумму; платформа фиксирует конфигурацию агента.
3. Плагин нормализует позиции, валюты и дату оценки, объединяет экспозиции одного эмитента.
4. Инструменты рассчитывают концентрацию и заданные сценарии; агент объясняет результаты с указанием недостающих данных.
5. Пользователь сохраняет отчёт. При необходимости включает еженедельный запуск и просматривает следующие срабатывания перед сохранением.
1. Пользователь выбирает GUARD и загружает снимок портфеля либо подключает доступный read-only источник
2. Задаёт дату потребности в деньгах и сумму; платформа фиксирует конфигурацию агента
3. Плагин нормализует позиции, валюты и дату оценки, объединяет экспозиции одного эмитента
4. Инструменты рассчитывают концентрацию и заданные сценарии; агент объясняет результаты с указанием недостающих данных
5. Пользователь сохраняет отчёт. При необходимости включает еженедельный запуск и просматривает следующие срабатывания перед сохранением
**Результат.** Сводка портфеля, концентрация по эмитентам и классам, сведения о сроках и ликвидности, сценарии и перечень пробелов. Для повторного обзора можно явно передать предыдущий результат; вывод об изменениях содержит обе даты оценки.
**Результат.** Сводка портфеля, концентрация по эмитентам и классам, сведения о сроках и ликвидности, сценарии и перечень пробелов. Для повторного обзора можно явно передать предыдущий результат; вывод об изменениях содержит обе даты оценки
**Если источник устарел или недоступен.** Отчёт обозначает возраст снимка; при превышении установленного порога задача не выдаёт его за актуальный обзор. Отзыв connection останавливает расписание с причиной. Низкая ликвидность не определяется только сроком погашения.
**Если источник устарел или недоступен.** Отчёт обозначает возраст снимка; при превышении установленного порога задача не выдаёт его за актуальный обзор. Отзыв connection останавливает расписание с причиной. Низкая ликвидность не определяется только сроком погашения
**Критерий приёмки.** Итоги на подготовленном портфеле совпадают с эталонными расчётами, отсутствующие сведения видимы. Повторная доставка одного occurrence не создаёт второй Run. Локальное расписание работает только при запущенном daemon; удалённое выполняется на выбранном Runner.
**Критерий приёмки.** Итоги на подготовленном портфеле совпадают с эталонными расчётами, отсутствующие сведения видимы. Повторная доставка одного occurrence не создаёт второй Run. Локальное расписание работает только при запущенном daemon; удалённое выполняется на выбранном Runner
## 3. GOAL — «Капитал под цель»
**Пользователь и цель.** Пользователь задаёт сумму и срок и хочет сравнить возможные планы накопления. Пример: «Какой ежемесячный взнос нужен для 3 млн рублей через семь лет?».
**Пользователь и цель.** Пользователь задаёт сумму и срок и хочет сравнить возможные планы накопления. Пример: «Какой ежемесячный взнос нужен для 3 млн рублей через семь лет?»
**Состав.** DSH harness; плагины `goal_calculator`, `scenario_engine` и графиков; скилл объяснения сценарных расчётов. Брокерское подключение необязательно; доходность и инфляция могут быть заданными пользователем допущениями.
**Состав.** DSH harness; плагины `goal_calculator`, `scenario_engine` и графиков; скилл объяснения сценарных расчётов. Брокерское подключение необязательно; доходность и инфляция могут быть заданными пользователем допущениями
**Настройки формы.** `targetAmount`, `targetDate`, `initialCapital`, `currency`, `contributionTiming`, массив сценариев с доходностью и инфляцией. Форма явно различает будущую номинальную сумму и сумму в сегодняшних ценах; не предлагает скрытого значения «ожидаемой доходности».
**Настройки формы.** `targetAmount`, `targetDate`, `initialCapital`, `currency`, `contributionTiming`, массив сценариев с доходностью и инфляцией. Форма явно различает будущую номинальную сумму и сумму в сегодняшних ценах; не предлагает скрытого значения «ожидаемой доходности»
**Ход сценария.**
1. Пользователь создаёт GOAL, заполняет цель и исходные параметры.
2. Валидатор отклоняет прошедшую дату, несовместимые валюты и неполные сценарии.
3. Калькулятор определяет периодичность, преобразует ставки по зафиксированной методике и рассчитывает взносы для каждого сценария.
4. Агент объясняет различия; график строится из результата калькулятора, а не из чисел, придуманных моделью.
5. Пользователь меняет срок или взнос через форму и получает новый расчёт, сохраняя предыдущую ревизию для сравнения.
1. Пользователь создаёт GOAL, заполняет цель и исходные параметры
2. Валидатор отклоняет прошедшую дату, несовместимые валюты и неполные сценарии
3. Калькулятор определяет периодичность, преобразует ставки по зафиксированной методике и рассчитывает взносы для каждого сценария
4. Агент объясняет различия; график строится из результата калькулятора, а не из чисел, придуманных моделью
5. Пользователь меняет срок или взнос через форму и получает новый расчёт, сохраняя предыдущую ревизию для сравнения
**Результат.** Таблица сценариев, требуемый взнос, траектории накопления, исходные допущения и методика. До появления встроенного chart-компонента достаточно таблицы и файла с рядами данных; интерактивный график — отдельная возможность UI.
**Результат.** Таблица сценариев, требуемый взнос, траектории накопления, исходные допущения и методика. До появления встроенного chart-компонента достаточно таблицы и файла с рядами данных; интерактивный график — отдельная возможность UI
**Если цель недостижима при заданном взносе.** Агент показывает расчётный разрыв и чувствительность к изменению параметров. Он не увеличивает допущение доходности молча и не представляет сценарии как прогноз рынка.
**Если цель недостижима при заданном взносе.** Агент показывает расчётный разрыв и чувствительность к изменению параметров. Он не увеличивает допущение доходности молча и не представляет сценарии как прогноз рынка
**Критерий приёмки.** Калькулятор корректно обрабатывает нулевую ставку, уже достигнутую цель, момент внесения взноса и номинальные/реальные суммы. Ответ и график используют один набор данных. Сценарий доступен локально без подключения брокера.
**Критерий приёмки.** Калькулятор корректно обрабатывает нулевую ставку, уже достигнутую цель, момент внесения взноса и номинальные/реальные суммы. Ответ и график используют один набор данных. Сценарий доступен локально без подключения брокера
## 4. PULSE — «Эксперты с доказательствами»
**Пользователь и цель.** Читатель хочет найти и сопоставить опубликованные взгляды автора. Пример: «Что автор писал о банках до отчётности и после неё?».
**Пользователь и цель.** Читатель хочет найти и сопоставить опубликованные взгляды автора. Пример: «Что автор писал о банках до отчётности и после неё?»
**Состав.** DSH harness; плагины `pulse_search`, `transcript_search`, `stance_timeline`, `conflict_checker`; скилл анализа источников. Для первого демо используется разрешённый набор публикаций с метаданными либо явно синтетический корпус. Живая интеграция с Пульсом требует отдельной проверки доступа.
**Состав.** DSH harness; плагины `pulse_search`, `transcript_search`, `stance_timeline`, `conflict_checker`; скилл анализа источников. Для первого демо используется разрешённый набор публикаций с метаданными либо явно синтетический корпус. Живая интеграция с Пульсом требует отдельной проверки доступа
**Настройки формы.** `authorIds`, временной интервал поиска, `answerDepth`, `includeContradictions`. Обязательность ссылок и запрет выдуманных цитат входят в политику шаблона и не выключаются пользовательской настройкой.
**Настройки формы.** `authorIds`, временной интервал поиска, `answerDepth`, `includeContradictions`. Обязательность ссылок и запрет выдуманных цитат входят в политику шаблона и не выключаются пользовательской настройкой
**Ход сценария.**
1. Пользователь выбирает автора и период, задаёт вопрос.
2. Поиск фильтрует разрешённый корпус по автору, датам и теме.
3. Инструменты возвращают фрагменты, идентификаторы публикаций, даты публикации/обновления и источник.
4. Агент разделяет факты и мнения, сопоставляет позиции во времени и показывает противоречия.
5. Пользователь открывает источник из ответа либо расширяет период и создаёт новый Run.
1. Пользователь выбирает автора и период, задаёт вопрос
2. Поиск фильтрует разрешённый корпус по автору, датам и теме
3. Инструменты возвращают фрагменты, идентификаторы публикаций, даты публикации/обновления и источник
4. Агент разделяет факты и мнения, сопоставляет позиции во времени и показывает противоречия
5. Пользователь открывает источник из ответа либо расширяет период и создаёт новый Run
**Результат.** Хронология тезисов с цитатами и источниками; отдельно — что найдено, что противоречит друг другу и чего подтвердить не удалось. Это поиск по высказываниям, а не выступление от имени живого автора.
**Результат.** Хронология тезисов с цитатами и источниками; отдельно — что найдено, что противоречит друг другу и чего подтвердить не удалось. Это поиск по высказываниям, а не выступление от имени живого автора
**Если подтверждения нет.** Агент сообщает, что позиция не найдена в выбранном корпусе и периоде. Старая публикация не превращается в утверждение о сегодняшней рекомендации. Команды внутри найденных текстов не получают полномочий управлять агентом.
**Если подтверждения нет.** Агент сообщает, что позиция не найдена в выбранном корпусе и периоде. Старая публикация не превращается в утверждение о сегодняшней рекомендации. Команды внутри найденных текстов не получают полномочий управлять агентом
**Критерий приёмки.** Каждая цитата совпадает с фрагментом корпуса, автор и дата атрибутированы правильно. Тестовый конфликт показывает обе позиции; запрос без источника не порождает выдуманный ответ. Разрешения корпуса проверяются и в локальном, и в удалённом режиме.
**Критерий приёмки.** Каждая цитата совпадает с фрагментом корпуса, автор и дата атрибутированы правильно. Тестовый конфликт показывает обе позиции; запрос без источника не порождает выдуманный ответ. Разрешения корпуса проверяются и в локальном, и в удалённом режиме
## 5. PRO — «Исследовательская панель»
**Пользователь и цель.** Аналитик хочет сократить сбор отчётности и расчёт сопоставимых показателей. Пример: «Сравни выбранные банки по ROE, капиталу и динамике маржи за один период».
**Пользователь и цель.** Аналитик хочет сократить сбор отчётности и расчёт сопоставимых показателей. Пример: «Сравни выбранные банки по ROE, капиталу и динамике маржи за один период»
**Состав.** DSH harness; плагины чтения документов, `statements_RAG`, `calculate_metrics`, графиков; опциональный read-only адаптер брокерских данных; скилл анализа отчётности. Идентификаторы инструментов — проектируемые контракты, а не утверждение о наличии готового MCP-сервера.
**Состав.** DSH harness; плагины чтения документов, `statements_RAG`, `calculate_metrics`, графиков; опциональный read-only адаптер брокерских данных; скилл анализа отчётности. Идентификаторы инструментов — проектируемые контракты, а не утверждение о наличии готового MCP-сервера
**Настройки формы.** `entityIds`, отчётный период, стандарт отчётности, валюта представления, `metricIds`, `checklistVersionId`, `sourcePolicy`. В первой версии пользователь выбирает проверенные формулы и чек-листы. Загрузка произвольного исполняемого кода формулы требует отдельного пакета, проверки и разрешений.
**Настройки формы.** `entityIds`, отчётный период, стандарт отчётности, валюта представления, `metricIds`, `checklistVersionId`, `sourcePolicy`. В первой версии пользователь выбирает проверенные формулы и чек-листы. Загрузка произвольного исполняемого кода формулы требует отдельного пакета, проверки и разрешений
**Ход сценария.**
1. Аналитик выбирает PRO, документы и набор показателей, сохраняет параметры через форму.
2. При конфиденциальных материалах выбирает локальный или on-prem Runner и модель, разрешённую политикой передачи данных.
3. Поиск находит строки документов с привязкой к страницам; нормализатор проверяет период, единицы, стандарт и периметр консолидации.
4. Калькулятор вычисляет показатели по выбранной версии методики. Агент формирует интерпретацию и перечисляет ограничения сравнения.
5. Результат сохраняется как отчёт, таблица расчётов и использованные ссылки. Повторное исследование закрепляет новый снимок входных данных.
1. Аналитик выбирает PRO, документы и набор показателей, сохраняет параметры через форму
2. При конфиденциальных материалах выбирает локальный или on-prem Runner и модель, разрешённую политикой передачи данных
3. Поиск находит строки документов с привязкой к страницам; нормализатор проверяет период, единицы, стандарт и периметр консолидации
4. Калькулятор вычисляет показатели по выбранной версии методики. Агент формирует интерпретацию и перечисляет ограничения сравнения
5. Результат сохраняется как отчёт, таблица расчётов и использованные ссылки. Повторное исследование закрепляет новый снимок входных данных
**Результат.** Сравнительная таблица, формулы и исходные числа со ссылками на страницы, графики при наличии UI capability, список несопоставимых или отсутствующих значений.
**Результат.** Сравнительная таблица, формулы и исходные числа со ссылками на страницы, графики при наличии UI capability, список несопоставимых или отсутствующих значений
**Если документы несопоставимы.** Показатель маркируется как несопоставимый или нерассчитанный; отсутствие данных не заменяется нулём. При недоступности своего Runner задача не переносится в облачный пул автоматически. Само размещение Runner on-prem не разрешает отправлять документы внешней модели.
**Если документы несопоставимы.** Показатель маркируется как несопоставимый или нерассчитанный; отсутствие данных не заменяется нулём. При недоступности своего Runner задача не переносится в облачный пул автоматически. Само размещение Runner on-prem не разрешает отправлять документы внешней модели
**Критерий приёмки.** На подготовленном наборе документов расчёты совпадают с эталоном в заранее заданной погрешности; каждое исходное число имеет источник. Переключение на совместимый свой Runner сохраняет контракт входа/выхода и не расширяет доступы.
**Критерий приёмки.** На подготовленном наборе документов расчёты совпадают с эталоном в заранее заданной погрешности; каждое исходное число имеет источник. Переключение на совместимый свой Runner сохраняет контракт входа/выхода и не расширяет доступы
## Связь с реализацией платформы
Финансовые инструменты перечисленных шаблонов расширяют [линейку плагинов](plugins.md), но не становятся частью диспетчера. Сначала можно реализовать один ручной запуск с подготовленными данными; расписания, графики и удалённое исполнение подключаются по мере готовности соответствующих компонентов.
Финансовые инструменты перечисленных шаблонов расширяют [линейку плагинов](plugins.md), но не становятся частью диспетчера. Сначала можно реализовать один ручной запуск с подготовленными данными; расписания, графики и удалённое исполнение подключаются по мере готовности соответствующих компонентов
| Возможность | Где определён контракт |
|---|---|
@@ -145,4 +145,4 @@
| Локальный и заменяемый Runner | [Исполнение](execution.md), [Runner Protocol](api/executor-api.md) |
| Этапы платформы | [Roadmap](roadmap.md) |
Успешный Run означает, что результат принят по техническому контракту. Финансовая корректность, точность цитат и понятность объяснений проверяются отдельными эталонными задачами каждого шаблона. Числа из примеров — входы демонстрации, а не обещания доходности или измеренные результаты продукта.
Успешный Run означает, что результат принят по техническому контракту. Финансовая корректность, точность цитат и понятность объяснений проверяются отдельными эталонными задачами каждого шаблона. Числа из примеров — входы демонстрации, а не обещания доходности или измеренные результаты продукта
+12 -12
View File
@@ -2,36 +2,36 @@
## Идентичность и роли
Tenant — персональное или организационное пространство. Роли: owner управляет доступами и удалением; admin — настройками и Runner; publisher — публикацией пакетов; operator — запуском и отменой доступных агентов; viewer — чтением разрешённых ресурсов. Сервер получает tenant из проверенного membership, а не доверяет tenantId в запросе. Каждый доступ к agent, run, package, connection и artifact проверяется отдельно.
Tenant — персональное или организационное пространство. Роли: owner управляет доступами и удалением; admin — настройками и Runner; publisher — публикацией пакетов; operator — запуском и отменой доступных агентов; viewer — чтением разрешённых ресурсов. Сервер получает tenant из проверенного membership, а не доверяет tenantId в запросе. Каждый доступ к agent, run, package, connection и artifact проверяется отдельно
Identity в MVP — модуль Platform API с существующими механизмами аккаунтов и сессий; внешний OIDC подключается при необходимости. Web использует HttpOnly Secure SameSite cookie и CSRF-защиту мутаций. CLI использует ограниченный токен; device authorization добавляется при поддержке identity-провайдером. Подписанный токен проверяется по issuer, audience, expiry и revocation policy.
Identity в MVP — модуль Platform API с существующими механизмами аккаунтов и сессий; внешний OIDC подключается при необходимости. Web использует HttpOnly Secure SameSite cookie и CSRF-защиту мутаций. CLI использует ограниченный токен; device authorization добавляется при поддержке identity-провайдером. Подписанный токен проверяется по issuer, audience, expiry и revocation policy
## Исполнители
Владелец tenant создаёт одноразовый registration grant для пула. Runner обменивает grant на собственную служебную идентичность. Отзыв блокирует новые задания и доступы. Capabilities — заявление исполнителя, а не доказательство изоляции; управляемые пулы проходят conformance checks. Пользовательские пулы явно маркируются как customer-managed.
Владелец tenant создаёт одноразовый registration grant для пула. Runner обменивает grant на собственную служебную идентичность. Отзыв блокирует новые задания и доступы. Capabilities — заявление исполнителя, а не доказательство изоляции; управляемые пулы проходят conformance checks. Пользовательские пулы явно маркируются как customer-managed
Каждому Attempt выдаётся короткоживущий токен с runId, attemptId, tenantId, leaseEpoch, audience и scope. Он не предоставляет чтение чужих Run и доступ к администрированию. Сервер проверяет активность lease при чувствительных операциях.
Каждому Attempt выдаётся короткоживущий токен с runId, attemptId, tenantId, leaseEpoch, audience и scope. Он не предоставляет чтение чужих Run и доступ к администрированию. Сервер проверяет активность lease при чувствительных операциях
## Секреты и интеграции
ConnectionRef указывает на запись подключения. Для server_vault секрет хранится с envelope encryption, ключ расшифровки управляется KMS. local_keychain и runner_private_store хранят секрет только в выбранной среде; сервер видит ссылку и состояние подключения. Значения не попадают в config, логи, схемы, артефакты и signed URL. Доступ ограничивается интеграцией и операцией. Шлюз по возможности вызывает API сам; для прямого доступа выдаются scoped credentials или секрет монтируется только в окружение конкретной попытки.
ConnectionRef указывает на запись подключения. Для server_vault секрет хранится с envelope encryption, ключ расшифровки управляется KMS. local_keychain и runner_private_store хранят секрет только в выбранной среде; сервер видит ссылку и состояние подключения. Значения не попадают в config, логи, схемы, артефакты и signed URL. Доступ ограничивается интеграцией и операцией. Шлюз по возможности вызывает API сам; для прямого доступа выдаются scoped credentials или секрет монтируется только в окружение конкретной попытки
Own Runner имеет техническую возможность прочитать выданные ему credentials; эта граница доверия показывается владельцу при назначении подключений. Отзыв токена платформы не отзывает уже раскрытый сторонний ключ: для этого нужен revoke у провайдера.
Own Runner имеет техническую возможность прочитать выданные ему credentials; эта граница доверия показывается владельцу при назначении подключений. Отзыв токена платформы не отзывает уже раскрытый сторонний ключ: для этого нужен revoke у провайдера
## Изоляция
Управляемое выполнение: отдельная рабочая директория и контейнер, non-root, лимиты CPU/RAM/PIDs/диска/времени, отсутствие host mounts, privileged mode и Docker socket внутри job. Сетевые политики ограничивают обращения к внутренним адресам и metadata endpoints. Для недоверенного кода выбирается усиленный sandbox runtime; один обычный контейнер не считается полной защитой от побега.
Управляемое выполнение: отдельная рабочая директория и контейнер, non-root, лимиты CPU/RAM/PIDs/диска/времени, отсутствие host mounts, privileged mode и Docker socket внутри job. Сетевые политики ограничивают обращения к внутренним адресам и metadata endpoints. Для недоверенного кода выбирается усиленный sandbox runtime; один обычный контейнер не считается полной защитой от побега
Runner Protocol не навязывает реализацию sandbox, но диспетчер не назначает защищённые задачи пулу без нужной trust policy. Невозможность обеспечить ограничение должна приводить к отказу до запуска.
Runner Protocol не навязывает реализацию sandbox, но диспетчер не назначает защищённые задачи пулу без нужной trust policy. Невозможность обеспечить ограничение должна приводить к отказу до запуска
## Аудит и данные
Аудит: actor, tenant, action, resource, result, timestamp, requestId. Без содержимого prompts и secrets по умолчанию. История публикаций, выдачи credentials, назначения, отмены, обновления настроек и изменений прав сохраняется отдельно от debug-логов.
Аудит: actor, tenant, action, resource, result, timestamp, requestId. Без содержимого prompts и secrets по умолчанию. История публикаций, выдачи credentials, назначения, отмены, обновления настроек и изменений прав сохраняется отдельно от debug-логов
Удаление tenant сначала блокирует новые запуски, отзывает доступ, останавливает задачи и удаляет данные по retention policy. Backup retention и сроки окончательного удаления явно сообщаются пользователю. Публичность пакета не распространяется на Run, connections или результаты.
Удаление tenant сначала блокирует новые запуски, отзывает доступ, останавливает задачи и удаляет данные по retention policy. Backup retention и сроки окончательного удаления явно сообщаются пользователю. Публичность пакета не распространяется на Run, connections или результаты
## Подключения аккаунтов провайдеров
Вход в Invest Harness не равен входу в аккаунт модели. Допустимый способ авторизации проверяется отдельно для провайдера и deployment mode. Собственный OAuth используется только при поддерживаемой регистрации приложения; credentials официальных клиентов не извлекаются и не копируются на сервер. Подробности: [плагины](plugins.md), [Provider API](api/provider-api.md).
Вход в Invest Harness не равен входу в аккаунт модели. Допустимый способ авторизации проверяется отдельно для провайдера и deployment mode. Собственный OAuth используется только при поддерживаемой регистрации приложения; credentials официальных клиентов не извлекаются и не копируются на сервер. Подробности: [плагины](plugins.md), [Provider API](api/provider-api.md)
Conformance собственного Runner проверяет протокол, но не доказывает защищённость чужой машины. Администратор явно утверждает trust policy пула. Доступы плагинов ограничены actor/tenant/Run; установка discovery-плагина не разрешает ему автоматически исполнять найденный пакет.
Conformance собственного Runner проверяет протокол, но не доказывает защищённость чужой машины. Администратор явно утверждает trust policy пула. Доступы плагинов ограничены actor/tenant/Run; установка discovery-плагина не разрешает ему автоматически исполнять найденный пакет