# Persistent Storage Schema Draft ## Database Target - production: PostgreSQL - local development: SQLite ## Persistence Path In Code SQLAlchemy adapter реализован в: - [src/ai_orchestrator/infrastructure/storage/sqlalchemy.py](/Z:/codex/ai_orchestrator/src/ai_orchestrator/infrastructure/storage/sqlalchemy.py) - [src/ai_orchestrator/infrastructure/storage/factory.py](/Z:/codex/ai_orchestrator/src/ai_orchestrator/infrastructure/storage/factory.py) Migration skeleton: - [alembic.ini](/Z:/codex/ai_orchestrator/alembic.ini) - [migrations/env.py](/Z:/codex/ai_orchestrator/migrations/env.py) - [migrations/versions/0001_initial_schema.py](/Z:/codex/ai_orchestrator/migrations/versions/0001_initial_schema.py) ## Tables ### projects - `project_id` pk - `name` - `config_blob` - `created_at` - `updated_at` ### conversations - `conversation_id` pk - `project_id` - `title` - `created_at` - `updated_at` ### messages - `message_id` pk - `conversation_id` - `role` - `content` - `attachments_json` - `created_at` ### tasks - `task_id` pk - `project_id` - `conversation_id` - `goal` - `inputs_json` - `status` - `requested_mode` - `effective_mode` - `current_node_id` - `result_summary_json` - `created_at` - `updated_at` ### task_graphs - `task_id` pk - `graph_version` - `graph_metadata_json` - `created_at` ### task_nodes - `node_id` pk - `task_id` - `node_type` - `status` - `input_json` - `output_json` - `dependencies_json` - `assigned_runner` - `attempts` - `retryable` - `timeout_ms` - `created_at` - `updated_at` ### task_events - `event_id` pk - `task_id` - `conversation_id` - `node_id` - `event_type` - `correlation_id` - `causation_id` - `payload_json` - `occurred_at` ### confirmations - `confirmation_id` pk - `task_id` - `node_id` - `status` - `scope` - `decision_json` - `preview_json` - `comment` - `created_at` - `resolved_at` ### worker_sessions - `session_id` pk - `worker_id` - `name` - `machine` - `os` - `version` - `status` - `capabilities_json` - `last_heartbeat_at` - `current_task_id` - `connected_at` - `disconnected_at` ### model_invocations - `invocation_id` pk - `task_id` - `node_id` - `slot` - `provider` - `model` - `status` - `request_json` - `response_json` - `usage_json` - `fallback_from_invocation_id` - `created_at` ### tool_invocations - `invocation_id` pk - `task_id` - `node_id` - `source_type` - `source_id` - `tool_name` - `status` - `request_json` - `response_json` - `created_at` ### artifacts - `artifact_id` pk - `task_id` - `node_id` - `artifact_type` - `storage_uri` - `metadata_json` - `created_at` ## Required Indexes - `tasks(status, updated_at)` - `task_nodes(task_id, status)` - `task_events(task_id, occurred_at)` - `confirmations(status, created_at)` - `worker_sessions(status, last_heartbeat_at)` ## Query Support Read-model adapters now support paginated queries for: - `task_events` - `model_invocations` - `tool_invocations` - `artifacts` This is implemented in both in-memory and SQLAlchemy adapters to keep test/runtime behavior aligned. ## Active Adapter Strategy - `memory` backend остается для быстрых unit/integration прогонов; - `sqlite` backend предназначен для локального development без Docker; - `postgres` backend является production target.