Get started

Рефакторинг стану з пріоритетом бази даних

Рефакторинг стану за принципом Database-First

Рішення

Використовувати дворівневу SQLite-схему:

  • Глобальна база даних: ~/.openclaw/state/openclaw.sqlite
  • База даних агента: одна SQLite-база даних на агента для робочого простору, стенограми, VFS, артефактів і великого runtime-стану, що належить агенту
  • Конфігурація залишається файловою: openclaw.json лишається поза базою даних. Runtime-профілі автентифікації переходять у SQLite; файли облікових даних зовнішнього провайдера або CLI залишаються керованими власником поза базою даних OpenClaw.

Глобальна база даних є базою даних control-plane. Вона володіє виявленням агентів, спільним станом Gateway, спарюванням, станом пристроїв/вузлів, журналами завдань і потоків, станом Plugin, runtime-станом планувальника, метаданими резервних копій і станом міграцій.

База даних агента є базою даних data-plane. Вона володіє метаданими сесії агента, потоком подій стенограми, робочим простором VFS або scratch-простором імен, артефактами інструментів, артефактами запусків і доступними для пошуку/індексування локальними кеш-даними агента.

Це дає один довговічний глобальний вигляд без примусового перенесення великих робочих просторів агентів, стенограм і бінарних scratch-даних у спільну смугу запису Gateway.

Жорсткий контракт

Ця міграція має одну канонічну runtime-форму:

  • Рядки сесій зберігають лише метадані сесії. Вони не повинні зберігати transcriptLocator, файлові шляхи стенограм, sibling JSONL-шляхи, шляхи lock-файлів, метадані pruning або вказівники сумісності файлової епохи.
  • Ідентичність стенограми завжди є SQLite-ідентичністю: {agentId, sessionId} плюс необов’язкові метадані теми там, де вони потрібні протоколу.
  • sqlite-transcript://... не є runtime- або протокольною ідентичністю. Новий код не повинен виводити, зберігати, передавати, парсити або мігрувати локатори стенограм. Runtime і тести взагалі не повинні містити псевдолокаторів; документація може згадувати цей рядок лише щоб заборонити його.
  • Застарілі sessions.json, transcript JSONL, .jsonl.lock, pruning, truncation і стара логіка session-path належать лише до шляху doctor-міграції/імпорту.
  • Застарілі псевдоніми конфігурації сесій належать лише до doctor-міграції. Runtime не інтерпретує session.idleMinutes, session.resetByType.dm або cross-agent agent:main:* псевдоніми main-session для іншого налаштованого агента.
  • Ідентичність маршрутизації сесії є типізованим реляційним станом. Гарячі runtime- та UI-шляхи мають читати sessions.session_scope, sessions.account_id, sessions.primary_conversation_id, conversations і session_conversations; вони не повинні парсити session_key або добувати session_entries.entry_json для ідентичності провайдера, окрім як compatibility shadow, поки старі call sites видаляються.
  • Маркери прямих повідомлень рівня каналу, як-от dm проти direct, є словником маршрутизації, а не локаторами стенограм або handles сумісності файлового сховища.
  • Застаріла конфігурація hook handler належить лише до поверхонь doctor-попередження/міграції. Runtime не повинен завантажувати hooks.internal.handlers; hooks виконуються лише через виявлені директорії hook і метадані HOOK.md.
  • Runtime startup, гарячі шляхи відповіді, Compaction, reset, recovery, diagnostics, TTS, memory hooks, subagents, маршрутизація команд Plugin, межі протоколу та hooks повинні передавати {agentId, sessionId} через runtime.
  • Тести мають seed-ити й перевіряти рядки SQLite-стенограм через {agentId, sessionId}. Тести, які лише доводять forwarding JSONL-шляху, збереження caller-supplied locator або сумісність transcript-file, треба видалити, якщо вони не покривають doctor-імпорт, non-session support/debug materialization або форму протоколу.
  • runEmbeddedPiAgent(...), підготовлені worker-запуски та внутрішня embedded-спроба не повинні приймати локатори стенограм. Вони відкривають SQLite transcript manager за {agentId, sessionId} і передають цей manager до internalized PI-compatible agent session, щоб застарілі callers не могли змусити runner записувати JSON/JSONL-стенограми.
  • Діагностика runner має зберігати runtime/cache/payload trace records у SQLite. Runtime-діагностика не повинна відкривати JSONL file override knobs або generic transcript JSONL export helpers; користувацькі експорти можуть матеріалізувати явні артефакти з рядків бази даних без передавання імен файлів назад у runtime.
  • Raw stream logging використовує OPENCLAW_RAW_STREAM=1 плюс SQLite diagnostics rows. Старий pi-mono контракт файлового logger PI_RAW_STREAM, PI_RAW_STREAM_PATH і raw-openai-completions.jsonl не є частиною runtime або тестів OpenClaw.
  • QMD memory indexing не повинен експортувати SQLite-стенограми у markdown-файли. QMD індексує лише налаштовані memory-файли; пошук стенограм сесій залишається SQLite-backed.
  • QMD SDK subpath є QMD-only для нового коду. Помічники індексування SQLite session transcript живуть у memory-core-host-engine-session-transcripts; будь-який QMD re-export є лише сумісністю і не повинен використовуватися runtime-кодом.
  • Вбудовані memory indexes живуть у базі даних агента-власника. Runtime config і resolved runtime contracts не повинні відкривати memorySearch.store.path; doctor видаляє цей застарілий config key, а поточний код передає агентський databasePath внутрішньо.

Робота з реалізації має продовжувати видаляти код, доки ці твердження не стануть істинними без винятків поза межами doctor/import/export/debug.

Цільовий стан і прогрес

Жорстка ціль

  • Одна глобальна SQLite-база даних володіє control-plane станом: state/openclaw.sqlite.
  • Одна SQLite-база даних на агента володіє data-plane станом: agents/<agentId>/agent/openclaw-agent.sqlite.
  • Конфігурація залишається файловою. openclaw.json не є частиною цього рефакторингу бази даних.
  • Застарілі файли є лише вхідними даними doctor-міграції.
  • Runtime ніколи не записує й не читає session або transcript JSONL як активний стан.

Цільові стани

  • not-started: runtime-код файлової епохи все ще записує активний стан.
  • migrating: doctor/import код може перенести файлові дані в SQLite.
  • dual-read: тимчасовий міст читає і SQLite, і застарілі файли. Цей стан заборонений для цього рефакторингу, якщо його явно не задокументовано як doctor-only.
  • sqlite-runtime: runtime читає і записує лише SQLite.
  • clean: застарілі runtime API й тести видалено, а guard запобігає регресіям.
  • done: документація, тести, резервне копіювання, doctor-міграція і changed checks доводять clean-стан.

Поточний стан

  • Сесії: clean для runtime. Рядки сесій живуть у базі даних на агента, runtime API використовують {agentId, sessionId} або {agentId, sessionKey}, а sessions.json є лише doctor-only застарілим входом.
  • Стенограми: clean для runtime. Події стенограм, ідентичності, snapshots і trajectory runtime events живуть у базі даних на агента. Runtime більше не приймає локатори стенограм або JSONL-шляхи стенограм.
  • PI embedded runner: clean. Embedded PI runs, prepared workers, Compaction і retry loops використовують SQLite session scope і відхиляють застарілі transcript handles.
  • Cron: clean для runtime. Runtime використовує cron_jobs і cron_run_logs; runtime-тести використовують SQLite storeKey naming, а файлові cron-шляхи залишаються лише в doctor legacy migration tests.
  • Реєстр завдань: clean. Runtime-рядки Task і Task Flow живуть у state/openclaw.sqlite; unshipped sidecar SQLite importers видалено.
  • Стан Plugin: clean. Рядки стану/blob Plugin живуть у спільній глобальній базі даних; старі plugin-state sidecar SQLite helpers захищені guard.
  • Пам’ять: sqlite-runtime для вбудованої пам’яті та індексування стенограм сесій. Таблиці memory index живуть у базі даних на агента, memory state Plugin використовує спільні plugin-state rows, а застарілі memory-файли є вхідними даними doctor-міграції або вмістом користувацького робочого простору.
  • Резервне копіювання: sqlite-runtime. Етапи резервного копіювання compact SQLite snapshots, пропускають live WAL/SHM sidecars, перевіряють SQLite integrity і записують backup runs у глобальну базу даних.
  • Doctor migration: migrating, навмисно. Doctor імпортує застарілі JSON, JSONL і retired sidecar stores у SQLite, записує migration runs/sources і видаляє успішні джерела.
  • E2E scripts: clean для runtime coverage. Docker MCP seeding записує SQLite rows. Runtime-context Docker script створює застарілий JSONL лише всередині doctor migration seed і явно називає legacy session index path.

Залишкова робота

  • [x] Перейменувати змінні cron runtime-test store подалі від storePath, якщо вони не є doctor legacy inputs. Файли: src/cron/service.test-harness.ts, src/cron/service.runs-one-shot-main-job-disables-it.test.ts, src/cron/service/timer.regression.test.ts, src/cron/service/ops.test.ts, src/cron/service/store.test.ts, src/cron/service.heartbeat-ok-summary-suppressed.test.ts, src/cron/service.main-job-passes-heartbeat-target-last.test.ts, src/cron/store.test.ts. Доказ: pnpm check:database-first-legacy-stores; rg -n 'storePath' src/cron --glob '!**/commands/doctor/**'.
  • [x] Видалити або перейменувати застарілі файлові export test mocks. Файл: src/auto-reply/reply/commands-export-test-mocks.ts. Доказ: rg -n 'resolveSessionFilePath|sessionFile|storePath|transcriptLocator' src/auto-reply/reply.
  • [x] Зробити Docker runtime-context legacy JSONL seed очевидно doctor-only. Файл: scripts/e2e/session-runtime-context-docker-client.ts. Доказ: rg -n 'sessions\\.json|sessionFile|\\.jsonl' scripts/e2e/session-runtime-context-docker-client.ts показує лише seedBrokenLegacySessionForDoctorMigration.
  • [x] Підтримувати згенеровані Kysely типи узгодженими після будь-якої зміни схеми. Файли: src/state/openclaw-state-schema.sql, src/state/openclaw-agent-schema.sql, src/state/*generated*. Доказ: зміни схеми в цьому проході немає; pnpm db:kysely:check; pnpm lint:kysely.
  • [x] Повторно запустити focused tests для змінених stores, commands і scripts. Доказ: pnpm test src/cron/service/store.test.ts src/cron/store.test.ts src/cron/service.heartbeat-ok-summary-suppressed.test.ts src/cron/service.main-job-passes-heartbeat-target-last.test.ts src/cron/service.every-jobs-fire.test.ts src/cron/service.persists-delivered-status.test.ts src/cron/service.runs-one-shot-main-job-disables-it.test.ts src/cron/service/ops.test.ts src/cron/service/timer.regression.test.ts src/auto-reply/reply/commands-export-trajectory.test.ts extensions/telegram/src/thread-bindings.test.ts extensions/slack/src/monitor/message-handler/prepare.test.ts src/acp/translator.session-lineage-meta.test.ts; git diff --check.
  • [x] Перед оголошенням done запустити changed gate або remote broad proof. Доказ: pnpm check:changed --timed -- <changed extension paths> пройшов на Hetzner Crabbox run run_3f1cabf6b25c після тимчасового налаштування Node 24/pnpm і явної path routing для synced no-.git workspace.

Не регресувати

  • Жодних transcript locators.
  • Жодних активних session files.
  • Жодних fake JSONL test fixtures, окрім doctor legacy migration tests.
  • Жодного raw SQLite access там, де очікується Kysely.
  • Жодних нових legacy DB migrations. Ця схема ще не постачалася; тримайте schema version на 1, якщо немає вагомої причини.

Припущення після читання коду

Жодні подальші продуктові рішення не блокують цей план. Реалізація має продовжуватися з такими припущеннями:

  • Використовуйте node:sqlite напряму та вимагайте середовище виконання Node 22+ для цього шляху сховища.
  • Залиште рівно один звичайний файл конфігурації. Не переносіть конфігурацію, маніфести Plugin або робочі області Git у SQLite під час цього рефакторингу.
  • Файли сумісності середовища виконання не потрібні. Застарілі файли JSON і JSONL є лише вхідними даними міграції. Локальні для гілки sidecar-файли SQLite ніколи не постачалися й видаляються замість імпорту.
  • openclaw doctor --fix відповідає за крок міграції застарілих файлів у базу даних. Запуск середовища виконання та openclaw migrate не повинні містити застарілі шляхи оновлення бази даних OpenClaw.
  • Сумісність облікових даних дотримується того самого правила: облікові дані середовища виконання зберігаються в SQLite. Старі файли auth-profiles.json, поагентні auth.json і спільні credentials/oauth.json є вхідними даними міграції doctor, а потім видаляються після імпорту.
  • Стан згенерованого каталогу моделей підтримується базою даних. Код середовища виконання не повинен записувати agents/<agentId>/agent/models.json; наявні файли models.json є застарілими вхідними даними doctor і видаляються після імпорту в agent_model_catalogs.
  • Середовище виконання не повинно мігрувати, нормалізувати або з’єднувати локатори транскриптів. Активна ідентичність транскрипта — це {agentId, sessionId} у SQLite. Шляхи файлів є лише застарілими вхідними даними doctor, а sqlite-transcript://... має зникнути з поверхонь середовища виконання, протоколу, хуків і Plugin, замість того щоб розглядатися як граничний дескриптор.
  • Читання транскриптів SQLite у середовищі виконання не запускають старі міграції форми записів JSONL і не переписують цілі транскрипти для сумісності. Нормалізація застарілих записів залишається в явних утилітах doctor/import. Doctor нормалізує застарілі файли транскриптів JSONL перед вставленням рядків SQLite; поточні рядки середовища виконання вже записані в поточній схемі транскриптів. Експорт траєкторії/сеансу читає ці рядки як є і не повинен виконувати застарілі міграції під час експорту.
  • Допоміжні функції розбору/міграції застарілих транскриптів JSONL призначені лише для doctor. Код формату транскриптів середовища виконання будує лише поточний контекст транскриптів SQLite; doctor відповідає за оновлення старих записів JSONL перед вставленням рядків.
  • Старий допоміжний модуль потокового передавання транскриптів JSONL, яким володіло середовище виконання, видалено. Код імпорту doctor відповідає за явне читання застарілих файлів; історія сеансів середовища виконання читає рядки SQLite.
  • Прив’язки app-server Codex використовують OpenClaw sessionId як канонічний ключ у просторі імен стану Plugin Codex. sessionKey — це метадані для маршрутизації/відображення й не повинен замінювати довговічний ідентифікатор сеансу або відроджувати ідентичність файла транскрипта.
  • Рушії контексту отримують поточний контракт середовища виконання напряму. Реєстр не повинен обгортати рушії повторними shim-обгортками, які видаляють sessionKey, transcriptScope або prompt; рушії, які не можуть приймати поточні параметри database-first, повинні явно падати, а не з’єднуватися мостом.
  • Вивід резервної копії має залишатися одним архівним файлом. Вміст бази даних має потрапляти до цього архіву як компактні знімки SQLite, а не як сирі live sidecar-файли WAL.
  • Пошук транскриптів корисний, але не потрібний для першого database-first зрізу. Спроєктуйте схему так, щоб FTS можна було додати пізніше.
  • Виконання worker має залишатися експериментальним за налаштуваннями, поки межа бази даних стабілізується.

Висновки читання коду

Поточна гілка вже пройшла етап proof-of-concept. Спільна база даних існує, Node node:sqlite під’єднано через невеликий допоміжний модуль середовища виконання, а колишні сховища тепер записують у state/openclaw.sqlite або у власну базу даних openclaw-agent.sqlite.

Робота, що залишилася, полягає не у виборі SQLite; вона полягає в тому, щоб утримати нову межу чистою і видалити всі інтерфейси у формі сумісності, які все ще виглядають як старий файловий світ:

  • Session storePath більше не є ідентичністю середовища виконання, формою тестової фікстури або полем корисного навантаження статусу. Тести середовища виконання та моста більше не містять назву контракту storePath; код doctor/міграції володіє цією застарілою лексикою.
  • Записи сеансів більше не проходять через стару внутрішньопроцесну чергу store-writer.ts. Записи патчів SQLite натомість використовують виявлення конфліктів і обмежений повтор.
  • Виявлення застарілих шляхів усе ще має чинні застосування для міграції, але код середовища виконання має припинити розглядати sessions.json і файли транскриптів JSONL як можливі цілі запису.
  • Таблиці, якими володіє агент, живуть у поагентних базах даних SQLite. Глобальна БД зберігає рядки реєстру/control-plane; ідентичність транскрипта — це {agentId, sessionId} у поагентних рядках транскриптів. Код середовища виконання не повинен зберігати шляхи файлів транскриптів або мігрувати локатори транскриптів.
  • Doctor уже імпортує кілька застарілих файлів. Очищення полягає в тому, щоб зробити це єдиною явною реалізацією міграції, яку викликає doctor, зі стійким звітом про міграцію.

Жодні додаткові продуктові питання не блокують реалізацію.

Поточна форма коду

Гілка вже має справжню спільну базу SQLite:

  • Мінімальна версія середовища виконання тепер Node 22+: package.json, захист середовища виконання CLI, стандартні налаштування інсталятора, локатор середовища виконання macOS, CI та публічна документація зі встановлення узгоджені. Старий канал сумісності з Node 22 вилучено.
  • src/state/openclaw-state-db.ts відкриває openclaw.sqlite, задає WAL, synchronous=NORMAL, busy_timeout=30000, foreign_keys=ON і застосовує згенерований модуль схеми, похідний від src/state/openclaw-state-schema.sql.
  • Типи таблиць Kysely і модулі схеми середовища виконання генеруються з одноразових баз даних SQLite, створених із зафіксованих файлів .sql; код середовища виконання більше не зберігає скопійовані вручну рядки схем для глобальних, поагентних або проксі- баз даних захоплення.
  • Сховища середовища виконання виводять вибрані та вставлені типи рядків із цих згенерованих інтерфейсів Kysely DB замість ручного дублювання форм рядків SQLite. Raw SQL залишається обмеженим застосуванням схеми, прагмами та DDL лише для міграцій.
  • Схеми SQLite зведено до user_version = 1, бо ця структура бази даних ще не постачалася. Відкривачі середовища виконання створюють лише поточну схему; імпорт із файлу до бази даних лишається в коді doctor, а локальні для гілки допоміжні засоби оновлення бази даних видалено.
  • Реляційне володіння забезпечується там, де межа володіння є канонічною: рядки міграції джерел каскадують від migration_runs, стан доставки завдань каскадує від task_runs, а рядки ідентичності транскриптів каскадують від подій транскриптів.
  • Поточні спільні таблиці включають agent_databases, auth_profile_stores, auth_profile_state, plugin_state_entries, plugin_blob_entries, media_blobs, skill_uploads, capture_sessions, capture_events, capture_blobs, sandbox_registry_entries, cron_run_logs, cron_jobs, commitments, delivery_queue_entries, model_capability_cache, workspace_setup_state, native_hook_relay_bridges, current_conversation_bindings, plugin_binding_approvals, tui_last_sessions, acp_sessions, acp_replay_sessions, acp_replay_events, task_runs, task_delivery_state, flow_runs, subagent_runs, migration_runs і backup_runs.
  • Довільний стан, яким володіє plugin, не отримує типізованих таблиць, якими володіє хост. Установлені plugins використовують plugin_state_entries для версіонованих JSON-навантажень і plugin_blob_entries для байтів, із володінням просторами імен/ключами, очищенням TTL, резервним копіюванням і записами міграцій plugin. Стан оркестрації plugins, яким володіє хост, усе ще може мати типізовані таблиці, коли хост володіє контрактом запитів, наприклад plugin_binding_approvals.
  • Міграції plugin — це міграції даних у просторах імен, якими володіє plugin, а не міграції схеми хоста. Plugin може мігрувати власні версіоновані записи стану/blob через провайдер міграцій, а хост записує стан джерела/запуску у звичайний журнал міграцій. Нові встановлення plugin не потребують змін openclaw-state-schema.sql, якщо сам хост не бере у володіння новий міжplugin-ний контракт.
  • src/state/openclaw-agent-db.ts відкриває agents/<agentId>/agent/openclaw-agent.sqlite, реєструє базу даних у глобальній DB і володіє агент-локальними таблицями сеансів, транскриптів, VFS, артефактів, кешу та індексу памʼяті. Спільне виявлення середовища виконання тепер читає згенеровано-типізований реєстр agent_databases замість повторної реалізації цього запиту в кожному місці виклику.
  • Глобальні та поагентні бази даних записують рядок schema_meta з роллю бази даних, версією схеми, часовими мітками та ідентифікатором агента для агентних баз даних. Структура все ще лишається на user_version = 1, бо ця схема SQLite ще не постачалася.
  • Ідентичність поагентного сеансу тепер має канонічну кореневу таблицю sessions із ключем session_id, з session_key, session_scope, account_id, primary_conversation_id, часовими мітками, полями відображення, метаданими моделі, ідентифікатором harness і звʼязками parent/spawn як колонками, доступними для запитів. session_routes є унікальним активним індексом маршруту від session_key до поточного session_id, тож ключ маршруту може перейти до нового довговічного сеансу без потреби для гарячих читань вибирати між дубльованими рядками sessions.session_key. Старе суміснісно-сформоване навантаження session_entries.entry_json привʼязане до довговічного кореня session_id зовнішнім ключем; воно більше не є єдиним представленням сеансу на рівні схеми.
  • Ідентичність зовнішньої розмови для агента теж реляційна: conversations зберігає нормалізовану ідентичність провайдера/облікового запису/розмови, а session_conversations повʼязує один сеанс OpenClaw з однією або кількома зовнішніми розмовами. Це покриває DM-сеанси shared-main, де кілька учасників можуть навмисно зіставлятися з одним сеансом без неправди в session_key. SQLite також забезпечує унікальність для природної ідентичності провайдера, тож той самий кортеж channel/account/kind/peer/thread не може розгалужуватися між ідентифікаторами розмов. Прямих учасників shared-main повʼязано з роллю participant, тож один сеанс OpenClaw може представляти кількох зовнішніх DM-учасників без пониження старіших учасників до нечітких related-рядків. sessions.primary_conversation_id усе ще вказує на поточну типізовану ціль доставки. Закриті колонки маршрутизації/стану забезпечуються обмеженнями SQLite CHECK, а не лише TypeScript-union. Проєкція сеансу середовища виконання очищає суміснісні тіні маршрутизації з session_entries.entry_json перед застосуванням типізованих колонок сеансу/розмови, тож застарілі JSON-навантаження не можуть воскресити цілі доставки. Маршрутизація оголошення subagent так само потребує типізованого контексту доставки SQLite; вона більше не повертається до суміснісних полів маршруту SessionEntry. Явне успадкування доставки Gateway chat.send читає типізований контекст доставки SQLite замість суміснісних полів origin/last*. tools.effective так само виводить контекст provider/account/thread із типізованих рядків доставки/маршрутизації SQLite, а не із застарілих тіней last* запису сеансу. Контекст prompt для системних подій перебудовує поля channel/to/account/thread із типізованих полів доставки замість тіней origin. Спільний helper deliveryContextFromSession і mapper сеансу до розмови тепер повністю ігнорують SessionEntry.origin; лише типізовані поля доставки та реляційні рядки розмов можуть створювати гарячу ідентичність маршруту. Нормалізація запису сеансу середовища виконання вилучає origin перед збереженням або проєктуванням entry_json, а вхідні метадані записують типізовані поля channel/chat плюс реляційні рядки розмов замість створення нових тіней origin.
  • Події транскриптів, знімки транскриптів і runtime-події траєкторії тепер посилаються на канонічний поагентний корінь sessions і каскадують під час видалення сеансу. Рядки ідентичності/ідемпотентності транскриптів далі каскадують від точного рядка події транскрипту.
  • Індекси memory-core тепер використовують явні таблиці агентної бази даних memory_index_meta, memory_index_sources, memory_index_chunks і memory_embedding_cache, а memory_index_state відстежує зміни ревізій. Необовʼязкові бічні FTS/vector-індекси названі memory_index_chunks_fts і memory_index_chunks_vec замість загальних таблиць meta, files, chunks, chunks_fts або chunks_vec. Канонічні назви зберігають поточну форму рядка path/source і сумісність серіалізованих embedding. Ці таблиці є похідним/пошуковим кешем, а не канонічним сховищем транскриптів; їх можна видалити й перебудувати з файлів робочої області памʼяті та налаштованих джерел. Відкриття поставленого індексу памʼяті із загальними назвами мігрує його метадані, джерела, chunks і кеш embedding у канонічні таблиці; похідні FTS/vector таблиці перебудовуються під їхніми канонічними назвами.
  • Стан відновлення запусків subagent тепер живе в типізованих спільних рядках subagent_runs з індексованими ключами дочірнього, requester і controller сеансів. Старий файл subagents/runs.json є лише вхідними даними міграції doctor.
  • Поточні привʼязки розмов тепер живуть у типізованих спільних рядках current_conversation_bindings із ключем за нормалізованим ідентифікатором розмови, з колонками цільового агента/сеансу, видом розмови, статусом, строком дії та метаданими, збереженими як реляційні колонки замість дубльованого непрозорого запису привʼязки. Довговічний ключ привʼязки включає нормалізований вид розмови, тож refs прямих/group/channel не можуть конфліктувати, а SQLite відхиляє неприпустимі значення виду/статусу привʼязки. Старий файл bindings/current-conversations.json є лише вхідними даними міграції doctor.
  • Відновлення черги доставки тепер накладає типізовані колонки черги для channel, target, account, session, retry, error, platform-send і стану відновлення на replay JSON. entry_json зберігає replay-навантаження, hooks і форматувальне навантаження, але типізовані колонки є авторитетними для гарячої маршрутизації/стану черги.
  • Вказівники відновлення останнього сеансу TUI тепер живуть у типізованих спільних рядках tui_last_sessions із ключем за хешованою областю підключення/сеансу TUI. Старий JSON-файл TUI є лише вхідними даними міграції doctor.
  • Стандартні налаштування TTS тепер живуть у спільних SQLite-рядках стану plugin з ключем під plugin speech-core. Старий файл settings/tts.json є лише вхідними даними міграції doctor; середовище виконання більше не читає й не записує JSON-файли налаштувань TTS, а legacy-розвʼязувач шляху живе в модулі міграції doctor.
  • Метадані цілі secret тепер говорять про сховища, а не вдають, що кожна ціль облікових даних є файлом конфігурації. openclaw.json лишається сховищем конфігурації; цілі auth-profile використовують типізовані SQLite-рядки auth_profile_stores з обліковими даними у формі провайдера, збереженими як JSON-навантаження.
  • Аудит secret більше не сканує вилучені поагентні файли auth.json. Doctor володіє попередженням про цей legacy-файл, його імпортом і видаленням.
  • Legacy-допоміжні засоби шляхів профілів auth тепер живуть у legacy-коді doctor. Допоміжні засоби шляхів core auth profile показують ідентичність SQLite auth-store та місця відображення, а не runtime-шляхи auth-profiles.json чи auth-state.json.
  • Модулі середовища виконання відновлення запусків subagent і кешу можливостей моделей OpenRouter тепер тримають читачі/писачі знімків SQLite окремо від допоміжних засобів імпорту legacy JSON, що призначені лише для doctor. Можливості OpenRouter використовують типізовані загальні рядки model_capability_cache під provider_id = "openrouter" замість одного непрозорого cache blob або специфічної для провайдера таблиці хоста. taskName запуску subagent зберігається в типізованій колонці subagent_runs.task_name; копія payload_json є даними для replay/debug, а не джерелом для гарячих полів відображення або lookup.
  • src/agents/filesystem/virtual-agent-fs.sqlite.ts реалізує SQLite VFS поверх таблиці vfs_entries агентної бази даних. Читання директорій, рекурсивні експорти, видалення та перейменування використовують індексовані діапазони префіксів (namespace, path) замість сканування всього простору імен або покладання на зіставлення шляхів через LIKE.
  • src/agents/runtime-worker.entry.ts створює по-запускові SQLite VFS, артефакти tool, артефакти запуску та scoped cache stores для workers.
  • Маркери завершення bootstrap робочої області тепер живуть у типізованих спільних рядках workspace_setup_state із ключем за розвʼязаним шляхом робочої області замість .openclaw/workspace-state.json; середовище виконання більше не читає й не перезаписує legacy-маркер робочої області, а helper API більше не передають фальшивий шлях .openclaw/setup-state лише для виведення ідентичності сховища.
  • Схвалення exec тепер живуть у типізованому singleton-рядку спільної SQLite exec_approvals_config. Doctor імпортує legacy ~/.openclaw/exec-approvals.json; записи середовища виконання більше не створюють, не перезаписують і не повідомляють цей файл як його активне місце сховища. Супутній застосунок macOS читає й записує той самий рядок таблиці state/openclaw.sqlite; він зберігає на диску лише Unix prompt socket, бо це IPC, а не довговічний стан середовища виконання.
  • Модулі середовища виконання ідентичності пристрою, auth пристрою та bootstrap тепер тримають свої читачі/писачі знімків SQLite окремо від допоміжних засобів імпорту legacy JSON, призначених лише для doctor. Ідентичність пристрою використовує типізовані рядки device_identities, а токени auth пристрою використовують типізовані рядки device_auth_tokens. Записи auth пристрою узгоджують рядки за device/role замість обрізання таблиці токенів, а середовище виконання більше не маршрутизує оновлення одного токена через старий whole-store adapter. Legacy JSON-навантаження версії 1 існують лише як форми імпорту/експорту doctor.
  • Кеш обміну токенів GitHub Copilot використовує спільну таблицю стану Plugin у SQLite за github-copilot/token-cache/default. Це кешований стан, яким володіє провайдер, тому він навмисно не додає таблицю схеми хоста.
  • Compaction GitHub Copilot більше не записує побічні файли робочого простору openclaw-compaction-*.json. Harness викликає RPC Compaction історії SDK для відстежуваного сеансу SDK, а OpenClaw зберігає довговічний стан сеансу/транскрипту в SQLite замість файлів-маркерів сумісності.
  • Спільний runtime Swift (OpenClawKit) використовує ті самі рядки state/openclaw.sqlite для ідентичності пристрою та автентифікації пристрою. Помічники застосунку macOS імпортують спільні помічники SQLite замість володіння другим JSON- або SQLite-шляхом. Залишковий застарілий identity/device.json блокує створення ідентичності, доки doctor не імпортує його в SQLite, що відповідає стартовому шлюзу TypeScript і Android.
  • Ідентичність пристрою Android використовує той самий сумісний із TypeScript ключовий матеріал, збережений у типізованих рядках state/openclaw.sqlite#table/device_identities. Він ніколи не читає і не записує openclaw/identity/device.json; залишковий застарілий файл блокує запуск, доки doctor не імпортує його в SQLite.
  • Кешовані токени автентифікації пристрою Android також використовують типізовані рядки state/openclaw.sqlite#table/device_auth_tokens і мають ту саму семантику токенів версії 1, що й TypeScript та Swift. Runtime більше не читає ключі сумісності SecurePrefs gateway.deviceToken*; вони належать лише логіці міграції/doctor.
  • Історія нещодавніх пакетів сповіщень Android використовує типізовані рядки android_notification_recent_packages. Runtime більше не мігрує і не читає старі CSV-ключі SharedPreferences.
  • Створення ідентичності пристрою завершується закритою відмовою, коли існує застарілий identity/device.json, коли рядок ідентичності SQLite недійсний або коли сховище ідентичності SQLite неможливо відкрити. Doctor спершу імпортує та видаляє цей файл, тому запуск runtime не може непомітно змінити ідентичність сполучення до міграції.
  • Вибір ідентичності пристрою є ключем рядка SQLite, а не локатором JSON-файлу. Тести й помічники Gateway передають явні ключі ідентичності; лише міграція doctor і стартовий шлюз із закритою відмовою знають назву вилученого файлу identity/device.json.
  • Сумісність скидання сеансу тепер живе в міграції конфігурації doctor: session.idleMinutes переноситься в session.reset.idleMinutes, session.resetByType.dm переноситься в session.resetByType.direct, а runtime-політика скидання читає лише канонічні ключі скидання.
  • Сумісність застарілої конфігурації тепер живе під src/commands/doctor/. Звичайна валідація readConfigFileSnapshot() не імпортує застарілі детектори doctor і не анотує застарілі проблеми; runDoctorConfigPreflight() додає ці проблеми для ремонту/звітування doctor. Потік конфігурації doctor імпортує src/commands/doctor/legacy-config.ts, а старий ремонт ідентифікаторів OAuth-профілів живе під src/commands/doctor/legacy/oauth-profile-ids.ts.
  • Команди не-doctor не запускають автоматично ремонт застарілої конфігурації. Наприклад, openclaw update --channel тепер завершується помилкою на недійсній застарілій конфігурації та просить користувача запустити doctor, замість непомітного імпорту коду міграції doctor.
  • Web push, APNs, Voice Wake, перевірки оновлень і стан конфігурації тепер використовують типізовані спільні таблиці SQLite для підписок, VAPID-ключів, реєстрацій вузлів, рядків тригерів, рядків маршрутизації, стану сповіщень про оновлення та записів стану конфігурації замість цілих непрозорих JSON-блобів. Записи знімків Web push і APNs тепер узгоджують підписки/реєстрації за первинним ключем замість очищення їхніх таблиць; стан конфігурації робить те саме за шляхом конфігурації. Їхні runtime-модулі тримають читачі/записувачі знімків SQLite окремо від допоміжних імпортерів застарілого JSON, призначених лише для doctor.
  • Конфігурація Node-хоста тепер використовує типізований singleton-рядок у спільній базі даних SQLite; doctor імпортує старий файл node.json перед звичайним використанням runtime.
  • Сполучення пристрою/вузла, сполучення каналів, allowlist каналів і стан bootstrap тепер використовують типізовані рядки SQLite замість цілих непрозорих JSON-блобів. Схвалення прив’язок Plugin і стан завдань Cron дотримуються того самого поділу: runtime-модулі надають операції на основі SQLite та нейтральні помічники знімків, а записи знімків сполучення/bootstrap і схвалення прив’язок Plugin узгоджують рядки за первинним ключем замість обрізання таблиць, тоді як doctor імпортує/видаляє старі JSON-файли через модулі src/commands/doctor/legacy/*.
  • Записи встановлених Plugin тепер живуть в індексі встановлених Plugin у SQLite. Runtime-читання/запис конфігурації більше не мігрує і не зберігає старі дані авторської конфігурації plugins.installs; doctor імпортує цю застарілу форму конфігурації в SQLite перед звичайним використанням runtime.
  • Знімки відновлення облікових даних QQBot тепер живуть у стані Plugin SQLite під qqbot/credential-backups. Runtime більше не записує qqbot/data/credential-backup*.json; контракт doctor QQBot імпортує та архівує ці застарілі файли резервних копій з активного каталогу стану.
  • Планування перезавантаження Gateway порівнює знімки індексу встановлених Plugin SQLite під внутрішнім простором імен diff installedPluginIndex.installRecords.*. Рішення runtime щодо перезавантаження більше не обгортають ці рядки у фальшиві об’єкти конфігурації plugins.installs.
  • Оновлення облікових даних іменованого акаунта Matrix більше не відбувається під час runtime читань. Doctor володіє перейменуванням старого верхньорівневого credentials/matrix/credentials.json, коли можна визначити один/default акаунт Matrix.
  • Основні модулі runtime для сполучення та cron більше не експортують застарілі побудовники JSON-шляхів. Застарілі модулі, якими володіє doctor, створюють вихідні шляхи pending.json, paired.json, bootstrap.json і cron/jobs.json лише для тестів імпорту та міграції. Нормалізація застарілої форми завдань cron і імпорт журналу запусків cron живуть під src/commands/doctor/legacy/cron*.ts.
  • src/commands/doctor/legacy/runtime-state.ts імпортує застарілі JSON-файли стану, включно з конфігурацією хоста вузла, у SQLite з doctor. Нові імпортери застарілих файлів залишаються під src/commands/doctor/legacy/.
  • src/commands/doctor/state-migrations.ts імпортує застарілі sessions.json і транскрипти *.jsonl безпосередньо в SQLite та видаляє успішні джерела. Він більше не проміжно розміщує кореневі застарілі транскрипти через agents/<agentId>/sessions/*.jsonl і не створює канонічну ціль JSONL перед імпортом.
  • Перевірки цілісності стану doctor більше не сканують застарілі каталоги сеансів і не пропонують видалення осиротілих JSONL. Застарілі файли транскриптів є лише вхідними даними міграції, а крок міграції володіє імпортом і видаленням джерел.
  • Імпорт застарілого реєстру sandbox живе під src/commands/doctor/legacy/sandbox-registry.ts; активні читання і записи реєстру sandbox залишаються лише SQLite.
  • Застарілий ремонт стану/імпорту транскриптів сеансів живе під src/commands/doctor/legacy/session-transcript-health.ts; runtime-модулі команд більше не містять парсинг JSONL-транскриптів або код ремонту активної гілки.

Основні моменти завершеної консолідації/видалення:

  • Стан Plugin тепер використовує спільну базу даних state/openclaw.sqlite. Старий імпортер sidecar plugin-state/state.sqlite, локальний для гілки, видалено, тому що ця SQLite-схема ніколи не постачалася. Допоміжні засоби probe/test повідомляють спільний databasePath замість розкриття специфічного для стану Plugin шляху SQLite.
  • Таблиці середовища виконання завдань і TaskFlow тепер зберігаються у спільній базі даних state/openclaw.sqlite замість tasks/runs.sqlite і tasks/flows/registry.sqlite; старі sidecar-імпортери видалено з тієї самої причини непоставленої схеми.
  • src/config/sessions/store.ts більше не потребує storePath для вхідних метаданих, оновлень маршруту або читання updated-at. Збереження команд, очищення сесій CLI, глибина підагентів, перевизначення автентифікації та ідентичність сесії транскрипта використовують API рядків агента/сесії. Записи застосовуються як патчі рядків SQLite з оптимістичним повтором у разі конфлікту.
  • Розв’язання цілі сесії тепер розкриває цілі бази даних для кожного агента, а не застарілі шляхи sessions.json. Спільний Gateway, метадані ACP, виправлення маршрутів doctor і openclaw sessions перелічують agent_databases плюс налаштованих агентів.
  • Маршрутизація сесій Gateway тепер використовує resolveGatewaySessionDatabaseTarget; повернена ціль містить databasePath і кандидатні ключі рядків SQLite замість застарілого файлового шляху сховища сесій.
  • Типи середовища виконання сесій каналів тепер розкривають {agentId, sessionKey} для читання updated-at, вхідних метаданих і оновлень останнього маршруту. Старий суміснісний тип saveSessionStore(storePath, store) вилучено.
  • Середовище виконання Plugin, API розширень і barrel-поверхні config/sessions тепер спрямовують код Plugin до допоміжних засобів рядків сесій на базі SQLite. Суміснісні експорти кореневої бібліотеки (loadSessionStore, saveSessionStore, resolveStorePath) залишаються як застарілі шими для наявних споживачів. Старий допоміжний засіб resolveLegacySessionStorePath вилучено; побудова застарілого шляху sessions.json тепер локальна для міграції та тестових фікстур.
  • src/config/sessions/session-entries.sqlite.ts тепер зберігає канонічні записи сесій у базі даних кожного агента та підтримує читання/upsert/delete-патчі на рівні рядків. Runtime upsert/patch/delete більше не сканує варіанти регістру й не очищає застарілі ключі-псевдоніми; канонізація належить doctor. Окремий допоміжний засіб імпорту JSON вилучено, а міграція зливає upsert-ом новіші рядки замість заміни всієї таблиці сесій. Публічні допоміжні засоби read/list/load проєктують гарячі метадані сесій із типізованих рядків sessions і conversations; entry_json є суміснісною/налагоджувальною тінню й може бути застарілим або недійсним без втрати типізованої ідентичності сесії чи контексту доставки.
  • src/config/sessions/delivery-info.ts тепер розв’язує контекст доставки з типізованих рядків sessions + conversations + session_conversations у базі кожного агента. Він більше не реконструює ідентичність доставки runtime із session_entries.entry_json; відсутній типізований рядок розмови є проблемою міграції/виправлення doctor, а не runtime fallback.
  • Рішення щодо скидання збережених сесій тепер надають перевагу типізованим метаданим sessions.session_scope, sessions.chat_type і sessions.channel. Розбір sessionKey залишається лише для явних суфіксів thread/topic у цілях команд; класифікація скидання group vs direct більше не походить із форми ключа.
  • Класифікація відображення списку/статусу сесій тепер використовує типізовані метадані чату та вид сесії Gateway. Вона більше не трактує підрядки :group: або :channel: всередині session_key як довговічну істину group/direct.
  • Вибір політики silent-reply тепер використовує лише явний тип розмови або метадані поверхні. Він більше не вгадує політику direct/group за підрядками session_key.
  • Розв’язання моделі відображення сесії тепер отримує id агента з цілі бази даних сесії SQLite замість виділення його з session_key.
  • Гідратація цілі оголошення agent-to-agent тепер використовує лише типізований deliveryContext із sessions.list. Вона більше не відновлює маршрутизацію channel/account/thread із застарілого origin, дзеркальних полів last* або форми session_key.
  • Відхилення thread-цілей sessions_send тепер читає типізовані метадані маршрутизації SQLite. Воно більше не відхиляє і не приймає цілі шляхом розбору суфіксів thread із ключа цілі.
  • Валідація групової політики інструментів тепер читає типізовану маршрутизацію розмов SQLite для поточної або породженої сесії. Вона більше не довіряє ідентичності group/channel через декодування sessionKey; надані викликачем group ids відкидаються, коли жоден типізований рядок сесії їх не підтверджує.
  • Зіставлення перевизначень моделі каналу тепер використовує явні метадані групи та батьківської розмови. Воно більше не декодує ідентифікатори батьківських розмов із parentSessionKey.
  • Успадкування збережених перевизначень моделі тепер потребує явного ключа батьківської сесії з типізованого контексту сесії. Воно більше не виводить батьківські перевизначення із суфіксів :thread: або :topic: у sessionKey.
  • Стару обгортку thread-info сесій і парсер thread завантаженого Plugin вилучено; жоден runtime-код не імпортує config/sessions/thread-info.
  • Допоміжний засіб розмов каналу більше не розкриває мости розбору повного ключа сесії. Core і далі нормалізує сирі ідентифікатори розмов, що належать провайдеру, через resolveSessionConversation(...), але не реконструює факти маршруту з sessionKey.
  • Доставка завершень, політика надсилання та обслуговування завдань більше не виводять тип чату з форми session_key. Старий парсер ключа типу чату видалено; ці шляхи потребують типізованих метаданих сесії, типізованого контексту доставки або явного словника цілі доставки.
  • Список/статус сесій, діагностика, прив’язування облікового запису схвалення, фільтрація Heartbeat у TUI та підсумки використання більше не добувають із SessionEntry.origin маршрутизацію provider/account/thread/display. Єдині runtime-читання origin, що залишилися, є несесійними поняттями або об’єктами доставки поточного ходу.
  • Нативний пошук розмови approval-request тепер читає типізовані рядки маршрутизації сесій для кожного агента. Він більше не розбирає ідентичність channel/group/thread розмови з sessionKey; відсутні типізовані метадані є проблемою міграції/виправлення.
  • Payload-и подій Gateway session changed/chat/session більше не відлунюють SessionEntry.origin або тіні маршруту last*; клієнти отримують типізовані channel, chatType і deliveryContext.
  • Розв’язання доставки Heartbeat тепер може отримувати типізований SQLite deliveryContext напряму, а runtime Heartbeat передає рядок доставки сесії кожного агента замість покладання на суміснісні тіні session_entries для поточної маршрутизації.
  • Розв’язання цілі доставки ізольованого агента Cron також гідратує свій поточний маршрут із типізованого рядка доставки сесії кожного агента перед fallback до суміснісного payload запису.
  • Розв’язання походження оголошення підагентів тепер протягує типізований контекст доставки requester-session через loadRequesterSessionEntry і надає перевагу цьому рядку над суміснісними тінями last*/deliveryContext.
  • Оновлення вхідних метаданих сесії тепер спершу зливаються з типізованим рядком доставки кожного агента; старі поля доставки SessionEntry є лише fallback, коли типізованого рядка розмови не існує.
  • Витяг доставки restart/update тепер дозволяє типізованому SQLite delivery threadId мати пріоритет над фрагментами topic/thread, розібраними з sessionKey; розбір є лише fallback для застарілих ключів у формі thread.
  • Id каналів контексту hook-агента тепер надають перевагу типізованій ідентичності розмови SQLite, потім явним метаданим повідомлення. Вони більше не розбирають фрагменти provider/group/channel із sessionKey.
  • Успадкування зовнішнього маршруту Gateway chat.send тепер читає типізовані метадані маршрутизації сесій SQLite замість виведення scope channel/direct/group із частин sessionKey. Сесії зі scope каналу успадковують лише тоді, коли типізований канал сесії та тип чату збігаються зі збереженим контекстом доставки; shared-main сесії зберігають своє суворіше правило CLI/без-клієнтських-метаданих.
  • Пробудження restart-sentinel і маршрутизація продовжень тепер читають типізовані рядки доставки/маршрутизації SQLite перед постановкою в чергу пробуджень Heartbeat або маршрутизованих продовжень agent-turn. Вони більше не реконструюють контекст доставки з JSON-тіні session-entry.
  • Розв’язання контексту Gateway tools.effective тепер читає типізовані рядки доставки/маршрутизації SQLite для входів provider, account, target, thread і reply-mode. Воно більше не відновлює ці гарячі поля маршрутизації із застарілих тіней origin у session_entries.entry_json.
  • Маршрутизація realtime voice consult тепер розв’язує доставку parent/call із типізованих рядків сесій SQLite для кожного агента. Вона більше не повертається до суміснісних тіней SessionEntry.deliveryContext під час вибору маршруту повідомлення вбудованого агента.
  • Ретрансляція Heartbeat для ACP spawn і маршрутизація parent-stream тепер читають доставку parent із типізованих рядків сесій SQLite. Вони більше не реконструюють контекст доставки parent із суміснісних тіней session-entry.
  • Збереження маршруту доставки сесії тепер слідує типізованим метаданим чату та збереженим стовпцям доставки. Воно більше не витягує підказки каналу, маркери direct/main або форму thread із sessionKey; внутрішні маршрути webchat успадковують зовнішню ціль лише тоді, коли SQLite вже має типізовану/збережену ідентичність доставки для сесії.
  • Загальний витяг доставки сесії тепер читає лише точний типізований рядок доставки сесії SQLite. Він більше не розбирає суфікси thread/topic і не виконує fallback із ключа у формі thread до базового ключа сесії.
  • Диспетчеризація відповіді, відновлення restart sentinel і маршрутизація realtime voice consult тепер використовують точні типізовані рядки сесій/розмов SQLite для маршрутизації thread. Вони більше не відновлюють thread ids або контекст доставки базової сесії через розбір ключів сесій у формі thread.
  • Обмеження історії Embedded PI тепер використовує типізовану проєкцію маршрутизації сесій SQLite (sessions + primary conversations) для provider, типу чату та ідентичності peer. Воно більше не розбирає provider, DM, group або форму thread із sessionKey.
  • Виведення доставки інструментів Cron тепер використовує лише явну доставку або поточний типізований контекст доставки. Воно більше не декодує цілі channel, peer, account або thread із agentSessionKey.
  • Runtime-рядки сесій більше не містять старий псевдонім маршруту lastProvider. Допоміжні засоби й тести використовують типізовані поля lastChannel і deliveryContext; міграція doctor є єдиним місцем, яке має перекладати старіші псевдоніми маршрутів або збережені тіні origin.
  • Події транскрипта, рядки VFS і рядки артефактів інструментів тепер записуються до бази даних кожного агента. Непоставлену глобальну таблицю зіставлення transcript-file вилучено; doctor натомість записує застарілі вихідні шляхи в довговічні рядки міграції.
  • Runtime-пошук транскрипта більше не сканує байтові зміщення JSONL і не перевіряє застарілі файли транскриптів. Шляхи Gateway chat/media/history читають рядки транскрипта з SQLite; JSONL сесії тепер є лише застарілим входом doctor, а не runtime-станом чи форматом експорту.
  • Батьківські та гілкові зв’язки транскрипта використовують структуровані метадані parentTranscriptScope: {agentId, sessionId} у заголовках транскриптів SQLite, а не path-like locator-рядки agent-db:...transcript_events....
  • Контракт менеджера транскриптів більше не розкриває неявні збережені конструктори create(cwd) або continueRecent(cwd). Збережені менеджери транскриптів відкриваються з явним scope {agentId, sessionId}; лише in-memory менеджери залишаються без scope для тестів і чистих перетворень транскриптів.
  • API runtime-сховища транскриптів розв’язують scope SQLite, а не файлові шляхи. Старий допоміжний засіб resolve...ForPath і невикористані параметри запису transcriptPath вилучено з runtime-викликачів.
  • Runtime-розв’язання сесій тепер використовує {agentId, sessionId} і не повинно виводити рядки sqlite-transcript://<agent>/<session> для зовнішніх меж. Застарілі абсолютні шляхи JSONL є лише входами міграції doctor.
  • Записи прямого bridge для нативного hook relay тепер зберігаються в типізованих спільних рядках native_hook_relay_bridges, ключованих за relay id. Runtime більше не записує JSON-реєстр у /tmp або непрозорі generic records для цих короткоживучих bridge-записів.
  • runEmbeddedPiAgent(...) більше не має параметра transcript-locator. Підготовлені дескриптори worker також не містять локаторів транскриптів. Стан сеансу середовища виконання та поставлені в чергу наступні запуски переносять {agentId, sessionId} замість похідних дескрипторів транскриптів.
  • Вбудоване Compaction тепер бере область SQLite з agentId і sessionId. Хуки Compaction, виклики context-engine, делегування CLI та відповіді протоколу не повинні отримувати похідні дескриптори sqlite-transcript://.... Код експорту/налагодження може матеріалізувати явні користувацькі артефакти з рядків, але не надає універсального шляху експорту JSONL сеансу й не передає імена файлів назад в ідентичність середовища виконання.
  • /export-session читає рядки транскрипта з SQLite і записує лише запитаний автономний HTML-перегляд. Вбудований переглядач більше не реконструює й не завантажує JSONL сеансу з цих рядків.
  • Делегування context-engine більше не розбирає локатор транскрипта, щоб відновити ідентичність агента. Підготовлений контекст середовища виконання переносить розв’язаний agentId у вбудований адаптер Compaction.
  • Перезапис транскрипта й обрізання результатів live-інструментів тепер читають і зберігають стан транскрипта за {agentId, sessionId} і не виводять тимчасові локатори для корисних навантажень подій оновлення транскрипта.
  • Поверхня допоміжних засобів стану транскрипта більше не має варіантів readTranscriptState, replaceTranscriptStateEvents або persistTranscriptStateMutation на основі локаторів. Виклики середовища виконання мають використовувати API {agentId, sessionId}. Імпорт Doctor читає застарілі файли за явним шляхом до файлу й записує рядки SQLite; він не мігрує рядки локаторів.
  • Контракт session-manager середовища виконання більше не надає open(locator), forkFrom(locator) або setTranscriptLocator(...). Збережені менеджери сеансів відкриваються лише за {agentId, sessionId}; допоміжні засоби списку/форку живуть у рядково-орієнтованих API сеансів і контрольних точок замість фасаду менеджера транскриптів.
  • API читача транскриптів Gateway спершу працюють з областю. Вони приймають {agentId, sessionId} і не приймають позиційний локатор транскрипта, який міг би випадково стати ідентичністю середовища виконання. Розбір локатора активного транскрипта прибрано; застарілі вихідні шляхи читає лише код імпорту Doctor.
  • Події оновлення транскрипта також спершу працюють з областю. emitSessionTranscriptUpdate більше не приймає голий рядок локатора, а слухачі маршрутизують за {agentId, sessionId} без розбору дескриптора.
  • Трансляція session-message Gateway розв’язує ключі сеансу з області агента/сеансу, а не з локатора транскрипта. Старий резолвер/кеш ключів transcript-locator-to-session прибрано.
  • SSE історії сеансів Gateway фільтрує live-оновлення за областю агента/сеансу. Він більше не канонізує кандидатів локатора транскрипта, realpath або файлові ідентичності транскриптів, щоб вирішити, чи має потік отримати оновлення.
  • Хуки життєвого циклу сеансу більше не виводять і не надають локатори транскриптів на session_end. Споживачі хуків отримують sessionId, sessionKey, ідентифікатори наступного сеансу та контекст агента; файли транскриптів не є частиною контракту життєвого циклу.
  • Хуки скидання також більше не виводять і не надають локатори транскриптів. Корисне навантаження before_reset переносить відновлені повідомлення SQLite та причину скидання, тоді як ідентичність сеансу залишається в контексті хука.
  • Скидання harness агента більше не приймає локатор транскрипта. Надсилання скидання обмежується sessionId/sessionKey плюс причиною.
  • Типи сеансів розширення агента більше не надають transcriptLocator; розширення мають використовувати контекст сеансу та API середовища виконання, а не звертатися до файлової ідентичності транскрипта.
  • Хуки Compaction для Plugin більше не надають локатори транскриптів. Контекст хука вже переносить ідентичність сеансу, а читання транскриптів має проходити через API SQLite, що враховують область, замість файлових дескрипторів.
  • Хуки before_agent_finalize більше не надають transcriptPath, включно з корисними навантаженнями ретрансляції native-хуків. Хуки фіналізації використовують лише контекст сеансу.
  • Відповіді скидання Gateway більше не синтезують локатор транскрипта в поверненому записі. Скидання створює рядки транскрипта SQLite, повертає чистий запис сеансу й залишає доступ до транскриптів читачам, що враховують область.
  • Результати вбудованого запуску та Compaction більше не показують локатори транскриптів для обліку сеансів. Автоматичне Compaction оновлює лише активний sessionId, лічильники Compaction і метадані токенів.
  • Результати вбудованих спроб більше не повертають transcriptLocatorUsed, а результати context-engine compact() більше не повертають локатори транскриптів. Цикли повторних спроб середовища виконання приймають лише наступний sessionId.
  • Результати додавання транскрипта delivery-mirror більше не повертають локатори транскриптів. Виклики отримують доданий messageId; сигнали оновлення транскрипта використовують область SQLite.
  • Допоміжні засоби форку батьківського сеансу повертають лише форкнутий sessionId. Підготовка субагента передає область дочірнього агента/сеансу в рушії.
  • Параметри CLI runner і повторне засівання історії більше не приймають локатори транскриптів. Читання історії CLI розв’язує область транскрипта SQLite з {agentId, sessionId} і контексту ключа сеансу.
  • Фікстури тестів CLI та embedded-runner тепер засівають і читають рядки транскриптів SQLite за ідентифікатором сеансу замість того, щоб удавати, що активні сеанси є файлами *.jsonl, або передавати рядок sqlite-transcript://... через параметри середовища виконання.
  • Події guard для результатів інструментів сеансу надсилаються з відомої області сеансу, навіть коли менеджер у пам’яті не має похідного локатора. Його тести більше не підробляють активні файли транскриптів /tmp/*.jsonl.
  • Допоміжні засоби BTW і compaction-checkpoint тепер читають і форкають рядки транскриптів за областю SQLite. Метадані контрольної точки тепер зберігають лише ідентифікатори сеансів та ідентифікатори leaf/entry; похідні локатори більше не записуються в корисні навантаження контрольних точок.
  • Пошук transcript-key у Gateway використовує область транскрипта SQLite на межах протоколу і більше не виконує realpath або stat для імен файлів транскриптів.
  • Автоматичне обертання транскриптів Compaction записує наступні рядки транскрипта безпосередньо через сховище транскриптів SQLite. Рядки сеансу зберігають лише ідентичність наступного сеансу, а не довговічний шлях JSONL чи збережений локатор.
  • Вбудоване Compaction context-engine використовує допоміжні засоби обертання транскриптів з іменами SQLite. Тести обертання більше не створюють наступні шляхи JSONL і не моделюють активні сеанси як файли.
  • Кероване збереження вихідних зображень формує ключ кешу transcript-message зі статистики транскриптів SQLite замість викликів stat файлової системи.
  • Блокування сеансів середовища виконання та автономну застарілу гілку Doctor для .jsonl.lock прибрано.
  • Runtime barrel Microsoft Teams і публічний Plugin SDK більше не реекспортують старий допоміжний засіб file-lock; шляхи довговічного стану Plugin підтримуються SQLite.
  • Обрізання за віком/кількістю сеансів і явне очищення сеансів прибрано. Doctor володіє застарілим імпортом; застарілі сеанси скидаються або видаляються явно.
  • Перевірки цілісності Doctor більше не рахують застарілий файл JSONL як дійсний активний транскрипт для рядка сеансу SQLite. Справність активного транскрипта є лише SQLite; застарілі файли JSONL повідомляються як вхідні дані для міграції/очищення orphan.
  • Doctor більше не вважає agents/<agent>/sessions/ обов’язковим станом середовища виконання. Він сканує цей каталог лише тоді, коли він уже існує, як вхідні дані застарілого імпорту або очищення orphan.
  • sessions.resolve Gateway, шляхи patch/reset/compact сеансу, створення субагентів, fast abort, метадані ACP, сеанси, ізольовані Heartbeat, і виправлення TUI більше не мігрують і не обрізають застарілі ключі сеансів як побічний ефект звичайної роботи середовища виконання.
  • Розв’язання сеансу команди CLI тепер повертає власний agentId замість storePath, і більше не копіює застарілі рядки main-session під час звичайного розв’язання --to або --session-id. Канонізація застарілих main-row належить лише Doctor.
  • Розв’язання глибини субагента середовища виконання більше не читає sessions.json або сховища сеансів JSON5. Воно читає SQLite session_entries за ідентифікатором агента, а застарілі метадані глибини/сеансу можуть потрапити лише через шлях імпорту Doctor.
  • Перевизначення сеансів профілю автентифікації зберігаються через прямі upsert рядків {agentId, sessionKey} замість лінивого завантаження файлового середовища виконання session-store.
  • Verbose gating автоматичних відповідей і допоміжні засоби оновлення сеансів тепер читають/upsert-ять рядки сеансів SQLite за ідентичністю сеансу й більше не потребують застарілого шляху сховища перед зміною збереженого стану рядків.
  • Допоміжні засоби метаданих сеансів command-run тепер використовують entry-орієнтовані імена та шляхи модулів; стару поверхню допоміжних команд session-store прибрано.
  • Засівання bootstrap header і посилення меж ручного Compaction тепер змінюють рядки транскриптів SQLite безпосередньо. Виклики середовища виконання передають ідентичність сеансу, а не записувані шляхи .jsonl.
  • Повторне відтворення silent session-rotation копіює останні репліки користувача/асистента за {agentId, sessionId} з рядків транскриптів SQLite. Воно більше не приймає вихідні або цільові локатори транскриптів.
  • Нові рядки сеансів середовища виконання більше не зберігають локатори транскриптів. Виклики використовують {agentId, sessionId} безпосередньо; команди експорту/налагодження можуть вибирати імена вихідних файлів, коли матеріалізують рядки.
  • Запуск нового збереженого сеансу транскрипта тепер завжди відкриває рядки SQLite за областю. Менеджер сеансів більше не повторно використовує попередній шлях або локатор транскрипта файлової епохи як ідентичність нового сеансу.
  • Збережені сеанси транскриптів використовують явний API openTranscriptSessionManagerForSession({agentId, sessionId}). Старі статичні фасади SessionManager.create/openForSession/list/forkFromSession прибрано, щоб тести й код середовища виконання не могли випадково відтворити виявлення сеансів файлової епохи.
  • Середовище виконання Plugin більше не надає api.runtime.agent.session.resolveTranscriptLocatorPath; код Plugin використовує допоміжні засоби рядків SQLite і значення області.
  • Публічна поверхня SDK session-store-runtime тепер експортує лише допоміжні засоби рядків сеансів і рядків транскриптів. Сфокусовані допоміжні засоби schema/path/transaction SQLite живуть у sqlite-runtime; сирі допоміжні засоби open/close/reset залишаються локальними лише для first-party тестів.
  • Застарілі класифікатори імен файлів траєкторій/контрольних точок .jsonl тепер живуть у застарілому модулі session-file Doctor. Основна перевірка сеансів більше не імпортує допоміжні засоби file-artifact, щоб визначати звичайні ідентифікатори сеансів SQLite.
  • Блокувальні запуски субагентів Active Memory використовують рядки транскриптів SQLite замість створення тимчасових або збережених файлів session.jsonl у стані Plugin. Старий параметр transcriptDir прибрано.
  • Одноразова генерація slug і запуски планувальника Crestodian використовують рядки транскриптів SQLite замість створення тимчасових файлів session.jsonl.
  • Запуски допоміжного засобу llm-task і приховане витягування commitment також використовують рядки транскриптів SQLite, тому ці model-only допоміжні сеанси більше не створюють тимчасових файлів транскриптів JSON/JSONL.
  • TranscriptSessionManager тепер є лише відкритою областю транскрипта SQLite. Код середовища виконання відкриває його через openTranscriptSessionManagerForSession({agentId, sessionId}); потоки create, branch, continue, list і fork живуть у відповідних допоміжних засобах рядків SQLite, а не в статичних фасадах менеджера. Код Doctor/import/debug обробляє явні застарілі вихідні файли поза менеджером сеансів середовища виконання.
  • Застарілі фасадні методи SessionManager.newSession() і SessionManager.createBranchedSession() було прибрано. Нові сеанси та нащадки транскриптів створюються відповідним робочим процесом SQLite замість зміни вже відкритого менеджера в інший збережений сеанс.
  • Рішення щодо форку батьківського транскрипта й створення форку більше не приймають storePath або sessionsDir; вони використовують область транскрипта SQLite {agentId, sessionId} замість збережених метаданих шляху файлової системи.
  • Memory-host більше не експортує no-op допоміжні засоби класифікації транскриптів каталогів сеансів; фільтрація транскриптів тепер виводиться з метаданих рядків SQLite під час побудови записів.
  • Тести експорту сеансів Memory-host і QMD використовують області транскриптів SQLite. Старі шляхи agents/<agentId>/sessions/*.jsonl залишаються покритими лише там, де тест навмисно доводить сумісність Doctor/import/export.
  • Сирий огляд сеансів QA-lab тепер використовує sessions.list через gateway замість читання agents/qa/sessions/sessions.json; відгуки MSteams додаються безпосередньо до транскриптів SQLite без створення штучного шляху JSONL.
  • Спільні вхідні звернення каналів тепер передають {agentId, sessionKey}, а не застарілий storePath. Шляхи запису LINE, WhatsApp, Slack, Discord, Telegram, Matrix, Signal, iMessage, BlueBubbles, Feishu, Google Chat, IRC, Nextcloud Talk, Zalo, Zalo Personal, QA Channel, Microsoft Teams, Mattermost, Synology Chat, Tlon, Twitch і QQBot тепер читають метадані updated-at і записують рядки вхідних сесій через ідентичність SQLite.
  • Збереження локатора транскрипту видалено з рядків активних сесій. resolveSessionTranscriptTarget повертає agentId, sessionId і необов’язкові метадані теми; doctor — єдиний код, який імпортує застарілі імена файлів транскриптів.
  • Заголовки транскриптів runtime починаються з версії SQLite 1. Оновлення старих форм JSONL V1/V2/V3 існують лише в імпорті doctor і нормалізують імпортовані заголовки до поточної версії транскриптів SQLite перед збереженням рядків.
  • Захист database-first тепер забороняє SessionManager.listAll і SessionManager.forkFromSession; списки сесій і робочі процеси fork/restore мають залишатися на рядкових/обмежених за scope API SQLite.
  • Захист також забороняє імена застарілих допоміжних функцій розбору JSONL транскриптів/ремонту active-branch поза кодом doctor/import, тож runtime не може отримати другий шлях міграції застарілих транскриптів.
  • Вбудовані запуски PI відхиляють вхідні handles транскриптів. Вони використовують ідентичність SQLite {agentId, sessionId} перед запуском worker і знову перед тим, як спроба торкнеться стану транскрипту. Застарілий вхід /tmp/*.jsonl не може вибрати ціль запису runtime.
  • Записи трасування кешу, Anthropic payload, raw stream і diagnostics timeline тепер записуються до типізованих рядків SQLite diagnostic_events. Пакети стабільності Gateway тепер записуються до типізованих рядків SQLite diagnostic_stability_bundles. Старі шляхи перевизначення JSONL diagnostics.cacheTrace.filePath, OPENCLAW_CACHE_TRACE_FILE, OPENCLAW_ANTHROPIC_PAYLOAD_LOG_FILE і OPENCLAW_DIAGNOSTICS_TIMELINE_PATH видалено, а звичайне захоплення стабільності більше не записує файли logs/stability/*.json.
  • Збереження Cron тепер узгоджує рядки SQLite cron_jobs замість видалення й повторного вставлення всієї таблиці завдань під час кожного збереження. Зворотні записи цілей Plugin оновлюють відповідні рядки cron напряму й тримають runtime-стан cron у тій самій транзакції бази даних стану.
  • Викликачі Cron runtime тепер використовують стабільний ключ сховища cron SQLite. Застарілі шляхи cron.store є лише вхідними даними імпорту doctor; production gateway, обслуговування завдань, status, run-log і шляхи зворотного запису цілі Telegram використовують resolveCronStoreKey і більше не нормалізують ключ як шлях. Статус Cron тепер повідомляє storeKey, а не старе поле storePath у формі файлу.
  • Завантаження й планування Cron runtime більше не нормалізують застарілі збережені форми завдань, як-от jobId, schedule.cron, числовий atMs, рядкові booleans або відсутній sessionTarget. Імпорт застарілих даних doctor відповідає за ці ремонти перед вставленням рядків у SQLite.
  • ACP spawn більше не визначає і не зберігає шляхи файлів JSONL транскриптів. Налаштування spawn і thread-bind зберігає рядок сесії SQLite напряму й залишає id сесії як утриману ідентичність транскрипту.
  • API метаданих сесій ACP тепер читають/перелічують/upsert рядки SQLite за agentId і більше не відкривають storePath як частину контракту запису сесії ACP.
  • Облік використання сесій і агрегація використання Gateway тепер визначають транскрипти лише за {agentId, sessionId}. Кеш cost/usage і підсумки знайдених сесій більше не синтезують і не повертають рядки локаторів транскриптів.
  • Gateway chat append, abort-partial persistence, /sessions.send і записи медіа транскриптів webchat додають дані напряму через scope транскрипту SQLite. Допоміжна функція ін’єкції транскрипту Gateway більше не приймає параметр transcriptLocator.
  • Виявлення транскриптів SQLite тепер перелічує лише scopes і stats транскриптів: {agentId, sessionId, updatedAt, eventCount}. Мертву сумісну допоміжну функцію listSqliteSessionTranscriptLocators і поле locator для кожного рядка видалено.
  • Runtime ремонту транскриптів тепер відкриває лише repairTranscriptSessionStateIfNeeded({agentId, sessionId}). Стару допоміжну функцію ремонту на основі локатора видалено; код doctor/debug читає явні шляхи вихідних файлів і ніколи не мігрує рядки локаторів.
  • Runtime replay ledger ACP тепер зберігає рядки replay для кожної сесії у спільній базі даних стану SQLite замість acp/event-ledger.json; doctor імпортує й видаляє застарілий файл.
  • Допоміжні функції читання транскриптів Gateway тепер розміщені в src/gateway/session-transcript-readers.ts замість старої назви модуля session-utils.fs. Перевірка історії fallback retry названа за вмістом транскриптів SQLite, а не за старою поверхнею file-helper.
  • Допоміжні функції injected-chat і compaction Gateway тепер передають scope транскрипту SQLite через внутрішні helper API замість називання значень шляхами транскриптів або вихідними файлами.
  • Виявлення продовження bootstrap тепер перевіряє рядки транскриптів SQLite через hasCompletedBootstrapTranscriptTurn; воно більше не відкриває helper-ім’я у формі файлу.
  • Тести embedded-runner тепер використовують ідентичність транскрипту SQLite, а відкриття нового менеджера транскриптів завжди потребує явного sessionId.
  • Допоміжні функції індексації пам’яті тепер наскрізно використовують термінологію транскриптів SQLite: host експортує listSessionTranscriptScopesForAgent і sessionTranscriptKeyForScope, цільові черги синхронізації sessionTranscripts, публічні результати пошуку сесій відкривають opaque-шляхи transcript:<agent>:<session>, а внутрішній ключ джерела DB — це session:<session> під source_kind='sessions' замість фальшивого файлового шляху.
  • Універсальна допоміжна функція persistent-dedupe Plugin SDK більше не відкриває опції у формі файлу. Викликачі надають ключі scope SQLite, а durable dedupe rows живуть у спільному стані Plugin.
  • SSO-токени Microsoft Teams перенесено із заблокованих JSON-файлів до стану Plugin SQLite. Doctor імпортує msteams-sso-tokens.json, перебудовує канонічні ключі SSO-токенів з payloads і видаляє вихідний файл. Делеговані OAuth-токени залишаються на наявній приватній межі credential-file.
  • Стан кешу синхронізації Matrix перенесено з bot-storage.json до стану Plugin SQLite. Doctor імпортує застарілі raw або wrapped sync payloads і видаляє вихідний файл. Активні клієнти Matrix і QA Matrix передають кореневий каталог sync-store SQLite, а не фальшивий шлях sync-store.json або bot-storage.json.
  • Статус застарілої crypto-міграції Matrix перенесено з legacy-crypto-migration.json до стану Plugin SQLite. Doctor імпортує старий файл статусу; snapshots IndexedDB Matrix SDK перенесено з crypto-idb-snapshot.json до blobs Plugin SQLite. Ключі відновлення Matrix і облікові дані є рядками стану Plugin SQLite; їхні старі JSON-файли є лише вхідними даними міграції doctor.
  • Журнали активності Memory Wiki тепер використовують стан Plugin SQLite замість .openclaw-wiki/log.jsonl. Провайдер міграції Memory Wiki імпортує старі журнали JSONL; wiki markdown і вміст користувацького vault залишаються file-backed як вміст workspace.
  • Memory Wiki більше не створює .openclaw-wiki/state.json або невикористаний каталог .openclaw-wiki/locks. Провайдер міграції видаляє ці виведені з ужитку файли метаданих Plugin, якщо старіший vault усе ще їх має.
  • Записи аудиту Crestodian тепер використовують core SQLite стан Plugin замість audit/crestodian.jsonl. Doctor імпортує застарілий журнал аудиту JSONL і видаляє його після успішного імпорту.
  • Записи аудиту запису/спостереження config тепер використовують core SQLite стан Plugin замість logs/config-audit.jsonl. Doctor імпортує застарілий журнал аудиту JSONL і видаляє його після успішного імпорту.
  • macOS companion більше не записує app-local sidecars logs/config-audit.jsonl або logs/config-health.json під час редагування openclaw.json. Файл config залишається file-backed, snapshots відновлення залишаються поруч із файлом config, а durable стан аудиту/health config належить до сховища SQLite Gateway.
  • Очікувані схвалення rescue Crestodian тепер використовують core SQLite стан Plugin замість crestodian/rescue-pending/*.json. Doctor імпортує застарілі файли очікуваних схвалень і видаляє їх після успішного імпорту.
  • Тимчасовий стан arm Phone Control тепер використовує стан Plugin SQLite замість plugins/phone-control/armed.json. Doctor імпортує застарілий файл armed-state у namespace phone-control/arm-state і видаляє файл.
  • Doctor більше не ремонтує JSONL транскрипти на місці й не створює backup JSONL файли. Він імпортує active branch у SQLite і видаляє застаріле джерело.
  • Пошук транскриптів hook session-memory використовує scope-only читання SQLite {agentId, sessionId}. Його helper більше не приймає і не виводить локатори транскриптів, застарілі читання файлів або опції перезапису файлів.
  • Прив’язки розмов Codex app-server тепер ключують стан Plugin SQLite за ключем сесії OpenClaw або явним scope {agentId, sessionId}. Вони не мають зберігати fallback-прив’язки за шляхом транскрипту.
  • Читання mirrored-history Codex app-server використовують лише scope транскрипту SQLite; вони не мають відновлювати ідентичність зі шляхів файлів транскриптів.
  • Шляхи скидання role-ordering і compaction більше не unlink старі файли транскриптів; reset лише ротує рядок сесії SQLite та ідентичність транскрипту.
  • Відповіді reset і checkpoint Gateway повертають чисті рядки сесій плюс session ids. Вони більше не синтезують локатори транскриптів SQLite для клієнтів.
  • Dreaming memory-core більше не обрізає рядки сесій через перевірку відсутніх JSONL-файлів. Очищення subagent проходить через session runtime API замість перевірок існування файлової системи. Його тести transcript-ingestion seed рядки SQLite напряму замість створення fixtures agents/<id>/sessions або placeholders локаторів.
  • Індексація транскриптів пам’яті може відкривати transcript:<agentId>:<sessionId> як віртуальний шлях результату пошуку для helpers цитування/читання. Durable index source є relational (source_kind='sessions', source_key='session:<sessionId>', session_id=<sessionId>), тож значення не є runtime локатором транскрипту, не є шляхом файлової системи й ніколи не має передаватися назад у session runtime APIs.
  • Статус пам’яті Gateway doctor читає short-term recall і лічильники phase-signal з рядків стану Plugin SQLite замість memory/.dreams/*.json; вивід CLI і doctor тепер позначає це сховище як SQLite store, а не як path.
  • Runtime memory-core, CLI status, методи Gateway doctor і facades Plugin SDK більше не аудіюють і не архівують застарілі файли .dreams/session-corpus. Ці файли є лише вхідними даними міграції; doctor імпортує їх у SQLite і видаляє джерело після перевірки. Активні рядки evidence session-ingestion тепер використовують віртуальний шлях SQLite memory/session-ingestion/<day>.txt; runtime ніколи не записує і не виводить стан з .dreams/session-corpus.
  • Публічні артефакти memory-core відкривають host events SQLite як віртуальний JSON артефакт memory/events/memory-host-events.json; вони більше не використовують повторно застарілий шлях джерела .dreams/events.jsonl.
  • Реєстри sandbox container/browser тепер використовують спільну таблицю SQLite sandbox_registry_entries з типізованими стовпцями session, image, timestamp, backend/config і browser port. Doctor імпортує застарілі монолітні та sharded JSON registry files і видаляє успішні джерела. Runtime reads використовують типізовані стовпці рядків як source of truth; entry_json є лише replay/debug копією.
  • Commitments тепер використовують типізовану спільну таблицю commitments замість whole-store JSON blob. Snapshot saves виконують upsert за commitment id і видаляють лише відсутні рядки замість очищення й повторного вставлення таблиці. Runtime loads commitments з типізованих стовпців scope, delivery-window, status, attempt і text; record_json є лише replay/debug копією. Doctor імпортує застарілий commitments.json і видаляє його після успішного імпорту.
  • Визначення завдань Cron, стан schedule і історія запусків більше не мають runtime JSON writers або readers. Runtime використовує рядки cron_jobs з типізованим schedule, payload, delivery, failure-alert, session, status і стовпці runtime-state, а також типізовані метадані cron_run_logs для статусу, діагностичного підсумку, статусу/помилки доставки, session/run, model і загальних token totals. job_json є лише копією для replay/debug; state_json зберігає вкладену runtime-діагностику, яка ще не має полів для hot-запитів, тоді як runtime регідратує hot-поля стану з типізованих стовпців. Doctor імпортує застарілі файли jobs.json, jobs-state.json і runs/*.jsonl та видаляє імпортовані джерела. Зворотні записи цілей Plugin оновлюють відповідні рядки cron_jobs замість завантаження й заміни всього cron-сховища.
  • Запуск Gateway ігнорує застарілі маркери notify: true у runtime-проєкції. Doctor перетворює їх на явну доставку SQLite, коли cron.webhook є дійсним, видаляє інертні маркери, коли його не задано, і зберігає їх із попередженням, коли налаштований webhook недійсний.
  • Черги вихідної доставки та доставки session тепер зберігають статус черги, тип запису, ключ session, channel, target, account id, кількість повторних спроб, останню спробу/помилку, стан recovery і маркери platform-send як типізовані стовпці у спільній таблиці delivery_queue_entries. Runtime recovery читає ці hot-поля з типізованих стовпців, а мутації retry/recovery оновлюють ці стовпці напряму без переписування replay JSON. Повний JSON payload залишається лише як replay/debug blob для тіл повідомлень та інших cold replay даних.
  • Керовані записи вихідних зображень тепер використовують типізовані спільні рядки managed_outgoing_image_records, а media bytes і далі зберігаються в media_blobs. JSON-запис залишається лише як копія для replay/debug.
  • Налаштування model-picker Discord, хеші command-deploy і прив’язки thread тепер використовують спільний SQLite-стан Plugin. Їхні плани імпорту застарілого JSON містяться на поверхні setup/doctor migration Plugin Discord, а не в коді міграції core.
  • Детектори застарілих імпортів Plugin використовують doctor-названі модулі, як-от doctor-legacy-state.ts або doctor-state-imports.ts; звичайні runtime-модулі channel не повинні імпортувати детектори застарілого JSON.
  • Курсори catchup BlueBubbles і вхідні маркери dedupe тепер використовують спільний SQLite-стан Plugin. Їхні плани імпорту застарілого JSON містяться на поверхні setup/doctor migration Plugin BlueBubbles, а не в коді міграції core.
  • Зсуви оновлень Telegram, рядки sticker cache, рядки sent-message cache, рядки topic-name cache і прив’язки thread тепер використовують спільний SQLite-стан Plugin. Їхні плани імпорту застарілого JSON містяться на поверхні setup/doctor migration Plugin Telegram, а не в коді міграції core.
  • Курсори catchup iMessage, мапінги reply short-id і рядки sent-echo dedupe тепер використовують спільний SQLite-стан Plugin. Старі файли imessage/catchup/*.json, imessage/reply-cache.jsonl і imessage/sent-echoes.jsonl є лише вхідними даними doctor.
  • Рядки dedupe повідомлень Feishu тепер використовують спільний SQLite-стан Plugin замість файлів feishu/dedup/*.json. Його план імпорту застарілого JSON міститься на поверхні setup/doctor migration Plugin Feishu, а не в коді міграції core.
  • Розмови Microsoft Teams, опитування, буфери pending upload і feedback learnings тепер використовують спільні таблиці SQLite plugin state/blob. Шлях pending upload використовує plugin_blob_entries, тому медіабуфери зберігаються як SQLite BLOB замість base64 JSON. Назви runtime-помічників тепер використовують іменування SQLite/state, а не іменування файлового сховища *-fs, і старий shim storePath вилучено з цих сховищ. Його план імпорту застарілого JSON міститься на поверхні setup/doctor migration Plugin Microsoft Teams.
  • Розміщені вихідні media Zalo тепер використовують спільний SQLite plugin_blob_entries замість тимчасових JSON/bin sidecar openclaw-zalo-outbound-media.
  • HTML і метадані переглядача diff тепер використовують спільний SQLite plugin_blob_entries замість тимчасових файлів meta.json/viewer.html. Згенеровані PNG/PDF outputs залишаються тимчасовими матеріалізаціями, бо доставка channel все ще потребує file path.
  • Керовані документи Canvas тепер використовують спільний SQLite plugin_blob_entries замість стандартного каталогу state/canvas/documents. Хост Canvas віддає ці blobs напряму; локальні файли створюються лише для явного операторського вмісту host.root або тимчасової матеріалізації, коли нижчий media reader потребує path.
  • Рішення audit File Transfer тепер використовують спільний SQLite plugin_state_entries замість необмеженого runtime-журналу audit/file-transfer.jsonl. Doctor імпортує застарілий JSONL audit-файл у стан Plugin і видаляє джерело після чистого імпорту.
  • Лізи процесів ACPX і ідентичність екземпляра Gateway тепер використовують спільний SQLite-стан Plugin. Doctor імпортує застарілий файл gateway-instance-id у стан Plugin і видаляє джерело.
  • Згенеровані wrapper scripts ACPX і ізольований Codex home є тимчасовою матеріалізацією під temp root OpenClaw, а не довговічним станом OpenClaw. Довговічні runtime-записи ACPX - це рядки SQLite lease і gateway-instance; стару поверхню конфігурації ACPX stateDir вилучено, бо runtime-стан туди більше не записується.
  • Media attachments Gateway тепер використовують спільну таблицю SQLite media_blobs як канонічне byte store. Локальні paths, повернені до channel і sandbox compatibility surfaces, є тимчасовими матеріалізаціями database row, а не довговічним media store. Runtime media allowlists більше не містять застарілі корені $OPENCLAW_STATE_DIR/media або config-dir media; ці каталоги є лише джерелами імпорту doctor.
  • Shell completion більше не записує cache-файли $OPENCLAW_STATE_DIR/completions/*. Шляхи install, doctor, update і release smoke використовують згенерований completion output або profile sourcing замість довговічних completion cache файлів.
  • Staging skill-upload Gateway тепер використовує спільні рядки skill_uploads. Upload metadata, idempotency keys і archive bytes зберігаються в SQLite; installer отримує лише тимчасово матеріалізований archive path, доки триває install.
  • Inline attachments subagent більше не матеріалізуються під workspace .openclaw/attachments/*. Шлях spawn готує seed-записи SQLite VFS, inline runs засівають ці записи в per-agent runtime scratch namespace, а disk-backed tools накладають цей SQLite scratch для attachment paths. Старі registry columns attachment-dir для subagent-run і cleanup hooks вилучено.
  • Гідратація CLI image більше не підтримує стабільні cache-файли openclaw-cli-images. Зовнішні CLI backends усе ще отримують file paths, але ці paths є per-run temp materializations із cleanup.
  • Діагностика cache-trace, діагностика Anthropic payload, діагностика raw model stream, diagnostics timeline events і stability bundles Gateway тепер записують рядки SQLite замість файлів logs/*.jsonl або logs/stability/*.json. Runtime path override flags і env vars вилучено; команди export/debug можуть явно матеріалізувати файли з database rows.
  • macOS companion більше не має rolling writer diagnostics.jsonl. App logs ідуть у unified logging, а довговічна діагностика Gateway лишається SQLite-backed.
  • Список записів macOS port-guardian тепер використовує типізовані спільні SQLite рядки macos_port_guardian_records замість JSON-файлу Application Support або непрозорого singleton blob.
  • Singleton locks Gateway тепер використовують типізовані спільні SQLite-рядки state_leases під scope gateway_locks замість lock-файлів у temp-dir. Документи Fly і OAuth troubleshooting тепер вказують на SQLite lease/auth refresh lock замість застарілого очищення file-lock.
  • Restart sentinel state Gateway тепер використовує типізовані спільні SQLite рядки gateway_restart_sentinel замість restart-sentinel.json; runtime читає sentinel kind, status, routing, message, continuation і stats з типізованих стовпців. payload_json є лише копією replay/debug. Runtime code очищає SQLite row напряму й більше не містить plumbing cleanup файлів.
  • Restart intent Gateway і supervisor handoff state тепер використовують типізовані спільні SQLite рядки gateway_restart_intent і gateway_restart_handoff замість sidecar-файлів gateway-restart-intent.json і gateway-supervisor-restart-handoff.json.
  • Singleton coordination Gateway тепер використовує типізовані рядки state_leases під gateway_locks замість запису файлів gateway.<hash>.lock. Рядок lease володіє lock owner, expiry, Heartbeat і debug payload; SQLite володіє atomic acquire/release boundary. Retired file-lock directory option вилучено; тести використовують SQLite row identity напряму.
  • Старий unused cron usage-report helper, який сканував файли cron/runs/*.jsonl, було видалено. Звіти Cron run history мають читати типізовані SQLite-рядки cron_run_logs.
  • Main-session restart recovery тепер знаходить candidate agents через SQLite-реєстр agent_databases замість сканування каталогів agents/*/sessions.
  • Gemini session-corruption recovery тепер видаляє лише SQLite session row; йому більше не потрібен застарілий gate storePath, і він не намагається unlink derived transcript JSONL path.
  • Обробка Path override тепер трактує буквальні env values undefined/null як unset, запобігаючи випадковим repo-root базам даних undefined/state/*.sqlite під час tests або shell handoffs.
  • Config health fingerprints тепер використовують типізовані спільні SQLite-рядки config_health_entries замість logs/config-health.json, залишаючи звичайний config file єдиним non-credential configuration document. macOS companion зберігає лише process-local health state і не відтворює старий JSON sidecar.
  • Runtime auth profile більше не імпортує й не записує credential JSON files. Канонічним credential store є SQLite; auth-profiles.json, per-agent auth.json і спільний credentials/oauth.json є вхідними даними doctor migration, які видаляються після імпорту.
  • Тести save/state для auth profile тепер напряму перевіряють типізовані SQLite auth tables і використовують застарілі auth-profile filenames лише для входів doctor migration.
  • openclaw secrets apply очищає лише config file, env file і SQLite auth-profile store. Він більше не містить compatibility logic, що редагує retired per-agent auth.json; doctor відповідає за імпорт і видалення цього файлу.
  • Плани Hermes secret migration і applies імпортували API-key profiles напряму в SQLite auth-profile store. Він більше не записує й не перевіряє auth-profiles.json як проміжну ціль.
  • User-facing auth docs тепер описують state/openclaw.sqlite#table/auth_profile_stores/<agentDir> замість інструкцій користувачам inspect або copy auth-profiles.json; застарілі назви OAuth/auth JSON залишаються задокументованими лише як doctor-import inputs.
  • Core state-path helpers більше не expose retired файл credentials/oauth.json. Застаріле filename є локальним для doctor auth import path.
  • Документи install, security, onboarding, model-auth і SecretRef тепер описують SQLite auth-profile rows і whole-state backup/migration замість per-agent auth-profile JSON files.
  • PI model discovery тепер передає canonical credentials у in-memory auth storage pi-coding-agent. Він більше не створює, не очищає й не записує per-agent auth.json під час discovery.
  • Налаштування Voice Wake trigger і routing тепер використовують типізовані спільні таблиці SQLite замість settings/voicewake.json, settings/voicewake-routing.json або opaque generic rows; doctor імпортує застарілі JSON-файли та видаляє їх після successful migration.
  • Update-check state тепер використовує типізований спільний рядок update_check_state замість update-check.json або opaque generic blob; doctor імпортує застарілий JSON-файл і видаляє його після successful migration.
  • Config health state тепер використовує типізовані спільні рядки config_health_entries замість logs/config-health.json або opaque generic blob; doctor імпортує застарілий JSON-файл і видаляє його після successful migration.
  • Plugin conversation binding approvals тепер використовують типізовані рядки plugin_binding_approvals замість opaque shared SQLite state або plugin-binding-approvals.json; застарілий файл є вхідними даними для міграції doctor.
  • Загальні прив’язки поточної розмови тепер зберігають типізовані рядки current_conversation_bindings замість перезапису bindings/current-conversations.json; doctor імпортує застарілий JSON-файл і видаляє його після успішної міграції.
  • Журнали синхронізації імпортованих джерел Memory Wiki тепер зберігають один рядок стану Plugin у SQLite на ключ сховища/джерела замість перезапису .openclaw-wiki/source-sync.json; провайдер міграції імпортує та видаляє застарілий JSON-журнал.
  • Записи запусків імпорту ChatGPT у Memory Wiki тепер зберігають один рядок стану Plugin у SQLite на ідентифікатор сховища/запуску замість запису .openclaw-wiki/import-runs/*.json. Знімки для відкату залишаються явними файлами сховища, доки архівацію знімків запусків імпорту не буде перенесено до сховища blob-об’єктів.
  • Скомпільовані дайджести Memory Wiki тепер зберігають рядки blob-об’єктів Plugin у SQLite замість запису .openclaw-wiki/cache/agent-digest.json і .openclaw-wiki/cache/claims.jsonl. Провайдер міграції імпортує старі файли кешу та видаляє каталог кешу, коли він стає порожнім.
  • Відстеження встановлення Skills у ClawHub тепер зберігає один рядок стану Plugin у SQLite на робочу область/Skill замість запису або читання супровідних файлів .clawhub/lock.json і .clawhub/origin.json під час виконання. Код середовища виконання використовує об’єкти стану відстежених встановлень, а не абстракції lockfile/origin у формі файлів. Doctor імпортує застарілі супровідні файли з налаштованих робочих областей агентів і видаляє їх після чистого імпорту.
  • Індекс установлених Plugin тепер читає та записує типізований спільний singleton-рядок SQLite installed_plugin_index замість plugins/installs.json; застарілий JSON-файл є лише вхідними даними для міграції doctor і видаляється після імпорту.
  • Застарілий допоміжний засіб шляху plugins/installs.json тепер живе в застарілому коді doctor. Модулі індексу Plugin у середовищі виконання надають лише параметри збереження на базі SQLite, а не шлях до JSON-файлу.
  • Sentinel перезапуску Gateway, намір перезапуску та стан передавання supervisor тепер використовують типізовані спільні рядки SQLite (gateway_restart_sentinel, gateway_restart_intent і gateway_restart_handoff) замість загальних opaque blob-об’єктів. Код перезапуску середовища виконання не має контракту sentinel/intent/handoff у формі файлів.
  • Кеш синхронізації Matrix, метадані сховища, прив’язки потоків, маркери дедуплікації вхідних подій, стан cooldown для перевірки запуску, криптографічні знімки SDK IndexedDB, облікові дані та ключі відновлення тепер використовують спільні таблиці стану/blob-об’єктів Plugin у SQLite. Структури шляхів середовища виконання більше не надають шлях метаданих storage-meta.json; ця назва файлу є лише вхідними даними застарілої міграції. Їхній план імпорту застарілого JSON живе в поверхні налаштування/міграції doctor Plugin Matrix.
  • Запуск Matrix більше не сканує, не звітує і не завершує застарілий файловий стан Matrix. Виявлення файлів Matrix, створення застарілого криптографічного знімка, стан міграції відновлення room-key, імпорт і видалення джерела повністю належать doctor.
  • Runtime barrels міграції Matrix було видалено. Допоміжні засоби виявлення та зміни застарілого стану/криптографії імпортуються doctor Matrix напряму, замість того щоб бути частиною runtime API.
  • Маркери повторного використання знімків міграції Matrix тепер живуть у стані Plugin SQLite замість matrix/migration-snapshot.json; doctor усе ще може повторно використовувати той самий перевірений передміграційний архів без запису супровідного файлу стану.
  • Курсори шини Nostr і стан публікації профілю тепер використовують спільний стан Plugin у SQLite. Їхній план імпорту застарілого JSON живе в поверхні налаштування/міграції doctor Plugin Nostr.
  • Перемикачі сесій Active Memory тепер використовують спільний стан Plugin у SQLite замість session-toggles.json; повторне ввімкнення пам’яті видаляє рядок замість перезапису JSON-об’єкта.
  • Пропозиції Skill Workshop і лічильники review тепер використовують спільний стан Plugin у SQLite замість сховищ skill-workshop/<workspace>.json для кожної робочої області. Кожна пропозиція є окремим рядком у skill-workshop/proposals, а лічильник review є окремим рядком у skill-workshop/reviews.
  • Запуски subagent reviewer у Skill Workshop тепер використовують resolver transcript сесії середовища виконання замість створення супровідних шляхів сесій skill-workshop/<sessionId>.json.
  • Оренди процесів ACPX тепер використовують спільний стан Plugin у SQLite під acpx/process-leases замість реєстру цілого файлу process-leases.json. Кожна оренда зберігається як власний рядок, зберігаючи прибирання застарілих процесів під час запуску без runtime-шляху перезапису JSON.
  • Wrapper-скрипти ACPX та ізольований home Codex генеруються в тимчасовому корені OpenClaw. Вони перестворюються за потреби й не є вхідними даними для резервного копіювання або міграції.
  • Збереження реєстру запусків subagent використовує типізовані спільні рядки subagent_runs. Старий шлях subagents/runs.json тепер є лише вхідними даними для міграції doctor, а назви runtime-допоміжних засобів більше не описують шар стану як disk-backed. Runtime-тести більше не створюють недійсні або порожні фікстури runs.json для доведення поведінки реєстру; вони напряму засівають/читають рядки SQLite.
  • Резервне копіювання готує каталог стану перед архівацією, копіює недатабазні файли, створює знімки баз даних *.sqlite через VACUUM INTO, пропускає live-супровідні файли WAL/SHM, записує метадані знімків у маніфест архіву та записує завершені запуски резервного копіювання в SQLite разом із маніфестом архіву. openclaw backup create за замовчуванням перевіряє записаний архів; --no-verify є явним швидким шляхом.
  • openclaw backup restore перевіряє архів перед видобуванням, повторно використовує нормалізований маніфест verifier і відновлює перевірені ресурси маніфесту до записаних для них вихідних шляхів. Для запису потрібен --yes, а для плану відновлення підтримується --dry-run.
  • Старий фільтр volatile-path для резервного копіювання видалено. Резервному копіюванню більше не потрібен live-tar skip list для застарілих JSON/JSONL файлів сесій або cron, оскільки знімки SQLite готуються до створення архіву.
  • Plain setup і підготовка робочої області onboarding більше не створюють каталоги agents/<agentId>/sessions/. Вони створюють лише config/робочу область; рядки сесій SQLite і рядки transcript створюються на вимогу в базі даних конкретного агента.
  • Виправлення дозволів безпеки тепер націлюється на глобальну та агентні бази даних SQLite разом із супровідними файлами WAL/SHM замість sessions.json і JSONL-файлів transcript.
  • Runtime-назви реєстру sandbox тепер описують види реєстру SQLite напряму замість перенесення застарілої термінології JSON-реєстру через активне сховище.
  • openclaw reset --scope config+creds+sessions видаляє агентні бази даних openclaw-agent.sqlite разом із супровідними файлами WAL/SHM, а не лише застарілі каталоги sessions/.
  • Допоміжні засоби aggregate session Gateway тепер використовують назви, орієнтовані на записи: loadCombinedSessionEntriesForGateway повертає { databasePath, entries }. Стару combined-store naming було видалено з runtime-викликачів.
  • Засівання Docker MCP channel тепер записує основний рядок сесії та події transcript у агентну базу даних SQLite замість створення sessions.json і JSONL transcript.
  • Вбудований hook session-memory тепер визначає контекст попередньої сесії з SQLite за {agentId, sessionId}. Він більше не сканує, не зберігає і не синтезує шляхи transcript або каталоги workspace/sessions.
  • Вбудований hook command-logger тепер записує рядки аудиту команд до спільної таблиці SQLite command_log_entries замість додавання до logs/commands.log.
  • Allowlist для pairing каналів тепер надають лише допоміжні засоби читання/запису на базі SQLite у середовищі виконання та plugin SDK. Старий resolver шляху *-allowFrom.json і reader файлу живуть лише в застарілому коді імпорту doctor.
  • migration_runs записує виконання міграцій застарілого стану зі статусом, часовими мітками та JSON-звітами.
  • migration_sources записує кожне імпортоване джерело застарілого файлу з hash, розміром, кількістю записів, цільовою таблицею, run id, статусом і станом видалення джерела.
  • backup_runs записує шляхи архівів резервного копіювання, статус і JSON маніфести.
  • Глобальна схема не зберігає невикористану таблицю реєстру agents. Виявлення баз даних агентів є канонічним реєстром agent_databases, доки runtime не матиме реального власника agent-record.
  • Згенерована config каталогу моделей зберігається в типізованих глобальних рядках SQLite agent_model_catalogs, ключованих за каталогом агента. Runtime-викликачі використовують ensureOpenClawModelCatalog; у runtime-коді немає API сумісності models.json. Реалізація записує SQLite, а вбудований PI registry гідратується з цього збереженого payload без створення файлу models.json.
  • Markdown-експорт transcript сесій QMD і config memory.qmd.sessions було видалено. Немає колекції transcript QMD, немає runtime-шляху qmd/sessions* і немає file-backed bridge пам’яті сесій.
  • Runtime memory-core імпортує допоміжні засоби індексації SQLite transcript з openclaw/plugin-sdk/memory-core-host-engine-session-transcripts, а не з підшляху QMD SDK. Підшлях QMD зберігає compatibility re-export лише для зовнішніх викликачів, доки major cleanup SDK не зможе його видалити.
  • Власний index.sqlite QMD тепер є тимчасовою runtime-матеріалізацією на базі основної таблиці SQLite plugin_blob_entries. Runtime більше не створює довговічний супровідний файл ~/.openclaw/agents/<agentId>/qmd.
  • Необов’язковий Plugin memory-lancedb більше не створює ~/.openclaw/memory/lancedb як неявне кероване OpenClaw сховище. Це зовнішній backend LanceDB, і він лишається вимкненим, доки operator не налаштує явний dbPath.
  • check:database-first-legacy-stores завершується з помилкою для нового runtime source, який поєднує назви застарілих сховищ із write-style API файлової системи. Він також завершується з помилкою для runtime source, який повторно вводить retired markers моста transcript transcriptLocator або sqlite-transcript://.... Код міграції, doctor, імпорту та явного експорту, не пов’язаного із сесіями, залишається дозволеним. Ширші назви застарілих контрактів, як-от sessionFile, storePath і старі file-era фасади SessionManager, усе ще мають поточних власників і потребують окремої роботи над guard міграції, перш ніж вони зможуть стати обов’язковою preflight перевіркою. Guard тепер також охоплює runtime-сховища cache/*.json, загальні супровідні файли thread-bindings.json, JSON стану/run-log cron, JSON health config, супровідні файли restart і lock, налаштування Voice Wake, затвердження прив’язок Plugin, JSON індексу встановлених Plugin, JSONL аудиту File Transfer, activity logs Memory Wiki, старий текстовий log вбудованого command-logger і ручки JSONL діагностики raw-stream pi-mono. Він також забороняє старі назви root-level doctor legacy module, щоб код сумісності залишався під src/commands/doctor/. Android debug handlers також використовують logcat/in-memory output замість підготовки cache-файлів camera_debug.log або debug_logs.txt.

Цільова форма схеми

Зберігайте схеми явними. Стан runtime, яким володіє хост, використовує типізовані таблиці. Непрозорий стан, яким володіє Plugin, використовує plugin_state_entries / plugin_blob_entries; універсальної таблиці хоста kv немає.

Глобальна база даних:

text
state_leases(scope, lease_key, owner, expires_at, heartbeat_at, payload_json, created_at, updated_at)exec_approvals_config(config_key, raw_json, socket_path, has_socket_token, default_security, default_ask, default_ask_fallback, auto_allow_skills, agent_count, allowlist_count, updated_at_ms)schema_meta(meta_key, role, schema_version, agent_id, app_version, created_at, updated_at)agent_databases(agent_id, path, schema_version, last_seen_at, size_bytes)task_runs(...)task_delivery_state(...)flow_runs(...)subagent_runs(run_id, child_session_key, requester_session_key, controller_session_key, created_at, ended_at, cleanup_handled, payload_json)current_conversation_bindings(binding_key, binding_id, target_agent_id, target_session_id, target_session_key, channel, account_id, conversation_kind, parent_conversation_id, conversation_id, target_kind, status, bound_at, expires_at, metadata_json, updated_at)plugin_binding_approvals(plugin_root, channel, account_id, plugin_id, plugin_name, approved_at)tui_last_sessions(scope_key, session_key, updated_at)plugin_state_entries(plugin_id, namespace, entry_key, value_json, created_at, expires_at)plugin_blob_entries(plugin_id, namespace, entry_key, metadata_json, blob, created_at, expires_at)media_blobs(subdir, id, content_type, size_bytes, blob, created_at, updated_at)skill_uploads(upload_id, kind, slug, force, size_bytes, sha256, actual_sha256, received_bytes, archive_blob, created_at, expires_at, committed, committed_at, idempotency_key_hash)web_push_subscriptions(endpoint_hash, subscription_id, endpoint, p256dh, auth, created_at_ms, updated_at_ms)web_push_vapid_keys(key_id, public_key, private_key, subject, updated_at_ms)apns_registrations(node_id, transport, token, relay_handle, send_grant, installation_id, topic, environment, distribution, token_debug_suffix, updated_at_ms)node_host_config(config_key, version, node_id, token, display_name, gateway_host, gateway_port, gateway_tls, gateway_tls_fingerprint, updated_at_ms)device_identities(identity_key, device_id, public_key_pem, private_key_pem, created_at_ms, updated_at_ms)device_auth_tokens(device_id, role, token, scopes_json, updated_at_ms)macos_port_guardian_records(pid, port, command, mode, timestamp)workspace_setup_state(workspace_key, workspace_path, version, bootstrap_seeded_at, setup_completed_at, updated_at)native_hook_relay_bridges(relay_id, pid, hostname, port, token, expires_at_ms, updated_at_ms)model_capability_cache(provider_id, model_id, name, input_text, input_image, reasoning, supports_tools, context_window, max_tokens, cost_input, cost_output, cost_cache_read, cost_cache_write, updated_at_ms)agent_model_catalogs(catalog_key, agent_dir, raw_json, updated_at)managed_outgoing_image_records(attachment_id, session_key, message_id, created_at, updated_at, retention_class, alt, original_media_id, original_media_subdir, original_content_type, original_width, original_height, original_size_bytes, original_filename, record_json)gateway_restart_sentinel(sentinel_key, version, kind, status, ts, session_key, thread_id, delivery_channel, delivery_to, delivery_account_id, message, continuation_json, doctor_hint, stats_json, payload_json, updated_at_ms)channel_pairing_requests(channel_key, account_id, request_id, code, created_at, last_seen_at, meta_json)channel_pairing_allow_entries(channel_key, account_id, entry, sort_order, updated_at)voicewake_triggers(config_key, position, trigger, updated_at_ms)voicewake_routing_config(config_key, version, default_target_mode, default_target_agent_id, default_target_session_key, updated_at_ms)voicewake_routing_routes(config_key, position, trigger, target_mode, target_agent_id, target_session_key, updated_at_ms)update_check_state(state_key, last_checked_at, last_notified_version, last_notified_tag, last_available_version, last_available_tag, auto_install_id, auto_first_seen_version, auto_first_seen_tag, auto_first_seen_at, auto_last_attempt_version, auto_last_attempt_at, auto_last_success_version, auto_last_success_at, updated_at_ms)config_health_entries(config_path, last_known_good_json, last_promoted_good_json, last_observed_suspicious_signature, updated_at_ms)sandbox_registry_entries(registry_kind, container_name, session_key, backend_id, runtime_label, image, created_at_ms, last_used_at_ms, config_label_kind, config_hash, cdp_port, no_vnc_port, entry_json, updated_at)cron_run_logs(store_key, job_id, seq, ts, status, error, summary, diagnostics_summary, delivery_status, delivery_error, delivered, session_id, session_key, run_id, run_at_ms, duration_ms, next_run_at_ms, model, provider, total_tokens, entry_json, created_at)cron_jobs(store_key, job_id, name, description, enabled, delete_after_run, created_at_ms, agent_id, session_key, schedule_kind, schedule_expr, schedule_tz, every_ms, anchor_ms, at, stagger_ms, session_target, wake_mode, payload_kind, payload_message, payload_model, payload_fallbacks_json, payload_thinking, payload_timeout_seconds, payload_allow_unsafe_external_content, payload_external_content_source_json, payload_light_context, payload_tools_allow_json, delivery_mode, delivery_channel, delivery_to, delivery_thread_id, delivery_account_id, delivery_best_effort, failure_delivery_mode, failure_delivery_channel, failure_delivery_to, failure_delivery_account_id, failure_alert_disabled, failure_alert_after, failure_alert_channel, failure_alert_to, failure_alert_cooldown_ms, failure_alert_include_skipped, failure_alert_mode, failure_alert_account_id, next_run_at_ms, running_at_ms, last_run_at_ms, last_run_status, last_error, last_duration_ms, consecutive_errors, consecutive_skipped, schedule_error_count, last_delivery_status, last_delivery_error, last_delivered, last_failure_alert_at_ms, job_json, state_json, runtime_updated_at_ms, schedule_identity, sort_order, updated_at)delivery_queue_entries(queue_name, id, status, entry_kind, session_key, channel, target, account_id, retry_count, last_attempt_at, last_error, recovery_state, platform_send_started_at, entry_json, enqueued_at, updated_at, failed_at)commitments(id, agent_id, session_key, channel, account_id, recipient_id, thread_id, sender_id, kind, sensitivity, source, status, reason, suggested_text, dedupe_key, confidence, due_earliest_ms, due_latest_ms, due_timezone, source_message_id, source_run_id, created_at_ms, updated_at_ms, attempts, last_attempt_at_ms, sent_at_ms, dismissed_at_ms, snoozed_until_ms, expired_at_ms, record_json)migration_runs(id, started_at, finished_at, status, report_json)migration_sources(source_key, migration_kind, source_path, target_table, source_sha256, source_size_bytes, source_record_count, last_run_id, status, imported_at, removed_source, report_json)backup_runs(id, created_at, archive_path, status, manifest_json)

База даних агента:

text
schema_meta(meta_key, role, schema_version, agent_id, app_version, created_at, updated_at)sessions(session_id, session_key, session_scope, created_at, updated_at, started_at, ended_at, status, chat_type, channel, account_id, primary_conversation_id, model_provider, model, agent_harness_id, parent_session_key, spawned_by, display_name)conversations(conversation_id, channel, account_id, kind, peer_id, parent_conversation_id, thread_id, native_channel_id, native_direct_user_id, label, metadata_json, created_at, updated_at)session_conversations(session_id, conversation_id, role, first_seen_at, last_seen_at)session_routes(session_key, session_id, updated_at)session_entries(session_id, session_key, entry_json, updated_at)transcript_events(session_id, seq, event_json, created_at)transcript_event_identities(session_id, event_id, seq, event_type, has_parent, parent_id, message_idempotency_key, created_at)transcript_snapshots(session_id, snapshot_id, reason, event_count, created_at, metadata_json)vfs_entries(namespace, path, kind, content_blob, metadata_json, updated_at)tool_artifacts(run_id, artifact_id, kind, metadata_json, blob, created_at)run_artifacts(run_id, path, kind, metadata_json, blob, created_at)trajectory_runtime_events(session_id, run_id, seq, event_json, created_at)memory_index_meta(key, value)memory_index_sources(path, source, hash, mtime, size)memory_index_chunks(id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)memory_embedding_cache(provider, model, provider_key, hash, embedding, dims, updated_at)memory_index_state(id, revision)cache_entries(scope, key, value_json, blob, expires_at, updated_at)

Майбутній пошук може додати таблиці FTS без зміни канонічних таблиць подій:

text
transcript_events_fts(session_id, seq, text)vfs_entries_fts(namespace, path, text)

Великі значення мають використовувати стовпці blob, а не кодування JSON-рядком. Зберігайте value_json для малих структурованих даних, які мають залишатися доступними для перегляду звичайними інструментами SQLite.

agent_databases є канонічним реєстром для цієї гілки. Не додавайте таблицю agents, доки не з’явиться реальний власник записів агентів; конфігурація агентів залишається в openclaw.json.

Форма міграції doctor

Doctor має викликати один явний крок міграції, який можна відзвітувати та безпечно повторно запускати:

bash
openclaw doctor --fix

openclaw doctor --fix викликає реалізацію міграції стану після звичайної попередньої перевірки конфігурації та створює перевірену резервну копію перед імпортом. Запуск runtime і openclaw migrate не повинні імпортувати застарілі файли стану OpenClaw.

Властивості міграції:

  • Один прохід міграції виявляє всі застарілі файлові джерела та створює план перед будь-якими змінами.
  • Doctor створює перевірений архів резервної копії перед міграцією до імпортування застарілих файлів.
  • Імпорти є ідемпотентними та прив’язані до шляху джерела, mtime, розміру, хешу й цільової таблиці.
  • Успішно оброблені файли джерел видаляються або архівуються після того, як цільова база даних виконає commit.
  • Невдалі імпорти залишають джерело без змін і записують попередження в migration_runs.
  • Код runtime читає лише SQLite після появи міграції.
  • Шлях downgrade/export-to-runtime-files не потрібен.

Інвентаризація міграції

Перемістіть це до глобальної бази даних:

  • Записи середовища виконання реєстру завдань тепер використовують спільну базу даних; невідвантажений імпортер sidecar tasks/runs.sqlite видалено. Збереження знімків виконують upsert за id завдання і видаляють лише відсутні рядки завдань/доставлення.
  • Записи середовища виконання Task Flow тепер використовують спільну базу даних; невідвантажений імпортер sidecar tasks/flows/registry.sqlite видалено. Збереження знімків виконують upsert за id потоку і видаляють лише відсутні рядки потоків.
  • Записи середовища виконання стану Plugin тепер використовують спільну базу даних; невідвантажений імпортер sidecar plugin-state/state.sqlite видалено.
  • Вбудований пошук пам’яті більше не використовує memory/<agentId>.sqlite за замовчуванням; його таблиці індексу живуть у базі даних власного агента, а явний sidecar opt-in memorySearch.store.path перенесено до міграції конфігурації doctor.
  • Переіндексація вбудованої пам’яті скидає лише таблиці, що належать пам’яті, у базі даних агента. Вона не повинна замінювати весь файл SQLite, бо та сама база даних містить сесії, транскрипти, рядки VFS, артефакти та кеші середовища виконання.
  • Реєстри контейнерів/браузерів пісочниці з монолітного та сегментованого JSON. Записи середовища виконання тепер використовують спільну базу даних; імпорт застарілого JSON збережено.
  • Визначення завдань Cron, стан розкладу та історія запусків тепер використовують спільний SQLite; doctor імпортує/видаляє застарілі файли jobs.json, jobs-state.json і cron/runs/*.jsonl
  • Ідентичність/автентифікація пристрою, push, перевірка оновлень, commitments, кеш моделей OpenRouter, індекс установлених Plugin і прив’язки app-server
  • Записи сполучення пристрою/вузла та bootstrap тепер використовують типізовані таблиці SQLite
  • Підписники сповіщень про сполучення пристроїв і маркери доставлених запитів тепер використовують спільну SQLite-таблицю стану Plugin замість device-pair-notify.json.
  • Записи дзвінків Voice-call тепер використовують спільну SQLite-таблицю стану Plugin у просторі назв voice-call / calls замість calls.jsonl; CLI Plugin відстежує хвіст і підсумовує історію дзвінків на базі SQLite.
  • Сесії Gateway QQBot, записи відомих користувачів і кеш цитат ref-index тепер використовують стан Plugin SQLite у просторах назв qqbot (gateway-sessions, known-users, ref-index) замість session-*.json, known-users.json і ref-index.jsonl. Ці застарілі файли є кешами й не мігруються.
  • Налаштування вибору моделі Discord, хеші розгортання команд і прив’язки потоків тепер використовують стан Plugin SQLite у просторах назв discord (model-picker-preferences, command-deploy-hashes, thread-bindings) замість model-picker-preferences.json, command-deploy-cache.json і thread-bindings.json; міграція doctor/setup Discord імпортує та видаляє застарілі файли.
  • Курсори наздоганяння BlueBubbles і вхідні маркери dedupe тепер використовують стан Plugin SQLite у просторах назв bluebubbles (catchup-cursors, inbound-dedupe) замість bluebubbles/catchup/*.json і bluebubbles/inbound-dedupe/*.json; міграція doctor/setup BlueBubbles імпортує та видаляє застарілі файли.
  • Зсуви оновлень Telegram, записи кешу стікерів, записи кешу ланцюжків відповідей, записи кешу надісланих повідомлень, записи кешу назв тем і прив’язки потоків тепер використовують стан Plugin SQLite у просторах назв telegram (update-offsets, sticker-cache, message-cache, sent-messages, topic-names, thread-bindings) замість update-offset-*.json, sticker-cache.json, *.telegram-messages.json, *.telegram-sent-messages.json, *.telegram-topic-names.json і thread-bindings-*.json; міграція doctor/setup Telegram імпортує та видаляє застарілі файли.
  • Курсори наздоганяння iMessage, зіставлення коротких id відповідей і рядки dedupe sent-echo тепер використовують стан Plugin SQLite у просторах назв imessage (catchup-cursors, reply-cache, sent-echoes) замість imessage/catchup/*.json, imessage/reply-cache.jsonl і imessage/sent-echoes.jsonl; міграція doctor/setup iMessage імпортує та видаляє застарілі файли.
  • Розмови Microsoft Teams, опитування, SSO-токени та навчальні дані зворотного зв’язку тепер використовують простори назв стану Plugin SQLite (conversations, polls, sso-tokens, feedback-learnings) замість msteams-conversations.json, msteams-polls.json, msteams-sso-tokens.json і *.learnings.json; міграція doctor/setup Microsoft Teams імпортує та архівує застарілі файли. Очікувані завантаження є короткоживучим кешем SQLite, а старі JSON-файли кешу не мігруються.
  • Кеш синхронізації Matrix, метадані сховища, прив’язки потоків, вхідні маркери dedupe, стан cooldown перевірки запуску, облікові дані, ключі відновлення та криптографічні знімки SDK IndexedDB тепер використовують простори назв стану/blob Plugin SQLite у matrix (sync-store, storage-meta, thread-bindings, inbound-dedupe, startup-verification, credentials, recovery-key, idb-snapshots) замість bot-storage.json, storage-meta.json, thread-bindings.json, inbound-dedupe.json, startup-verification.json, credentials.json, recovery-key.json і crypto-idb-snapshot.json; міграція doctor/setup Matrix імпортує та видаляє ці застарілі файли з коренів сховища Matrix у межах облікового запису.
  • Курсори шини Nostr і стан публікації профілю тепер використовують стан Plugin SQLite у просторах назв nostr (bus-state, profile-state) замість bus-state-*.json і profile-state-*.json; міграція doctor/setup Nostr імпортує та видаляє застарілі файли.
  • Перемикачі сесій Active Memory тепер використовують стан Plugin SQLite у active-memory/session-toggles замість session-toggles.json.
  • Черги пропозицій Skill Workshop і лічильники рев’ю тепер використовують стан Plugin SQLite у skill-workshop/proposals і skill-workshop/reviews замість файлів skill-workshop/<workspace>.json для кожного workspace.
  • Черги вихідного доставлення та доставлення сесій тепер спільно використовують глобальну SQLite таблицю delivery_queue_entries з окремими назвами черг (outbound-delivery, session-delivery) замість довговічних файлів delivery-queue/*.json, delivery-queue/failed/*.json і session-delivery-queue/*.json. Крок doctor legacy-state імпортує очікувані та failed рядки, видаляє застарілі маркери доставлення і видаляє старі JSON-файли після імпорту. Поля гарячої маршрутизації та повторних спроб є типізованими стовпцями; JSON payload зберігається лише для replay/debug.
  • Оренди процесів ACPX тепер використовують стан Plugin SQLite у acpx/process-leases замість process-leases.json.
  • Метадані запусків резервного копіювання та міграції

Перемістити це до баз даних агентів:

  • Корені сесій агентів і payloads session-entry у сумісній формі. Виконано для записів середовища виконання: гарячі метадані сесій доступні для запитів у sessions, тоді як повний payload SessionEntry у застарілій формі лишається в session_entries.
  • Події транскриптів агентів. Виконано для записів середовища виконання.
  • Контрольні точки Compaction і знімки транскриптів. Виконано для записів середовища виконання: копії транскриптів контрольних точок є рядками транскриптів SQLite, а метадані контрольних точок записуються в transcript_snapshots. Допоміжні засоби контрольних точок Gateway тепер називають ці значення знімками транскриптів, а не вихідними файлами.
  • Scratch/workspace простори назв VFS агентів. Виконано для записів VFS середовища виконання.
  • Payloads вкладень subagent. Виконано для записів середовища виконання: це seed entries VFS SQLite і ніколи не довговічні файли workspace.
  • Артефакти інструментів. Виконано для записів середовища виконання.
  • Артефакти запусків. Виконано для записів середовища виконання worker через таблицю run_artifacts для кожного агента.
  • Локальні кеші середовища виконання агента. Виконано для scoped cache записів середовища виконання worker через таблицю cache_entries для кожного агента. Кеші моделей на рівні Gateway лишаються в глобальній базі даних, якщо вони не стануть agent-specific.
  • Батьківські stream logs ACP. Виконано для записів середовища виконання.
  • Сесії ledger replay ACP. Виконано для записів середовища виконання через acp_replay_sessions і acp_replay_events; застарілий acp/event-ledger.json лишається лише як вхід doctor.
  • Метадані сесій ACP. Виконано для записів середовища виконання через acp_sessions; застарілі блоки entry.acp у sessions.json є лише вхідними даними міграції doctor.
  • Sidecars траєкторій, коли вони не є явними файлами експорту. Виконано для записів середовища виконання: захоплення траєкторії записує рядки trajectory_runtime_events у базу даних агента і дзеркалить run-scoped артефакти в SQLite. Застарілі sidecars є лише вхідними даними імпорту doctor; export може матеріалізувати свіжі JSONL-виводи support-bundle, але не читає і не мігрує старі sidecars траєкторій/транскриптів під час виконання. Захоплення траєкторії середовища виконання відкриває scope SQLite; helpers шляхів JSONL ізольовані для підтримки export/debug і не реекспортуються з runtime module. Метадані траєкторії embedded-runner записують ідентичність {agentId, sessionId, sessionKey} замість збереження locator транскрипту.

Поки що залишити файловими:

  • openclaw.json
  • файли облікових даних провайдера або CLI
  • маніфести Plugin/package
  • користувацькі workspace і Git-репозиторії, коли вибрано дисковий режим
  • журнали, призначені для tailing оператором, якщо конкретну поверхню журналу не переміщено

План міграції

Етап 0: Зафіксувати межу

Зробити межу довговічного стану явною, перш ніж переносити більше рядків:

  • Додати таблицю migration_runs до глобальної бази даних. Виконано для звітів виконання міграції legacy-state.
  • Додати єдиний сервіс міграції стану, що належить doctor, для імпорту з файлів у базу даних. Виконано: openclaw doctor --fix використовує реалізацію міграції legacy-state.
  • Зробити plan read-only і зробити так, щоб apply створював резервну копію, імпортував, перевіряв, а потім видаляв або поміщав у карантин старі файли. Виконано: doctor створює перевірену резервну копію перед міграцією, передає шлях резервної копії у migration_runs і повторно використовує шляхи імпортера/видалення.
  • Додати статичні заборони, щоб новий runtime code не міг записувати застарілі файли стану, тоді як migration code і tests усе ще можуть seed/read їх. Виконано для поточно мігрованих legacy stores; guard також сканує вкладені tests на заборонені runtime transcript locator contracts.

Етап 1: Завершити глобальну control plane

Тримати спільний координаційний стан у state/openclaw.sqlite:

  • Агенти та реєстр баз даних агентів
  • Ledgers Task і Task Flow
  • Стан Plugin
  • Реєстр контейнерів/браузерів пісочниці
  • Історія запусків Cron/scheduler
  • Pairing, device, push, update-check, TUI, кеші OpenRouter/model та інший невеликий gateway-scoped runtime state
  • Метадані резервного копіювання та міграції
  • Байти медіавкладень Gateway. Виконано для записів середовища виконання; прямі файлові шляхи є тимчасовими матеріалізаціями для сумісності з відправниками каналів і staging пісочниці. Runtime allowlists приймають шляхи матеріалізації SQLite, а не застарілі state/config media roots. Doctor імпортує застарілі медіафайли в media_blobs і видаляє вихідні файли після успішного запису рядків.
  • Сесії, події та payload blobs захоплення debug proxy. Виконано: captures живуть у shared state DB і відкриваються через bootstrap shared state DB, schema, WAL і busy-timeout settings. Байти payload gzip-стиснені в capture_blobs.data; немає runtime sidecar DB override для debug proxy, blob directory або proxy-capture-only generated schema/codegen target. Міграція doctor/startup імпортує відвантажені рядки debug-proxy/capture.sqlite і referenced payload blobs, включно з активними legacy DB/blob environment overrides, а потім архівує ці джерела, залишаючи сертифікати CA незмінними.

Цей етап також видаляє дубльовані sidecar openers, permission helpers, WAL setup, filesystem pruning і compatibility writers з цих підсистем.

Етап 2: Запровадити бази даних для кожного агента

Створити одну базу даних на агента й зареєструвати її з глобальної БД:

text
~/.openclaw/state/openclaw.sqlite~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite

Глобальний рядок agent_databases зберігає шлях, версію схеми, timestamp last-seen і базові метадані size/integrity. Runtime code запитує в registry agent DB замість виведення файлових шляхів напряму.

Agent DB володіє:

  • sessions як канонічний корінь сесій, із session_entries як таблицею корисного навантаження сумісної форми, прив’язаною до цього кореня, і session_routes як унікальним пошуком активного session_key
  • conversations і session_conversations як нормалізована ідентичність маршрутизації провайдера, прив’язана до сесій
  • transcript_events
  • знімки транскриптів і контрольні точки Compaction. Виконано для runtime-записів.
  • vfs_entries
  • tool_artifacts і артефакти запусків
  • локальні для агента runtime/cache-рядки. Виконано для кешів у межах worker.
  • події батьківського потоку ACP
  • runtime-події траєкторії, коли вони не є явними артефактами експорту

Етап 3: Замінити API сховища сесій

Виконано для runtime. Файлоподібна поверхня сховища сесій не є активним runtime-контрактом:

  • Runtime більше не викликає loadSessionStore(storePath) і не трактує storePath як ідентичність сесії.
  • Операції runtime-рядків: getSessionEntry, upsertSessionEntry, patchSessionEntry, deleteSessionEntry і listSessionEntries.
  • Помічники переписування всього сховища, файлові writer-и, тести черг, pruning псевдонімів і параметри видалення legacy-ключів прибрано з runtime.
  • Застарілі експорти сумісності кореневого пакета все ще адаптують канонічні шляхи sessions.json до API SQLite-рядків.
  • Розбір sessions.json лишається тільки в коді doctor-міграції/імпорту та тестах doctor.
  • Runtime fallback життєвого циклу читає SQLite-заголовки транскриптів, а не перші рядки JSONL.

Продовжуйте видаляти все, що повторно вводить параметри file-lock, словник pruning/truncation-as-file-maintenance, ідентичність store-path або тести, єдине твердження яких — JSON-персистентність.

Етап 4: Перенести транскрипти, потоки ACP, траєкторії та VFS

Зробіть кожен потік даних агента database-native:

  • Записи додавання транскриптів проходять через одну SQLite-транзакцію, яка забезпечує заголовок сесії, перевіряє ідемпотентність повідомлення, вибирає батьківський tail, вставляє у transcript_events і записує метадані ідентичності, доступні для запитів, у transcript_event_identities. Виконано для прямих додавань повідомлень транскриптів і звичайних persisted-додавань TranscriptSessionManager; явні branch-операції зберігають свій явний вибір батька й усе ще записують SQLite-рядки без виведення будь-якого файлового locator.
  • Журнали батьківського потоку ACP стають рядками, а не файлами .acp-stream.jsonl. Виконано.
  • Налаштування ACP spawn більше не зберігає JSONL-шляхи транскриптів. Виконано.
  • Runtime-захоплення траєкторії напряму записує рядки подій/артефакти. Явна команда support/export усе ще може створювати JSONL-артефакти support-bundle як формат експорту, але експорт сесії не відтворює session JSONL. Виконано.
  • Дискові workspaces лишаються на диску, коли налаштовано disk mode.
  • VFS scratch і експериментальний режим workspace лише для VFS використовують DB агента.

Міграція один раз імпортує старі JSONL-файли, записує counts/hashes у migration_runs і видаляє імпортовані файли після перевірок цілісності.

Етап 5: Backup, Restore, Vacuum і Verify

Backup лишається одним архівним файлом:

  • Зробіть checkpoint кожної глобальної та агентської бази даних.
  • Створіть snapshot кожної DB за допомогою SQLite backup semantics або VACUUM INTO.
  • Заархівуйте компактні DB snapshots, config, зовнішні credentials і запитані workspace exports.
  • Не включайте сирі live-файли *.sqlite-wal і *.sqlite-shm.
  • Перевірте, відкривши кожен DB snapshot і виконавши PRAGMA integrity_check. openclaw backup create виконує цю перевірку архіву за замовчуванням; --no-verify пропускає лише post-write archive pass, а не перевірку цілісності створення snapshot.
  • Restore копіює snapshots назад у їхні цільові шляхи. Ця branch скидає невипущений SQLite layout до user_version = 1; майбутні випущені зміни schema можуть додати явні міграції, коли вони знадобляться.

Етап 6: Worker Runtime

Тримайте worker mode експериментальним, поки впроваджується поділ баз даних:

  • Workers отримують agent id, run id, filesystem mode і DB registry identity.
  • Кожен worker відкриває власне SQLite-з’єднання.
  • Parent зберігає повноваження channel delivery, approvals, config і cancellation.
  • Почніть з одного worker на active run; додавайте pooling лише після того, як lifecycle і DB connection ownership стануть стабільними.

Етап 7: Видалити старий світ

Виконано для runtime-керування сесіями. Старий світ дозволено лише як явний doctor input або support/export output:

  • Жодних runtime-записів sessions.json, transcript JSONL, sandbox registry JSON, task sidecar SQLite або plugin-state sidecar SQLite.
  • Жодного JSON/session file pruning, file transcript truncation, session file locks або lock-shaped session tests.
  • Жодних runtime compatibility exports, мета яких — підтримувати старі session files актуальними.
  • Явні support exports лишаються user-requested archive/materialization formats і не повинні повертати назви файлів у runtime identity.

Backup і Restore

Backups мають бути одним архівним файлом, але захоплення бази даних має бути SQLite-native:

  1. Зупиніть довготривалу write activity або увійдіть у короткий backup barrier.
  2. Для кожної глобальної та агентської бази даних виконайте checkpoint.
  3. Створіть snapshot кожної бази даних за допомогою SQLite backup semantics або VACUUM INTO у тимчасовий backup directory.
  4. Заархівуйте compacted database snapshots, config file, credentials directory, selected workspaces і manifest.
  5. Перевірте архів, відкривши кожен включений SQLite snapshot і виконавши PRAGMA integrity_check. openclaw backup create робить це за замовчуванням; --no-verify призначено лише для навмисного пропуску post-write archive pass.

Не покладайтеся на сирі live-копії *.sqlite, *.sqlite-wal і *.sqlite-shm як основний формат backup. Manifest архіву має записувати database role, agent id, schema version, source path, snapshot path, byte size і integrity status.

Restore має відновлювати global database і agent database files зі snapshot-ів архіву. Оскільки SQLite layout ще не випущено, цей refactor зберігає лише version-1 schema плюс doctor file-to-database import. Команда restore спершу перевіряє архів, потім замінює кожен manifest asset із перевіреного extracted payload.

План runtime-refactor

  1. Додати API database registry.

    • Resolve global DB і per-agent DB paths.
    • Тримайте невипущені schemas на user_version = 1; не додавайте код schema migration runner, доки він не знадобиться випущеній schema.
    • Додайте close/checkpoint/integrity helpers, які використовують tests, backup і doctor.
  2. Collapse sidecar SQLite stores.

    • Перенесіть plugin state tables у global database. Виконано для runtime writes; невипущений legacy sidecar importer видалено.
    • Перенесіть task registry tables у global database. Виконано для runtime writes; невипущений legacy sidecar importer видалено.
    • Перенесіть Task Flow tables у global database. Виконано для runtime writes; невипущений legacy sidecar importer видалено.
    • Перенесіть builtin memory-search tables у кожну agent database. Виконано; явний custom memorySearch.store.path тепер видаляється doctor config migration. Full reindex виконується in place лише проти memory tables; старий whole-file swap path і sidecar index swap helper видалено.
    • Видаліть duplicate database openers, WAL setup, permission helpers і close paths із цих subsystems.
  3. Перенести agent-owned tables у per-agent databases.

    • Створюйте agent DB on demand через global database registry. Виконано.
    • Перенесіть runtime session entries, transcript events, VFS rows і tool artifacts до agent DBs. Виконано.
    • Не мігруйте branch-local shared-DB session entries, transcript events, VFS rows або tool artifacts; цей layout ніколи не випускався. Залиште лише legacy file-to-database import у doctor.
  4. Замінити API session store.

    • Видалити storePath як runtime identity. Виконано для runtime і захищено check:database-first-legacy-stores: session metadata, route updates, command persistence, CLI session cleanup, Feishu reasoning previews, transcript-state persistence, subagent depth, auth profile session overrides, parent-fork logic і QA-lab inspection тепер resolve базу даних із канонічних agent/session keys. Gateway/TUI/UI/macOS session-list responses тепер expose databasePath замість legacy path; macOS debug surfaces показують per-agent database як read-only state замість запису session.store config. /status, chat-driven trajectory export і CLI dependency proxies більше не propagate legacy store paths; transcript usage fallback reads SQLite за agent/session identity. Runtime і bridge tests більше не expose storePath; doctor/migration inputs володіють цією legacy field name. Gateway combined-session loading більше не має спеціальної runtime branch для non-templated session.store values; він aggregates per-agent SQLite rows. Legacy session-lock doctor lane і його .jsonl.lock cleanup helper було видалено; SQLite тепер є session concurrency boundary. Hot runtime call sites використовують row-oriented helper names, такі як resolveSessionRowEntry; старий compatibility alias resolveSessionStoreEntry видалено з runtime і plugin SDK exports.
  • Використовуйте row operations { agentId, sessionKey }. Виконано: getSessionEntry, upsertSessionEntry, deleteSessionEntry, patchSessionEntry і listSessionEntries — це SQLite-first APIs, які не вимагають session store path. Status summary, local agent status, health і команда listing openclaw sessions тепер читають per-agent rows напряму та відображають per-agent SQLite database paths замість шляхів sessions.json.
  • Замініть whole-store delete/insert на upsertSessionEntry, deleteSessionEntry, listSessionEntries і SQL cleanup queries. Виконано для runtime: hot paths тепер використовують row APIs і conflict-retried row patches; remaining whole-store import/replace helpers обмежені migration import code і SQLite backend tests.
    • Видаліть store-writer.ts і writer-queue tests. Виконано.
    • Видаліть runtime legacy-key pruning і alias-delete parameters із session row upserts/patches. Виконано.
  1. Видалити runtime JSON registry behavior.
    • Зробіть sandbox registry reads і writes SQLite-only. Виконано.
    • Імпортуйте monolithic і sharded JSON лише з migration step. Виконано.
    • Видаліть sharded registry locks і JSON writes. Виконано.
  • Тримайте одну typed registry table замість зберігання registry rows як generic opaque JSON, якщо shape лишається hot-path operational state. Виконано.
  1. Видалити file-lock-shaped session mutation.

    • Виконано для runtime lock creation і runtime lock APIs.
    • Standalone legacy .jsonl.lock doctor cleanup lane видалено.
    • session.writeLock є doctor-migrated legacy config, а не typed runtime setting.
    • State integrity більше не має окремого orphan transcript-file pruning path; doctor migration imports/removes legacy JSONL sources в одному місці.
    • Gateway singleton coordination використовує typed SQLite state_leases rows під gateway_locks і більше не expose file-lock directory seam.
    • Generic plugin SDK dedupe persistence більше не використовує file locks або JSON files; він writes shared SQLite plugin-state rows. Виконано.
    • QMD embed coordination використовує SQLite state lease замість qmd/embed.lock. Виконано.
  2. Зробити workers database-aware.

    • Workers відкривають власні SQLite-з’єднання.
    • Parent володіє delivery, channel callbacks і config.
    • Worker отримує agent id, run id, filesystem mode і DB registry identity, а не live handles.
    • vfs-only лишається експериментальним і використовує agent database як storage root.
    • Спершу тримайте один worker на active run. Pooling може зачекати, доки DB connection lifetime і cancellation behavior не стануть передбачуваними.
  3. Інтеграція резервного копіювання.

    • Навчити резервне копіювання створювати знімки глобальних і агентських баз даних через SQLite backup або VACUUM INTO. Виконано для виявлених файлів *.sqlite в активі стану.
    • Додати перевірку резервної копії на цілісність SQLite і версію схеми. Виконано для створення резервної копії та стандартних перевірок цілісності архіву.
    • Записувати метадані запуску резервного копіювання в SQLite. Виконано через спільну таблицю backup_runs зі шляхом до архіву, статусом і JSON маніфесту.
    • Додати відновлення з перевірених архівних знімків. Виконано: openclaw backup restore перевіряє перед витягненням, використовує нормалізований маніфест верифікатора, підтримує --dry-run і вимагає --yes перед заміною записаних вихідних шляхів.
    • Включати експорт VFS/робочого простору лише за запитом; не експортувати внутрішні дані сесії як JSON або JSONL.
  4. Видалити застарілі тести й код. Виконано для відомих поверхонь runtime-сесій.

  • Видалити тести, які перевіряють створення runtime sessions.json або файлів transcript JSONL. Виконано для core session store, chat, gateway transcript events, preview, lifecycle, command session-entry updates, auto-reply reset/trace, і memory-core dreaming fixtures, approval target routing, session transcript repair, security permission repair, trajectory export, і session export. Тести transcript для active-memory тепер перевіряють області SQLite і відсутність створення тимчасових або збережених файлів JSONL. Стару регресію heartbeat transcript-pruning видалено, оскільки runtime більше не обрізає JSONL transcripts. Тести інструмента agent session-list більше не моделюють застарілі шляхи sessions.json як форму відповіді gateway; тести app/UI/macOS використовують databasePath. Тести використання transcript для /status тепер напряму засівають рядки transcript SQLite замість запису файлів JSONL. Тести життєвого циклу сесій Gateway тепер напряму використовують helpers засівання transcript SQLite; старої форми fixture одно рядкового session-file більше немає в покритті reset і delete. sessions.delete більше не повертає поле файлової епохи archived: []; видалення повідомляє лише результат мутації рядка. Старої опції deleteTranscript також більше немає: видалення сесії прибирає канонічний корінь sessions і дозволяє SQLite каскадно видалити належні сесії рядки transcript, snapshot і trajectory, тож жоден викликач не може залишити осиротілі transcripts або забути гілку очищення. Тести захоплення trajectory у context-engine тепер читають рядки trajectory_runtime_events з ізольованої агентської бази даних замість читання session.trajectory.jsonl. Seed-скрипти Docker MCP channel тепер напряму засівають рядки SQLite. Прямі записи sessions.json обмежені fixtures для doctor. Tool Search Gateway E2E читає докази tool-call з рядків transcript SQLite замість сканування файлів agents/<agentId>/sessions/*.jsonl. Host events memory-core і scratch-рядки session-corpus тепер живуть у спільному SQLite plugin-state; events.jsonl і session-corpus/*.txt є лише застарілими вхідними даними міграції doctor. Активні рядки використовують віртуальні шляхи memory/session-ingestion/, а не .dreams/session-corpus. Старий модуль repair для memory-core dreaming і його CLI/Gateway тести видалено, оскільки runtime більше не володіє file archive repair для цього корпусу. Тести memory-core bridge/public-artifact більше не показують .dreams/events.jsonl; вони використовують віртуальну назву JSON-артефакту на базі SQLite. Документація тестування Public SDK/Codex тепер говорить про стан сесій SQLite замість session files, а приклад channel-turn більше не відкриває аргумент storePath. Стан синхронізації Matrix тепер напряму використовує сховище SQLite plugin-state. Активні контракти client/runtime передають корінь сховища облікового запису, а не шлях bot-storage.json, і doctor імпортує застарілий bot-storage.json у SQLite перед видаленням джерела. Сценарії QA Matrix restart/destructive тепер напряму змінюють рядок синхронізації SQLite замість створення або видалення фальшивих файлів bot-storage.json, а підкладка E2EE передає корінь sync-store замість фальшивого шляху sync-store.json. Вибір storage-root для Matrix більше не оцінює корені за застарілими sync/thread JSON файлами; він використовує довговічні метадані кореня плюс реальний crypto state. Набір тестів runtime SQLite session backend більше не фабрикує sessions.json; застарілі source fixtures тепер живуть у тестах doctor, які їх імпортують. Тести сесій Gateway більше не відкривають helper createSessionStoreDir або невикористане налаштування тимчасового session-store path; fixture dirs явні, а пряме налаштування рядків використовує SQLite session-row naming. Покриття parser для doctor-only JSON5 session-store перенесено з infra tests у doctor migration tests, тож runtime test suites більше не володіють застарілим parsing session-file. Runtime-тести Microsoft Teams SSO/pending-upload більше не несуть JSON sidecar fixtures або parsers; парсинг застарілих SSO token живе лише в модулі міграції Plugin. Тести Telegram більше не засівають фальшиві шляхи сховища /tmp/*.json; вони напряму скидають message cache на базі SQLite. Generic OpenClaw test-state helper більше не відкриває застарілий writer auth-profiles.json; тести міграції doctor auth володіють цим fixture локально. Runtime-тести для TUI last-session pointers, exec approvals, active-memory toggles, Matrix dedupe/startup verification, Memory Wiki source sync, current-conversation bindings, onboarding auth, і Hermes secret imports більше не створюють старі sidecar files і не перевіряють, що старі filenames відсутні. Вони доводять поведінку через рядки SQLite і публічні store APIs; тести doctor/migration є єдиним місцем, де мають бути застарілі source filenames. Runtime-тести для device/node pairing, channel allowFrom, restart intents, restart handoff, session delivery queue entries, config health, iMessage caches, cron jobs, PI transcript headers, subagent registries, і managed image attachments також більше не створюють виведені з ужитку JSON/JSONL files лише для доказу, що їх ігнорують або що вони відсутні. PI overflow recovery більше не має fallback SessionManager rewrite/truncation: tool-result truncation і context-engine transcript rewrites змінюють рядки transcript SQLite, потім оновлюють активний prompt state з бази даних. Збережені додавання повідомлень SessionManager делегують atomic SQLite transcript append helper для parent selection і idempotency. Звичайні metadata/custom entry appends також вибирають поточного parent всередині SQLite, тож застарілі manager instances не відроджують pre-SQLite parent-chain races. Synthetic PI tail cleanup для mid-turn prechecks і sessions_yield тепер напряму обрізає стан transcript SQLite; старий SessionManager tail-removal bridge і його тести видалені. Захоплення checkpoint для Compaction також робить знімки лише з SQLite; викликачі більше не передають живий SessionManager як альтернативне джерело transcript.

  • Зберегти тести, які засівають застарілі файли лише для міграції.

  • Доказ JSON-file замінено доказом SQL row для активних runtime surfaces.

  • Додати статичні заборони на runtime-записи до застарілих JSON-шляхів сесій/cache. Виконано для repo guard.

  1. Зробити звіт міграції придатним для аудиту.
    • Записувати запуски міграції в SQLite з часовими мітками started/finished, source paths, source hashes, counts, warnings і backup path. Виконано: виконання legacy-state migration тепер зберігають звіт migration_runs з інвентарем source path/table, SHA-256 source file, sizes, record counts, warnings і backup path. Виконано: виконання legacy-state migration також зберігають рядки migration_sources для аудиту на рівні джерел і майбутніх рішень skip/backfill.
    • Зробити apply ідемпотентним. Повторний запуск після часткового імпорту має або пропускати вже імпортоване джерело, або зливати за стабільним ключем. Виконано: session indexes, transcripts, delivery queues, plugin state, task ledgers і agent-owned global SQLite rows імпортуються через стабільні ключі або семантику upsert/replace, тож повторні запуски зливають без дублювання довговічних рядків.
    • Невдалі імпорти мають залишати оригінальний source file на місці. Виконано: невдалі імпорти transcript тепер залишають оригінальне JSONL джерело за його виявленим шляхом, а migration_sources записує джерело як warning з removed_source=0 для наступного запуску doctor.

Правила продуктивності

  • Одне з'єднання на thread/process — нормально; не діліться handles між workers.
  • Використовуйте WAL, foreign_keys=ON, 30s busy timeout і короткі write transactions BEGIN IMMEDIATE.
  • Тримайте helpers write transaction синхронними, доки/якщо async transaction API не додасть явну семантику mutex/backpressure.
  • Тримайте parent delivery writes малими й транзакційними.
  • Уникайте переписування всього сховища; використовуйте row-level upsert/delete.
  • Додайте indexes для list-by-agent, list-by-session, updated-at, run id і expiration paths перед перенесенням hot code.
  • Зберігайте великі artifacts, media і vectors як BLOBs або chunked BLOB rows, а не base64 чи numeric-array JSON.
  • Тримайте opaque plugin-state entries малими й scoped.
  • Додайте SQL cleanup для TTL/expiration замість filesystem pruning. Виконано для database-owned runtime stores: media, plugin state, plugin blobs, persistent dedupe і agent cache — усі завершуються через SQLite rows. Решта filesystem cleanup обмежена тимчасовими materializations або явними removal commands.

Статичні заборони

Додати repo check, який провалює нові runtime writes до застарілих state paths:

  • sessions.json
  • *.trajectory.jsonl, окрім матеріалізованих виходів support-bundle
  • .acp-stream.jsonl
  • acp/event-ledger.json
  • файли кешу середовища виконання cache/*.json
  • agents/<agentId>/agent/auth.json
  • agents/<agentId>/agent/models.json
  • credentials/oauth.json
  • github-copilot.token.json
  • openrouter-models.json
  • auth-profiles.json
  • auth-state.json
  • exec-approvals.json
  • workspace-state.json
  • Matrix credentials*.json і recovery-key.json
  • cron/runs/*.jsonl
  • cron/jobs.json
  • jobs-state.json
  • device-pair-notify.json
  • devices/pending.json
  • devices/paired.json
  • devices/bootstrap.json
  • nodes/pending.json
  • nodes/paired.json
  • identity/device.json
  • identity/device-auth.json
  • push/web-push-subscriptions.json
  • push/vapid-keys.json
  • push/apns-registrations.json
  • process-leases.json
  • gateway-instance-id
  • session-toggles.json
  • Memory-core .dreams/events.jsonl
  • Memory-core .dreams/session-corpus/
  • Memory-core .dreams/daily-ingestion.json
  • Memory-core .dreams/session-ingestion.json
  • Memory-core .dreams/short-term-recall.json
  • Memory-core .dreams/phase-signals.json
  • Memory-core .dreams/short-term-promotion.lock
  • Skill Workshop skill-workshop/<workspace>.json
  • Skill Workshop skill-workshop/skill-workshop-review-*.json
  • Nostr bus-state-*.json
  • Nostr profile-state-*.json
  • calls.jsonl
  • known-users.json
  • ref-index.jsonl
  • QQBot session-*.json
  • BlueBubbles bluebubbles/catchup/*.json
  • BlueBubbles bluebubbles/inbound-dedupe/*.json
  • Telegram update-offset-*.json
  • Telegram sticker-cache.json
  • Telegram *.telegram-messages.json
  • Telegram *.telegram-sent-messages.json
  • Telegram *.telegram-topic-names.json
  • Telegram thread-bindings-*.json
  • iMessage catchup/*.json
  • iMessage reply-cache.jsonl
  • iMessage sent-echoes.jsonl
  • Microsoft Teams msteams-conversations.json
  • Microsoft Teams msteams-polls.json
  • Microsoft Teams msteams-sso-tokens.json
  • Microsoft Teams *.learnings.json
  • Matrix bot-storage.json
  • Matrix sync-store.json
  • Matrix thread-bindings.json
  • Matrix inbound-dedupe.json
  • Matrix startup-verification.json
  • Matrix storage-meta.json
  • Matrix crypto-idb-snapshot.json
  • Discord model-picker-preferences.json
  • Discord command-deploy-cache.json
  • сегментовані JSON-файли реєстру пісочниці
  • JSON-файли /tmp-моста реле native hook
  • plugin-state/state.sqlite
  • спеціальні допоміжні файли середовища виконання openclaw-state.sqlite
  • tasks/runs.sqlite
  • tasks/flows/registry.sqlite
  • bindings/current-conversations.json
  • restart-sentinel.json
  • gateway-restart-intent.json
  • gateway-supervisor-restart-handoff.json
  • gateway.<hash>.lock
  • qmd/embed.lock
  • commands.log
  • config-health.json
  • port-guard.json
  • settings/voicewake.json
  • settings/voicewake-routing.json
  • plugin-binding-approvals.json
  • plugins/installs.json
  • audit/file-transfer.jsonl
  • audit/crestodian.jsonl
  • crestodian/rescue-pending/*.json
  • plugins/phone-control/armed.json
  • Memory Wiki .openclaw-wiki/log.jsonl
  • Memory Wiki .openclaw-wiki/state.json
  • Memory Wiki .openclaw-wiki/locks/
  • Memory Wiki .openclaw-wiki/source-sync.json
  • Memory Wiki .openclaw-wiki/import-runs/*.json
  • Memory Wiki .openclaw-wiki/cache/agent-digest.json
  • Memory Wiki .openclaw-wiki/cache/claims.jsonl
  • ClawHub .clawhub/lock.json
  • ClawHub .clawhub/origin.json
  • декорація профілю браузера .openclaw-profile-decorated
  • відкривачі сеансів із файловим бекендом SessionManager.open(...)
  • фасади списку транскриптів SessionManager.listAll(...) і TranscriptSessionManager.listAll(...)
  • фасади форку транскриптів SessionManager.forkFromSession(...) і TranscriptSessionManager.forkFromSession(...)
  • фасади заміни змінного сеансу SessionManager.newSession(...) і TranscriptSessionManager.newSession(...)
  • фасади розгалужених сеансів SessionManager.createBranchedSession(...) і TranscriptSessionManager.createBranchedSession(...)

Заборона має дозволяти тестам створювати застарілі фікстури, а коду міграції — читати/імпортувати/видаляти застарілі файлові джерела. Невипущені допоміжні SQLite-файли залишаються забороненими й не отримують дозволів на імпорт через doctor.

Критерії завершення

  • Записи даних і кешу середовища виконання йдуть у глобальну або агентську базу даних SQLite.
  • Середовище виконання більше не записує індекси сеансів, JSONL транскриптів, JSON реєстру пісочниці, допоміжні SQLite-файли завдань або допоміжні SQLite-файли plugin-state. Імпортери невипущених допоміжних SQLite-файлів завдань і plugin-state видалено.
  • Імпорт застарілих файлів виконується лише через doctor.
  • Резервне копіювання створює один архів із компактними знімками SQLite та доказом цілісності.
  • Агентські workers можуть працювати з диском, scratch VFS або експериментальним сховищем лише VFS.
  • Файли конфігурації та явні файли облікових даних залишаються єдиними очікуваними постійними керівними файлами не баз даних.
  • Перевірки репозиторію запобігають повторному впровадженню застарілих файлових сховищ середовища виконання.
Was this useful?
On this page

On this page