Forge
markdownf8555a15
1# ADR-0001: Binding architecture — bridge MVP and native production tier
2
3**Статус:** принято
4**Дата:** 2026-06-06
5**Репозиторий:** [AI-Guiders/pywitdb](https://github.com/AI-Guiders/pywitdb)
6**Upstream:** [WitDatabase](https://github.com/dmitrat/WitDatabase) (`OutWit.Database.Core`)
7
8---
9
10## Решение (одной фразой)
11
12**Двухфазная архитектура:** MVP — **JSON subprocess bridge** через маленький .NET CLI (`witdb-bridge`); production — **NativeAOT C ABI + `ctypes`** с wheels per-platform. Оба тира читают/пишут тот же `.witdb`; Python API один.
13
14---
15
16## Контекст
17
18- WitDatabase — source of truth для формата `.witdb` и ACID semantics (.NET, NuGet).
19- Python-экосистема (agents, lab, ETL) нуждается в официальном пакете **pywitdb** (PyPI), не в subprocess-хаках и не в форке формата.
20- CascadeIDE / Intercom уже используют `.witdb` через `UseWitDb`; cross-lang сценарий: C# пишет store, Python читает.
21- В репозитории **AI-Guiders** — отдельный продукт; замена sqlite в CASA — out of scope (отдельный ADR при необходимости).
22
23## Цели v0
24
25| API | Семантика |
26|-----|-----------|
27| `open(path, password=...)` | Открыть/создать `.witdb` |
28| `get` / `put` / `delete` | KV по bytes-ключам |
29| `transaction()` | ACID batch; rollback on exception |
30| context manager | `close` on exit |
31
32SQL, EF, Studio UI — **не** в v0.
33
34---
35
36## Рассмотренные варианты
37
38### A. JSON subprocess bridge (`.NET` CLI)
39
40Python spawn `witdb-bridge`; протокол — **newline-delimited JSON** (NDJSON) по stdin/stdout.
41
42**Плюсы:** быстрый MVP; без изменений в WitDatabase Core; контрактные тесты C#↔Python сразу; один CLI для dev/CI.
43**Минусы:** latency; нужен .NET runtime рядом; отдельный процесс на store (или connection pool позже).
44
45### B. `pythonnet` / embedded CLR
46
47Python грузит .NET runtime in-process.
48
49**Плюсы:** без subprocess overhead.
50**Минусы:** тяжёлая зависимость; fragile wheels; плохой DX на Linux/macOS CI; не цель PyPI «лёгкий pip install».
51
52### C. gRPC / HTTP sidecar
53
54Отдельный long-lived .NET service.
55
56**Плюсы:** масштабирование, remote store позже.
57**Минусы:** overkill для embedded local `.witdb`; ops burden для v0.
58
59### D. NativeAOT C export + `ctypes`
60
61WitDatabase (upstream PR) экспортирует стабильный C ABI; pywitdb публикует platform wheels.
62
63**Плюсы:** prod latency; нет .NET в Python-процессе; стандартный путь для Python native extensions.
64**Минусы:** работа в upstream; ABI versioning; matrix win/linux/macOS в CI.
65
66### E. Чистый Python reimplementation формата
67
68**Отклонено:** дублирует source of truth, риск drift от `.witdb`.
69
70---
71
72## Принятое решение
73
74| Tier | Роль (2026-06) | Статус |
75|------|----------------|--------|
76| **D — Native ctypes** | **Prod default** (`backend="auto"` → native если DLL/wheel есть) | ✅ win-x64 publish + pytest |
77| **A — JSON bridge** | **Dev / CI / fallback** (нет native под RID; contract tests без AOT matrix) | ✅ `bridge/WitDbBridge` |
78
79`pythonnet` (B) и sidecar (C) — **не** выбираем.
80
81**Prod path дальше:** per-RID NativeAOT publish → PyPI wheels; upstream PR `OutWit.Database.Native` → `dmitrat/WitDatabase`. Bridge в release не обязателен.
82
83### MVP: `witdb-bridge` CLI
84
85Расположение: `bridge/WitDbBridge/` в репо **AI-Guiders/pywitdb**.
86
87- Target: `net10.0` (aligned с Core multi-TFM).
88- Project ref: `OutWit.Database.Core` + `BouncyCastle` (submodule witdatabase в monorepo).
89- Один процесс = один open store; Python держит subprocess lifecycle.
90
91**Протокол (v1):** запрос/ответ — одна JSON-строка на сообщение.
92
93```json
94{"id": 1, "op": "open", "path": "store.witdb", "password": null}
95{"id": 1, "ok": true}
96{"id": 2, "op": "put", "key": "bWV0YTpmdg==", "value": "OTQyNjY="}
97{"id": 2, "ok": true}
98{"id": 3, "op": "get", "key": "bWV0YTpmdg=="}
99{"id": 3, "ok": true, "value": "OTQyNjY=", "found": true}
100```
101
102- `key` / `value`: base64 bytes.
103- Ошибки: `{"id": N, "ok": false, "error": {"code": "...", "message": "..."}}`.
104- `transaction`: `begin` → ops → `commit` | `rollback` (nested не поддерживаем в v0).
105
106Python: `pywitdb._bridge` (`BridgeClient`, `BridgeDatabase`).
107
108### Native tier (prod)
109
110- Fork/upstream: `OutWit.Database.Native` + `include/witdb.h` (ADR-0003).
111- pywitdb: `pywitdb._native` + bundled wheels per RID (CI TBD).
112- `open(..., backend="auto")`: **native first**, иначе bridge если `witdb-bridge` собран.
113
114ABI versioning: `WITDB_ABI_VERSION` в заголовке; pywitdb pin minor at build time.
115
116---
117
118## PyPI и именование
119
120| Решение | Значение |
121|---------|----------|
122| **PyPI package name** | `pywitdb` (зафиксировано) |
123| **GitHub** | `AI-Guiders/pywitdb` only |
124| **Bridge executable** | `witdb-bridge` (shipped as .NET tool or alongside package in `bridge/` artifacts) |
125
126Имя `witdatabase` на PyPI — **не** используем (коллизия с брендом upstream).
127
128---
129
130## Тестирование и CI
131
1321. **pytest** (Python): unit + integration against bridge.
1332. **Contract fixture (C#):** test project пишет `.witdb` через `OutWit.Database.Core`; Python читает через pywitdb — тот же файл, те же KV.
1343. CI matrix: `windows-latest`, `ubuntu-latest` (bridge MVP); native tier добавляет per-RID jobs позже.
135
136---
137
138## Последствия
139
140### Положительные
141
142- MVP без блокера на upstream PR.
143- Один Python API; смена backend прозрачна для callers.
144- Cross-lang контракт проверяется в CI до native tier.
145
146### Отрицательные / долг
147
148- Bridge требует .NET SDK/runtime в dev и CI.
149- Два code path до v1 — поддерживать parity tests.
150- Native tier = отдельный трек PR в WitDatabase (не в AI-Guiders org).
151
152### Non-goals (повтор)
153
154- Не подменять `agent_field.db` / sqlite в ca-substrate-agent без ADR.
155- Не тащить EF Core в Python.
156- Не дублировать WitDatabase Studio.
157
158---
159
160## План реализации
161
162| # | Задача | Репо |
163|---|--------|------|
164| 1 | Bootstrap pywitdb layout, этот ADR | AI-Guiders/pywitdb |
165| 2 | `witdb-bridge` CLI + NDJSON protocol | ✅ AI-Guiders/pywitdb |
166| 3 | `pywitdb.open` / KV / `transaction` (bridge + native) | ✅ |
167| 4 | C# fixture + pytest contract (T1a/T1b) | ✅ `tests/test_contract.py` |
168| 5 | ADR-0002: provider keys при reopen | ✅ |
169| 6 | ADR-0003: C ABI + Native | ✅ fork; upstream PR pending |
170| 7 | PyPI wheels: linux-x64, osx-arm64, … | pending |
171| 8 | ADR-0004: SQL (WitSQL) для CASA journal | ✅ `0004-sql-layer-and-casa-journal.md` → implement |
172
173---
174
175## Ссылки
176
177- Канон-карточка: `knowledge/work/projects/door-to-singularity/pywitdb/README.md`
178- WitDatabase NuGet: `OutWit.Database.Core`
179
View only · write via MCP/CIDE