Files
microdao-daarion/docs/fabric_contract.md
Apple 9a36020316 P3.5-P3.7: 2-layer inventory, capability routing, STT/TTS adapters, Dev Contract
NCS:
- _collect_worker_caps() fetches capability flags from node-worker /caps
- _derive_capabilities() merges served model types + worker provider flags
- installed_artifacts replaces inventory_only (disk scan with DISK_SCAN_PATHS env)
- New endpoints: /capabilities/caps, /capabilities/installed

Node Worker:
- STT_PROVIDER, TTS_PROVIDER, OCR_PROVIDER, IMAGE_PROVIDER env flags
- /caps endpoint returns capabilities + providers for NCS aggregation
- STT adapter (providers/stt_mlx_whisper.py) — remote + local mode
- TTS adapter (providers/tts_mlx_kokoro.py) — remote + local mode
- OCR handler via vision_prompted (ollama_vision with OCR prompt)
- NATS subjects: node.{id}.stt/tts/ocr/image.request

Router:
- POST /v1/capability/{stt,tts,ocr,image} — capability-based offload routing
- GET /v1/capabilities — global view with capabilities_by_node
- require_fresh_caps(ttl) preflight guard
- find_nodes_with_capability(cap) + load-based node selection

Ops:
- ops/fabric_snapshot.py — full runtime snapshot collector
- ops/fabric_preflight.sh — quick check + snapshot save + diff
- docs/fabric_contract.md — Dev Contract v0.1 (preflight-first)
- tests/test_fabric_contract.py — CI enforcement (6 tests)

Made-with: Cursor
2026-02-27 05:24:09 -08:00

160 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Dev Contract: Preflight-first, Node-specific, Zero Assumptions (v0.1)
## 0. Заборона припущень
Будь-яка дія/пропозиція щодо моделей, провайдерів, портів, compose або routing **заборонена без preflight snapshot** з цільової ноди.
Без snapshot — ні коміт, ні деплой, ні рекомендація.
## 1. Обов'язковий Preflight Snapshot
### 1.1 Збір
Перед кожною зміною запустити `ops/fabric_snapshot.py` на цільовій ноді:
```bash
# NODA2 (локально)
python3 ops/fabric_snapshot.py --node-id NODA2
# NODA1 (через SSH tunnel)
ssh -L 18099:127.0.0.1:8099 -L 18109:127.0.0.1:8109 \
-L 19102:127.0.0.1:9102 -fN root@144.76.224.179
python3 ops/fabric_snapshot.py --node-id noda1 \
--ncs http://127.0.0.1:18099 --worker http://127.0.0.1:18109 \
--router http://127.0.0.1:19102 --ollama http://127.0.0.1:21434 \
--ssh root@144.76.224.179
```
Snapshot зберігається в `ops/preflight_snapshots/<node_id>_<timestamp>.json`.
### 1.2 Endpoints (всі обов'язкові)
| Endpoint | Що перевіряє |
|---|---|
| `NCS /capabilities` | served_models, capabilities, node_load, runtimes |
| `NCS /capabilities/caps` | capability flags (stt/tts/ocr/image) |
| `NCS /capabilities/installed` | installed_artifacts (disk scan) |
| `node-worker /caps` | provider flags (STT_PROVIDER, TTS_PROVIDER...) |
| `node-worker /healthz` | NATS connection, concurrency |
| `Router /v1/capabilities` | global view (всі ноди, capabilities_by_node) |
| `Router /v1/models` | глобальний пул моделей |
| `Ollama /api/tags` | реальні Ollama моделі на ноді |
| `docker ps` | список контейнерів |
### 1.3 Quality gate (must-pass)
Snapshot валідний тільки якщо:
- Router healthy
- NCS healthy
- Node-worker healthy
- `capabilities_by_node` містить цільову ноду
- `served_models` не порожній (або є пояснення "compute-less node")
## 2. Served ≠ Installed
### 2.1 Два шари правди
| Шар | Джерело | Використання |
|---|---|---|
| **served_models** | NCS /capabilities → runtimes (Ollama/llama-server/...) | Routing, model selection, offload |
| **installed_artifacts** | NCS /capabilities/installed → disk scan | Інвентаризація, recommendations, cleanup |
Модель на диску — це **candidate**, не "доступна".
### 2.2 Заборона hardcode
- Заборонено комітити `models:` списки в swapper/router configs
- Дозволено: policy-only `prefer` (тип/клас моделі), але не імена, крім критичних cloud SKU
## 3. Capability-first routing
### 3.1 Routing rules
Router обирає **ноду**, не "модель":
1. `find_nodes_with_capability(cap)` — тільки ноди де cap=true
2. `require_fresh_caps(ttl=30)` — preflight guard
3. Circuit breaker — виключити ноди з відкритим breaker
4. Load scoring — `inflight * 10 + (100 if mem_pressure=high)`
5. Offload через NATS `node.{id}.{cap}.request`
### 3.2 Fail fast
Якщо capability відсутня на всіх нодах — **fail fast** з явним повідомленням:
```json
{"error": "No node with capability 'stt' available", "capabilities_by_node": {...}}
```
Заборонено: тихий fallback на cloud без WARNING log.
### 3.3 Нодозалежність
STT/TTS/OCR/Image **можуть бути різними** на різних нодах:
- NODA2: `STT_PROVIDER=mlx_whisper`, `TTS_PROVIDER=mlx_kokoro`
- NODA1: `STT_PROVIDER=none`, `OCR_PROVIDER=vision_prompted`
Вмикання capability = тільки через env flags в node-worker → `/caps`.
## 4. Безпечний контроль змін
### 4.1 План змін (обов'язково)
Перед зміною відповісти на:
1. **Що** міняємо
2. **Чому**
3. **Що може зламатися**
4. **Як перевіряємо** (postflight)
5. **Rollback** (точна команда)
### 4.2 Rollback
Кожна зміна має мати:
- git commit hash / tag
- одну команду rollback (`docker compose up -d --force-recreate <service>`, `git checkout`)
## 5. Postflight
Після кожної зміни — повторний snapshot і порівняння:
- served_models count (не зменшився без причини)
- capabilities map (нові = очікувані)
- container count
- error rate (prom_metrics)
## 6. Жодних прихованих fallback
- Невідомий профіль або відсутній API key → WARNING + deterministic fallback на `agent.fallback_llm`
- Заборонено: "мовчки пішли в DeepSeek" без логу
## 7. Канонічні артефакти
| Артефакт | Призначення |
|---|---|
| `ops/fabric_snapshot.py` | Збір повного snapshot |
| `ops/fabric_preflight.sh` | Quick check + snapshot save |
| `ops/preflight_snapshots/` | Зберігання snapshots |
| `docs/fabric_contract.md` | Цей контракт |
## Реальний стан (snapshot 2026-02-27)
### NODA1 (production)
- **49 контейнерів** (gateway, router, memory, qdrant, neo4j, redis, postgres, minio, rag, swapper, farmos, brand-*, oneok-*, plant-vision, crawl4ai, grafana, prometheus...)
- **5 Ollama моделей**: qwen3-vl:8b (vision), qwen3:8b, qwen3.5:27b-q4_K_M, smollm2:135m, deepseek-v3.1:671b-cloud
- **14 Telegram агентів** active
- **NCS P3.5 не задеплоєний** — capabilities flags відсутні, installed_artifacts = 0
- `swapper=disabled`, worker NATS connected
### NODA2 (development)
- **14 контейнерів** (router, node-worker, node-capabilities, nats, gateway, memory, qdrant, postgres, neo4j, redis, open-webui, sofiia-console, swapper)
- **13 served моделей** (Ollama: 12 + llama_server: 1)
- **29 installed artifacts** на диску (150.3GB LLM + 0.3GB TTS kokoro-v1_0)
- **capabilities**: llm=Y, vision=Y, ocr=Y, stt=N, tts=N, image=N
- `OCR_PROVIDER=vision_prompted`