refactor: outbox становится live-only стримом, cursor вынесен в :cursor-api

Семантика outbox'а — теперь чистый live-канал:
  * OutboxStore.conversationEvents(id) — больше не принимает after-cursor.
    Catchup (replay) делает клиент: journal.listFlow(afterSeq) + подписка
    на live. Outbox ответственен только за уведомления «что-то произошло».
  * OutboxStore.oldestCursor()/currentCursor()/OutboxGapException — удалены.
    Эпоха и offset живут ТОЛЬКО в CursorHolder/CursorStore, переживают
    рестарт и инкремент для каждого commit.
  * DurableEvent: commit принимает блок { cursor -> MessageRecord }
    (cursor выдаёт CursorStore; клиент не вычисляет offset сам).
  * MessageRecord больше не несёт cursor — это не его ответственность.

Новые модули:
  * :cursor-api         — Cursor(epoch, offset) + CursorHolder / MutableCursorHolder
  * :cursor-ksqlite     — KsqliteCursorHolder (персистентный)
  * :cursor-inmemory    — для тестов
  * :client-sync        — LocalSyncAgent (мини-агент поверх :client для десктопа)

Удалены:
  * :sync-core          — старая референсная реализация, заменена
                           cursor-разделением и :client.
  * outbox-ksqlite      — CursorStore/Schema уехали в :cursor-ksqlite.
  * OffsetSequencer / PersistentOffsetSequencer / InMemoryOffsetSequencer.

standalone:
  * ChatAgent/ConversationLoop/DurableLog/ToolDispatcher/ReflectionScheduler/
    ConversationEvents — подписка через push-паттерн (collect событий).
  * A2aBridge — currentCursor() и conversationEvents(after=) убраны.
  * SqliteStores — cursor_offset удалён из schema v4; seedNextFromJournal
    читает MAX(created_at).
  * Main.kt — outboxSequencer → outboxCursorHolder; user→agent (:server)
    transport удалён; debug-routes удалены; A2A остался.
  * Тесты ChatAgentTest/PersistenceTest переписаны на push-паттерн
    (subscribe-before-act, snapshot∪live = итоговое состояние). 25/25 + 19/19 ✅

server / client:
  * Routes эпоху читают из CursorHolder; снимки несут Cursor? для catchup.
  * AgentikAgent и HttpEventStore — те же подписки, без after-параметра.
  * ReconnectingOutbox / ReconnectingOutboxTest — без изменений API.
  * JournalStore API расширен count(after=Instant?) для unread-badge.
This commit is contained in:
2026-10-05 23:33:35 +03:00
parent 22a167ed03
commit 9e888227a3
115 changed files with 2147 additions and 6025 deletions
+21 -10
View File
@@ -44,6 +44,12 @@ include(":skills")
include(":server")
// Ktor-клиент, превращающий HTTP-фасад в `Agent`/`Conversation`.
include(":client")
// Транспорт-агностичный слой клиентской синхронизации: оборачивает `Agent`
// локальным стором бесед + durable-курсором (MutableCursorHolder) и ведёт
// протокол «снапшот + дельты». Зависит только от :proto/:journal-api/:cursor-api,
// поэтому переиспользуется любым клиентом (desktop, CLI, embedded), не только
// HTTP-овым :client.
include(":client-sync")
// CLI-клиент поверх :client — REPL со slash-командами и стримингом ответов.
// KMP со всеми целями (jvm + весь натив), jvm-таргет собирается как shadowJar.
// include(":agentik-cli") — отключено 2026-09-21: пользователь временно вывел
@@ -114,10 +120,14 @@ include(":context-ksqlite")
// ConversationStore / conversation table). Минимальный модуль:
// таблицы `message` + `conversation` + индексы.
include(":journal-ksqlite")
// ksqlite-реализация :outbox-api (CursorStore / outbox_cursor table).
// ksqlite-реализация :cursor-api (CursorHolder / outbox_cursor table).
// Персистентная позиция счётчика событий агента — переживает рестарт, чтобы
// клиент продолжал инкрементально (см. PersistentOffsetSequencer).
include(":outbox-ksqlite")
// клиент продолжал инкрементально (см. CursorHolder).
include(":cursor-ksqlite")
// In-memory-реализация :cursor-api (CursorHolder) — для тестов, dev-режима
// и ephemeral runtime; эпоха не переживает пересоздание holder'а.
include(":cursor-inmemory")
// ksqlite-реализация :reflection-api (ReflectionStore / reflection table).
// Минимальный модуль: только таблица `reflection` + 2 индекса.
include(":reflection-ksqlite")
@@ -150,10 +160,11 @@ include(":agent-api")
// SkillMiningComponent, слушающий outbox (Event.ConversationClosing /
// Event.CompactionTriggered) и добывающий новые скилы через SkillMiner.
include(":skill-mining")
// Референсная реализация спеки `SYNC-SYSTEM.md` — журнал событий с
// монотонным курсором + материализация + replace-resync, единый протокол
// для клиента и сервера. KMP с jvm/linuxX64/mingwX64 целями (ksqlite-
// ограничение). Тесты спеки в commonTest, интеграция с ksqlite — в jvmTest.
// Существующий код (outbox/journal/client/server) не трогаем; это чистый
// референс для последующей миграции.
include(":sync-core")
include(":cursor-api")
include(":sync")
include(":ksqlite-message-storage")
// Мосты между :proto-агентом и внешними мессенджерами. Каждый модуль —
// `pw.binom.agentik.integrations.<messenger>` с `TelegramBridgeComponent`
// (реализация `pw.binom.agentik.agent.Component`). Подключаются в
// `:standalone` при наличии соответствующего токена в env (см. AppConfig).
include(":integrations-telegram")