Source: live external MCP run against ss-prod Sales Dashboard (docs/2026-09-07-sales-prod-mcp-run.md) proved the initial-bootstrap chain externally unreachable: register_draft_pack requires a principal-owned AgentRun but no MCP operation created one after the chat decommission; the vertical E2E masked the gap with a raw-ORM prerequisite seed. T029i: MCP create_agent_run/get_agent_run (mcp_server/tools_agent_run.py) over Services.AgentRuns.Service.Create — REST-parity EXECUTE/READ permissions, human-only, server-pinned UIContext, idempotency-key replay; catalog 2.1.0->2.2.0; MCPX-FR-027 external-reachability invariant pinned; initial-scenario E2E converted to the fully external chain (zero non-MCP seeding); strict-xfail pin flipped as designed, unmarked and hardened (E2E-EXT-001 CLOSED). T029k: ScenarioGraph.CapabilityAuthority — truthful capability facts derived from the authoritative DashboardQueryModel (mutation-context capabilities never derived), derived-wins merge over caller declarations, single choke point wired into MCP inspect_scenario / inspect_dashboard_context and REST api_compile_scenario; CAP-001 classification-fix test on the sales-shape fixture (B02-B04/T01-T03 automated, C04-C06 unsupported, unsafe-mutation cases legitimately human). T029l: disposition vocabulary clarity — RU/EN labels name the persisted outcome (confirm->passed), confirm restyled bg-destructive->bg-primary, decide_checkpoint description carries the immutable outcome table; lifecycle mapping and API vocabulary unchanged (DISP-001 CLOSED). Decision memory: ADR-0024 (IMPLEMENTED, 4 rejected alternatives incl. no-AgentRun boundary and implicit auto-create) + README registry; 050 MCPX-FR-027/028/029 + release-gate rows + Clarifications session 2026-09-07; 038/044/045 field-run amendments -> IMPLEMENTED; WORKSTATE checkpoints (plan round + execution round). Pre-existing HEAD regressions surfaced by the first full-suite rerun since 4d5ef6be/58c5ae39 and fixed: (1) stale SC-007 resource pin — canonical identifier is the post-redirect /mcp/ (code + twin pin aligned since the batches; test_mcp_client_flow_http pin updated with rationale); (2) app-lifespan tests re-entered the run-once StreamableHTTPSessionManager module singleton — autouse fresh-transport-app fixture (production lifespan runs once per process; singleton stays correct there). Gates: full backend suite 11357 passed / 243 skipped / 1 xpassed / 0 failed (first green full run since the batches); MCP+catalog slice 70 passed; capability slice 67 passed; frontend vitest 3507 passed (206 files), lint 0 errors (364 baseline warnings), build OK; ruff/compileall clean; anchors balanced; scoped git diff --check clean. INV_7 watch: tools_scenario.py 508 LOC and routes scenario.py 442 LOC flagged for the next decomposition pass (new code lives in new modules 155/236 LOC). OPEN: T029m / E2E-EXT-002 — live-stand replay of the sales scenario through the full external chain. Not included (foreign uncommitted workstream): translate/migration integration tests, _job_routes.py, .kilo/agent-manager.json, specs-036-050-20260907-111314.md.
55 lines
9.2 KiB
Markdown
55 lines
9.2 KiB
Markdown
# Реестр архитектурных решений
|
||
|
||
ADR фиксирует принятое и проверяемое архитектурное решение. Это не план работ и
|
||
не каталог желаемой архитектуры: обещание, которое ещё не реализовано, должно
|
||
иметь статус `PROPOSED` или быть вынесено в spec.
|
||
|
||
## Статусы
|
||
|
||
| Статус | Значение |
|
||
|---|---|
|
||
| `ACCEPTED` | Решение действует и соответствует реализации. |
|
||
| `PARTIALLY IMPLEMENTED` | Направление принято, но в репозитории есть существенная незавершённая часть. |
|
||
| `SUPERSEDED` | Решение заменено указанным ADR; исторический файл не меняет действующую архитектуру. |
|
||
| `REJECTED` | Альтернатива запрещена; это не описание действующей реализации. |
|
||
| `PROPOSED` | Решение обсуждается и не должно считаться обязательным. |
|
||
|
||
## Актуальный реестр
|
||
|
||
| ADR | Статус | Проверенное содержание |
|
||
|---|---|---|
|
||
| [0001](ADR-0001-module-layout.md) | `PARTIALLY IMPLEMENTED` | Базовое разделение backend/frontend/docs/specs сохранено; точная схема файла устарела. |
|
||
| [0002](ADR-0002-semantic-protocol.md) | `ACCEPTED` | Семантические skills и контракты в исходном коде остаются правилом репозитория. |
|
||
| [0003](ADR-0003-orchestrator-pattern.md) | `ACCEPTED` | Сервис остаётся внешним оркестратором Superset. |
|
||
| [0004](ADR-0004-plugin-architecture.md) | `SUPERSEDED` | Заменён ADR-0016: исходный subprocess/TOML-контракт не был реализован. |
|
||
| [0005](ADR-0005-auth-rbac.md) | `ACCEPTED` | Локальная аутентификация, RBAC и ADFS JIT provisioning реализованы. |
|
||
| [0006](ADR-0006-frontend-architecture.md) | `ACCEPTED` | Svelte 5, Screen Models и UI atoms применяются в frontend. |
|
||
| [0007](ADR-0007-rejected-fromStore-derived.md) | `REJECTED` | Комбинация `fromStore` с несколькими `$derived` запрещена. |
|
||
| [0008](ADR-0008-assistant-tool-registry.md) | `ACCEPTED` | Декораторный registry реализован в `backend/src/api/routes/assistant/_tool_registry.py`. |
|
||
| [0009](ADR-0009-ssl-certificate-management.md) | `ACCEPTED` | Управление корпоративными CA реализовано в Docker и HTTP-клиентах. |
|
||
| [0010](ADR-0010-model-decomposition-gate.md) | `ACCEPTED` | Порог декомпозиции Screen Model остаётся архитектурным ограничением. |
|
||
| [0011](ADR-0011-async-backend.md) | `PARTIALLY IMPLEMENTED` | Async Task Manager, EventBus и bounded executors внедрены; утверждение о полном отказе от sync-кода не подтверждено. |
|
||
| [0012](ADR-0012-superset-testcontainers.md) | `ACCEPTED` | Интеграционные Superset-тесты используют Postgres, init/web контейнеры и `superset_config.py`. |
|
||
| [0013](ADR-0013-coverage-reporting.md) | `ACCEPTED` | `scripts/coverage-summary.sh` существует и собирает сводный отчёт. |
|
||
| [0014](ADR-0014-agent-source-copy-strategy.md) | `SUPERSEDED` | Заменён [ADR-0015](ADR-0015-agent-shared-package-boundaries.md). |
|
||
| [0015](ADR-0015-agent-shared-package-boundaries.md) | `SUPERSEDED` | Заменён ADR-0022: agent-контейнер удалён, второй runtime исчез. |
|
||
| [0016](ADR-0016-in-process-plugin-runtime.md) | `ACCEPTED` | Плагины загружаются в процессе из `backend/src/plugins` через `PluginBase`. |
|
||
| [0017](ADR-0017-agent-centric-logging.md) | `ACCEPTED` | Agent-centric traces achieved by editing call sites (meaningful intents, removal of per-request noise) rather than only adding complexity to the logger. |
|
||
| [0018](ADR-0018-rejected-dataset-review.md) | `REJECTED` | Dataset Review is removed from the active product; `specs/027-dataset-llm-orchestration/` is retained only as archived history. |
|
||
| [0019](ADR-0019-dashboard-import-mechanism.md) | `ACCEPTED` | UUID-трансформация БД (не strip_databases), cross-filter patching через IdMappingService, password injection flow (await_input→wait_for_input→retry), разделение dry-run/execute, парсинг имён YAML-файлов БД. |
|
||
| [0020](ADR-0020-maintenance-virtual-dataset-discovery.md) | `ACCEPTED` | Обнаружение виртуальных (SQL) датасетов в maintenance discovery через серверный фильтр `sql is_not_null` (fallback — клиентский скан по непустому `sql`); `AsyncAPIClient.request` поднимает не-2xx ответы (`raise_for_status`); sqlparse token-limit (10000) fallback к regex-only для гигантских виртуальных датасетов. |
|
||
| [0021](ADR-0021-self-diagnosing-explore.md) | `ACCEPTED` | Самодиагностируемый EXPLORE: опциональные `contract_id`/`claim`/`error_code`/`loc` в wire-формате; токен-экономика (payload-cap 2KB, heartbeat-правило, bond-метрики единым движком `src/core/log_stats.py`); ground-truth триангуляция task-log-gaps (T1/T2/T3); детекция тихих отказов — только в axiom-mcp (`BELIEF_SILENT_*`), без pytest-гейта. |
|
||
| [0022](ADR-0022-absorb-shared-into-backend.md) | `ACCEPTED` | Пакет `shared/` поглощён backend'ом после удаления агента: `cot_logger` → `src/core/`, `CotJsonFormatter` → `src/core/cot_formatter.py`, `_llm_*`/`ssl` → `src/core/utils/`; единый фасад `src/core/logger.py`; run.sh/Dockerfile без `pip install -e ../shared`. |
|
||
| [0023](ADR-0023-mcp-scenario-pipeline-handle-gap.md) | `IMPLEMENTED` | MCP-стадии inspect/compile/validate/resolve/draft-pack изначально не создавали серверные `*Handle`, а `create_scenario`/`create_initial` писали в `graph_snapshot` только provenance-метаданные (риск вакуумного false PASS, закрыт guard'ом `BOOTSTRAP_REVISION_NOT_RUNNABLE`). Реализован полный handle-слой: `CompiledScenarioHandle`/`ValidationResultHandle`/`DraftPackHandle` (migrations 0019–0021), canonical-bytes authority, single consumption под `FOR UPDATE` (PostgreSQL-proven), материализация графа в create-транзакции, outbox-worker в scheduler poll loop, MCP `register_draft_pack` + handle-only bootstrap, гибрид T029h (`inspect_dashboard_context` + `context_authority` binding + PROD gate). Guard демотирован до defense-in-depth. |
|
||
| [0024](ADR-0024-mcp-agent-run-external-boundary.md) | `IMPLEMENTED` | Полевой MCP-прогон 2026-09-07 (ss-prod Sales Dashboard) доказал: `register_draft_pack` требует principal-owned `AgentRun`, но после демонтажа чата (050 T041) ни одна MCP-операция его не создаёт — external initial-bootstrap цепочка недостижима, хотя все звенья реализованы. Вертикальный E2E маскировал разрыв raw-ORM-seed'ом предусловия. Реализовано в тот же день: MCP `create_agent_run`/`get_agent_run` (`tools_agent_run.py`, каталог 2.2.0, EXECUTE/READ human-only), инвариант внешней достижимости MCPX-FR-027 с hard-green пином (`test_mcp_agent_run_reachability.py`), test-honesty remediation (E2E-вертикаль конвертирована в fully external chain, zero non-MCP seeding), companion-gaps T029k (derived capabilities, CAP-001) и T029l (disposition clarity, DISP-001). Полные гейты: backend 11357 passed / frontend 3507 passed. Open: live-stand replay E2E-EXT-002 (T029m). |
|
||
|
||
## Правила сопровождения
|
||
|
||
1. Новый ADR добавляется только для решения, которое меняет границу модулей,
|
||
runtime/topology, безопасность, данные или постоянный способ разработки.
|
||
2. Каждый ADR содержит контекст, решение, последствия и отклонённые альтернативы.
|
||
3. При изменении решения создаётся новый ADR со ссылкой на заменённый, а прежний
|
||
получает `SUPERSEDED`; историю не переписывают.
|
||
4. В ADR указываются существующие пути и проверяемые факты. Версии, пороги и
|
||
команды обновляются вместе с кодом либо заменяются ссылкой на источник истины.
|