commit 37f058938c88b7ba1bd56331c60d1b693833af40 Author: ochenstarik-ui <267932263+ochenstarik-ui@users.noreply.github.com> Date: Sun Jul 19 23:04:04 2026 +0700 [verified] docs: add Agent Control Center specification diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d50e94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Secrets and local configuration +.env +.env.* +!.env.example +*.pem +*.key +*.p12 +secrets/ + +# Editors / OS +.idea/ +.vscode/ +.DS_Store +Thumbs.db + +# Build, cache and local state +node_modules/ +dist/ +build/ +coverage/ +.cache/ +.tmp/ +.omo/ +*.log +__pycache__/ +*.py[cod] +.venv/ + +# Specification rendering artifacts +*.tmp.docx +*.tmp.pdf diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..90e9edd --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# Contribution policy + +Проект находится на стадии спецификации. + +## До утверждения v1 + +Разрешены только изменения требований, архитектуры, исследований, ADR и validation tooling. Реализация продукта блокирована до явного operator approval и G1 PASS. + +## Правила изменений + +1. Каждое функциональное требование получает стабильный ID и acceptance test ID. +2. Изменение security boundary, API, данных, retention или integration contract требует обновить traceability и соответствующий ADR/open question. +3. Источники для внешних API должны быть официальными, с датой проверки. +4. Нельзя коммитить credentials, tokens, private keys, session exports или реальные пользовательские данные. +5. Перед локальным commit спецификационных изменений: structural validation, secret scan, `git diff --cached --check` и independent peer review точного staged-кандидата. Термин G2 зарезервирован за implementation gate из `SPECIFICATION.md` §12.3. +6. Local commit не означает разрешение на push; публикация проходит отдельный pre-publish gate. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1687599 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Agent Control Center + +Единое рабочее пространство для управления проектами, задачами и серверными ИИ-агентами с Web-, Desktop- и Android-клиентами. + +## Статус + +**Specification Draft v0.1.0 — implementation blocked.** + +Репозиторий содержит требования и архитектурный baseline. Он не содержит реализации и не даёт разрешения начинать разработку. Перед реализацией обязательны: + +1. закрытие блокирующих открытых решений; +2. утверждение спецификации оператором; +3. G1 requirement-completeness PASS; +4. отдельная явная команда на implementation. + +## Документы + +- [Каноническое ТЗ](docs/SPECIFICATION.md) +- [Архитектура](docs/ARCHITECTURE.md) +- [Исследование интеграций](docs/RESEARCH.md) +- [Матрица трассируемости](docs/TRACEABILITY.md) +- [Открытые решения](docs/OPEN-QUESTIONS.md) +- [Правила участия](CONTRIBUTING.md) + +## Ключевой принцип + +Agent Control Center не пытается унифицировать внутреннее устройство Hermes, OpenClaw, Claude Code, Codex, ChatGPT/OpenAI и Gemini. Серверный Connector подключает каждый runtime через версионируемый адаптер, публикующий нормализованные capabilities, события, checkpoints и usage-сигналы. + +## Предлагаемый MVP + +- Web/PWA, desktop wrapper и Android-клиент с общим интерфейсным ядром; +- рабочие пространства, проекты, Kanban-задачи и артефакты; +- реестр серверов, агентов и их capabilities; +- запуск, наблюдение, остановка и ручной handoff работы между агентами; +- общая проектная память, версионируемые skills и wiki; +- квоты/лимиты, approvals, аудит и безопасный outbound-only Connector. + +## Лицензия + +Лицензия пока не выбрана. Репозиторий приватный; отсутствие файла `LICENSE` означает отсутствие предоставленной публичной лицензии. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..a9e2df6 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,208 @@ +# Архитектура Agent Control Center + +**Версия:** 0.1.0-draft +**Дата:** 2026-07-19 +**Нормативность:** supporting architecture; при конфликте приоритет у `SPECIFICATION.md`. + +## 1. Контекст + +Система разделяется на центральный Control Plane и один или несколько Connector, установленных рядом с серверными агентами. Клиенты не подключаются к агентам напрямую. Connector устанавливает исходящее mTLS/WebSocket-соединение, поэтому MVP не требует открывать входящий порт на каждом сервере агента. + +```mermaid +flowchart LR + W[Web / PWA] -->|HTTPS + WSS| API[Control Plane API] + D[Desktop] -->|HTTPS + WSS| API + M[Android] -->|HTTPS + WSS| API + API --> IAM[Identity & Policy] + API --> CORE[Projects / Tasks / Runs] + API --> CTX[Context Broker] + API --> REG[Memory / Skills / Wiki] + CORE --> BUS[Durable Event Bus] + CTX --> BUS + BUS --> GW[Connector Gateway] + GW <-->|outbound mTLS WSS| C1[Server Connector] + C1 --> H[Hermes adapter] + C1 --> O[OpenClaw adapter] + C1 --> C[Claude adapter] + C1 --> X[Codex adapter] + C1 --> G[Gemini adapter] + C1 --> P[Generic API/CLI/MCP adapter] + CORE --> PG[(PostgreSQL)] + REG --> OBJ[(Object Storage)] + REG --> VEC[(Vector Index)] +``` + +## 2. Клиенты + +Предлагаемый baseline, подлежащий утверждению ADR: + +- **UI core:** React + TypeScript, responsive design, offline-capable read cache. +- **Web:** PWA, основной административный клиент. +- **Desktop:** Tauri wrapper для native notifications, secure local storage и controlled file pickers. +- **Android:** Capacitor wrapper над тем же UI core; native bridge только для push, biometrics, share/open-file и encrypted storage. + +Запрещено помещать provider/server credentials в web bundle. Desktop/Android хранят только refresh credential устройства в OS keystore. Все provider credentials остаются на Connector или в серверном secret manager. + +## 3. Control Plane компоненты + +| Компонент | Ответственность | Не отвечает за | +|---|---|---| +| API Gateway | REST/WS, schema validation, idempotency, rate limits | бизнес-оркестрацию | +| Identity & Policy | OIDC/local bootstrap, RBAC/ABAC, device sessions, approvals | provider auth внутри Connector | +| Project Service | workspaces, projects, tasks, dependencies, artifacts | запуск runtime | +| Run Orchestrator | run state machine, leases, retries, cancel, handoff | интерпретацию vendor payload | +| Connector Gateway | регистрацию Connector, command/event delivery, health | исполнение adapter process | +| Context Broker | сбор bounded context bundle, redaction, token budgeting | хранение скрытого chain-of-thought | +| Memory Service | scoped/versioned memory, provenance, conflicts, retrieval | автоматическое объявление непроверенных выводов фактами | +| Skill Registry | immutable versions, review/signature state, compatibility | молчаливое выполнение skill-кода | +| Wiki Service | Markdown pages, versions, links, search | замена source artifacts | +| Usage Service | нормализованные usage/quota/budget signals | обещание точного остатка при отсутствии API | +| Audit Service | append-only security and lifecycle events | хранение секретов и полного sensitive content | +| Notification Service | in-app/push/email hooks, dedupe | authoritative task state | + +## 4. Connector + +### 4.1 Trust boundary + +Connector — отдельный сервис с уникальной identity и минимальными правами. Он: + +1. устанавливает только исходящее соединение; +2. исполняет команды с lease/idempotency key; +3. запускает adapters в отдельных OS identities/containers, где возможно; +4. не передаёт секреты в Control Plane; +5. redacts события до отправки; +6. хранит короткий encrypted spool при разрыве связи; +7. не принимает новый destructive action без policy/approval token. + +### 4.2 Agent Adapter Protocol (AAP) + +Версионированный внутренний контракт: + +```text +handshake() -> identity, adapter_version, runtime_version, capabilities +health() -> status, latency, active_runs +start(run_spec, context_bundle, approval_token?) -> native_run_ref +stream(native_run_ref, cursor) -> ordered normalized events +checkpoint(native_run_ref, reason) -> observable checkpoint +cancel(native_run_ref, mode) -> outcome +resume(native_run_ref | checkpoint) -> outcome +usage(scope) -> measured|estimated|unknown signal +artifacts(native_run_ref) -> metadata + content references +``` + +Обязательные envelope-поля: `schema_version`, `connector_id`, `agent_id`, `run_id`, `event_id`, `sequence`, `occurred_at`, `classification`, `payload`, `vendor_extension`. Команды идемпотентны; события дедуплицируются по `(connector_id,event_id)`. + +Capabilities включают как минимум: `stream`, `cancel`, `native_resume`, `checkpoint`, `approvals`, `tools`, `mcp`, `artifacts`, `usage_exact`, `usage_estimated`, `filesystem_scope`, `structured_output`. Отсутствующая capability никогда не симулируется молча. + +## 5. Run и handoff state machine + +```mermaid +stateDiagram-v2 + [*] --> queued + queued --> dispatching + dispatching --> running + running --> waiting_approval + waiting_approval --> running + running --> checkpointing + checkpointing --> handoff_ready + handoff_ready --> dispatching: target selected + running --> succeeded + running --> failed + running --> cancelling + cancelling --> cancelled + dispatching --> blocked + handoff_ready --> blocked + blocked --> handoff_ready: user requests target selection +``` + +Handoff — новая attempt в рамках той же TaskRun lineage, а не перенос непрозрачной provider session. Handoff bundle содержит objective, acceptance criteria, bounded conversation, verified memory, decisions, completed/pending work, artifact refs, observed errors и provenance. Target adapter подтверждает ingestion; только после этого lease предыдущего attempt закрывается. + +Автоматический fallback в MVP может **предложить** target, но не запускает платный или более привилегированный runtime без policy и, где требуется, user approval. Из `blocked` пользователь возвращает run в `handoff_ready`, чтобы выбрать совместимый target, либо явно отменяет run через обычный cancel flow. + +## 6. Общий контекст + +### 6.1 Scopes + +`organization -> workspace -> project -> task -> run`; отдельно существуют `user-private` и `agent-private`. Более узкая область наследует разрешённые записи широкой области, но не наоборот. + +### 6.2 Memory entry + +Поля: `id`, `scope`, `kind`, `content`, `summary`, `provenance`, `confidence`, `verification_state`, `sensitivity`, `valid_from`, `valid_until`, `supersedes`, `acl`, `created_by`, `created_at`, `content_hash`. + +Kinds: fact, decision, constraint, preference, lesson, entity, artifact_reference, run_summary. Непроверенный вывод агента имеет `verification_state=unverified`; conflict не перезаписывается, а создаёт новую версию и conflict record. + +### 6.3 Skills + +Skill package содержит manifest, Markdown instructions, optional assets/scripts, compatibility, permissions, provenance, digest, signature/review state. Версии immutable. Активация executable части требует policy review; downloaded/untrusted package по умолчанию quarantined. + +### 6.4 Wiki + +Markdown source, immutable revisions, backlinks, aliases, attachments, ACL и full-text/semantic search. Автосформированная страница сначала draft и показывает источники; публикация в authoritative namespace требует review. + +## 7. Данные + +Основные сущности: + +- Organization, User, DeviceSession, RoleBinding; +- Workspace, Project, Task, TaskDependency, AcceptanceCriterion; +- Connector, Agent, Adapter, CapabilitySnapshot, CredentialReference; +- Conversation, Message, TaskRun, RunAttempt, RunEvent, Approval, Checkpoint; +- Artifact, ArtifactVersion; +- MemoryEntry, MemoryVersion, MemoryConflict; +- Skill, SkillVersion, SkillActivation; +- WikiPage, WikiRevision, WikiLink; +- UsageSignal, BudgetPolicy, AuditEvent, Notification. + +PostgreSQL — authoritative metadata; object storage — artifacts/packages; vector index — derived retrieval index. Удаление vector index не должно уничтожать source content; индекс полностью перестраиваем. + +## 8. API baseline + +REST commands используют `Idempotency-Key`; event subscriptions — WSS с resume cursor. + +```text +POST /v1/workspaces +GET /v1/projects/{projectId} +POST /v1/projects/{projectId}/tasks +PATCH /v1/tasks/{taskId} +POST /v1/connectors/enrollment-tokens +GET /v1/agents?project_id=&capability= +POST /v1/tasks/{taskId}/runs +POST /v1/runs/{runId}/approvals/{approvalId} +POST /v1/runs/{runId}/checkpoint +POST /v1/runs/{runId}/handoffs +POST /v1/runs/{runId}/cancel +GET /v1/runs/{runId}/events?cursor= +POST /v1/memory/query +POST /v1/memory/entries +POST /v1/skills/{skillId}/versions +POST /v1/skills/{skillId}/activations +PUT /v1/wiki/pages/{pageId} +GET /v1/usage/summary +GET /v1/audit/events +WS /v1/events?cursor= +``` + +Error envelope: `code`, `message`, `correlation_id`, `retryable`, `details`. Optimistic writes use `If-Match`/revision. Server timestamps are authoritative. + +## 9. Deployment baseline + +- self-hosted single-node MVP: container compose, PostgreSQL, S3-compatible storage, embedded/managed queue; +- production profile: redundant stateless API, managed PostgreSQL/object store, durable queue, separate workers; +- Connector upgrades are staged, signed, rollback-capable and never forced during active run; +- configuration is declarative; secrets supplied only through secret manager/file descriptors, not committed env files; +- migrations are forward-compatible for one release and have restore-tested rollback/roll-forward procedure. + +## 10. Threat model summary + +Threat actors: compromised agent, malicious skill, prompt injection in artifact/wiki, stolen device, rogue Connector, tenant user exceeding privilege, supply-chain compromise, replayed command, poisoned memory. + +Controls: tenant isolation, mTLS device identity, short-lived command tokens, RBAC/ABAC, human approvals, immutable audit, content classification/redaction, egress policy, adapter sandbox, skill quarantine/signatures, provenance-aware retrieval, idempotency/replay protection, secret references, encrypted backup, revocation. + +## 11. ADRs required before implementation + +1. ADR-001 UI wrappers: Tauri + Capacitor versus alternative shared-client stack. +2. ADR-002 deployment topology and supported database/queue profile. +3. ADR-003 authentication: local bootstrap, OIDC providers, enterprise SSO phase. +4. ADR-004 vector backend and embedding data residency. +5. ADR-005 Connector sandbox baseline for Linux/Windows/macOS servers. +6. ADR-006 adapter SDK language and process isolation model. diff --git a/docs/OPEN-QUESTIONS.md b/docs/OPEN-QUESTIONS.md new file mode 100644 index 0000000..eb7c444 --- /dev/null +++ b/docs/OPEN-QUESTIONS.md @@ -0,0 +1,42 @@ +# Открытые решения + +**Версия:** 0.1.0-draft +**Правило:** вопросы с severity `BLOCKER` должны быть закрыты ADR/approval до реализации затрагиваемой части. + +| ID | Severity | Решение | Варианты / критерии | Владелец | Deadline | Статус | +|---|---|---|---|---|---|---| +| OQ-001 | BLOCKER | Модель продукта и deployment | single-tenant self-hosted first vs multi-tenant hosted; data residency, ops cost | Product/Architecture | До M0 exit | Open | +| OQ-002 | BLOCKER | Client stack | React+Tauri+Capacitor baseline vs Flutter/другое; security, parity, terminal/editor UX, team skills | Architecture | До M0 exit | Open | +| OQ-003 | BLOCKER | Auth baseline | local bootstrap + OIDC; enterprise SSO/SCIM phase; recovery and break-glass | Security/Product | До M1 | Open | +| OQ-004 | BLOCKER | Supported OS/Android API matrix | реальные устройства, distribution channels, update/signing ownership | Product/Release | До M0 exit | Open | +| OQ-005 | BLOCKER | Adapter MVP matrix | обязательны Hermes/OpenClaw; выбрать Claude/Codex/Gemini spike и exact pinned versions | Product/Integration | До M0 exit | Open | +| OQ-006 | BLOCKER | Connector sandbox | container/systemd users/Windows job objects/macOS sandbox; filesystem/network policies | Security/Architecture | До M2 | Open | +| OQ-007 | BLOCKER | Data classification/retention | classes, regions, default retention, legal hold/privacy delete | Security/Legal | До M1 | Open | +| OQ-008 | BLOCKER | Persistence/queue/vector stack | managed vs self-hosted; extensions, backup, data residency, rebuild | Architecture/Operations | До M1 | Open | +| OQ-009 | BLOCKER | Approval/risk policy | destructive definitions, dual-control, self-approval, in-flight budget action | Security/Product | До M1 | Open | +| OQ-010 | BLOCKER | License/business model | repository/product license, third-party redistribution, SDK/CLI terms | Owner/Legal | До external distribution | Open | +| OQ-011 | MAJOR | Offline mobile policy | exact safe mutation allowlist, cache sensitivity, retention and remote wipe | Product/Security | До M5 | Open | +| OQ-012 | MAJOR | Usage/cost normalization | currencies/units, authoritative providers, manual budgets, exchange rates | Product/Finance | До M3 | Open | +| OQ-013 | MAJOR | Memory embeddings | provider, local/remote, sensitivity, re-embedding version policy | Architecture/Security | До M4 | Open | +| OQ-014 | MAJOR | Skill signing/review | organization signing keys, scanner set, approval roles, revocation distribution | Security | До M4 | Open | +| OQ-015 | MAJOR | Handoff bundle limits | token/byte limits, summary algorithm, human preview UX, language handling | Product/Integration | До M3 | Open | +| OQ-016 | MAJOR | SLO ownership and pilot size | production profile, on-call, telemetry, capacity and pilot tenants | Operations/Product | До M6 | Open | +| OQ-017 | MINOR | Branding/localization | product name validation, Russian/English MVP, terminology | Product/Design | До UX freeze | Open | +| OQ-018 | MINOR | Notifications | FCM/email providers, privacy-safe previews, quiet hours | Product/Operations | До M5 | Open | + +## Decision template + +```markdown +# ADR-NNN: Title +Status: proposed | accepted | superseded +Date: +Owners: +Related: OQ-..., FR-..., NFR-... + +## Context +## Options and evidence +## Decision +## Security/privacy/operational consequences +## Migration and rollback +## Validation +``` diff --git a/docs/RESEARCH.md b/docs/RESEARCH.md new file mode 100644 index 0000000..7957454 --- /dev/null +++ b/docs/RESEARCH.md @@ -0,0 +1,40 @@ +# Исследование интеграционных поверхностей + +**Дата проверки:** 2026-07-19 +**Статус:** source notes for Specification v0.1.0 + +## Метод + +Проверялись официальные страницы продуктов и протоколов. Сведения ниже описывают доступную интеграционную поверхность на дату проверки, но не гарантируют стабильность API или наличие функции в конкретном тарифе/версии. Перед реализацией каждого адаптера обязательны pinned-версия, contract tests и повторная проверка документации. + +## Проверенные источники + +| Runtime | Подтверждённая поверхность | Проектное решение | Источник | +|---|---|---|---| +| Hermes Agent | HTTP API с `/v1/chat/completions`, `/v1/responses`, `/v1/runs`; session headers; отдельные profiles | Нативный HTTP adapter; capabilities определяются handshake, а не предположением | [Hermes API Server](https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server), [Profiles](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) | +| OpenClaw | Gateway protocol предоставляет status, channels, models, chat, agent, sessions, nodes и approvals; схема является источником точного контракта | Нативный Gateway adapter с pinned schema/version и reconnect/resume | [Gateway protocol](https://docs.openclaw.ai/gateway/protocol), [Gateway CLI](https://docs.openclaw.ai/cli/gateway) | +| Claude Code | Agent SDK документирует sessions, permissions, hooks, subagents и MCP | SDK adapter; permission/approval события нормализуются без обхода политики Claude | [Agent SDK overview](https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-overview), [MCP](https://docs.anthropic.com/en/docs/claude-code/mcp) | +| OpenAI Codex | Для глубоких клиентов доступен app-server; также документированы SDK/headless use cases | App-server или SDK adapter после version-specific spike; CLI fallback только при структурированном выводе | [Codex App Server](https://learn.chatgpt.com/docs/app-server), [Codex resources](https://developers.openai.com/learn/codex) | +| OpenAI API / ChatGPT models | Responses API поддерживает conversation state; background mode допускает асинхронное выполнение | API adapter представляет API run, а не потребительский ChatGPT UI. Consumer ChatGPT account automation не входит в MVP | [Conversation state](https://platform.openai.com/docs/guides/conversation-state), [Background mode](https://platform.openai.com/docs/guides/background) | +| Gemini CLI | Документированы headless mode и MCP integration | Headless adapter с JSON output/exit semantics и explicit capability probe | [Gemini CLI](https://google-gemini.github.io/gemini-cli/), [Headless mode](https://google-gemini.github.io/gemini-cli/docs/cli/headless.html) | +| MCP | Стандартизирует discovery и вызов tools, resources и prompts | Используется как capability bridge, но не как полный lifecycle/session protocol | [Tools](https://modelcontextprotocol.io/specification/2025-06-18/server/tools), [Resources](https://modelcontextprotocol.io/specification/2025-06-18/server/resources), [Prompts](https://modelcontextprotocol.io/specification/2025-06-18/server/prompts) | + +## Ограничения и выводы + +1. **Нет универсальной семантики session/run/approval.** Нормализация должна сохранять vendor-specific payload в изолированном extension-поле и не скрывать потерю возможностей. +2. **MCP недостаточен для управления жизненным циклом агента.** Он полезен для tools/resources/prompts, но запуск, streaming, usage, cancel, checkpoint и resume задаются Agent Adapter Protocol. +3. **ChatGPT и OpenAI API — не одно и то же.** MVP не автоматизирует закрытый пользовательский UI ChatGPT и не извлекает из него токены/сессии. +4. **Лимиты не всегда доступны программно.** Connector принимает verified usage API, rate-limit headers, локальные метрики и ручные budget policies; приблизительные данные маркируются `estimated`. +5. **Handoff не переносит скрытые рассуждения.** Передаются только пользовательские сообщения, наблюдаемые tool results, проверенные факты, решения, артефакты, acceptance criteria и явно сформированный checkpoint. +6. **CLI-адаптеры рискованнее SDK/API.** Они требуют фиксированной версии, timeout/cancel contract, JSONL или иной структурированный канал, отдельный stderr и запрет parsing human UI как основного контракта. +7. **Capability negotiation обязательна.** UI не показывает resume, approvals, filesystem, terminal или usage как доступные, пока adapter handshake это не подтвердил. + +## Неподтверждённые детали + +Следующее не считается фактом до implementation spike: + +- точная совместимость конкретных версий Codex app-server и Agent Control Center; +- полнота usage/quota API каждого провайдера; +- возможность безопасного resume после смены runtime без пользовательского checkpoint; +- лицензии на встраивание/redistribution каждого SDK и CLI; +- parity функций между personal, team и enterprise тарифами. diff --git a/docs/SPECIFICATION.md b/docs/SPECIFICATION.md new file mode 100644 index 0000000..4c7bb50 --- /dev/null +++ b/docs/SPECIFICATION.md @@ -0,0 +1,397 @@ +# Техническое задание: Agent Control Center + +| Поле | Значение | +|---|---| +| Версия | 0.1.0-draft | +| Дата | 2026-07-19 | +| Статус | **Draft — implementation blocked** | +| Владелец решения | Product owner / operator | +| Нормативный документ | Этот файл | +| Поддерживающие документы | `ARCHITECTURE.md`, `RESEARCH.md`, `OPEN-QUESTIONS.md` | + +> Разработка продукта не начинается до закрытия блокирующих решений, G1 PASS и явного утверждения оператором. Формулировки MUST/SHALL обязательны; SHOULD требуют обоснования отклонения. + +## 1. Назначение + +Agent Control Center (ACC) — единое рабочее пространство для управления проектами, задачами и долгоживущими серверными ИИ-агентами через Web, Desktop и Android. Система обеспечивает контролируемый перенос наблюдаемого контекста между разными runtime, общую проектную память, реестр skills и wiki, не пытаясь переносить скрытые рассуждения модели или обходить политики провайдеров. + +### 1.1 Цели и метрики результата + +| Цель | Метрика MVP | +|---|---| +| Единое управление | ≥95% поддерживаемых run lifecycle действий доступны из всех трёх клиентов | +| Безопасный handoff | ≥99% принятых handoff не теряют objective, acceptance criteria, decisions и artifact refs по contract test | +| Общий контекст | 100% memory/wiki/skill результатов показывают scope и provenance | +| Контроль рисков | 100% destructive/high-risk действий имеют audit event; policy-required действия требуют approval | +| Наблюдаемость | ≥99% нормализованных run events доставлены либо восстановлены после reconnect в пределах retention | +| Практичность | p95 открытия проекта ≤2 с, p95 появления live event ≤1,5 с при целевой нагрузке | + +### 1.2 Не-цели MVP + +- замена IDE, Git hosting, CI/CD, issue tracker или model provider; +- автоматизация закрытого consumer UI ChatGPT либо извлечение browser cookies/session tokens; +- перенос hidden chain-of-thought, provider-internal state или секретов между агентами; +- полностью автономное переключение на платный/привилегированный агент без policy/approval; +- marketplace публичных skills; +- iOS-клиент; +- кросс-региональный active-active control plane; +- гарантированно точный остаток квоты, если runtime не предоставляет authoritative API. + +## 2. Пользователи и роли + +| Роль | Основные задачи | +|---|---| +| Organization Owner | tenant settings, billing/budgets, SSO, retention, emergency access | +| Workspace Admin | участники, connectors, agent policies, project templates | +| Project Lead | проекты, priorities, approvals, handoff, authoritative memory/wiki | +| Operator | наблюдение и управление runs, incidents, Connector health | +| Contributor | задачи, диалоги, artifacts, drafts memory/wiki | +| Viewer/Auditor | read-only view, audit export в разрешённой области | +| Server Connector | machine identity; исполняет только подписанные/авторизованные commands | +| AI Agent | untrusted workload identity с ограниченными capabilities и scope | + +RBAC задаёт базовые права; ABAC учитывает tenant/workspace/project, sensitivity, action risk, agent capability и device assurance. + +## 3. Термины + +- **Agent** — зарегистрированная конфигурация runtime/model/tools на конкретном Connector. +- **Connector** — сервис рядом с агентами, устанавливающий исходящее защищённое соединение с Control Plane. +- **Adapter** — versioned integration с конкретным runtime. +- **TaskRun** — логическая попытка выполнить задачу; содержит один или несколько RunAttempt. +- **RunAttempt** — исполнение на одном агенте/runtime. +- **Checkpoint** — наблюдаемый, provenance-aware снимок переносимого состояния. +- **Handoff** — контролируемое создание следующего attempt из checkpoint. +- **Memory entry** — версионируемая запись факта/решения/ограничения и т. п. с scope и provenance. +- **Skill** — версионируемый пакет инструкций/ресурсов и, опционально, исполняемых assets. +- **Wiki** — версионируемое проектное знание в Markdown. +- **Capability** — функция, явно подтверждённая adapter handshake. +- **Measured/estimated/unknown usage** — authoritative, вычисленная или недоступная информация о лимитах. + +## 4. Scope и релизы + +### 4.1 MVP + +- multi-tenant control plane и OIDC/local bootstrap; +- Web/PWA, Desktop, Android с общим UX contract; +- workspaces/projects/Kanban tasks/dependencies/artifacts; +- enrollment Connector, registry agent, capability/health view; +- run start/stream/approval/cancel/checkpoint/manual handoff; +- adapters: Hermes, OpenClaw и минимум один SDK/CLI runtime после spike; generic adapter contract; +- memory, skill registry, wiki, search; +- usage/budget signals, notifications, audit, backup/restore. + +### 4.2 Post-MVP + +- policy-governed automatic fallback; +- workflows/DAG orchestration и scheduled runs; +- enterprise SCIM/advanced DLP/legal hold; +- iOS and richer native integrations; +- public/organization skill catalog; +- analytics, cost optimization and provider routing. + +## 5. Предпосылки и зависимости + +1. Connector host поддерживает безопасное service execution и outbound TLS. +2. Runtime уже установлен/лицензирован владельцем; ACC не распространяет его без прав. +3. Provider credentials остаются в Connector-side secret store либо approved secret manager. +4. Control Plane располагает PostgreSQL, object storage, durable queue и backup destination. +5. Push notifications зависят от platform services и являются best-effort дополнением, не source of truth. +6. Семантика adapters определяется pinned version и contract tests; исследование — в `RESEARCH.md`. +7. Блокирующие продуктовые решения перечислены в `OPEN-QUESTIONS.md`. + +## 6. Функциональные требования + +Формат каждой строки: приоритет; предусловия; основной flow; ошибки/edge cases; acceptance test. `P0` обязателен для MVP, `P1` желателен при сохранении срока, `P2` post-MVP. + +### 6.1 Identity, access, tenancy + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-IAM-001** | P0 | Новый deployment | Первый owner создаётся одноразовым bootstrap token; после первого успеха token инвалидируется | Повтор/expired token → 401 без user creation | **AT-FR-IAM-001:** второй вызов тем же token отклонён; ровно один owner и audit event | +| **FR-IAM-002** | P0 | Настроен IdP либо local auth | Login выдаёт short-lived access и rotating refresh credential, привязанный к device session | revoked/rotated credential → 401; replay отзывает credential family | **AT-FR-IAM-002:** rotation/replay integration test подтверждает отзыв и повторный login | +| **FR-IAM-003** | P0 | Actor состоит в tenant | Каждая операция проходит RBAC+ABAC и tenant scoping до чтения данных | IDOR/cross-tenant ID → 404, не раскрывая существование объекта | **AT-FR-IAM-003:** matrix test всех ролей и cross-tenant identifiers не обнаруживает утечек | +| **FR-IAM-004** | P0 | Risk policy требует approval | Создаётся approval с snapshot действия, approver scope и TTL; execution ждёт решение | self-approval запрещён политикой; expiry → blocked | **AT-FR-IAM-004:** high-risk command не доставлен Connector до валидного approval | +| **FR-IAM-005** | P1 | Пользователь управляет devices | Пользователь видит и отзывает device sessions; отзыв закрывает WS и refresh | offline client теряет write-доступ при следующей проверке | **AT-FR-IAM-005:** revoked device не обновляет task и получает auth event | + +### 6.2 Connectors and agents + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-CON-001** | P0 | Admin создал одноразовый enrollment token | Connector регистрирует machine identity, public key, labels и version через outbound TLS | token reuse/tenant mismatch → reject и security audit | **AT-FR-CON-001:** повтор enrollment и подменённый tenant отклоняются | +| **FR-CON-002** | P0 | Connector enrolled | mTLS WSS поддерживает heartbeat, reconnect, cursor resume и encrypted bounded spool | duplicate/out-of-order events дедуплицируются/упорядочиваются; gap отмечается | **AT-FR-CON-002:** network fault test восстанавливает ordered stream без двойных side effects | +| **FR-CON-003** | P0 | Adapter установлен | Handshake публикует adapter/runtime versions, identity и capabilities snapshot | неизвестная schema/version → incompatible, запуск запрещён | **AT-FR-CON-003:** UI/API скрывают unsupported actions и блокируют forged capability | +| **FR-CON-004** | P0 | Admin имеет доступ | Agent создаётся из Connector+adapter+runtime config+policy; secret хранится только как reference | secret в request/log/event → validation failure/redaction alert | **AT-FR-CON-004:** secret canary отсутствует в DB, API, audit и logs | +| **FR-CON-005** | P0 | Agent зарегистрирован | Health показывает online/degraded/offline/incompatible, last seen, latency и active runs | stale heartbeat переводит в offline без удаления агента | **AT-FR-CON-005:** state transitions происходят по заданным thresholds и видны всем клиентам | +| **FR-CON-006** | P0 | Команда готова к dispatch | Каждая command имеет idempotency key, lease, deadline, policy digest и optional approval token | expired lease/replay/policy mismatch → не исполнять, вернуть typed outcome | **AT-FR-CON-006:** повтор start/cancel не создаёт второй native run/side effect | +| **FR-CON-007** | P1 | Доступна совместимая версия | Admin выполняет staged Connector/adapter upgrade с drain и rollback | active run не прерывается forced update; failed health → rollback | **AT-FR-CON-007:** upgrade fault test возвращает previous healthy version | + +### 6.3 Workspaces, projects, tasks and artifacts + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-PRJ-001** | P0 | Authorized user | Создание workspace/project задаёт name, key, visibility, retention, default policies и wiki root | duplicate key → 409; invalid policy → 422 | **AT-FR-PRJ-001:** созданный project атомарно содержит defaults и audit event | +| **FR-PRJ-002** | P0 | Project существует | Task хранит title, description, status, priority, assignees, agent policy, acceptance criteria, labels, due date | stale revision → 409 с current revision | **AT-FR-PRJ-002:** optimistic concurrency не теряет параллельное изменение | +| **FR-PRJ-003** | P0 | Tasks существуют | Kanban поддерживает configurable columns, ordering, filters и bulk move в рамках policy | invalid transition/partial bulk → atomic reject с per-item reason | **AT-FR-PRJ-003:** одинаковый порядок/статусы наблюдаются Web/Desktop/Android | +| **FR-PRJ-004** | P0 | Tasks одного project | Dependencies образуют DAG; blocked task не стартует без authorized override | cycle/self-link → 422; deleted dependency сохраняет audit reference | **AT-FR-PRJ-004:** property test не позволяет создать цикл и корректно считает blocked | +| **FR-PRJ-005** | P0 | Actor имеет artifact permission | Artifact загружается multipart, получает hash, MIME, sensitivity, provenance и immutable version | hash mismatch/malware/policy violation → quarantine | **AT-FR-PRJ-005:** download проверяет ACL; изменённый blob не проходит integrity check | +| **FR-PRJ-006** | P1 | Есть Git integration | Project может хранить repository reference/branch/commit/PR metadata без provider secret | webhook replay/out-of-scope repo → reject | **AT-FR-PRJ-006:** task links commit metadata и не раскрывает integration token | + +### 6.4 Runs, conversations, approvals and handoff + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-RUN-001** | P0 | Task runnable; agent online/capable | User выбирает agent, ввод, context scopes и budget; система создаёт TaskRun/Attempt и dispatch command | offline/incompatible/budget blocked → typed blocked state, без native start | **AT-FR-RUN-001:** successful start создаёт одну lineage и ordered initial events | +| **FR-RUN-002** | P0 | Attempt active | Нормализованные events stream в реальном времени: text, tool, progress, usage, approval, artifact, status | disconnect использует cursor resume; unsupported event сохраняется как vendor extension | **AT-FR-RUN-002:** reconnect не дублирует события и сохраняет sequence | +| **FR-RUN-003** | P0 | User sends message | Conversation message immutable после отправки, допускает correction message; sensitivity/redaction применяются до dispatch | слишком большой input → 413 с limits; prohibited secret → block | **AT-FR-RUN-003:** correction сохраняет original/provenance и agent получает разрешённую версию | +| **FR-RUN-004** | P0 | Adapter запрашивает approval | UI показывает точный action, args diff, risk, expiry и target; approve/deny подписывается actor identity | changed args после approval → approval invalid; timeout → denied/blocked policy | **AT-FR-RUN-004:** TOCTOU test блокирует command с изменённым digest | +| **FR-RUN-005** | P0 | Attempt active | Cancel поддерживает graceful и force (при праве), показывает acknowledgement и terminal outcome | lost Connector → cancelling_pending; повтор cancel идемпотентен | **AT-FR-RUN-005:** cancel fault test не переводит в cancelled без подтверждения/timeout policy | +| **FR-RUN-006** | P0 | Attempt имеет observable state | Checkpoint формирует objective, criteria, messages, verified facts, decisions, completed/pending work, errors, artifact refs и source hashes | hidden reasoning/secrets исключаются; oversized bundle bounded с manifest omissions | **AT-FR-RUN-006:** schema/secret tests и human-readable preview проходят до handoff | +| **FR-RUN-007** | P0 | Checkpoint valid; target capable | Manual handoff показывает source/target, estimated cost/limits и preview; создаёт новый Attempt, target подтверждает ingestion, затем source lease закрывается | target reject/timeout → source остаётся resumable; lineage не разрывается | **AT-FR-RUN-007:** fault injection в каждой фазе не теряет runnable state и не запускает два writer lease | +| **FR-RUN-008** | P0 | Usage/budget signal изменён | На rate limit/quota система классифицирует signal, ставит run в blocked/handoff_ready и предлагает совместимые targets | estimated signal явно маркируется; неизвестное не показывается как zero | **AT-FR-RUN-008:** 429/headers/local budget/unknown дают разные корректные UI states | +| **FR-RUN-009** | P1 | Run terminal | User может retry from checkpoint, fork с изменённым context или close; lineage и cost сохраняются | retry non-idempotent completed steps требует explicit plan/approval | **AT-FR-RUN-009:** retry не помечает старый attempt active и предупреждает о side effects | + +### 6.5 Shared memory and retrieval + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-MEM-001** | P0 | Actor имеет write scope | Memory entry создаётся с kind, scope, provenance, verification, sensitivity, validity и content hash | отсутствующая provenance/запрещённый scope → 422/403 | **AT-FR-MEM-001:** запись без обязательных metadata не индексируется | +| **FR-MEM-002** | P0 | Entry существует | Update создаёт immutable version/supersedes link; concurrent contradiction создаёт conflict, не silent overwrite | stale revision → conflict response | **AT-FR-MEM-002:** concurrent property test сохраняет обе версии и conflict record | +| **FR-MEM-003** | P0 | Query authorized | Retrieval применяет ACL до lexical/semantic ranking, filters scope/time/type/verification и возвращает citations | недоступная запись не влияет даже через count/timing в заданном threat model | **AT-FR-MEM-003:** cross-scope leakage suite не находит content/metadata | +| **FR-MEM-004** | P0 | Context bundle строится | Context Broker выбирает bounded verified context по policy/token budget и записывает retrieval manifest | overflow сокращает низший приоритет и сообщает omissions | **AT-FR-MEM-004:** deterministic fixture даёт bounded bundle и воспроизводимый manifest | +| **FR-MEM-005** | P0 | Agent предлагает memory | Agent-created запись остаётся draft/unverified до policy либо human review | prompt injection не может повысить trust/scope | **AT-FR-MEM-005:** malicious artifact не создаёт authoritative memory | +| **FR-MEM-006** | P1 | Entry устарела/ошибочна | Authorized user revokes/expires/supersedes entry; прошлые runs сохраняют ссылку на использованную version | hard delete ограничен retention/privacy workflow | **AT-FR-MEM-006:** новый retrieval исключает revoked, старый manifest остаётся auditable | +| **FR-MEM-007** | P1 | Index повреждён/сменён | Derived vector/full-text index полностью перестраивается из authoritative source | rebuild failure не удаляет source; degraded search обозначен | **AT-FR-MEM-007:** empty-index restore даёт эквивалентный authorized result set | + +### 6.6 Skills registry + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-SKL-001** | P0 | Contributor имеет publish-draft | Skill version загружается с manifest, digest, provenance, compatibility и permission declaration; version immutable | digest mismatch/zip traversal/oversize → quarantine | **AT-FR-SKL-001:** malicious package corpus не выходит из scanner sandbox | +| **FR-SKL-002** | P0 | Version scanned | Reviewer видит diff, permissions, executable assets и sources; устанавливает approved/rejected/quarantined | author self-approval запрещается policy | **AT-FR-SKL-002:** executable skill нельзя активировать без required review | +| **FR-SKL-003** | P0 | Approved compatible version | Project/agent activation pin-ит exact version и grants; Adapter получает только разрешённый bundle | incompatible runtime/capability → blocked | **AT-FR-SKL-003:** update latest не меняет pinned active run | +| **FR-SKL-004** | P0 | Новая version опубликована | UI показывает semantic diff, risk changes и rollout; rollback возвращает предыдущий pin | revoked vulnerable version нельзя активировать заново | **AT-FR-SKL-004:** staged rollout/rollback сохраняет audit и deterministic resolution | +| **FR-SKL-005** | P1 | User ищет skill | Search/filter по owner, tags, compatibility, review state; results показывают trust/provenance | quarantined скрыт для non-admin | **AT-FR-SKL-005:** ACL/trust filters согласованы API и все клиенты | + +### 6.7 Wiki + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-WIK-001** | P0 | Project существует | Wiki page хранит Markdown, path/title, aliases, ACL, status draft/published и immutable revisions | path collision/stale revision → 409 | **AT-FR-WIK-001:** concurrent edit не теряет content и предлагает merge | +| **FR-WIK-002** | P0 | Pages/artifacts существуют | Backlinks, links и attachments резолвятся version-aware; broken links видимы | forbidden target не раскрывает title | **AT-FR-WIK-002:** link checker и ACL suite проходят на mixed-scope fixture | +| **FR-WIK-003** | P0 | Agent генерирует страницу | Generated content сохраняется draft с citations/provenance; authoritative publish требует policy review | unsupported citation → flagged, не published | **AT-FR-WIK-003:** agent не может самостоятельно повысить draft до authoritative | +| **FR-WIK-004** | P1 | Query authorized | Full-text/semantic search возвращает snippets, revision, scope и citations | stale index отмечается; ACL до ranking | **AT-FR-WIK-004:** index rebuild и leakage tests эквивалентны memory retrieval controls | + +### 6.8 Usage, notifications and audit + +| ID | Pri | Предусловия | Требование и основной flow | Ошибки / edge cases | Acceptance | +|---|---:|---|---|---|---| +| **FR-OPS-001** | P0 | Adapter/provider signal доступен | Usage Service нормализует units, window, reset, source и confidence measured/estimated/unknown | несопоставимые units не суммируются как одно значение | **AT-FR-OPS-001:** fixtures всех confidence states визуально/в API различимы | +| **FR-OPS-002** | P0 | Budget policy задана | Soft threshold уведомляет; hard threshold блокирует новый dispatch либо требует override approval | in-flight policy задаёт allow/checkpoint/cancel, не подразумевается | **AT-FR-OPS-002:** boundary tests на reset/race/timezone исполняют выбранную policy ровно один раз | +| **FR-OPS-003** | P0 | Event соответствует preference | In-app и push notification дедуплицируются, deep-link ведёт к объекту после auth | push failure не меняет authoritative state | **AT-FR-OPS-003:** duplicate event даёт одно notification; revoked user не получает content | +| **FR-OPS-004** | P0 | Security/lifecycle action | Append-only audit хранит actor/workload, action, target, result, policy, correlation, timestamp и safe diff | sensitive payload redacted; gap/tamper observable | **AT-FR-OPS-004:** audit completeness test покрывает auth, policy, run, handoff, skill и admin actions | +| **FR-OPS-005** | P1 | Auditor authorized | Filter/export audit формирует signed manifest и bounded export без запрещённых данных | oversized export асинхронен; expired link → 410 | **AT-FR-OPS-005:** export hash проверяется и obeys tenant/time/ACL boundaries | + +## 7. Нефункциональные требования + +### 7.1 Security and privacy + +| ID | Требование | Проверка | +|---|---|---| +| **NFR-SEC-001** | TLS 1.3 предпочтительно, минимум TLS 1.2 по утверждённой policy; Connector mTLS; encryption at rest для DB/object/backup | **AT-NFR-SEC-001:** automated TLS/config scan и restore encrypted backup | +| **NFR-SEC-002** | Credentials только в approved secret store; API/log/audit/artifact проходят secret redaction; rotation без redeploy Control Plane | **AT-NFR-SEC-002:** canary secret e2e scan и rotation test | +| **NFR-SEC-003** | OWASP ASVS L2 baseline для web/API; mobile secure storage; desktop bridge allowlist и CSP | **AT-NFR-SEC-003:** SAST/DAST/dependency/mobile/desktop security gates без high findings | +| **NFR-SEC-004** | Tenant isolation enforced server-side and tested на direct IDs, search, events, exports, caches и vectors | **AT-NFR-SEC-004:** adversarial multi-tenant suite имеет zero cross-tenant disclosures | +| **NFR-SEC-005** | Prompt/tool output/artifacts считаются untrusted; provenance, quarantine, content-type validation, no instruction privilege escalation | **AT-NFR-SEC-005:** injection corpus не меняет policy/scope/approval state | +| **NFR-SEC-006** | Command replay protection, idempotency, signed policy/approval digest и server-authoritative time | **AT-NFR-SEC-006:** replay/TOCTOU/clock-skew suite не повторяет side effects | +| **NFR-SEC-007** | Data export/delete/privacy workflow с legal retention override; deletion tombstone и verified background purge | **AT-NFR-SEC-007:** lifecycle test подтверждает export completeness и purge по policy | +| **NFR-SEC-008** | SBOM, pinned dependencies, signed release artifacts и provenance; critical CVE policy блокирует release | **AT-NFR-SEC-008:** release gate проверяет SBOM/signature/provenance и policy thresholds | + +### 7.2 Reliability, consistency and recovery + +| ID | Требование | Проверка | +|---|---|---| +| **NFR-REL-001** | Production monthly availability target 99.5% без плановых окон; status component-wise | **AT-NFR-REL-001:** SLI calculation from synthetic checks and documented exclusions | +| **NFR-REL-002** | At-least-once command/event transport plus application idempotency; per-run ordering and explicit gap | **AT-NFR-REL-002:** chaos test disconnect/duplicate/reorder не повторяет side effects | +| **NFR-REL-003** | RPO ≤15 мин, RTO ≤4 ч для production profile; restore drill минимум ежеквартально | **AT-NFR-REL-003:** timed clean-environment restore meets RPO/RTO and integrity checks | +| **NFR-REL-004** | Run lease исключает двух concurrent writers; failover не заявляет success без runtime evidence | **AT-NFR-REL-004:** partition test preserves single-writer invariant | +| **NFR-REL-005** | Schema migrations resumable, backup-first, observable; совместимость server/client/Connector минимум N-1 | **AT-NFR-REL-005:** upgrade/rollback matrix N and N-1 passes with representative data | + +### 7.3 Performance and capacity + +Целевая MVP-нагрузка: 100 concurrent users, 50 connected Connectors, 500 registered agents, 200 concurrent runs, 10 000 projects, 1 000 000 tasks, 10 000 000 run events и 1 000 000 memory/wiki revisions на deployment. Увеличение требует capacity test, а не предположения линейности. + +| ID | Требование | Проверка | +|---|---|---| +| **NFR-PERF-001** | p95 read API ≤500 мс, write acknowledgement ≤800 мс при target load, без provider runtime latency | **AT-NFR-PERF-001:** reproducible load profile; error rate <1% excluding intentional 4xx | +| **NFR-PERF-002** | p95 live event latency Connector→online client ≤1.5 с; reconnect catch-up 10k events ≤30 с | **AT-NFR-PERF-002:** instrumented streaming benchmark | +| **NFR-PERF-003** | Project/Kanban initial usable view p95 ≤2 с broadband и ≤4 с simulated 4G, warm cache | **AT-NFR-PERF-003:** Web/Desktop/Android performance test with declared devices | +| **NFR-PERF-004** | Search p95 ≤2 с на target corpus; context bundle p95 ≤3 с до runtime dispatch | **AT-NFR-PERF-004:** representative ACL-heavy corpus benchmark | + +### 7.4 UX, accessibility and portability + +| ID | Требование | Проверка | +|---|---|---| +| **NFR-UX-001** | Web соответствует WCAG 2.2 AA; keyboard, focus, contrast, screen-reader labels; native wrappers сохраняют semantics | **AT-NFR-UX-001:** automated scan + manual keyboard/screen-reader checklist on critical journeys | +| **NFR-UX-002** | Critical action показывает target, consequence, risk and status; destructive action требует confirmation/approval по policy | **AT-NFR-UX-002:** usability acceptance для run/cancel/handoff/skill activation/admin | +| **NFR-UX-003** | UI различает measured/estimated/unknown, queued/running/blocked/offline и stale/fresh data не только цветом | **AT-NFR-UX-003:** visual/accessibility state matrix passes | +| **NFR-PORT-001** | Web: последние 2 major Chrome/Edge/Firefox/Safari; responsive ≥360 CSS px | **AT-NFR-PORT-001:** browser matrix smoke/e2e | +| **NFR-PORT-002** | Desktop MVP: Windows 11, macOS current+previous, Ubuntu 24.04 LTS; final matrix утверждается ADR | **AT-NFR-PORT-002:** signed install/upgrade/uninstall and critical journeys per OS | +| **NFR-PORT-003** | Android MVP: API level определяется ADR, target current Play policy; degraded read cache offline, writes queued only для explicitly safe operations | **AT-NFR-PORT-003:** device/emulator matrix and offline conflict tests | +| **NFR-PORT-004** | Клиенты version-aware: unsupported server API получает upgrade-required, а не undefined behavior | **AT-NFR-PORT-004:** compatibility matrix N/N-1/incompatible versions | + +### 7.5 Operations and observability + +| ID | Требование | Проверка | +|---|---|---| +| **NFR-OPS-001** | Structured logs, metrics, traces с correlation/run/connector IDs; content/secrets excluded by default | **AT-NFR-OPS-001:** e2e trace links command to result; canary absent from telemetry | +| **NFR-OPS-002** | Alerts покрывают availability, queue lag, event gaps, Connector churn, auth anomalies, backup/restore, storage and error budgets | **AT-NFR-OPS-002:** alert tests reach on-call route with runbook links | +| **NFR-OPS-003** | Health/readiness различают process, dependencies and migration state; readiness false during unsafe state | **AT-NFR-OPS-003:** dependency fault matrix produces expected health codes | +| **NFR-OPS-004** | Retention configurable per tenant within operator bounds: audit ≥365d default, events 90d, artifacts/memory/wiki project policy, telemetry 30d; legal hold overrides purge | **AT-NFR-OPS-004:** time-travel retention suite validates purge/hold/export | +| **NFR-OPS-005** | Admin operations and incident recovery documented as executable runbooks; quarterly restore and Connector revocation drills | **AT-NFR-OPS-005:** fresh operator completes sampled runbooks without tribal knowledge | + +## 8. UI/UX specification + +### 8.1 Information architecture + +Primary navigation: Home, Workspaces, Projects, Tasks, Runs, Agents, Memory, Skills, Wiki, Usage, Notifications; Admin adds Connectors, Members, Policies, Audit, System. + +### 8.2 Critical screens + +1. **Home:** assigned/blocked tasks, active runs, approvals, quota warnings, unhealthy Connectors. +2. **Project:** overview, Kanban/list, runs, artifacts, memory, skills, wiki, settings. +3. **Task detail:** requirements/criteria, dependencies, conversation, run timeline, agent selector, context preview, artifacts. +4. **Run console:** ordered event stream, status/usage, approvals, checkpoint/cancel/handoff controls, reconnect indicator. +5. **Handoff dialog:** reason, source/target capabilities, unavailable features, usage confidence, exact context preview/omissions, policy/approval impact. +6. **Agent registry:** runtime/adapter versions, Connector, health, capabilities, active work, limits, policy. +7. **Memory:** scope/type/trust filters, citations, conflicts, version history, revoke/supersede. +8. **Skills:** manifest/diff/permissions/trust, version pins, activation/rollout/rollback. +9. **Wiki:** tree/editor/preview/backlinks/history/citations/draft-publish state. +10. **Admin:** Connector enrollment/revocation, policies, audit and retention. + +### 8.3 Client parity + +Все клиенты MUST поддерживать read/triage, task updates, run observation, approvals и manual handoff. Server/Connector/retention/security administration MAY быть ограничено Web/Desktop, но Android показывает понятную причину и deep-link, а не скрывает существование операции. + +### 8.4 Offline/conflicts + +- Read cache показывает `last_synced_at` и может содержать только разрешённые non-secret данные. +- Offline write по умолчанию запрещён для approvals, run actions, policy, skill activation, membership и secrets. +- Safe task/wiki draft edits используют client mutation ID и base revision; conflict не разрешается last-write-wins молча. + +## 9. API и event contract + +Полный baseline endpoints описан в `ARCHITECTURE.md`. Общие правила: + +- JSON UTF-8; version prefix `/v1`; UUID/ULID opaque IDs. +- Commands требуют `Idempotency-Key`; mutations возвращают revision/ETag. +- List: cursor pagination, stable ordering, bounded page size, explicit filters. +- Errors: `code`, localized-safe `message`, `correlation_id`, `retryable`, `details` без секретов. +- 401 — нет/истёк auth; 403 — известный actor без права; cross-tenant opaque object — 404; 409 — revision/state/idempotency conflict; 422 — semantic validation; 429 — rate/budget с source/confidence; 503 — dependency/runtime unavailable. +- WS events: schema version, globally unique ID, object/run sequence, timestamp, classification; client подтверждает cursor. +- Breaking change требует новой major API/AAP version и migration guide. + +## 10. Data lifecycle + +1. Authoritative records — PostgreSQL/object storage; search/vector — rebuildable derivatives. +2. Artifacts, wiki, memory и skills versioned; mutable metadata меняется optimistic concurrency. +3. Soft delete скрывает объект; purge идёт после retention/hold checks и создаёт non-sensitive tombstone. +4. Audit append-only; correction создаёт compensating event. +5. Backup охватывает DB, objects, encryption metadata, configuration manifests; секреты восстанавливаются отдельным approved process. +6. Tenant export включает schemas, versions, provenance and checksums, но не provider credentials/hidden reasoning. + +## 11. State invariants + +- Один TaskRun имеет не более одного writable active Attempt lease. +- Terminal Attempt не возвращается в active; retry/fork создаёт новый Attempt. +- Handoff не закрывает source resumability до подтверждения target ingestion. +- Capability используется только из актуального compatible handshake snapshot. +- Approval валиден только для exact action/policy/arguments digest и не переживает expiry/revocation. +- Memory/wiki/skill trust не повышается на основании инструкции внутри untrusted content. +- Cross-tenant references не существуют на уровне API, queue, cache, vector и export. +- `unknown` usage не преобразуется в `0` или `unlimited`. + +## 12. Acceptance strategy и quality gates + +### 12.1 Test layers + +- unit/property tests: state machines, policies, DAG, idempotency, conflicts, redaction; +- contract tests: каждый AAP adapter против pinned runtime fixture; +- integration: DB/queue/object/Connector, auth, search, migration; +- e2e: Web/Desktop/Android critical journeys; +- security: tenant isolation, injection, replay, secrets, sandbox, supply chain; +- chaos/recovery: network partition, duplicate/reorder, process/DB/queue failure, restore; +- performance/accessibility/compatibility matrices; +- user acceptance на сценариях ниже. + +Каждый `FR-*` и `NFR-*` имеет одноимённый `AT-*` в таблицах выше. CI/QA case может реализовать несколько AT, но отчёт MUST сохранять прямое отображение ID→результат→evidence. + +### 12.2 End-to-end acceptance journeys + +- **E2E-001 Onboarding:** owner bootstrap → IdP/local login → Connector enrollment → Hermes/OpenClaw agent discovery → capability view. +- **E2E-002 Project work:** project → dependent tasks → criteria → artifact → start run → live events → approval → success. +- **E2E-003 Quota handoff:** active run получает measured/estimated limit → checkpoint preview → manual compatible target → ingestion → continuation без duplicate writer. +- **E2E-004 Shared knowledge:** agent proposes memory/wiki draft → reviewer verifies → second agent retrieves citation → revoked version больше не попадает в новый context. +- **E2E-005 Skill lifecycle:** upload malicious/valid packages → quarantine/review → pin → staged activation → rollback. +- **E2E-006 Failure recovery:** Connector disconnect during run → spool/reconnect/cursor resume → no duplicate side effect → audit continuity. +- **E2E-007 Cross-client:** task/run started Web, approved Android, observed Desktop; state/revisions identical. +- **E2E-008 Tenant security:** attacker probes IDs/search/events/export/vector timing; no unauthorized disclosure. + +### 12.3 Release gates + +- G0 decisions: blocking open questions/ADRs approved. +- G1 requirements: completeness, traceability, measurable NFR, security/privacy review — PASS. +- G2 implementation: tests, independent review, migration/recovery evidence — PASS. +- P1 security: no unresolved critical/high; medium accepted by owner with expiry. +- P2 supply-chain/Watcher advisory: PASS or explicit operator disposition. +- P3 publish/deploy: exact candidate, clean tree, CI/evidence, rollback and explicit approval. + +## 13. Delivery plan + +| Milestone | Deliverable | Exit criteria | +|---|---|---| +| M0 Discovery/ADRs | decisions, threat model, UX prototypes, adapter spikes | all blocking questions closed; executable contract fixtures | +| M1 Platform skeleton | auth/tenant, project/task, audit, CI/CD, observability | isolation/security baseline and Web shell | +| M2 Connector/AAP | enrollment, command/event transport, Hermes/OpenClaw adapters | chaos/idempotency/compatibility tests pass | +| M3 Runs/handoff | console, approvals, checkpoint, manual handoff, usage | E2E-002/003/006 pass | +| M4 Knowledge | memory, skills, wiki, context broker | E2E-004/005 and leakage tests pass | +| M5 Clients | Desktop/Android wrappers, push/offline-safe flows | E2E-007 + platform/accessibility matrices | +| M6 Hardening/pilot | backup/restore, performance, runbooks, pilot migration | all gates, SLO evidence and operator sign-off | + +Оценки срока/команды не фиксируются до M0 spikes и ADR; псевдоточные даты запрещены. + +## 14. Риски и меры + +| Риск | Влияние | Мера | +|---|---|---| +| Vendor API/CLI drift | adapter outage/data loss | pinned versions, capability handshake, contract CI, N-1 policy | +| Handoff semantic loss | повтор работы/ошибка | observable checkpoint schema, preview, provenance, target ack, lineage | +| Poisoned shared memory | persistent compromise | untrusted drafts, verification, provenance, ACL-before-retrieval, revoke | +| Skill supply chain | remote execution | quarantine, scanner, declared permissions, sandbox, signatures/review | +| Quota uncertainty | wrong routing expectation | measured/estimated/unknown, policies, no false precision | +| Secret leakage through agents | credential compromise | connector-side refs, redaction, DLP, least privilege, audit | +| Event duplication/partition | duplicate side effects | idempotency, leases, ordering, cursor, reconciliation | +| Cross-tenant search leak | privacy breach | server-side ACL before indexing/ranking, adversarial tests | +| Shared UI wrapper limitations | inconsistent UX/security | ADR/spike, narrow native bridge, parity contract | +| Scope expansion | delayed MVP | strict non-goals, P0/P1/P2, change-control and traceability | + +## 15. Change control and Definition of Ready + +Любое изменение P0 scope, trust boundary, data model, retention, API/AAP или supported platform требует обновить version, affected requirement IDs, ATs, risks, ADR/open question и migration impact. + +Implementation task считается Ready только если: + +- связана с утверждённым requirement/AT ID; +- входы, output, errors, permissions и telemetry определены; +- зависимости/миграция/rollback известны; +- test approach согласован; +- отсутствует unresolved blocking question; +- G1 не заблокирован. + +## 16. Approval record + +| Роль | Имя | Решение | Дата | Версия | +|---|---|---|---|---| +| Product owner/operator | — | Pending | — | 0.1.0-draft | +| Architecture | — | Pending | — | 0.1.0-draft | +| Security/privacy | — | Pending | — | 0.1.0-draft | +| Operations | — | Pending | — | 0.1.0-draft | diff --git a/docs/TRACEABILITY.md b/docs/TRACEABILITY.md new file mode 100644 index 0000000..6baf172 --- /dev/null +++ b/docs/TRACEABILITY.md @@ -0,0 +1,46 @@ +# Traceability matrix + +**Версия:** 0.1.0-draft +**Статус значений:** `Specified` означает «описано и имеет acceptance contract», а не «реализовано». + +## Пользовательский запрос → нормативные требования + +| Верхнеуровневый запрос | Нормативные требования | Архитектурный артефакт | Acceptance evidence | Статус | +|---|---|---|---|---| +| Единое рабочее пространство | FR-PRJ-001..006, FR-RUN-001..009, NFR-UX-001..003 | `ARCHITECTURE.md` §1–3 | E2E-002, E2E-007 | Specified | +| Проекты и задачи | FR-PRJ-001..006 | canonical entities + Project Service | AT-FR-PRJ-001..006 | Specified | +| Управление серверными ИИ-агентами | FR-CON-001..007, FR-RUN-001..009 | outbound Connector + AAP | E2E-001, E2E-002, E2E-006 | Specified | +| Hermes | FR-CON-003..006, AAP contract | Hermes native HTTP adapter; `RESEARCH.md` | pinned adapter contract suite (M2) | Specified; spike pending | +| OpenClaw | FR-CON-003..006, AAP contract | OpenClaw Gateway adapter; `RESEARCH.md` | pinned adapter contract suite (M2) | Specified; spike pending | +| Claude Code | FR-CON-003..006, AAP contract | Agent SDK adapter; `RESEARCH.md` | adapter spike/contract suite | Specified; OQ-005 open | +| OpenAI Codex | FR-CON-003..006, AAP contract | app-server/SDK adapter; `RESEARCH.md` | adapter spike/contract suite | Specified; OQ-005 open | +| ChatGPT/OpenAI | FR-CON-003..006, FR-RUN-001..009 | Responses/Conversations API adapter; consumer ChatGPT UI excluded | API adapter contract suite | Specified; boundary explicit | +| Gemini | FR-CON-003..006, AAP contract | headless structured adapter; `RESEARCH.md` | adapter spike/contract suite | Specified; OQ-005 open | +| Web-клиент | NFR-UX-001..003, NFR-PORT-001/004 | shared React UI/PWA baseline | E2E-007 + browser matrix | Specified; ADR-001 open | +| Desktop-клиент | NFR-UX-001..003, NFR-PORT-002/004 | Tauri wrapper baseline | E2E-007 + OS install/upgrade matrix | Specified; ADR-001/OQ-004 open | +| Android-клиент | NFR-UX-001..003, NFR-PORT-003/004 | Capacitor wrapper baseline | E2E-007 + device/offline matrix | Specified; ADR-001/OQ-004 open | +| Переключение при исчерпании лимитов | FR-RUN-006..009, FR-OPS-001..002, NFR-REL-004 | checkpoint/handoff state machine + Usage Service | E2E-003; fault/boundary tests | Specified | +| Общая память проекта | FR-MEM-001..007, NFR-SEC-004/005/007 | Context Broker + Memory Service | E2E-004; leakage/conflict/rebuild tests | Specified | +| База skills | FR-SKL-001..005, NFR-SEC-005/008 | Skill Registry + quarantine/review/pinning | E2E-005 | Specified | +| Wiki | FR-WIK-001..004 | Wiki Service + revision/citation model | E2E-004 + AT-FR-WIK-* | Specified | +| Безопасность, approvals, audit | FR-IAM-001..005, FR-OPS-004..005, NFR-SEC-001..008 | Identity/Policy/Audit + threat model | E2E-008 + security gates | Specified | +| Архитектура и модель данных | SPEC §9–11; ARCH §1–8 | `ARCHITECTURE.md` | structural G1 + later migration/contract tests | Specified | +| API и события | SPEC §9; FR-CON/RUN | REST/WSS/AAP baseline | adapter/API contract tests | Specified | +| Acceptance-тесты | каждый FR/NFR связан с одноимённым AT | SPEC §12 | `scripts/validate_spec.py`, QA evidence in implementation phase | Specified | + +## Артефакты → назначение + +| Файл | Назначение | Gate | +|---|---|---| +| `README.md` | входная точка, статус и запрет реализации | G1 | +| `docs/SPECIFICATION.md` | канонические требования и acceptance contract | G1 | +| `docs/ARCHITECTURE.md` | component/data/API/AAP baseline и trust boundaries | G1/ADR | +| `docs/RESEARCH.md` | source-backed integration constraints | G1 + implementation spikes | +| `docs/OPEN-QUESTIONS.md` | blocking decisions и owners | G0 | +| `docs/TRACEABILITY.md` | запрос → requirement → evidence mapping | G1 | +| `scripts/validate_spec.py` | machine-checkable structural invariants | G1/CI | +| `tests/test_validate_spec.py` | regression tests validator/trace mapping | G1/CI | + +## Реализация + +На момент этой версии отсутствует. Ни одна строка `Specified` не должна интерпретироваться как готовая функция. Переход к реализации разрешён только после G0/G1 и явного operator approval. diff --git a/scripts/validate_spec.py b/scripts/validate_spec.py new file mode 100644 index 0000000..3e5f91a --- /dev/null +++ b/scripts/validate_spec.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Structural validator for Agent Control Center specification documents.""" +from __future__ import annotations + +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +SPEC = ROOT / "docs" / "SPECIFICATION.md" +ARCH = ROOT / "docs" / "ARCHITECTURE.md" +RESEARCH = ROOT / "docs" / "RESEARCH.md" +QUESTIONS = ROOT / "docs" / "OPEN-QUESTIONS.md" +TRACEABILITY = ROOT / "docs" / "TRACEABILITY.md" +README = ROOT / "README.md" +VALIDATOR = ROOT / "scripts" / "validate_spec.py" + +REQUIRED_FILES = [ + SPEC, + ARCH, + RESEARCH, + QUESTIONS, + TRACEABILITY, + README, + VALIDATOR, +] +REQUIRED_SECTIONS = [ + "Назначение", + "Не-цели MVP", + "Пользователи и роли", + "Функциональные требования", + "Нефункциональные требования", + "UI/UX specification", + "API и event contract", + "Data lifecycle", + "Acceptance strategy", + "Delivery plan", + "Риски и меры", + "Approval record", +] +REQ_RE = re.compile(r"\*\*((?:FR|NFR)-[A-Z]+-\d{3})\*\*") +AT_RE = re.compile(r"\*\*(AT-(?:FR|NFR)-[A-Z]+-\d{3})[:*]") +BLOCKER_RE = re.compile(r"\|\s*OQ-\d{3}\s*\|\s*BLOCKER\s*\|") +LOCAL_LINK_RE = re.compile(r"\[[^\]]+\]\((?!https?://|mailto:|#)([^)]+)\)") + + +def fail(message: str) -> None: + print(f"ERROR: {message}") + + +def main() -> int: + errors = 0 + for path in REQUIRED_FILES: + if not path.is_file() or path.stat().st_size == 0: + fail(f"missing or empty required file: {path.relative_to(ROOT)}") + errors += 1 + + if errors: + return 1 + + spec = SPEC.read_text(encoding="utf-8") + questions = QUESTIONS.read_text(encoding="utf-8") + + for section in REQUIRED_SECTIONS: + if section not in spec: + fail(f"missing required section: {section}") + errors += 1 + + reqs = REQ_RE.findall(spec) + ats = AT_RE.findall(spec) + req_set = set(reqs) + at_targets = {at.removeprefix("AT-") for at in ats} + + duplicates = sorted({req for req in reqs if reqs.count(req) > 1}) + duplicate_ats = sorted({at for at in ats if ats.count(at) > 1}) + if duplicates: + fail(f"duplicate requirement IDs: {', '.join(duplicates)}") + errors += 1 + if duplicate_ats: + fail(f"duplicate acceptance test IDs: {', '.join(duplicate_ats)}") + errors += 1 + + missing_at = sorted(req_set - at_targets) + orphan_at = sorted(at_targets - req_set) + if missing_at: + fail(f"requirements without acceptance test: {', '.join(missing_at)}") + errors += 1 + if orphan_at: + fail(f"acceptance tests without requirement: {', '.join(orphan_at)}") + errors += 1 + + for prefix, minimum in (("FR-", 35), ("NFR-", 20)): + count = sum(req.startswith(prefix) for req in req_set) + if count < minimum: + fail(f"too few {prefix} requirements: {count} < {minimum}") + errors += 1 + + blockers = BLOCKER_RE.findall(questions) + if not blockers: + fail("OPEN-QUESTIONS.md must identify blocking decisions") + errors += 1 + + for markdown in ROOT.rglob("*.md"): + text = markdown.read_text(encoding="utf-8") + for raw_target in LOCAL_LINK_RE.findall(text): + target = raw_target.split("#", 1)[0] + if target and not (markdown.parent / target).resolve().exists(): + fail( + f"broken local Markdown link in {markdown.relative_to(ROOT)}: " + f"{raw_target}" + ) + errors += 1 + + if "implementation blocked" not in spec.lower() or "implementation blocked" not in README.read_text(encoding="utf-8").lower(): + fail("draft implementation block must be explicit in spec and README") + errors += 1 + + if errors: + print(f"FAIL: {errors} structural issue(s)") + return 1 + + print( + "PASS: specification structure valid; " + f"requirements={len(req_set)} (FR={sum(r.startswith('FR-') for r in req_set)}, " + f"NFR={sum(r.startswith('NFR-') for r in req_set)}); " + f"acceptance_tests={len(at_targets)}; blockers={len(blockers)}" + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/test_validate_spec.py b/tests/test_validate_spec.py new file mode 100644 index 0000000..01891a9 --- /dev/null +++ b/tests/test_validate_spec.py @@ -0,0 +1,41 @@ +from __future__ import annotations + +import importlib.util +import subprocess +import sys +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +VALIDATOR = ROOT / "scripts" / "validate_spec.py" + + +class ValidateSpecTests(unittest.TestCase): + def test_repository_specification_is_structurally_valid(self) -> None: + result = subprocess.run( + [sys.executable, str(VALIDATOR)], + cwd=ROOT, + capture_output=True, + text=True, + check=False, + ) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("PASS: specification structure valid", result.stdout) + + def test_requirement_and_acceptance_ids_are_one_to_one(self) -> None: + module_spec = importlib.util.spec_from_file_location("validate_spec", VALIDATOR) + if module_spec is None or module_spec.loader is None: + self.fail("could not load specification validator module") + module = importlib.util.module_from_spec(module_spec) + module_spec.loader.exec_module(module) + + text = (ROOT / "docs" / "SPECIFICATION.md").read_text(encoding="utf-8") + requirements = module.REQ_RE.findall(text) + acceptance = [item.removeprefix("AT-") for item in module.AT_RE.findall(text)] + self.assertEqual(len(requirements), len(set(requirements))) + self.assertEqual(len(acceptance), len(set(acceptance))) + self.assertSetEqual(set(requirements), set(acceptance)) + + +if __name__ == "__main__": + unittest.main()