Forge

docs/ / adr/0001-binding-architecture-bridge-and-native.md · branch master

ADR-0001: Binding architecture — bridge MVP and native production tier

Статус: принято
Дата: 2026-06-06
Репозиторий: AI-Guiders/pywitdb
Upstream: WitDatabase (OutWit.Database.Core)


Решение (одной фразой)

Двухфазная архитектура: MVP — JSON subprocess bridge через маленький .NET CLI (witdb-bridge); production — NativeAOT C ABI + ctypes с wheels per-platform. Оба тира читают/пишут тот же .witdb; Python API один.


Контекст

  • WitDatabase — source of truth для формата .witdb и ACID semantics (.NET, NuGet).
  • Python-экосистема (agents, lab, ETL) нуждается в официальном пакете pywitdb (PyPI), не в subprocess-хаках и не в форке формата.
  • CascadeIDE / Intercom уже используют .witdb через UseWitDb; cross-lang сценарий: C# пишет store, Python читает.
  • В репозитории AI-Guiders — отдельный продукт; замена sqlite в CASA — out of scope (отдельный ADR при необходимости).

Цели v0

API Семантика
open(path, password=...) Открыть/создать .witdb
get / put / delete KV по bytes-ключам
transaction() ACID batch; rollback on exception
context manager close on exit

SQL, EF, Studio UI — не в v0.


Рассмотренные варианты

A. JSON subprocess bridge (.NET CLI)

Python spawn witdb-bridge; протокол — newline-delimited JSON (NDJSON) по stdin/stdout.

Плюсы: быстрый MVP; без изменений в WitDatabase Core; контрактные тесты C#↔Python сразу; один CLI для dev/CI.
Минусы: latency; нужен .NET runtime рядом; отдельный процесс на store (или connection pool позже).

B. pythonnet / embedded CLR

Python грузит .NET runtime in-process.

Плюсы: без subprocess overhead.
Минусы: тяжёлая зависимость; fragile wheels; плохой DX на Linux/macOS CI; не цель PyPI «лёгкий pip install».

C. gRPC / HTTP sidecar

Отдельный long-lived .NET service.

Плюсы: масштабирование, remote store позже.
Минусы: overkill для embedded local .witdb; ops burden для v0.

D. NativeAOT C export + ctypes

WitDatabase (upstream PR) экспортирует стабильный C ABI; pywitdb публикует platform wheels.

Плюсы: prod latency; нет .NET в Python-процессе; стандартный путь для Python native extensions.
Минусы: работа в upstream; ABI versioning; matrix win/linux/macOS в CI.

E. Чистый Python reimplementation формата

Отклонено: дублирует source of truth, риск drift от .witdb.


Принятое решение

Tier Роль (2026-06) Статус
D — Native ctypes Prod default (backend="auto" → native если DLL/wheel есть) ✅ win-x64 publish + pytest
A — JSON bridge Dev / CI / fallback (нет native под RID; contract tests без AOT matrix) bridge/WitDbBridge

pythonnet (B) и sidecar (C) — не выбираем.

Prod path дальше: per-RID NativeAOT publish → PyPI wheels; upstream PR OutWit.Database.Nativedmitrat/WitDatabase. Bridge в release не обязателен.

MVP: witdb-bridge CLI

Расположение: bridge/WitDbBridge/ в репо AI-Guiders/pywitdb.

  • Target: net10.0 (aligned с Core multi-TFM).
  • Project ref: OutWit.Database.Core + BouncyCastle (submodule witdatabase в monorepo).
  • Один процесс = один open store; Python держит subprocess lifecycle.

Протокол (v1): запрос/ответ — одна JSON-строка на сообщение.

{"id": 1, "op": "open", "path": "store.witdb", "password": null}
{"id": 1, "ok": true}
{"id": 2, "op": "put", "key": "bWV0YTpmdg==", "value": "OTQyNjY="}
{"id": 2, "ok": true}
{"id": 3, "op": "get", "key": "bWV0YTpmdg=="}
{"id": 3, "ok": true, "value": "OTQyNjY=", "found": true}
  • key / value: base64 bytes.
  • Ошибки: {"id": N, "ok": false, "error": {"code": "...", "message": "..."}}.
  • transaction: begin → ops → commit | rollback (nested не поддерживаем в v0).

Python: pywitdb._bridge (BridgeClient, BridgeDatabase).

Native tier (prod)

  • Fork/upstream: OutWit.Database.Native + include/witdb.h (ADR-0003).
  • pywitdb: pywitdb._native + bundled wheels per RID (CI TBD).
  • open(..., backend="auto"): native first, иначе bridge если witdb-bridge собран.

ABI versioning: WITDB_ABI_VERSION в заголовке; pywitdb pin minor at build time.


PyPI и именование

Решение Значение
PyPI package name pywitdb (зафиксировано)
GitHub AI-Guiders/pywitdb only
Bridge executable witdb-bridge (shipped as .NET tool or alongside package in bridge/ artifacts)

Имя witdatabase на PyPI — не используем (коллизия с брендом upstream).


Тестирование и CI

  1. pytest (Python): unit + integration against bridge.
  2. Contract fixture (C#): test project пишет .witdb через OutWit.Database.Core; Python читает через pywitdb — тот же файл, те же KV.
  3. CI matrix: windows-latest, ubuntu-latest (bridge MVP); native tier добавляет per-RID jobs позже.

Последствия

Положительные

  • MVP без блокера на upstream PR.
  • Один Python API; смена backend прозрачна для callers.
  • Cross-lang контракт проверяется в CI до native tier.

Отрицательные / долг

  • Bridge требует .NET SDK/runtime в dev и CI.
  • Два code path до v1 — поддерживать parity tests.
  • Native tier = отдельный трек PR в WitDatabase (не в AI-Guiders org).

Non-goals (повтор)

  • Не подменять agent_field.db / sqlite в ca-substrate-agent без ADR.
  • Не тащить EF Core в Python.
  • Не дублировать WitDatabase Studio.

План реализации

# Задача Репо
1 Bootstrap pywitdb layout, этот ADR AI-Guiders/pywitdb
2 witdb-bridge CLI + NDJSON protocol ✅ AI-Guiders/pywitdb
3 pywitdb.open / KV / transaction (bridge + native)
4 C# fixture + pytest contract (T1a/T1b) tests/test_contract.py
5 ADR-0002: provider keys при reopen
6 ADR-0003: C ABI + Native ✅ fork; upstream PR pending
7 PyPI wheels: linux-x64, osx-arm64, … pending
8 ADR-0004: SQL (WitSQL) для CASA journal 0004-sql-layer-and-casa-journal.md → implement

Ссылки

  • Канон-карточка: knowledge/work/projects/door-to-singularity/pywitdb/README.md
  • WitDatabase NuGet: OutWit.Database.Core
View only · write via MCP/CIDE