ducklm/ARCHITECTURE.md

8.8 KiB
Raw Blame History

ARCHITECTURE

Этот документ фиксирует целевую архитектуру ducklm как локального event-driven multi-model execution runtime.

TASK_3.md — это директива для ИИ-кодера. ARCHITECTURE.md — это короткая инженерная карта системы: что является ядром, какие есть слои, как течёт управление, где принимаются решения, а где только исполняются переходы.

1. Core Principle

Система строится вокруг Runtime Loop Controller.

Центр системы:

  • не router
  • не orchestrator
  • не execution engine

Центр системы:

  • runtime loop

Именно он замыкает жизненный цикл задачи:

task
  -> state load/create
  -> context build
  -> orchestration decision
  -> plan/directive
  -> execution
  -> critic
  -> memory policy
  -> checkpoint
  -> next step / complete / fail

2. Layer Model

Целевая форма системы:

Client / CLI / API
        |
        v
Runtime Loop Controller
        |
        +--> State Store / Checkpoints
        +--> Context Builder
        +--> Router
        +--> Orchestrator / Planner
        +--> Execution Engine / Scheduler
        |         |
        |         +--> Tool Layer
        |         +--> Coder
        |
        +--> Critic
        +--> Memory Write Policy
        +--> Memory Store + Vector Index
        +--> Event Bus + Event Store
        +--> Streaming Projection

Принцип:

  • runtime loop координирует
  • router рекомендует
  • orchestrator думает
  • execution engine исполняет
  • tools/coder делают работу
  • critic оценивает
  • memory policy решает запись
  • event bus фиксирует историю
  • state store даёт resume

3. Responsibility Boundaries

Runtime Loop Controller

Отвечает за:

  • task lifecycle
  • state transitions
  • вызов компонентов в правильном порядке
  • применение decision objects
  • checkpointing
  • completion / failure path

Не отвечает за:

  • policy reasoning
  • raw tool execution
  • prompt assembly inline

Router

Это policy evaluator + decision suggester.

Контракт:

(input state + assembled context) -> ExecutionDirective

Свойства:

  • pure function
  • no side effects
  • no tool execution
  • no state mutation

Orchestrator / Planner

Отвечает за:

  • orchestration reasoning
  • deciding whether planning is needed
  • generating plan JSON
  • returning structured directives

Не отвечает за:

  • execution
  • direct state mutation
  • tool invocation

Execution Engine / Scheduler

Отвечает за:

  • step scheduling
  • task graph traversal
  • step execution coordination
  • calling tool/coder adapters
  • reporting structured results

Не отвечает за:

  • ownership of global lifecycle
  • high-level policy

Critic

Отвечает за:

  • evaluation of tool/coder outputs
  • returning structured scores and explanation

Не отвечает за:

  • final memory write decision
  • execution retry policy

Memory Write Policy

Отвечает за:

  • deterministic decision about storing memory
  • dedup / merge / skip behavior

Не отвечает за:

  • semantic retrieval
  • critic scoring

4. Decision Model

Все decision-producing components должны возвращать структурированные объекты.

Базовый контракт:

{
  "type": "plan|tool|coder|respond|replan|store_memory|request_permission|complete|fail|noop",
  "payload": {},
  "requires_permission": false,
  "confidence": 0.0,
  "reason": "string"
}

Это главный антихаосный инвариант системы.

Следствие:

  • компоненты не исполняют решения напрямую
  • компоненты не мутируют state напрямую
  • runtime loop применяет решения и переводит систему дальше

5. Execution Flow

Нормальный путь выполнения:

  1. Клиент отправляет task.
  2. Runtime loop создаёт или загружает task state.
  3. Публикуется task_received.
  4. Context builder собирает execution context.
  5. Router возвращает decision object.
  6. Orchestrator возвращает direct action или plan.
  7. План валидируется и преобразуется в task graph.
  8. Execution engine выбирает следующий шаг.
  9. Tool или coder исполняет шаг через adapter.
  10. Result возвращается в runtime loop.
  11. Critic возвращает evaluation suggestion.
  12. Memory policy возвращает decision по записи.
  13. State checkpoint сохраняется.
  14. Event bus фиксирует события.
  15. Runtime loop выбирает continue / replan / complete / fail.

6. Task Graph Model

Внешний planner может вернуть список шагов.

Внутри runtime план должен жить как task graph:

{
  "nodes": [
    {
      "id": "step-1",
      "kind": "tool",
      "tool": "shell_exec",
      "args": {"command": "hostnamectl"},
      "depends_on": []
    }
  ]
}

Сейчас допускается sequential DAG execution. В будущем это даёт путь к parallel scheduling без переписывания модели.

7. Event Backbone

Система event-driven.

EventBus нужен не только для стриминга, а как внутренняя хребтовая шина.

Минимальные свойства:

  • ordering per task
  • monotonic sequence per task
  • durable append to event store
  • replay capability
  • consumer idempotency

Минимальная модель доставки:

  • at least once

Правило идемпотентности:

  • событие дедуплицируется по task_id + sequence

Streaming layer — это projection от event bus, а не источник правды.

8. State Persistence

Так как runtime задуман как long-running autonomous system, in-memory lifecycle недостаточен.

Нужны:

  • task state store
  • checkpoint store
  • resume from crash/restart

Минимальная стратегия:

  • checkpoint after critical transitions
  • latest valid checkpoint is resumable

Primary choice для MVP:

  • SQLite

9. Async and Isolation

LLM loop не должен блокироваться долгими tool operations.

Поэтому нужны:

  • async execution adapters
  • timeout wrappers
  • cancellation handling
  • bounded concurrency

Для опасных или тяжёлых операций нужен отдельный sandbox layer.

Особенно для:

  • shell_exec
  • browser/web fallback
  • generated helper scripts

10. Memory Architecture

Memory — отдельная подсистема хранения, а не JSON dump.

Рекомендуемая форма:

  • metadata store: SQLite
  • vector index: FAISS или hnswlib

Два разных процесса:

  • retrieval
  • write decision

Это специально разделено.

critic только оценивает. memory write policy принимает финальное решение.

Минимальная логика записи должна быть детерминированной:

(critic_score + memory_type + runtime_weight + dedup_state + safety_state) -> decision

11. Failure Model

Система должна быть устойчивой к частичным сбоям.

Ожидаемые controlled failure paths:

  • invalid planner output -> replan or fail
  • tool timeout -> retry or fail
  • critic failure -> fallback policy
  • memory failure -> skip write and continue where safe
  • streaming failure -> sync fallback

Главный принцип:

  • subsystem failure не должен автоматически означать runtime collapse

12. Why This Shape

Эта архитектура нужна, чтобы система не деградировала в один из плохих вариантов:

  • router-god-object
  • runtime loop with hidden policy logic
  • LLM that directly executes tools
  • streaming instead of event model
  • critic as memory authority
  • in-memory only autonomous runtime

Если держать эти границы жёстко, проект остаётся расширяемым. Если границы размыть, система быстро превратится в трудноотлаживаемый procedural agent.