348 lines
8.8 KiB
Markdown
348 lines
8.8 KiB
Markdown
# 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`
|
||
|
||
Именно он замыкает жизненный цикл задачи:
|
||
|
||
```text
|
||
task
|
||
-> state load/create
|
||
-> context build
|
||
-> orchestration decision
|
||
-> plan/directive
|
||
-> execution
|
||
-> critic
|
||
-> memory policy
|
||
-> checkpoint
|
||
-> next step / complete / fail
|
||
```
|
||
|
||
## 2. Layer Model
|
||
|
||
Целевая форма системы:
|
||
|
||
```text
|
||
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`.
|
||
|
||
Контракт:
|
||
|
||
```text
|
||
(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 должны возвращать структурированные объекты.
|
||
|
||
Базовый контракт:
|
||
|
||
```json
|
||
{
|
||
"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:
|
||
|
||
```json
|
||
{
|
||
"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` принимает финальное решение.
|
||
|
||
Минимальная логика записи должна быть детерминированной:
|
||
|
||
```text
|
||
(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.
|