# Sofiia CTO Agent — Intelligence System Trace (C)

> Generated: 2026-02-26 | Реконструкція "інтелектуальної системи" Sofiia

---

## Загальна схема мислення

```
User Input (Telegram / Console / Voice)
        │
        ▼
  [BFF: sofiia-console]
  Auth + Rate limit + Session
        │
        ├─── Voice turn? ──► STT (memory-service) → sanitize_for_voice() → voice_fast_uk
        │
        └─── Text turn? ──► [Router /v1/agents/sofiia/infer]
                                     │
                        ┌────────────┴────────────┐
                        │                         │
                   LLM selection            Tool call?
                   (profile-based)          (tool_manager)
                        │                         │
                  [LLM response]          [Tool execution]
                        │                         │
                   <think> strip          RBAC check
                        │                         │
                   Memory save            Evidence
                        │                         │
                        └────────┬────────────────┘
                                 │
                         [Dialog Map update]
                         (SQLite tree / future Postgres graph)
                                 │
                         [Response to User]
                                 │
                         [TTS if voice mode]
```

---

## 1. Intent → Plan → Execute (Canonical CTO Flow)

### 1.1 Документовано
- **Docs:** `AGENTS.md` §Example Commands, `docs/ADR_ARCHITECTURE_VNEXT.md` §3.1 CrewAI Workers
- **Concept:** "Chat/Intent → Plan (Artifacts) → Execute as Job → Evidence → Dialog Map"
- **vNext Design:** вся концепція описана в цьому сеансі розмови

### 1.2 Реалізовано
- **Intent → Plan:** ✅ LLM inference через Router (`/v1/agents/sofiia/infer`)
- **Plan → Execute (Ops):** ✅ `/api/ops/run` dispatches pre-defined actions
- **Execute → Evidence:** ⚠️ частково — ops повертає result, але не зберігає як artifact
- **Evidence → Dialog Map:** ❌ ops artifacts не зшиваються в dialog_nodes

### 1.3 Розриви
- Немає загального **Job System** (тільки pre-defined ops actions)
- Немає `repo_changesets` / `ops_runs` як артефактів у DB
- Dialog Map не оновлюється автоматично від ops actions

---

## 2. Модулі Архітектури

### 2.1 BFF (sofiia-console)

**Документовано тут:**
- `docs/runbook/sofiia-control-plane.md`
- `docs/sofiia_ui_vnext_audit.md`
- `docs/fabric_contract.md`

**Реалізовано тут:**
- `services/sofiia-console/app/main.py` — FastAPI v0.3.0
- `services/sofiia-console/app/config.py` — node registry, ENV loading
- `docker-compose.node2-sofiia.yml` — deployment config

**Що BFF робить:**
```
1. API Gateway для UI (chat/voice/projects/ops/nodes)
2. Session management (SQLite sofiia.db)
3. Multi-provider LLM proxy (ollama/router/glm/grok)
4. Voice pipeline (STT→LLM→TTS, Phase 2 streaming)
5. Ops dispatcher (risk/pressure/backlog/notion/release)
6. Multi-node health monitor (polling + WebSocket fan-out)
7. Memory save (SQLite first, then Memory Service best-effort)
```

**Розриви:**
- Відсутній єдиний Job tracking (кожен ops action — one-shot, без persist)
- Відсутній `repo_changesets` flow
- `ops.html`, `chat.html`, `nodes.html` — fallback HTML, не окремі файли

---

### 2.2 LLM Routing

**Документовано тут:**
- `services/router/router-config.yml`
- `docs/architecture_inventory/01_SERVICE_CATALOG.md`
- `docs/OPENAPI_CONTRACTS.md`

**Реалізовано тут:**
- `services/router/main.py` — `/v1/agents/{agent_id}/infer`
- `services/router/router-config.yml` — `sofiia:` entry

**Конфігурація Sofiia (router-config.yml):**
```yaml
sofiia:
  primary: cloud_grok        # Grok API (Telegram mode)
  fallback: cloud_deepseek   # DeepSeek API
  # Console mode може override через ollama
```

**Voice profiles:**
```yaml
voice_fast_uk:
  prefer_models: [gemma3:latest, qwen3.5:35b-a3b, qwen3:14b]
  deadline_ms: 9000
  max_tokens: 256
  
voice_quality_uk:
  prefer_models: [qwen3.5:35b-a3b, qwen3:14b]
  deadline_ms: 12000
  max_tokens: 256
```

**Розриви:**
- Відсутній профіль для `repo_changeset` (long-form, structured output)
- Відсутній профіль для `plan_generation` (CTO structured plans)

---

### 2.3 Tool System

**Документовано тут:**
- `AGENTS.md` §Tool List
- `docs/architecture_inventory/02_TOOL_CATALOG.md`
- `config/rbac_tools_matrix.yml`

**Реалізовано тут:**
- `services/router/tool_manager.py` — TOOL_DEFINITIONS + execution
- `services/router/agent_tools_config.py` — per-agent allowlists

**RBAC роль `agent_cto`** (39 permissions):
```
docs: read       ops: read/exec_safe
repo: read       jobs: smoke/drift/backup/deploy
kb: read         risk: read/write
pr_review: use   pressure: read/write
contract: use    backlog: read/write/admin
config_lint: use deps: read/gate
threatmodel: use cost: read/gate
observability    drift: read/gate
incidents: write alerts: ingest/read/ack/claim
```

**Sofiia спеціалізовані tools (agent_tools_config.py):**
```python
AGENT_SPECIALIZED_TOOLS["sofiia"] = [
    "comfy_generate_image",
    "comfy_generate_video",
    "risk_engine_tool",
    "architecture_pressure_tool",
    "backlog_tool",
    "job_orchestrator_tool",
    "dependency_scanner_tool",
    "incident_intelligence_tool",
    "cost_analyzer_tool",
    "pieces_tool",
    "notion_tool",
]
```

**FULL_STANDARD_STACK** (16 tools available to all agents):
```
memory_search, graph_query, web_search, web_extract, crawl4ai_scrape,
remember_fact, image_generate, tts_speak, presentation_create/status/download,
file_tool, repo_tool, pr_reviewer_tool, contract_tool, oncall_tool,
observability_tool, config_linter_tool, threatmodel_tool, job_orchestrator_tool,
kb_tool, drift_analyzer_tool, pieces_tool
```

**Розриви:**
- Відсутній `repo_changeset_tool` (create/patch/plan/pr)
- Відсутній `ops_job_tool` (start/status/cancel з job tracking)
- `job_orchestrator_tool` є, але не пов'язаний з Dialog Map artifact creation

---

### 2.4 Memory System

**Документовано тут:**
- `docs/ADR_ARCHITECTURE_VNEXT.md` §2.5 Memory Service
- `docs/MEMORY_API_POLICY.md`
- `docs/AGENT-MEMORY-STANDARD.md`

**Реалізовано тут:**
- `services/memory-service/app/main.py` — threads/events/memories/facts/agents
- `services/memory-service/app/vector_store.py` — Qdrant
- `docker-compose.memory-node2.yml` — Postgres + Qdrant + Neo4j

**3 рівні пам'яті (згідно ADR):**

| Рівень | Qdrant | Neo4j | Postgres |
|--------|--------|-------|----------|
| Personal | `user_{id}_*` | `:User` nodes | `user_facts`, `user_sessions` |
| Team/DAO | `team_{id}_*` | `:Team`, `:Project` | `team_facts`, `team_quotas` |
| Public | `public_*` | `:Public` | `indexed_content` |

**Реальні колекції (NODA2):**
- `sofiia_messages` — 1183+ points
- `sofiia_summaries`
- Memory Service Postgres (port 5433, db `daarion_memory`)

**Console-рівень пам'яті (SQLite `sofiia.db`):**
```sql
projects, documents, sessions, messages
```

**Розриви:**
- Team/DAO namespace: описаний в ADR, реалізований лише для Personal
- E2EE для confidential: тільки в ADR, не реалізовано
- BFF і Memory Service "знають" одне про одного, але sync неповний

---

### 2.5 Planning System (Supervisor)

**Документовано тут:**
- `docs/supervisor/langgraph_supervisor.md`
- `docs/supervisor/postmortem_draft_graph.md`

**Реалізовано тут:**
- `services/sofiia-supervisor/app/main.py`
- `services/sofiia-supervisor/app/graphs/`

**Доступні LangGraph графи:**
```
alert_triage     → класифікація/ескалація алертів
incident_triage  → тріаж інцидентів (SLO, labels, owners)
postmortem_draft → автогенерація postmortem документа
release_check    → pre-release gate checks
```

**Архітектура (загальна):**
```
Event/Trigger → LangGraph Node → State update → Next Node
      ↓              ↓
  NATS event    Tool calls (via gateway_client)
                Memory writes
                Structured output (JSON)
```

**Розриви:**
- Немає `cto_intent_graph` (intent → plan → execute)
- Немає `repo_changeset_graph` (diff → plan → PR)
- Немає `dialog_map_builder_graph` (events → nodes/edges)
- Supervisor ізольований від BFF (не інтегрований у `/api/ops/run`)

---

## 3. Policies (Безпека, Дозволи, Approval)

### 3.1 Документовано
- `docs/PRIVACY_GATE.md` — Privacy Gate middleware
- `docs/ADR_ARCHITECTURE_VNEXT.md` §4 Privacy Gate
- `docs/AGENT_RUNTIME_POLICY.md`
- `config/rbac_tools_matrix.yml`
- `config/data_governance_policy.yml`
- `config/risk_policy.yml`

### 3.2 Реалізовано
- RBAC tool allowlist: ✅ `agent_tools_config.py`
- API key auth: ✅ `auth.py`
- Rate limiting: ✅ per-endpoint
- Upload sanitization: ✅ mime + filename + size
- Voice guardrails: ✅ `sanitize_for_voice()`
- Config linter (secrets detection): ✅ `tool_manager.py`

### 3.3 Не реалізовано
- **Privacy Gate middleware** (перевірка `mode=confidential` в Router): 📄 описаний, не реалізований
- **2-step Plan → Apply flow**: 📄 описаний як "dangerous actions", не реалізований
- **E2EE client-side encryption**: 📄 тільки ADR, не реалізований
- **Confidential doc indexing block**: 📄 тільки ADR, не реалізований

---

## 4. Event Model

### 4.1 Документовано
- `docs/ADR_ARCHITECTURE_VNEXT.md` §5 NATS Standards
- `docs/NATS_SUBJECTS.md`
- `docs/NATS_SUBJECT_MAP.md`

### 4.2 NATS Subjects (ADR canonical)
```
message.created.{channel_id}      # chat messages
attachment.created.{type}          # uploaded files
agent.run.requested.{agent_id}    # agent activation
agent.run.completed.{agent_id}
quota.consumed.{user_id}
audit.{service}.{action}          # append-only audit
ops.health.{service}
ops.alert.{severity}
```

### 4.3 Fabric Subjects (реалізовані у node-worker)
```
node.{id}.llm.request             # LLM offload
node.{id}.tts.request             # TTS offload
node.{id}.stt.request             # STT offload
node.{id}.voice.llm.request       # Voice LLM (dedicated)
node.{id}.voice.tts.request       # Voice TTS (dedicated)
node.{id}.voice.stt.request       # Voice STT (dedicated)
node.{id}.ocr.request             # OCR offload
node.{id}.crawl.request           # Crawl offload
node.{id}.image.request           # Image generation
```

### 4.4 Розриви
- `attachment.created` — реалізований частково (upload зберігає файл, але не публікує у NATS)
- `task_create`, `doc_upsert`, `meeting_create` — не реалізовані (потрібні для Dialog Map auto-edge)
- `agent.run.requested` → legacy flat subject ще може бути в деяких шляхах (відомий drift)
- Dialog Map не підписаний на NATS events

---

## 5. Memory Architecture (деталізована)

```
┌──────────────────────────────────────────────────────────┐
│                    Sofiia Memory Layers                   │
├──────────────────────────────────────────────────────────┤
│ Layer 0: Working Context (per-turn)                       │
│   - history[-12:] in BFF request                         │
│   - sanitize_for_voice() for voice turns                 │
├──────────────────────────────────────────────────────────┤
│ Layer 1: Session Memory (sofiia-console SQLite)           │
│   Tables: projects, documents, sessions, messages         │
│   TTL: indefinite (volume-backed)                        │
│   Fork: parent_msg_id для branching                      │
├──────────────────────────────────────────────────────────┤
│ Layer 2: Long-term Memory (Memory Service)                │
│   Qdrant: sofiia_messages (1183+ vectors)                │
│            sofiia_summaries                              │
│   Postgres: daarion_memory DB (facts, threads, events)   │
│   Neo4j: agent memory graph (infrastructure ready)       │
├──────────────────────────────────────────────────────────┤
│ Layer 3: Factual Memory (Key-Value)                       │
│   /facts/upsert, /facts/{key}                            │
│   Rolling summaries via /threads/{id}/summarize          │
└──────────────────────────────────────────────────────────┘
```

**Namespaces (implemented):**
- `sofiia_messages` — agent-specific collection
- Загальний: `{agent_id}_{type}` pattern

**Sync між Layer 1 і Layer 2:**
- `_do_save_memory()` у `main.py`: спочатку SQLite, потім Memory Service (best-effort)
- Немає зворотнього sync (Memory Service → SQLite)
- Немає конфліктів (append-only обидва)

---

## 6. Dialog Map Intelligence

### Поточна реалізація (Phase 1)
```
SQLite messages table (parent_msg_id = branching)
       ↓
GET /api/sessions/{sid}/map
       ↓
Python: build_tree(messages) → nodes/edges
       ↓
UI: <details><summary> tree
```

### Цільова реалізація (vNext Phase 2)
```
NATS events (task_create, doc_upsert, meeting_create)
       ↓
Dialog Map Builder (новий сервіс або Supervisor граф)
       ↓
Postgres: dialog_nodes + dialog_edges
       ↓
GET /projects/{id}/dialog-map
       ↓
UI: D3/Cytoscape canvas + live WS updates
```

**Node types (vNext):**
- `message` — chat message
- `task` — задача
- `doc` — документ/wiki
- `meeting` — зустріч
- `agent_run` — виклик агента
- `decision` — ADR/рішення
- `goal` — ціль/OKR

**Edge types (vNext):**
- `references` — A посилається на B
- `resolves` — A вирішує B
- `derives_task` — повідомлення → задача
- `updates_doc` — action → doc version
- `schedules` — message → meeting
- `summarizes` — rollup вузол

---

## 7. Preflight-First Policy

**Документовано тут:**
- `ops/fabric_preflight.sh`
- `docs/fabric_contract.md`

**Принцип:** "Zero assumptions" — перед будь-яким deploy/change:
1. Запустити `ops/fabric_preflight.sh`
2. Перевірити моделі (VOICE_REQUIRED_MODELS fail / VOICE_PREFERRED_MODELS warn)
3. Перевірити `ops/fabric_snapshot.py --save`
4. Тільки потім deploy

**Реалізовано:**
- `ops/fabric_preflight.sh` — перевірки моделей, voice health, canary
- `ops/scripts/voice_canary.py` — runtime canary (кожні 5–10 хв)
- `ops/voice_latency_audit.sh` — 10-сценарний latency audit

---

## Next Actions for UI Team (1–2 days)

1. **Ознайомитись із Supervisor API** (`/v1/graphs/{name}/runs`) — це готовий "job runner" для CTO workflows
2. **Розширити Supervisor**: додати `cto_intent_graph` на базі `release_check_graph` (спільна структура)
3. **NATS attachment events**: при upload в `docs_router.py` — публікувати `attachment.created` (1 рядок коду)
4. **Dialog Map NATS listener**: простий consumer що upsert-ить SQLite nodes при events
5. **`docs_versions` table**: ALTER TABLE + endpoint — 1–2 год роботи
6. **Privacy Gate stub**: додати перевірку `mode` поля в BFF, навіть якщо без шифрування
7. **Plan → Apply pattern**: для ops actions — показувати "план" перед запуском
8. **`agent_id` нормалізація**: замінити `"l"` на `"sofiia"` в node2 router-config.yml
9. **Memory sync**: додати endpoint для завантаження Sofiia memory з Memory Service у SQLite
10. **CTO Panel**: mock `/api/repo/changesets` і `/api/ops/runs` endpoints для UI розробки
