---
read_when:
    - نقل بيانات وقت تشغيل OpenClaw وذاكرة التخزين المؤقت والنصوص وحالة المهام أو ملفات المسودة إلى SQLite
    - تصميم عمليات ترحيل doctor من ملفات JSON أو JSONL القديمة
    - تغيير سلوك النسخ الاحتياطي أو الاستعادة أو VFS أو تخزين العامل
    - إزالة أقفال الجلسات، والتقليم، والاقتطاع، أو مسارات توافق JSON
summary: خطة الترحيل لجعل SQLite طبقة الحالة والتخزين المؤقت الدائمة الأساسية مع إبقاء التكوين مدعومًا بالملفات
title: إعادة هيكلة الحالة وفق نهج قاعدة البيانات أولًا
x-i18n:
    generated_at: "2026-06-27T18:29:58Z"
    model: gpt-5.5
    postprocess_version: locale-links-v1
    provider: openai
    source_hash: 54995a9f43f740e7cc3ac3e0a4b69d73ddba6b2c30731193ab7ce3aa1dfc9d94
    source_path: refactor/database-first.md
    workflow: 16
---

# إعادة هيكلة الحالة وفق نهج قاعدة البيانات أولًا

## القرار

استخدم تخطيط SQLite من مستويين:

- قاعدة البيانات العامة: `~/.openclaw/state/openclaw.sqlite`
- قاعدة بيانات الوكيل: قاعدة بيانات SQLite واحدة لكل وكيل لمساحة العمل المملوكة للوكيل،
  والنص، وVFS، والأثر، وحالة وقت التشغيل الكبيرة الخاصة بكل وكيل
- يظل التكوين مدعومًا بالملفات: يبقى `openclaw.json` خارج
  قاعدة البيانات. تنتقل ملفات تعريف مصادقة وقت التشغيل إلى SQLite؛ وتبقى ملفات بيانات اعتماد المزوّد الخارجي أو CLI
  مُدارة من مالكها خارج قاعدة بيانات OpenClaw.

قاعدة البيانات العامة هي قاعدة بيانات مستوى التحكم. وهي تملك اكتشاف الوكلاء،
وحالة Gateway المشتركة، والاقتران، وحالة الجهاز/العقدة، ودفاتر المهام والتدفقات، وحالة Plugin،
وحالة وقت تشغيل المجدول، وبيانات تعريف النسخ الاحتياطي، وحالة الترحيل.

قاعدة بيانات الوكيل هي قاعدة بيانات مستوى البيانات. وهي تملك بيانات تعريف جلسة الوكيل،
وتدفق أحداث النص، ومساحة عمل VFS أو مساحة الأسماء المؤقتة، وآثار الأدوات،
وآثار التشغيل، وبيانات ذاكرة التخزين المؤقت المحلية للوكيل القابلة للبحث/الفهرسة.

يوفر هذا عرضًا عامًا دائمًا واحدًا من دون إجبار مساحات عمل الوكلاء الكبيرة،
والنصوص، وبيانات المسودة الثنائية على الدخول في مسار كتابة Gateway المشترك.

## العقد الصارم

لهذا الترحيل شكل وقت تشغيل قانوني واحد:

- تحتفظ صفوف الجلسات ببيانات تعريف الجلسة فقط. يجب ألا تحتفظ بـ
  `transcriptLocator`، أو مسارات ملفات النص، أو مسارات JSONL الشقيقة، أو مسارات القفل،
  أو بيانات تعريف التقليم، أو مؤشرات التوافق مع حقبة الملفات.
- هوية النص هي دائمًا هوية SQLite: `{agentId, sessionId}` بالإضافة إلى
  بيانات تعريف اختيارية للموضوع عندما يحتاجها البروتوكول.
- `sqlite-transcript://...` ليست هوية وقت تشغيل أو بروتوكول. يجب ألا تقوم الشيفرة الجديدة
  باشتقاق محددات النص أو الاحتفاظ بها أو تمريرها أو تحليلها أو ترحيلها. ويجب ألا يحتوي وقت التشغيل والاختبارات
  على محددات زائفة إطلاقًا؛ يجوز للوثائق ذكر السلسلة
  فقط لحظرها.
- تنتمي `sessions.json` القديمة، وJSONL للنص، و`.jsonl.lock`، والتقليم، والاقتطاع،
  ومنطق مسار الجلسة القديم فقط إلى مسار ترحيل/استيراد doctor.
- تنتمي الأسماء البديلة القديمة لتكوين الجلسة فقط إلى ترحيل doctor. لا يفسّر وقت التشغيل
  `session.idleMinutes`، أو `session.resetByType.dm`، أو
  الأسماء البديلة للجلسة الرئيسية عبر الوكلاء `agent:main:*` لوكيل آخر مكوَّن.
- هوية توجيه الجلسة هي حالة علائقية مكتوبة الأنواع. يجب أن تقرأ مسارات وقت التشغيل الساخنة وواجهة المستخدم
  `sessions.session_scope`، و`sessions.account_id`،
  و`sessions.primary_conversation_id`، و`conversations`، و
  `session_conversations`؛ ويجب ألا تحلل `session_key` أو تستخرج
  `session_entries.entry_json` لهوية المزوّد إلا كظل توافق
  أثناء حذف مواقع الاستدعاء القديمة.
- علامات الرسائل المباشرة على مستوى القناة مثل `dm` مقابل `direct` هي مفردات توجيه،
  وليست محددات نص أو مقابض توافق لمخزن الملفات.
- ينتمي تكوين معالج الخطافات القديم فقط إلى أسطح تحذير/ترحيل doctor.
  يجب ألا يحمّل وقت التشغيل `hooks.internal.handlers`؛ تعمل الخطافات عبر أدلة الخطافات المكتشفة
  وبيانات تعريف `HOOK.md` فقط.
- يجب أن تمرر بداية وقت التشغيل، ومسارات الرد الساخنة، وCompaction، وإعادة الضبط، والاسترداد، والتشخيصات،
  وTTS، وخطافات الذاكرة، والوكلاء الفرعيون، وتوجيه أوامر Plugin، وحدود البروتوكول، و
  الخطافات `{agentId, sessionId}` عبر وقت التشغيل.
- يجب أن تزرع الاختبارات صفوف نص SQLite وتتحقق منها عبر
  `{agentId, sessionId}`. يجب حذف الاختبارات التي تثبت فقط تمرير مسار JSONL،
  أو الحفاظ على محدد مقدم من المستدعي، أو توافق ملف النص
  ما لم تغطِّ استيراد doctor، أو تجسيد مواد الدعم/التصحيح غير المرتبطة بالجلسة،
  أو شكل البروتوكول.
- يجب ألا يقبل `runEmbeddedPiAgent(...)`، وتشغيلات العاملين المحضّرة، والمحاولة المضمنة الداخلية
  محددات نص. فهي تفتح مدير نص SQLite
  بواسطة `{agentId, sessionId}` وتمرر ذلك المدير إلى جلسة الوكيل الداخلية المتوافقة مع PI،
  بحيث لا يستطيع المستدعون القدامى جعل المشغّل يكتب
  نصوص JSON/JSONL.
- يجب أن تخزن تشخيصات المشغّل سجلات تتبع وقت التشغيل/ذاكرة التخزين المؤقت/الحمولة في SQLite.
  يجب ألا تكشف تشخيصات وقت التشغيل مفاتيح تجاوز ملفات JSONL أو أدوات مساعدة عامة
  لتصدير JSONL للنص؛ يمكن للصادرات الموجهة للمستخدم تجسيد آثار صريحة
  من صفوف قاعدة البيانات من دون إعادة أسماء الملفات إلى وقت التشغيل.
- يستخدم تسجيل التدفق الخام `OPENCLAW_RAW_STREAM=1` بالإضافة إلى صفوف تشخيص SQLite.
  عقد مسجل الملفات القديم في pi-mono، وهو `PI_RAW_STREAM` و`PI_RAW_STREAM_PATH` و
  `raw-openai-completions.jsonl`، ليس جزءًا من وقت تشغيل OpenClaw
  أو اختباراته.
- يجب ألا تفهرس ذاكرة QMD نصوص SQLite بتصديرها إلى ملفات markdown.
  تفهرس QMD ملفات الذاكرة المكوّنة فقط؛ ويبقى بحث نصوص الجلسات
  مدعومًا بـ SQLite.
- المسار الفرعي لـ QMD SDK خاص بـ QMD فقط في الشيفرة الجديدة. تعيش أدوات مساعدة فهرسة نصوص جلسات SQLite
  على `memory-core-host-engine-session-transcripts`؛ وأي
  إعادة تصدير من QMD هي توافق فقط ويجب ألا تستخدمها شيفرة وقت التشغيل.
- تعيش فهارس الذاكرة المضمنة في قاعدة بيانات الوكيل المالكة. يجب ألا يكشف تكوين وقت التشغيل
  وعقود وقت التشغيل المحلولة `memorySearch.store.path`؛ يحذف doctor
  مفتاح التكوين القديم ذاك، وتمرر الشيفرة الحالية
  `databasePath` الخاصة بالوكيل داخليًا.

يجب أن يواصل عمل التنفيذ حذف الشيفرة حتى تصبح هذه العبارات صحيحة
من دون استثناءات خارج حدود doctor/import/export/debug.

## حالة الهدف والتقدم

### الهدف الصارم

- تملك قاعدة بيانات SQLite عامة واحدة حالة مستوى التحكم:
  `state/openclaw.sqlite`.
- تملك قاعدة بيانات SQLite واحدة لكل وكيل حالة مستوى البيانات:
  `agents/<agentId>/agent/openclaw-agent.sqlite`.
- يبقى التكوين مدعومًا بالملفات. لا يُعد `openclaw.json` جزءًا من إعادة هيكلة
  قاعدة البيانات هذه.
- الملفات القديمة هي مدخلات ترحيل doctor فقط.
- لا يكتب وقت التشغيل أو يقرأ أبدًا جلسة أو نص JSONL كحالة نشطة.

### حالات الهدف

- `not-started`: ما زالت شيفرة وقت التشغيل من حقبة الملفات تكتب حالة نشطة.
- `migrating`: تستطيع شيفرة doctor/import نقل بيانات الملفات إلى SQLite.
- `dual-read`: جسر مؤقت يقرأ من SQLite والملفات القديمة معًا. هذه الحالة
  محظورة في إعادة الهيكلة هذه ما لم تُوثَّق صراحة على أنها
  خاصة بـ doctor فقط.
- `sqlite-runtime`: يقرأ وقت التشغيل ويكتب SQLite فقط.
- `clean`: أزيلت واجهات برمجة تطبيقات وقت التشغيل والاختبارات القديمة، ويمنع الحارس
  التراجعات.
- `done`: تثبت الوثائق والاختبارات والنسخ الاحتياطي وترحيل doctor وفحوصات التغييرات
  الحالة النظيفة.

### الحالة الحالية

- الجلسات: `clean` لوقت التشغيل. تعيش صفوف الجلسات في قاعدة البيانات الخاصة بكل وكيل،
  وتستخدم واجهات برمجة تطبيقات وقت التشغيل `{agentId, sessionId}` أو `{agentId, sessionKey}`، و
  `sessions.json` هو مدخل قديم خاص بـ doctor فقط.
- النصوص: `clean` لوقت التشغيل. تعيش أحداث النص، والهويات، واللقطات،
  وأحداث وقت تشغيل المسار في قاعدة البيانات الخاصة بكل وكيل. لم يعد وقت التشغيل
  يقبل محددات النص أو مسارات نص JSONL.
- مشغّل PI المضمن: `clean`. تستخدم تشغيلات PI المضمنة، والعاملون المحضرون، وCompaction،
  وحلقات إعادة المحاولة نطاق جلسة SQLite وترفض مقابض النص القديمة.
- Cron: `clean` لوقت التشغيل. يستخدم وقت التشغيل `cron_jobs` و`cron_run_logs`؛
  وتستخدم اختبارات وقت التشغيل تسمية `storeKey` في SQLite، وتبقى مسارات Cron من حقبة الملفات
  في اختبارات ترحيل doctor القديمة فقط.
- سجل المهام: `clean`. تعيش صفوف وقت تشغيل المهام وTask Flow في
  `state/openclaw.sqlite`؛ وحُذفت مستوردات SQLite الجانبية غير المشحونة.
- حالة Plugin: `clean`. تعيش صفوف حالة/كتل Plugin في قاعدة البيانات العامة المشتركة؛
  وتوجد حراسة ضد أدوات SQLite الجانبية القديمة لحالة Plugin.
- الذاكرة: `sqlite-runtime` للذاكرة المضمنة وفهرسة نصوص الجلسات.
  تعيش جداول فهرس الذاكرة في قاعدة البيانات الخاصة بكل وكيل، وتستخدم حالة ذاكرة Plugin
  صفوف حالة Plugin المشتركة، والملفات القديمة للذاكرة هي مدخلات ترحيل doctor
  أو محتوى مساحة عمل المستخدم.
- النسخ الاحتياطي: `sqlite-runtime`. تضغط مراحل النسخ الاحتياطي لقطات SQLite، وتحذف ملفات
  WAL/SHM الجانبية الحية، وتتحقق من سلامة SQLite، وتسجل تشغيلات النسخ الاحتياطي في
  قاعدة البيانات العامة.
- ترحيل doctor: `migrating`، عن قصد. يستورد doctor ملفات JSON القديمة،
  وJSONL، والمخازن الجانبية المتقاعدة إلى SQLite، ويسجل تشغيلات/مصادر الترحيل،
  ويزيل المصادر الناجحة.
- سكربتات E2E: `clean` لتغطية وقت التشغيل. تكتب تهيئة Docker MCP صفوف SQLite.
  ينشئ سكربت Docker لسياق وقت التشغيل JSONL قديمًا فقط داخل
  بذرة ترحيل doctor ويسمي مسار فهرس الجلسة القديم صراحة.

### العمل المتبقي

- [x] إعادة تسمية متغيرات مخزن اختبارات وقت تشغيل Cron بعيدًا عن `storePath` ما لم
      تكن مدخلات doctor قديمة.
      الملفات: `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] إزالة أو إعادة تسمية محاكيات اختبار التصدير القديمة من حقبة الملفات.
      الملف: `src/auto-reply/reply/commands-export-test-mocks.ts`.
      الدليل: `rg -n 'resolveSessionFilePath|sessionFile|storePath|transcriptLocator' src/auto-reply/reply`.
- [x] جعل بذرة JSONL القديمة في سياق وقت تشغيل Docker واضحة أنها خاصة بـ doctor فقط.
      الملف: `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] إعادة تشغيل الاختبارات المركزة للمخازن والأوامر والسكربتات التي لُمست.
      الدليل: `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`، تشغيل بوابة التغييرات أو دليل واسع عن بُعد.
      الدليل: نجح `pnpm check:changed --timed -- <changed extension paths>` على
      تشغيل Hetzner Crabbox رقم `run_3f1cabf6b25c` بعد إعداد Node 24/pnpm مؤقت
      وتوجيه مسار صريح لمساحة العمل المتزامنة التي لا تحتوي على `.git`.

### لا تتراجع

- لا محددات نص.
- لا ملفات جلسة نشطة.
- لا تركيبات اختبار JSONL مزيفة إلا لاختبارات ترحيل doctor القديمة.
- لا وصول خام إلى SQLite حيث يُتوقع Kysely.
- لا ترحيلات قاعدة بيانات قديمة جديدة. لم يُشحن هذا التخطيط؛ أبقِ إصدار المخطط
  عند `1` ما لم يوجد سبب قوي.

## افتراضات قراءة الشيفرة

لا توجد قرارات منتج لاحقة تعيق هذه الخطة. يجب أن يمضي التنفيذ
وفق هذه الافتراضات:

- استخدم `node:sqlite` مباشرةً واشترط بيئة تشغيل Node 22+ لمسار التخزين
  هذا.
- احتفظ بملف إعدادات عادي واحد بالضبط. لا تنقل الإعدادات أو بيانات Plugin
  أو مساحات عمل Git إلى SQLite في هذا refactor.
- ملفات توافق وقت التشغيل غير مطلوبة. ملفات JSON وJSONL القديمة هي
  مُدخلات ترحيل فقط. لم تُشحن ملفات 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/الاستيراد الصريحة. يطبّع doctor ملفات نصوص JSONL القديمة قبل
  إدراج صفوف SQLite؛ صفوف وقت التشغيل الحالية مكتوبة بالفعل بمخطط النص
  الحالي. تقرأ عملية تصدير المسار/الجلسة تلك الصفوف كما هي ويجب ألا تنفذ
  ترحيلات قديمة وقت التصدير.
- مساعدو تحليل/ترحيل نصوص JSONL القديمة مخصصون لـ doctor فقط. تبني شيفرة
  تنسيق نصوص وقت التشغيل سياق نصوص SQLite الحالي فقط؛ يتولى doctor ترقيات
  إدخالات JSONL القديمة قبل إدراج الصفوف.
- حُذف مساعد بث نصوص JSONL القديم الذي كان يملكه وقت التشغيل. تتولى شيفرة
  استيراد doctor قراءات الملفات القديمة الصريحة؛ وتقرأ محفوظات جلسات وقت
  التشغيل صفوف SQLite.
- تستخدم ارتباطات خادم تطبيق Codex قيمة `sessionId` في OpenClaw كمفتاح
  معياري في مساحة حالة Plugin الخاصة بـ Codex. تُعد `sessionKey` بيانات
  وصفية للتوجيه/العرض ويجب ألا تستبدل معرّف الجلسة الدائم أو تُعيد إحياء
  هوية ملف النص.
- تتلقى محركات السياق عقد وقت التشغيل الحالي مباشرةً. يجب ألا يغلّف السجل
  المحركات بطبقات إعادة محاولة تحذف `sessionKey` أو `transcriptScope` أو
  `prompt`؛ ويجب أن تفشل المحركات التي لا تقبل معلمات قاعدة البيانات أولًا
  الحالية بوضوح بدلًا من جسرها.
- يجب أن يبقى خرج النسخ الاحتياطي ملف أرشيف واحدًا. يجب أن تدخل محتويات
  قاعدة البيانات إلى ذلك الأرشيف كلقطات SQLite مضغوطة، لا كملفات WAL جانبية
  مباشرة خام.
- البحث في النصوص مفيد لكنه غير مطلوب لأول قطع قائم على قاعدة البيانات أولًا.
  صمّم المخطط بحيث يمكن إضافة FTS لاحقًا.
- يجب أن يبقى تنفيذ العامل تجريبيًا خلف الإعدادات بينما تستقر حدود قاعدة
  البيانات.

## نتائج قراءة الشيفرة

تجاوز الفرع الحالي بالفعل مرحلة إثبات المفهوم. قاعدة البيانات المشتركة موجودة،
و`node:sqlite` في Node موصول عبر مساعد وقت تشغيل صغير، والمخازن السابقة تكتب
الآن إلى `state/openclaw.sqlite` أو قاعدة بيانات `openclaw-agent.sqlite` المالكة.

العمل المتبقي ليس اختيار SQLite؛ بل الحفاظ على نظافة الحد الجديد وحذف أي
واجهات ذات شكل توافقي ما زالت تشبه عالم الملفات القديم:

- لم يعد `storePath` للجلسة هوية وقت تشغيل أو شكل تجهيز اختبار أو حقل حمولة
  حالة. لم تعد اختبارات وقت التشغيل والجسر تحتوي اسم عقد `storePath`؛ تتولى
  شيفرة doctor/الترحيل تلك المفردات القديمة.
- لم تعد كتابات الجلسة تمر عبر طابور `store-writer.ts` القديم داخل العملية.
  تستخدم كتابات رقع SQLite اكتشاف التعارض وإعادة محاولة محدودة بدلًا من ذلك.
- لا يزال اكتشاف المسارات القديمة له استخدامات ترحيل صالحة، لكن يجب أن تتوقف
  شيفرة وقت التشغيل عن التعامل مع `sessions.json` وملفات نصوص JSONL كأهداف
  كتابة محتملة.
- تعيش الجداول المملوكة للوكيل في قواعد بيانات SQLite الخاصة بكل وكيل. تحتفظ
  قاعدة البيانات العامة بصفوف السجل/مستوى التحكم؛ وهوية النص هي
  `{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 يدويا. يظل SQL الخام مقتصرا على
  تطبيق المخطط وpragmas و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. ولا يزال بإمكان حالة تنسيق الـ
  Plugin المملوكة للمضيف أن تملك جداول نمطية عندما يمتلك المضيف عقد الاستعلام،
  مثل `plugin_binding_approvals`.
- ترحيلات الـ Plugin هي ترحيلات بيانات فوق مساحات أسماء مملوكة للـ Plugin، لا
  ترحيلات مخطط المضيف. يمكن لأي Plugin ترحيل إدخالات الحالة/الكتل الثنائية ذات
  الإصدارات الخاصة به عبر موفر ترحيل، ويسجل المضيف حالة المصدر/التشغيل في سجل
  الترحيلات العادي. لا تتطلب تثبيتات الـ Plugin الجديدة تغيير
  `openclaw-state-schema.sql` إلا إذا كان المضيف نفسه يتولى ملكية عقد جديد عابر
  للـ plugins.
- يفتح `src/state/openclaw-agent-db.ts`
  `agents/<agentId>/agent/openclaw-agent.sqlite`، ويسجل قاعدة البيانات في قاعدة
  البيانات العامة، ويمتلك جداول الجلسات المحلية للوكيل والنسخ النصية وVFS
  والقطع الأثرية والذاكرة المؤقتة وفهارس الذاكرة. يقرأ اكتشاف وقت التشغيل
  المشترك الآن سجل `agent_databases` ذي الأنواع المولدة بدلا من إعادة تنفيذ ذلك
  الاستعلام في كل موضع استدعاء.
- تسجل قواعد البيانات العامة والخاصة بكل وكيل صف `schema_meta` يتضمن دور قاعدة
  البيانات وإصدار المخطط والطوابع الزمنية ومعرف الوكيل لقواعد بيانات الوكلاء.
  ويظل التخطيط عند `user_version = 1` لأن مخطط SQLite هذا لم يُشحن بعد.
- باتت هوية الجلسة الخاصة بكل وكيل تملك الآن جدول جذر معياري `sessions` بمفتاح
  `session_id`، مع `session_key`، و`session_scope`، و`account_id`،
  و`primary_conversation_id`، والطوابع الزمنية، وحقول العرض، وبيانات النموذج
  الوصفية، ومعرف العدة، وروابط الأصل/التفريخ كأعمدة قابلة للاستعلام.
  `session_routes` هو فهرس المسار النشط الفريد من `session_key` إلى
  `session_id` الحالي، بحيث يمكن لمفتاح مسار الانتقال إلى جلسة دائمة جديدة
  من دون جعل القراءات الساخنة تختار بين صفوف `sessions.session_key` مكررة.
  حمولة التوافق القديمة `session_entries.entry_json` معلقة على جذر
  `session_id` الدائم بمفتاح أجنبي؛ ولم تعد التمثيل الوحيد على مستوى المخطط
  للجلسة.
- هوية المحادثة الخارجية الخاصة بكل وكيل علائقية أيضا:
  يخزن `conversations` هوية الموفر/الحساب/المحادثة المعيارية، ويربط
  `session_conversations` جلسة OpenClaw واحدة بمحادثة خارجية واحدة أو أكثر. يغطي
  هذا جلسات الرسائل المباشرة الرئيسية المشتركة حيث يمكن لعدة أقران أن يشيروا
  عمدا إلى جلسة واحدة من دون الكذب في `session_key`. يفرض SQLite أيضا التفرد
  لهوية الموفر الطبيعية بحيث لا يمكن لزوج
  القناة/الحساب/النوع/النظير/الموضوع نفسه أن يتفرع عبر معرفات محادثة. يتم ربط
  أقران الرسائل المباشرة الرئيسية المشتركة بدور `participant`، بحيث يمكن لجلسة
  OpenClaw واحدة تمثيل عدة أقران DM خارجيين من دون خفض الأقران الأقدم إلى صفوف
  ذات صلة مبهمة. لا يزال `sessions.primary_conversation_id` يشير إلى هدف
  التسليم النمطي الحالي. تُفرض أعمدة التوجيه/الحالة المغلقة بقيود `CHECK` في
  SQLite بدلا من الاعتماد فقط على اتحادات TypeScript.
  يمسح إسقاط جلسة وقت التشغيل ظلال توجيه التوافق من
  `session_entries.entry_json` قبل تطبيق أعمدة الجلسة/المحادثة النمطية، بحيث لا
  يمكن لحمولات JSON القديمة إحياء أهداف التسليم.
  كذلك يتطلب توجيه إعلان الوكيل الفرعي سياق تسليم SQLite النمطي؛ ولم يعد يرجع
  إلى حقول مسار التوافق `SessionEntry`.
  يقرأ توريث التسليم الصريح في Gateway `chat.send` سياق تسليم SQLite النمطي
  بدلا من حقول التوافق `origin`/`last*`.
  وبالمثل، يستمد `tools.effective` سياق الموفر/الحساب/الموضوع من صفوف التسليم/
  التوجيه النمطية في SQLite، لا من ظلال `last*` القديمة في إدخال الجلسة.
  يعيد سياق مطالبة حدث النظام بناء حقول القناة/إلى/الحساب/الموضوع من حقول
  التسليم النمطية بدلا من ظلال `origin`.
  يتجاهل مساعد `deliveryContextFromSession` المشترك ومحوّل الجلسة إلى المحادثة
  الآن `SessionEntry.origin` بالكامل؛ وحدها حقول التسليم النمطية وصفوف المحادثة
  العلائقية يمكنها إنشاء هوية مسار ساخنة.
  يزيل تطبيع إدخال جلسة وقت التشغيل `origin` قبل حفظ أو إسقاط `entry_json`،
  وتكتب البيانات الوصفية الواردة حقول القناة/الدردشة النمطية بالإضافة إلى صفوف
  المحادثة العلائقية بدلا من إنشاء ظلال origin جديدة.
- تشير أحداث النسخ النصية ولقطات النسخ النصية وأحداث وقت تشغيل المسار الآن إلى
  جذر `sessions` المعياري الخاص بكل وكيل وتتدرج عند حذف الجلسة. وتستمر صفوف
  هوية/عدم تكرار النسخة النصية في التدرج من صف حدث النسخة النصية المحدد.
- تستخدم فهارس نواة الذاكرة الآن جداول قاعدة بيانات وكيل صريحة
  `memory_index_meta`، و`memory_index_sources`، و`memory_index_chunks`،
  و`memory_embedding_cache`، مع تتبع `memory_index_state` لتغييرات المراجعة.
  تُسمى فهارس FTS/المتجه الجانبية الاختيارية `memory_index_chunks_fts` و
  `memory_index_chunks_vec` بدلا من جداول عامة مثل `meta`، و`files`، و`chunks`،
  و`chunks_fts`، أو `chunks_vec`. تحتفظ الأسماء المعيارية بشكل صف المسار/المصدر
  الحالي وتوافق تضمين التسلسل. هذه الجداول ذاكرة بحث/مشتقة، لا تخزين نسخ نصية
  معياري؛ يمكن حذفها وإعادة بنائها من ملفات مساحة عمل الذاكرة والمصادر
  المضبوطة. يؤدي فتح فهرس ذاكرة مشحون باسم عام إلى ترحيل بياناته الوصفية
  ومصادره وقطعه وذاكرة التضمين المؤقتة إلى الجداول المعيارية؛ وتُعاد بناء
  جداول FTS/المتجه المشتقة تحت أسمائها المعيارية.
- تعيش حالة استرداد تشغيل الوكيل الفرعي الآن في صفوف `subagent_runs` المشتركة
  النمطية مع مفاتيح جلسات مفهرسة للطفل والطالب والمتحكم. أصبح ملف
  `subagents/runs.json` القديم مدخل ترحيل doctor فقط.
- تعيش ارتباطات المحادثة الحالية الآن في صفوف `current_conversation_bindings`
  مشتركة نمطية، مفاتيحها معرف المحادثة المعياري، مع أعمدة الوكيل/الجلسة الهدف،
  ونوع المحادثة، والحالة، والانتهاء، والبيانات الوصفية مخزنة كأعمدة علائقية
  بدلا من سجل ارتباط مبهم ومكرر. يتضمن مفتاح الارتباط الدائم نوع المحادثة
  المعياري بحيث لا يمكن لمراجع المباشر/المجموعة/القناة أن تتصادم، ويرفض SQLite
  قيم نوع/حالة الارتباط غير الصالحة. أصبح ملف
  `bindings/current-conversations.json` القديم مدخل ترحيل doctor فقط.
- يستعرض استرداد قائمة انتظار التسليم الآن أعمدة قائمة انتظار نمطية للقناة
  والهدف والحساب والجلسة وإعادة المحاولة والخطأ وإرسال المنصة وحالة الاسترداد
  فوق JSON الإعادة. يحتفظ `entry_json` بحمولات الإعادة والخطافات وحمولة
  التنسيق، لكن الأعمدة النمطية هي المرجع لتوجيه/حالة قائمة الانتظار الساخنة.
- تعيش مؤشرات استعادة آخر جلسة في TUI الآن في صفوف `tui_last_sessions` مشتركة
  نمطية، مفاتيحها نطاق اتصال/جلسة TUI المجزأ. أصبح ملف JSON القديم الخاص بـ
  TUI مدخل ترحيل doctor فقط.
- تعيش تفضيلات TTS الافتراضية الآن في صفوف SQLite لحالة الـ Plugin المشتركة
  مفاتيحها تحت Plugin `speech-core`. أصبح ملف `settings/tts.json` القديم مدخل
  ترحيل doctor فقط؛ ولم يعد وقت التشغيل يقرأ أو يكتب ملفات JSON لتفضيلات TTS،
  ويعيش محلل المسار القديم في وحدة ترحيل doctor.
- تتحدث بيانات هدف السر الوصفية الآن عن المخازن بدلا من التظاهر بأن كل هدف
  اعتماد هو ملف إعداد. يظل `openclaw.json` مخزن الإعداد؛ وتستخدم أهداف ملفات
  تعريف المصادقة صفوف SQLite نمطية `auth_profile_stores` مع اعتماديات بشكل
  الموفر محفوظة كحمولات JSON.
- لم يعد تدقيق الأسرار يمسح ملفات `auth.json` الخاصة بكل وكيل المتقاعدة. يمتلك
  doctor التحذير من ذلك الملف القديم واستيراده وإزالته.
- تعيش مساعدات مسار ملف تعريف المصادقة القديمة الآن في كود doctor القديم. تكشف
  مساعدات مسار ملف تعريف المصادقة الأساسية هوية مخزن مصادقة SQLite ومواقع العرض،
  لا مسارات وقت تشغيل `auth-profiles.json` أو `auth-state.json`.
- تحافظ وحدات وقت تشغيل استرداد تشغيل الوكيل الفرعي وذاكرة قدرات نماذج
  OpenRouter الآن على قارئات/كاتبات لقطات SQLite منفصلة عن مساعدات استيراد JSON
  القديمة الخاصة بـ doctor فقط. تستخدم قدرات OpenRouter صفوف
  `model_capability_cache` العامة النمطية تحت `provider_id = "openrouter"` بدلا
  من كتلة ذاكرة مؤقتة مبهمة واحدة أو جدول مضيف خاص بالموفر. يُخزن
  `taskName` لتشغيل الوكيل الفرعي في عمود `subagent_runs.task_name` النمطي؛
  نسخة `payload_json` هي بيانات إعادة/تصحيح، وليست المصدر لحقول العرض الساخنة
  أو البحث.
- ينفذ `src/agents/filesystem/virtual-agent-fs.sqlite.ts` نظام ملفات VFS فوق جدول
  `vfs_entries` في قاعدة بيانات الوكيل. تستخدم قراءات المجلدات والتصديرات
  المتكررة والحذف وإعادة التسمية نطاقات بادئات مفهرسة `(namespace, path)` بدلا
  من مسح مساحة اسم كاملة أو الاعتماد على مطابقة مسار `LIKE`.
- ينشئ `src/agents/runtime-worker.entry.ts` مخازن VFS في SQLite، وقطع أدوات
  أثرية، وقطع تشغيل أثرية، وذاكرة مؤقتة محددة النطاق لكل تشغيل للعمال.
- تعيش علامات اكتمال تمهيد مساحة العمل الآن في صفوف `workspace_setup_state`
  مشتركة نمطية، مفاتيحها مسار مساحة العمل المحلول، بدلا من
  `.openclaw/workspace-state.json`؛ ولم يعد وقت التشغيل يقرأ أو يعيد كتابة علامة
  مساحة العمل القديمة، ولم تعد واجهات API المساعدة تمرر مسار
  `.openclaw/setup-state` مزيفا لمجرد اشتقاق هوية التخزين.
- تعيش موافقات التنفيذ الآن في صف singleton نمطي في SQLite المشترك
  `exec_approvals_config`. يستورد doctor الملف القديم
  `~/.openclaw/exec-approvals.json`؛ ولم تعد كتابات وقت التشغيل تنشئ ذلك الملف
  أو تعيد كتابته أو تبلغ عنه كموقع تخزينها النشط. يقرأ رفيق macOS ويكتب صف
  الجدول نفسه في `state/openclaw.sqlite`؛ ولا يحتفظ على القرص إلا بمقبس مطالبة
  Unix لأنه IPC، وليس حالة وقت تشغيل دائمة.
- تحافظ وحدات وقت تشغيل هوية الجهاز ومصادقة الجهاز والتمهيد الآن على قارئات/
  كاتبات لقطات SQLite منفصلة عن مساعدات استيراد JSON القديمة الخاصة بـ doctor
  فقط. تستخدم هوية الجهاز صفوف `device_identities` نمطية وتستخدم رموز مصادقة
  الجهاز صفوف `device_auth_tokens` نمطية. توفق كتابات مصادقة الجهاز الصفوف حسب
  الجهاز/الدور بدلا من اقتطاع جدول الرموز، ولم يعد وقت التشغيل يوجه تحديثات
  الرمز الواحد عبر محول المخزن الكامل القديم. القديم
  توجد حمولات JSON من الإصدار 1 فقط كأشكال استيراد/تصدير خاصة بـ doctor.
- تستخدم ذاكرة التخزين المؤقت لتبادل رمز GitHub Copilot جدول حالة Plugin المشترك في SQLite
  ضمن `github-copilot/token-cache/default`. إنها حالة ذاكرة مؤقتة مملوكة للمزوّد،
  لذلك لا تضيف عمدًا جدول مخطط للمضيف.
- لم يعد GitHub Copilot compaction يكتب ملفات جانبية لمساحة العمل باسم `openclaw-compaction-*.json`.
  تستدعي الحاضنة استدعاء RPC الخاص بـ SDK history compaction لجلسة SDK المتتبعة،
  ويحتفظ OpenClaw بحالة الجلسة/النص الدائمة في
  SQLite بدلًا من ملفات علامات التوافق.
- يستخدم وقت تشغيل 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. لم يعد وقت التشغيل يقرأ مفاتيح توافق `SecurePrefs`
  `gateway.deviceToken*`؛ فهذه تخص منطق الترحيل/doctor فقط.
- يستخدم سجل الحزم الأخيرة لإشعارات Android صفوفًا مكتوبة من
  `android_notification_recent_packages`. لم يعد وقت التشغيل يرحّل أو
  يقرأ مفاتيح CSV القديمة في SharedPreferences.
- يفشل إنشاء هوية الجهاز بشكل مغلق عند وجود `identity/device.json` القديم،
  أو عندما يكون صف الهوية في SQLite غير صالح، أو عندما لا يمكن فتح مخزن هوية
  SQLite. يستورد doctor ذلك الملف ويزيله أولًا، لذلك لا يمكن لبدء تشغيل وقت التشغيل
  تدوير هوية الاقتران بصمت قبل الترحيل.
- اختيار هوية الجهاز هو مفتاح صف في SQLite، وليس محدد موقع ملف JSON. تمرر الاختبارات
  ومساعدات Gateway مفاتيح هوية صريحة؛ ولا يعرف اسم الملف المتقاعد
  `identity/device.json` إلا ترحيل doctor وبوابة بدء التشغيل ذات الفشل المغلق.
- أصبح توافق إعادة تعيين الجلسة موجودًا الآن في ترحيل تكوين doctor:
  يُنقل `session.idleMinutes` إلى `session.reset.idleMinutes`،
  ويُنقل `session.resetByType.dm` إلى `session.resetByType.direct`، ولا تقرأ
  سياسة إعادة التعيين في وقت التشغيل إلا مفاتيح إعادة التعيين القياسية.
- أصبح توافق التكوين القديم الآن ضمن `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 والإيقاظ الصوتي وفحوصات التحديث وصحة التكوين الآن جداول SQLite مشتركة مكتوبة
  للاشتراكات ومفاتيح VAPID وتسجيلات Node وصفوف المشغّلات
  وصفوف التوجيه وحالة إشعارات التحديث ومدخلات صحة التكوين بدلًا من
  كتل JSON مبهمة كاملة. أصبحت كتابات لقطات Web push وAPNs الآن توائم
  الاشتراكات/التسجيلات حسب المفتاح الأساسي بدلًا من مسح جداولها؛
  وتفعل صحة التكوين الأمر نفسه حسب مسار التكوين.
  تحتفظ وحدات وقت التشغيل الخاصة بها بقارئات/كاتبات لقطات SQLite منفصلة عن
  مساعدات استيراد JSON القديمة الخاصة بـ doctor فقط.
- يستخدم تكوين مضيف Node الآن صفًا مفردًا مكتوبًا في قاعدة بيانات SQLite المشتركة؛
  يستورد doctor ملف `node.json` القديم قبل الاستخدام العادي في وقت التشغيل.
- يستخدم اقتران الجهاز/Node واقتران القنوات وقوائم السماح للقنوات وحالة التمهيد
  الآن صفوف SQLite مكتوبة بدلًا من كتل JSON مبهمة كاملة. تتبع موافقات ربط
  Plugin وحالة مهام cron التقسيم نفسه: تعرض وحدات وقت التشغيل
  عمليات مدعومة بـ SQLite ومساعدات لقطات محايدة، وتوائم كتابات لقطات الاقتران/التمهيد
  وموافقة ربط Plugin الصفوف حسب المفتاح الأساسي
  بدلًا من اقتطاع الجداول، بينما يستورد doctor ملفات JSON القديمة ويزيلها عبر
  وحدات `src/commands/doctor/legacy/*`.
- أصبحت سجلات Plugin المثبتة موجودة الآن في فهرس Plugin المثبت في SQLite.
  لم تعد قراءة/كتابة تكوين وقت التشغيل ترحّل أو تحفظ بيانات تكوين مؤلفة قديمة
  من `plugins.installs`؛ يستورد doctor شكل التكوين القديم هذا
  إلى SQLite قبل الاستخدام العادي في وقت التشغيل.
- أصبحت لقطات استرداد بيانات اعتماد QQBot موجودة الآن في حالة Plugin في SQLite ضمن
  `qqbot/credential-backups`. لم يعد وقت التشغيل يكتب
  `qqbot/data/credential-backup*.json`؛ يستورد doctor ملفات النسخ الاحتياطي
  القديمة هذه ويزيلها مع مدخلات حالة QQBot الأخرى.
- تقارن خطة إعادة تحميل Gateway لقطات فهرس Plugin المثبت في SQLite ضمن
  مساحة أسماء فروق داخلية `installedPluginIndex.installRecords.*`. لم تعد
  قرارات إعادة التحميل في وقت التشغيل تغلف تلك الصفوف في كائنات تكوين زائفة
  من `plugins.installs`.
- لم تعد ترقية بيانات اعتماد حساب Matrix المسمى تحدث أثناء قراءات وقت التشغيل.
  يمتلك doctor إعادة تسمية `credentials/matrix/credentials.json` القديم ذي المستوى الأعلى
  عندما يمكن حل حساب Matrix واحد/افتراضي.
- لم تعد وحدات وقت تشغيل الاقتران الأساسية و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 القديمة،
  بما في ذلك تكوين مضيف Node، إلى 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`؛ لم تعد وحدات أوامر وقت التشغيل
  تحمل تحليل نصوص JSONL أو كود إصلاح الفرع النشط.

أبرز عمليات الدمج/الحذف المكتملة:

- تستخدم حالة Plugin الآن قاعدة البيانات المشتركة `state/openclaw.sqlite`. تمت إزالة مستورِد الملحق الجانبي القديم
  `plugin-state/state.sqlite` المحلي للفرع لأن
  بنية SQLite تلك لم تُشحن قط. تُبلغ مساعدات الفحص/الاختبار عن
  `databasePath` المشتركة بدلًا من كشف مسار SQLite خاص بحالة Plugin.
  تُغفل واصفات العاملين المُحضّرة أيضًا محددات مواقع النصوص. تحمل حالة جلسة وقت التشغيل
  وتشغيلات المتابعة الموضوعة في قائمة الانتظار `{agentId, sessionId}` بدلًا من
  مقابض النصوص المشتقة.
- يأخذ Compaction المضمن الآن نطاق SQLite من `agentId` و`sessionId`.
  يجب ألا تتلقى خطافات Compaction، واستدعاءات محرك السياق، وتفويض CLI، وردود البروتوكول
  مقابض `sqlite-transcript://...` مشتقة. يمكن لكود التصدير/التصحيح إنشاء عناصر مستخدم صريحة من الصفوف،
  لكنه لا يوفر مسار تصدير JSONL عامًا للجلسة ولا يعيد أسماء الملفات إلى هوية وقت التشغيل.
- يقرأ `/export-session` صفوف النص من SQLite ويكتب عرض HTML المستقل المطلوب فقط.
  لم يعد العارض المضمن يعيد بناء JSONL الجلسة أو ينزله من تلك الصفوف.
- لم يعد تفويض محرك السياق يحلل محدد موقع نص لاستعادة
  هوية الوكيل. يحمل سياق وقت التشغيل المُحضّر `agentId` المحلول
  إلى محول Compaction المضمن.
- أصبحت إعادة كتابة النص واقتطاع نتائج الأدوات الحية تقرأ وتثبت
  حالة النص بواسطة `{agentId, sessionId}` ولا تشتق محددات
  مواقع مؤقتة لحمولات أحداث تحديث النص.
- لم يعد سطح مساعد حالة النص يحتوي على بدائل قائمة على محدد الموقع
  لـ `readTranscriptState` أو `replaceTranscriptStateEvents` أو
  `persistTranscriptStateMutation`. يجب على مستدعي وقت التشغيل استخدام واجهات API
  الخاصة بـ `{agentId, sessionId}`. يقرأ استيراد Doctor الملفات القديمة عبر مسار ملف صريح
  ويكتب صفوف SQLite؛ ولا يرحّل سلاسل محددات المواقع.
- لم يعد عقد مدير جلسات وقت التشغيل يكشف `open(locator)` أو
  `forkFrom(locator)` أو `setTranscriptLocator(...)`. تفتح مديرات الجلسات المثبتة
  بواسطة `{agentId, sessionId}` فقط؛ وتعيش مساعدات السرد/التفريع
  على واجهات API الموجهة للصفوف الخاصة بالجلسات ونقاط التحقق بدلًا من واجهة مدير النصوص.
- واجهات API لقارئ نصوص Gateway تبدأ بالنطاق. تأخذ
  `{agentId, sessionId}` ولا تقبل محدد موقع نص موضعيًا
  قد يصبح هوية وقت التشغيل بالخطأ. اختفى تحليل محدد موقع النص النشط؛
  ولا تُقرأ مسارات المصادر القديمة إلا بواسطة كود استيراد Doctor.
- أحداث تحديث النص تبدأ بالنطاق أيضًا. لم يعد `emitSessionTranscriptUpdate`
  يقبل سلسلة محدد موقع مجردة، ويُوجّه المستمعون بواسطة
  `{agentId, sessionId}` دون تحليل مقبض.
- يحل بث رسائل جلسة Gateway مفاتيح الجلسات من نطاق الوكيل/الجلسة،
  وليس من محدد موقع نص. اختفى محلل/ذاكرة تخزين مؤقتة تحويل محدد موقع النص القديم إلى
  مفتاح جلسة.
- ترشح session-history SSE في Gateway التحديثات الحية حسب نطاق الوكيل/الجلسة. لم تعد
  تطبع مرشحي محددات مواقع النصوص، أو realpaths، أو هويات النصوص ذات شكل الملفات
  لتقرر ما إذا كان يجب أن يتلقى تدفق ما تحديثًا.
- لم تعد خطافات دورة حياة الجلسة تشتق أو تكشف محددات مواقع النصوص على
  `session_end`. يحصل مستهلكو الخطافات على `sessionId` و`sessionKey` ومعرفات
  الجلسة التالية وسياق الوكيل؛ وليست ملفات النصوص جزءًا من عقد دورة الحياة.
- لم تعد خطافات إعادة الضبط تشتق أو تكشف محددات مواقع النصوص أيضًا. تحمل حمولة
  `before_reset` رسائل SQLite المستعادة إضافة إلى سبب إعادة الضبط،
  بينما تبقى هوية الجلسة في سياق الخطاف.
- لم يعد ضبط حزمة اختبار الوكيل يقبل محدد موقع نص. يُحدَّد نطاق إرسال إعادة الضبط
  بواسطة `sessionId`/`sessionKey` إضافة إلى السبب.
- لم تعد أنواع جلسات امتداد الوكيل تكشف `transcriptLocator`؛ يجب على الامتدادات
  استخدام سياق الجلسة وواجهات API وقت التشغيل بدلًا من الوصول إلى
  هوية نص ذات شكل ملف.
- لم تعد خطافات Compaction في Plugin تكشف محددات مواقع النصوص. يحمل سياق الخطاف
  هوية الجلسة مسبقًا، ويجب أن تمر قراءات النصوص عبر واجهات API واعية بنطاق SQLite
  بدلًا من مقابض ذات شكل ملف.
- لم تعد خطافات `before_agent_finalize` تكشف `transcriptPath`، بما في ذلك
  حمولات ترحيل الخطافات الأصلية. تستخدم خطافات الإنهاء سياق الجلسة فقط.
- لم تعد ردود إعادة ضبط Gateway تُنشئ محدد موقع نص على
  الإدخال المُعاد. تنشئ إعادة الضبط صفوف نصوص SQLite، وتعيد إدخال الجلسة النظيف،
  وتترك الوصول إلى النصوص للقراء الواعين بالنطاق.
- لم تعد نتائج التشغيل المضمن وCompaction تعرض محددات مواقع النصوص من أجل
  محاسبة الجلسات. لا يحدث Compaction التلقائي إلا `sessionId` النشط،
  وعدادات Compaction، وبيانات تعريف الرموز.
- لم تعد نتائج المحاولة المضمنة تعيد `transcriptLocatorUsed`، ولم تعد نتائج
  `compact()` الخاصة بمحرك السياق تعيد محددات مواقع النصوص.
  تقبل حلقات إعادة المحاولة في وقت التشغيل `sessionId` لاحقًا فقط.
- لم تعد نتائج إلحاق نصوص مرآة التسليم تعيد محددات مواقع النصوص.
  يحصل المستدعون على `messageId` المُلحَق؛ وتستخدم إشارات تحديث النص نطاق SQLite.
- تعيد مساعدات تفريع الجلسة الأصلية `sessionId` المتفرع فقط. يمرر تحضير الوكيل الفرعي
  نطاق الوكيل/الجلسة الابن إلى المحركات.
- لم تعد معاملات مشغل CLI وإعادة بذور السجل تقبل محددات مواقع النصوص.
  تحل قراءات سجل CLI نطاق نص SQLite من `{agentId,
sessionId}` وسياق مفتاح الجلسة.
- أصبحت تجهيزات اختبار CLI ومشغل التشغيل المضمن تبذر وتقرأ صفوف نصوص SQLite
  بواسطة معرف الجلسة بدلًا من التظاهر بأن الجلسات النشطة هي ملفات `*.jsonl` أو
  تمرير سلسلة `sqlite-transcript://...` عبر معاملات وقت التشغيل.
- تُصدر أحداث حارس نتائج أدوات الجلسة من نطاق جلسة معروف حتى عندما لا يملك
  مدير داخل الذاكرة محدد موقع مشتقًا. لم تعد اختباراته تزيّف ملفات نصوص
  `/tmp/*.jsonl` نشطة.
- أصبحت مساعدات BTW ونقاط تحقق Compaction تقرأ وتفرّع صفوف النصوص بواسطة
  نطاق SQLite. تخزن بيانات تعريف نقاط التحقق الآن معرفات الجلسات ومعرفات الورقة/الإدخال
  فقط؛ ولم تعد محددات المواقع المشتقة تُكتب في حمولات نقاط التحقق.
- يستخدم بحث مفتاح نص Gateway نطاق نص SQLite عند حدود البروتوكول
  ولم يعد يستخدم realpaths أو stat لأسماء ملفات النصوص.
- تكتب تدويرة النصوص التلقائية لـ Compaction صفوف النصوص اللاحقة
  مباشرة عبر مخزن نصوص SQLite. تحتفظ صفوف الجلسات بهوية الجلسة اللاحقة فقط،
  وليس مسار JSONL دائمًا أو محدد موقع مثبتًا.
- يستخدم Compaction لمحرك السياق المضمن مساعدات تدوير نصوص مسماة وفق SQLite.
  لم تعد اختبارات التدوير تنشئ مسارات JSONL لاحقة أو
  تمثل الجلسات النشطة كملفات.
- يستمد احتفاظ الصور الصادرة المُدارة مفتاح ذاكرة التخزين المؤقتة لرسائل النصوص من
  إحصاءات نص SQLite بدلًا من استدعاءات stat لنظام الملفات.
- أُزيلت أقفال جلسات وقت التشغيل ومسار Doctor القديم المستقل `.jsonl.lock`.
- لم يعد barrel وقت تشغيل Microsoft Teams وSDK العام لـ Plugin يعيدان تصدير
  مساعد قفل الملفات القديم؛ فمسارات حالة Plugin الدائمة مدعومة بـ SQLite.
- أُزيل تقليم الجلسات حسب العمر/العدد والتنظيف الصريح للجلسات.
  يمتلك Doctor الاستيراد القديم؛ وتُعاد ضبط الجلسات الراكدة أو تُحذف صراحة.
- لم تعد فحوصات سلامة Doctor تعد ملف JSONL قديمًا نصًا نشطًا صالحًا
  لصف جلسة SQLite. صحة النص النشط تعتمد على SQLite فقط؛
  وتُبلّغ ملفات JSONL القديمة كمدخلات للترحيل/تنظيف العناصر اليتيمة.
- لم يعد Doctor يتعامل مع `agents/<agent>/sessions/` كحالة وقت تشغيل
  مطلوبة. لا يفحص ذلك الدليل إلا عندما يكون موجودًا بالفعل، كمدخل
  استيراد قديم أو تنظيف عناصر يتيمة.
- لم تعد مسارات Gateway `sessions.resolve` وتصحيح/إعادة ضبط/ضغط الجلسة،
  وتفريخ الوكلاء الفرعيين، والإجهاض السريع، وبيانات ACP التعريفية، والجلسات المعزولة عن Heartbeat، وتصحيح TUI
  ترحّل أو تقلّم مفاتيح الجلسات القديمة كأثر جانبي للعمل العادي في وقت التشغيل.
- أصبح حل جلسة أمر CLI يعيد `agentId` المالك بدلًا من
  `storePath`، ولم يعد ينسخ صفوف الجلسة الرئيسية القديمة أثناء حل
  `--to` أو `--session-id` العادي. تنتمي طبعة الصف الرئيسي القديم
  إلى Doctor فقط.
- لم يعد حل عمق الوكيل الفرعي في وقت التشغيل يقرأ `sessions.json` أو مخازن جلسات JSON5.
  يقرأ SQLite `session_entries` بواسطة معرف الوكيل، ولا يمكن لبيانات تعريف
  العمق/الجلسة القديمة الدخول إلا عبر مسار استيراد Doctor.
- تستمر تجاوزات جلسة ملف تعريف المصادقة عبر upserts مباشرة لصفوف `{agentId, sessionKey}`
  بدلًا من التحميل الكسول لوقت تشغيل مخزن جلسات ذي شكل ملف.
- أصبحت بوابة الإسهاب للرد التلقائي ومساعدات تحديث الجلسة تقرأ/upsert صفوف جلسات SQLite
  بواسطة هوية الجلسة ولم تعد تتطلب مسار مخزن قديمًا
  قبل لمس حالة الصف المثبتة.
- تستخدم مساعدات بيانات تعريف جلسة تشغيل الأوامر الآن أسماء ومسارات وحدات موجهة للإدخالات؛
  وأُزيل سطح مساعد أوامر `session-store` القديم.
- أصبحت تهيئة ترويسة الإقلاع وتقوية حدود Compaction اليدوي تعدل
  صفوف نصوص SQLite مباشرة. يمرر مستدعو وقت التشغيل هوية الجلسة، وليس
  مسارات `.jsonl` قابلة للكتابة.
- تنسخ إعادة تشغيل تدوير الجلسة الصامتة أحدث أدوار المستخدم/المساعد بواسطة
  `{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` يصدر فقط مساعدات صفوف الجلسات
  وصفوف النصوص. تعيش مساعدات مخطط/مسار/معاملة SQLite المركزة
  في `sqlite-runtime`؛ وتبقى مساعدات الفتح/الإغلاق/إعادة الضبط الخام محلية فقط
  لاختبارات الطرف الأول.
- أصبحت مصنفات أسماء ملفات المسارات/نقاط التحقق القديمة `.jsonl` تعيش الآن في
  وحدة ملفات الجلسات القديمة في Doctor. لم يعد تحقق الجلسات الأساسي يستورد
  مساعدات عناصر الملفات ليقرر معرفات جلسات SQLite العادية.
- تستخدم تشغيلات الوكلاء الفرعيين الحاجبة في Active Memory صفوف نصوص SQLite بدلًا من
  إنشاء ملفات `session.jsonl` مؤقتة أو مثبتة تحت حالة Plugin. أُزيل خيار
  `transcriptDir` القديم.
- يستخدم توليد slug لمرة واحدة وتشغيلات مخطط Crestodian صفوف نصوص SQLite بدلًا من
  إنشاء ملفات `session.jsonl` مؤقتة.
- تستخدم تشغيلات مساعد `llm-task` واستخراج الالتزام المخفي أيضًا صفوف
  نصوص SQLite، لذلك لم تعد جلسات المساعدة الخاصة بالنموذج فقط تنشئ
  ملفات نصوص JSON/JSONL مؤقتة.
- أصبح `TranscriptSessionManager` الآن نطاق نص SQLite مفتوحًا فقط.
  يفتحه كود وقت التشغيل باستخدام `openTranscriptSessionManagerForSession({agentId,
sessionId})`؛ وتعيش تدفقات الإنشاء، والتفريع، والمتابعة، والسرد، والتفريع
  في مساعدات صفوف SQLite المالكة لها بدلًا من واجهات المدير الثابتة.
  يتعامل كود Doctor/الاستيراد/التصحيح مع ملفات المصادر القديمة الصريحة خارج
  مدير جلسات وقت التشغيل.
- أُزيلت طريقتا الواجهة القديمتان `SessionManager.newSession()` و
  `SessionManager.createBranchedSession()`. تُنشأ الجلسات الجديدة وأحفاد النصوص
  بواسطة سير عمل SQLite المالك لها بدلًا من تحويل مدير مفتوح بالفعل إلى
  جلسة مثبتة مختلفة.
- لم تعد قرارات تفريع النص الأصلي وإنشاء التفريع تقبل
  `storePath` أو `sessionsDir`؛ إنها تستخدم نطاق نص SQLite
  `{agentId, sessionId}` بدلًا من بيانات تعريف مسار نظام الملفات المحتفظ بها.
- لم يعد مضيف الذاكرة يصدر مساعدات تصنيف نصوص دليل الجلسة عديمة الأثر؛
  يُشتق ترشيح النصوص الآن من بيانات تعريف صفوف SQLite أثناء إنشاء الإدخال.
- تستخدم اختبارات تصدير الجلسات في مضيف الذاكرة وQMD نطاقات نصوص SQLite. تبقى مسارات
  `agents/<agentId>/sessions/*.jsonl` القديمة مغطاة فقط عندما يكون الاختبار
  يثبت عمدًا توافق Doctor/الاستيراد/التصدير.
- يستخدم فحص الجلسات الخام في 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 هو الكود الوحيد الذي يستورد أسماء ملفات النصوص القديمة.
- تبدأ ترويسات نصوص وقت التشغيل عند إصدار SQLite رقم `1`. لا تعيش ترقيات أشكال JSONL V1/V2/V3 القديمة إلا في استيراد doctor، وتطبع الترويسات المستوردة على إصدار نص SQLite الحالي قبل تخزين الصفوف.
- يمنع حارس أولوية قاعدة البيانات الآن `SessionManager.listAll` و`SessionManager.forkFromSession`؛ يجب أن تبقى مسارات عمل سرد الجلسات والتفريع/الاستعادة على واجهات SQLite ذات الصفوف/النطاق.
- يمنع الحارس أيضًا أسماء مساعدي تحليل JSONL القديم للنصوص/إصلاح الفرع النشط خارج كود doctor/import، حتى لا ينشئ وقت التشغيل مسار ترحيل نصوص قديمًا ثانيًا.
- ترفض تشغيلات PI المضمنة مقابض النصوص الواردة. تستخدم هوية SQLite `{agentId, sessionId}` قبل إطلاق العامل ومرة أخرى قبل أن تلمس المحاولة حالة النص. لا يمكن لإدخال `/tmp/*.jsonl` قديم أن يختار هدف كتابة وقت التشغيل.
- تكتب سجلات تتبع الذاكرة المؤقتة وحمولة Anthropic والبث الخام والمخطط الزمني للتشخيصات الآن إلى صفوف 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 المطابقة مباشرةً وتُبقي حالة cron في وقت التشغيل ضمن معاملة قاعدة بيانات الحالة نفسها.
- يستخدم مستدعو وقت تشغيل Cron الآن مفتاح مخزن cron ثابتًا في SQLite. مسارات `cron.store` القديمة هي مدخلات استيراد doctor فقط؛ تستخدم مسارات Gateway الإنتاجية وصيانة المهام والحالة وسجل التشغيل ورد كتابة هدف Telegram `resolveCronStoreKey` ولم تعد تطبع المفتاح كمسار. تُبلغ حالة Cron الآن عن `storeKey` بدلاً من حقل `storePath` القديم ذي الشكل الملفي.
- لم يعد تحميل وقت تشغيل Cron وجدولته يطبّعان أشكال المهام المستمرة القديمة مثل `jobId` و`schedule.cron` و`atMs` الرقمي والقيم المنطقية النصية أو `sessionTarget` المفقود. يملك استيراد doctor القديم هذه الإصلاحات قبل إدراج الصفوف في SQLite.
- لم يعد إنشاء ACP يحل أو يستمر في تخزين مسارات ملفات JSONL للنصوص. يستمر إعداد الإنشاء وربط السلاسل في صف جلسة SQLite مباشرةً ويُبقي معرف الجلسة بوصفه هوية النص المحتفظ بها.
- تقرأ/تسرد/تُدرج أو تحدّث واجهات API لبيانات تعريف جلسات ACP صفوف SQLite الآن بحسب `agentId` ولم تعد تعرض `storePath` كجزء من عقد إدخال جلسة ACP.
- تحل محاسبة استخدام الجلسات وتجميع استخدام Gateway النصوص الآن بحسب `{agentId, sessionId}` فقط. لم تعد الذاكرة المؤقتة للتكلفة/الاستخدام وملخصات الجلسات المكتشفة تصطنع أو تعيد سلاسل محددات مواقع النصوص.
- تُلحق كتابة محادثة Gateway، واستمرار الإلغاء الجزئي، و`sessions.send/`، وكتابات نصوص وسائط webchat مباشرةً عبر نطاق نص SQLite. لم يعد مساعد حقن نص Gateway يقبل معامل `transcriptLocator`.
- يدرج اكتشاف نصوص SQLite الآن نطاقات النصوص وإحصاءاتها فقط:
  `{agentId, sessionId, updatedAt, eventCount}`. أُزيل مساعد التوافق الميت `listSqliteSessionTranscriptLocators` وحقل `locator` لكل صف.
- يعرّض وقت تشغيل إصلاح النصوص الآن
  `repairTranscriptSessionStateIfNeeded({agentId, sessionId})` فقط. حُذف مساعد الإصلاح القديم المعتمد على المحدد؛ يقرأ كود doctor/debug مسارات ملفات مصدر صريحة ولا يرحّل سلاسل المحددات أبدًا.
- يخزن وقت تشغيل دفتر إعادة تشغيل ACP الآن صفوف إعادة التشغيل لكل جلسة في قاعدة بيانات حالة SQLite المشتركة بدلاً من `acp/event-ledger.json`؛ يستورد doctor الملف القديم ويزيله.
- تعيش مساعدات قارئ نصوص Gateway الآن في
  `src/gateway/session-transcript-readers.ts` بدلاً من اسم الوحدة القديم
  `session-utils.fs`. سُمي فحص سجل إعادة محاولة الرجوع نسبةً إلى محتوى نص SQLite بدلاً من سطح مساعد الملفات القديم.
- تمرر مساعدات المحادثة المحقونة وCompaction في Gateway الآن نطاق نص SQLite عبر واجهات API للمساعدات الداخلية بدلاً من تسمية القيم كمسارات نصوص أو ملفات مصدر.
- يتحقق اكتشاف استمرار Bootstrap الآن من صفوف نصوص SQLite عبر `hasCompletedBootstrapTranscriptTurn`؛ ولم يعد يعرّض اسم مساعد ذي شكل ملفي.
- تستخدم اختبارات المشغل المضمن الآن هوية نص SQLite، وفتح مدير نصوص جديد يتطلب دائمًا `sessionId` صريحًا.
- تستخدم مساعدات فهرسة الذاكرة الآن مصطلحات نصوص SQLite من البداية إلى النهاية:
  يصدّر المضيف `listSessionTranscriptScopesForAgent` و`sessionTranscriptKeyForScope`، وتستخدم طوابير المزامنة الموجهة `sessionTranscripts`، وتعرض نتائج البحث العامة في الجلسات مسارات مبهمة `transcript:<agent>:<session>`، ومفتاح مصدر قاعدة البيانات الداخلي هو `session:<session>` تحت
  `source_kind='sessions'` بدلاً من مسار ملف وهمي.
- لم يعد مساعد إزالة التكرار المستمر العام في Plugin SDK يعرّض خيارات ذات شكل ملفي. يقدم المستدعون مفاتيح نطاق SQLite وتعيش صفوف إزالة التكرار الدائمة في حالة Plugin المشتركة.
- انتقلت رموز SSO الخاصة بـ Microsoft Teams من ملفات JSON المقفلة إلى حالة Plugin في SQLite. يستورد doctor `msteams-sso-tokens.json`، ويعيد بناء مفاتيح رموز SSO القانونية من الحمولات، ويزيل ملف المصدر. تبقى رموز OAuth المفوضة على حد ملفات الاعتماد الخاصة الحالي.
- انتقلت حالة ذاكرة مزامنة Matrix المؤقتة من `bot-storage.json` إلى حالة Plugin في SQLite. يستورد doctor حمولات المزامنة القديمة الخام أو المغلفة ويزيل ملف المصدر. تمرر عملاء Matrix النشطون وعملاء QA Matrix دليل جذر لمخزن مزامنة SQLite، لا مسار `sync-store.json` أو `bot-storage.json` وهميًا.
- انتقلت حالة ترحيل التشفير القديم في Matrix من
  `legacy-crypto-migration.json` إلى حالة Plugin في SQLite. يستورد doctor ملف الحالة القديم؛ انتقلت لقطات IndexedDB الخاصة بـ Matrix SDK من
  `crypto-idb-snapshot.json` إلى كتل Plugin في SQLite. مفاتيح استرداد Matrix وبيانات الاعتماد هي صفوف حالة Plugin في SQLite؛ وملفات JSON القديمة الخاصة بها هي مدخلات ترحيل doctor فقط.
- تستخدم سجلات نشاط Memory Wiki الآن حالة Plugin في SQLite بدلاً من
  `.openclaw-wiki/log.jsonl`. يستورد مزود ترحيل Memory Wiki سجلات JSONL القديمة؛ تبقى ملفات markdown للويكي ومحتوى خزنة المستخدم مستندة إلى الملفات كمحتوى مساحة عمل.
- لم تعد Memory Wiki تنشئ `.openclaw-wiki/state.json` أو دليل
  `.openclaw-wiki/locks` غير المستخدم. يزيل مزود الترحيل ملفات بيانات تعريف Plugin المتقاعدة هذه إذا كانت خزنة أقدم لا تزال تحتويها.
- تستخدم إدخالات تدقيق Crestodian الآن حالة Plugin في SQLite الأساسية بدلاً من
  `audit/crestodian.jsonl`. يستورد doctor سجل تدقيق JSONL القديم ويزيله بعد الاستيراد الناجح.
- تستخدم إدخالات تدقيق كتابة/مراقبة الإعدادات الآن حالة Plugin في SQLite الأساسية بدلاً من
  `logs/config-audit.jsonl`. يستورد doctor سجل تدقيق JSONL القديم ويزيله بعد الاستيراد الناجح.
- لم يعد مرافق macOS يكتب ملفات جانبية محلية للتطبيق `logs/config-audit.jsonl` أو
  `logs/config-health.json` أثناء تحرير `openclaw.json`. يبقى ملف الإعدادات مستندًا إلى الملفات، وتبقى لقطات الاسترداد بجانب ملف الإعدادات، وتنتمي حالة تدقيق/صحة الإعدادات الدائمة إلى مخزن SQLite الخاص بـ Gateway.
- تستخدم موافقات الإنقاذ المعلقة في Crestodian الآن حالة Plugin في SQLite الأساسية بدلاً من
  `crestodian/rescue-pending/*.json`. يستورد doctor ملفات الموافقات المعلقة القديمة ويزيلها بعد الاستيراد الناجح.
- تستخدم حالة التسليح المؤقتة في Phone Control الآن حالة Plugin في SQLite بدلاً من
  `plugins/phone-control/armed.json`. يستورد doctor ملف حالة التسليح القديم إلى مساحة الاسم `phone-control/arm-state` ويزيل الملف.
- لم يعد doctor يصلح نصوص JSONL في مكانها أو ينشئ ملفات JSONL احتياطية. يستورد الفرع النشط إلى SQLite ويزيل المصدر القديم.
- يستخدم بحث نصوص خطاف ذاكرة الجلسة قراءات SQLite بنطاق `{agentId, sessionId}` فقط. لم يعد مساعده يقبل أو يشتق محددات النصوص أو قراءات الملفات القديمة أو خيارات إعادة كتابة الملفات.
- تربط روابط محادثات خادم تطبيق Codex الآن حالة Plugin في SQLite بمفتاح جلسة OpenClaw أو نطاق `{agentId, sessionId}` الصريح. يجب ألا تحفظ روابط الرجوع إلى مسار النص.
- تستخدم قراءات السجل المعكوس في خادم تطبيق Codex نطاق نص SQLite فقط؛ يجب ألا تستعيد الهوية من مسارات ملفات النصوص.
- لم تعد مسارات ترتيب الأدوار وإعادة ضبط Compaction تفك ارتباط ملفات النصوص القديمة؛ لا تفعل إعادة الضبط إلا تدوير صف جلسة SQLite وهوية النص.
- تعيد استجابات إعادة ضبط Gateway ونقاط التفتيش صفوف جلسات نظيفة مع معرفات الجلسات. ولم تعد تصطنع محددات نصوص SQLite للعملاء.
- لم يعد Dreaming في memory-core يشذب صفوف الجلسات عبر فحص ملفات JSONL المفقودة. يمر تنظيف الوكلاء الفرعيين عبر واجهة API لوقت تشغيل الجلسات بدلاً من فحوص وجود نظام الملفات. تزرع اختبارات استيعاب النصوص الخاصة به صفوف SQLite مباشرةً بدلاً من إنشاء تجهيزات `agents/<id>/sessions` أو عناصر نائبة للمحددات.
- قد تعرض فهرسة نصوص الذاكرة `transcript:<agentId>:<sessionId>` كمسار افتراضي لنتيجة بحث لمساعدات الاستشهاد/القراءة. مصدر الفهرس الدائم علائقي (`source_kind='sessions'`، و`source_key='session:<sessionId>'`،
  و`session_id=<sessionId>`)، لذا فالقيمة ليست محدد نص وقت تشغيل، ولا مسار نظام ملفات، ويجب ألا تُمرر أبدًا مرة أخرى إلى واجهات API لوقت تشغيل الجلسات.
- تقرأ حالة ذاكرة doctor في Gateway أعداد الاستدعاء قصير الأمد وإشارات المراحل من صفوف حالة Plugin في SQLite بدلاً من `memory/.dreams/*.json`؛ وتصف مخرجات CLI وdoctor الآن ذلك التخزين بأنه مخزن SQLite، لا مسار.
- لم تعد واجهات وقت تشغيل memory-core وحالة CLI وطرق doctor في Gateway وواجهات Plugin SDK تدقق أو تؤرشف ملفات `.dreams/session-corpus` القديمة. تلك الملفات هي مدخلات ترحيل فقط؛ يستوردها doctor إلى SQLite ويحذف المصدر بعد التحقق. تستخدم صفوف أدلة استيعاب الجلسات النشطة الآن مسار SQLite الافتراضي `memory/session-ingestion/<day>.txt`؛ لا يكتب وقت التشغيل الحالة أو يشتقها أبدًا من `.dreams/session-corpus`.
- تعرض الآثار العامة في memory-core أحداث مضيف SQLite كأثر JSON افتراضي
  `memory/events/memory-host-events.json`؛ ولم تعد تعيد استخدام مسار المصدر القديم
  `.dreams/events.jsonl`.
- تستخدم سجلات حاويات/متصفحات Sandbox الآن جدول SQLite المشترك
  `sandbox_registry_entries` مع أعمدة ذات أنواع للجلسة والصورة والطابع الزمني والواجهة الخلفية/الإعدادات ومنفذ المتصفح. يستورد doctor ملفات سجل JSON القديمة الأحادية والمجزأة ويزيل المصادر الناجحة. تستخدم قراءات وقت التشغيل أعمدة الصفوف ذات الأنواع كمصدر للحقيقة؛ أما `entry_json` فهو نسخة لإعادة التشغيل/التصحيح فقط.
- تستخدم الالتزامات الآن جدول `commitments` مشتركًا ذا أنواع بدلاً من كتلة JSON للمخزن كله. تُدرج حفظات اللقطات أو تحدّث بحسب معرف الالتزام وتحذف الصفوف المفقودة فقط بدلاً من مسح الجدول وإعادة إدراجه. يحمّل وقت التشغيل الالتزامات من أعمدة النطاق ونافذة التسليم والحالة والمحاولة والنص ذات الأنواع؛ أما `record_json` فهو نسخة لإعادة التشغيل/التصحيح فقط. يستورد doctor `commitments.json` القديم ويزيله بعد استيراد ناجح.
- لم تعد لتعريفات مهام Cron وحالة الجدولة وسجل التشغيل كاتبات أو قارئات JSON في وقت التشغيل. يستخدم وقت التشغيل صفوف `cron_jobs` ذات الجدولة،
  أعمدة الحمولة، والتسليم، وتنبيه الفشل، والجلسة، والحالة، وحالة وقت التشغيل، إضافة إلى بيانات
  `cron_run_logs` الوصفية المهيكلة للحالة، وملخص التشخيصات، وحالة/خطأ التسليم،
  والجلسة/التشغيل، والنموذج، وإجماليات الرموز. `job_json` هو مجرد نسخة لإعادة التشغيل/تصحيح الأخطاء؛ ويحتفظ `state_json` بالتشخيصات
  المتداخلة لوقت التشغيل التي لا تملك بعد حقول استعلام ساخنة، بينما يعيد وقت التشغيل
  ترطيب حقول الحالة الساخنة من الأعمدة المهيكلة. يستورد Doctor
  ملفات `jobs.json` و`jobs-state.json` و`runs/*.jsonl` القديمة ويزيل
  المصادر المستوردة. تحدّث عمليات إعادة الكتابة إلى هدف Plugin صفوف `cron_jobs`
  المطابقة بدل تحميل مخزن Cron بالكامل واستبداله.
- يتجاهل بدء تشغيل Gateway علامات `notify: true` القديمة في إسقاط وقت التشغيل.
  يترجمها Doctor إلى تسليم SQLite صريح عندما يكون
  `cron.webhook` صالحًا، ويزيل العلامات الخاملة عندما لا يكون مضبوطًا، ويحافظ
  عليها مع تحذير عندما يكون Webhook المضبوط غير صالح.
- تخزن طوابير التسليم الصادر وتسليم الجلسات الآن حالة الطابور، ونوع الإدخال،
  ومفتاح الجلسة، والقناة، والهدف، ومعرّف الحساب، وعدد إعادة المحاولات، وآخر محاولة/خطأ،
  وحالة الاسترداد، وعلامات إرسال المنصة كأعمدة مهيكلة في جدول
  `delivery_queue_entries` المشترك. يقرأ استرداد وقت التشغيل هذه الحقول الساخنة من
  الأعمدة المهيكلة، وتحدّث طفرات إعادة المحاولة/الاسترداد تلك الأعمدة مباشرة
  من دون إعادة كتابة JSON إعادة التشغيل. تبقى حمولة JSON الكاملة فقط ككتلة
  إعادة تشغيل/تصحيح أخطاء لنصوص الرسائل وبيانات إعادة التشغيل الباردة الأخرى.
- تستخدم سجلات الصور الصادرة المُدارة الآن صفوفًا مشتركة مهيكلة
  `managed_outgoing_image_records` مع استمرار تخزين بايتات الوسائط في
  `media_blobs`. يبقى سجل JSON فقط كنسخة لإعادة التشغيل/تصحيح الأخطاء.
- تستخدم تفضيلات منتقي النماذج في Discord، وتجزئات نشر الأوامر، وروابط السلاسل
  الآن حالة Plugin مشتركة في SQLite. تعيش خطط استيراد JSON القديمة الخاصة بها في
  سطح إعداد/ترحيل Doctor الخاص بـ Discord plugin، وليس في كود ترحيل core.
- تستخدم كواشف استيراد Plugin القديمة وحدات مسماة باسم Doctor مثل
  `doctor-legacy-state.ts` أو `doctor-state-imports.ts`؛ ويجب ألا تستورد وحدات وقت التشغيل
  العادية للقنوات كواشف JSON القديمة.
- تستخدم مؤشرات استدراك BlueBubbles وعلامات إزالة التكرار الواردة الآن حالة Plugin
  مشتركة في SQLite. تعيش خطط استيراد JSON القديمة الخاصة بها في سطح إعداد/ترحيل Doctor الخاص بـ BlueBubbles plugin، وليس في كود ترحيل core.
- تستخدم إزاحات تحديث Telegram، وصفوف ذاكرة التخزين المؤقت للملصقات، وصفوف ذاكرة التخزين المؤقت للرسائل المرسلة،
  وصفوف ذاكرة التخزين المؤقت لأسماء المواضيع، وروابط السلاسل الآن حالة Plugin مشتركة في SQLite.
  تعيش خطط استيراد JSON القديمة الخاصة بها في سطح إعداد/ترحيل Doctor الخاص بـ Telegram plugin،
  وليس في كود ترحيل core.
- تستخدم مؤشرات استدراك iMessage، وتعيينات معرّفات الرد القصيرة، وصفوف إزالة تكرار صدى الإرسال
  الآن حالة Plugin مشتركة في SQLite. ملفات `imessage/catchup/*.json`
  و`imessage/reply-cache.jsonl` و`imessage/sent-echoes.jsonl` القديمة هي
  مدخلات Doctor فقط.
- تستخدم صفوف إزالة تكرار رسائل Feishu الآن حالة Plugin مشتركة في SQLite بدلًا من
  ملفات `feishu/dedup/*.json`. تعيش خطة استيراد JSON القديمة الخاصة بها في سطح إعداد/ترحيل Doctor الخاص بـ Feishu
  plugin، وليس في كود ترحيل core.
- تستخدم محادثات Microsoft Teams، والاستطلاعات، ومخازن الرفع المؤقتة المعلقة، وتعلّمات الملاحظات
  الآن جداول حالة/كتل Plugin مشتركة في SQLite. يستخدم مسار الرفع المعلق
  `plugin_blob_entries` بحيث تُخزن مخازن الوسائط المؤقتة ككائنات SQLite BLOB
  بدلًا من JSON بترميز base64. تستخدم أسماء مساعد وقت التشغيل الآن تسمية SQLite/الحالة
  بدل تسمية مخزن الملفات `*-fs`، وأزيل وسيط `storePath` القديم
  من هذه المخازن. تعيش خطة استيراد JSON القديمة الخاصة به في سطح إعداد/ترحيل Doctor الخاص بـ Microsoft Teams
  plugin.
- تستخدم الوسائط الصادرة المستضافة في Zalo الآن `plugin_blob_entries` المشتركة في SQLite
  بدلًا من ملفات JSON/bin الجانبية المؤقتة `openclaw-zalo-outbound-media`.
- يستخدم HTML عارض الفروقات والبيانات الوصفية الآن `plugin_blob_entries` المشتركة في SQLite
  بدلًا من ملفات `meta.json`/`viewer.html` المؤقتة. تبقى مخرجات PNG/PDF المعروضة
  تمثيلات مؤقتة لأن تسليم القنوات لا يزال يحتاج إلى مسار ملف.
- تستخدم مستندات Canvas المُدارة الآن `plugin_blob_entries` المشتركة في SQLite بدلًا
  من دليل `state/canvas/documents` الافتراضي. يقدّم مضيف Canvas تلك
  الكتل مباشرة؛ ولا تُنشأ الملفات المحلية إلا لمحتوى المشغّل الصريح `host.root`
  أو للتمثيل المؤقت عندما يتطلب قارئ وسائط لاحق مسارًا.
- تستخدم قرارات تدقيق File Transfer الآن `plugin_state_entries` المشتركة في SQLite
  بدلًا من سجل وقت التشغيل غير المحدود `audit/file-transfer.jsonl`. يستورد Doctor
  ملف تدقيق JSONL القديم إلى حالة Plugin ويزيل المصدر
  بعد استيراد نظيف.
- تستخدم عقود عمليات ACPX وهوية مثيل Gateway الآن حالة Plugin مشتركة في SQLite.
  يستورد Doctor ملف `gateway-instance-id` القديم إلى حالة Plugin
  ويزيل المصدر.
- تُعد نصوص التغليف المولدة لـ ACPX وبيت Codex المعزول تمثيلًا مؤقتًا
  تحت جذر OpenClaw المؤقت، وليست حالة OpenClaw دائمة. سجلات وقت تشغيل ACPX
  الدائمة هي صفوف عقد SQLite ومثيل Gateway؛ وقد أزيل سطح إعداد
  `stateDir` القديم الخاص بـ ACPX لأنه لم تعد تُكتب أي حالة وقت تشغيل
  هناك.
- تستخدم مرفقات وسائط Gateway الآن جدول `media_blobs` المشترك في SQLite
  كمخزن البايتات القانوني. المسارات المحلية المعادة إلى أسطح توافق القناة وبيئة sandbox
  هي تمثيلات مؤقتة لصف قاعدة البيانات، وليست مخزن الوسائط
  الدائم. لم تعد قوائم السماح لوسائط وقت التشغيل تتضمن جذور
  `$OPENCLAW_STATE_DIR/media` القديمة أو جذور `media` في دليل الإعداد؛ فهذه الأدلة
  هي مصادر استيراد Doctor فقط.
- لم يعد إكمال Shell يكتب ملفات ذاكرة تخزين مؤقت
  `$OPENCLAW_STATE_DIR/completions/*`. تستخدم مسارات install وDoctor وupdate وتجارب smoke للإصدار
  مخرجات إكمال مولدة أو تحميلًا من الملف الشخصي بدلًا من ملفات ذاكرة تخزين مؤقت دائمة
  للإكمال.
- يستخدم تمهيد رفع Skills في Gateway الآن صفوف `skill_uploads` مشتركة. تعيش
  بيانات الرفع الوصفية، ومفاتيح عدم التكرار، وبايتات الأرشيف في SQLite؛ ولا يتلقى المثبت
  إلا مسار أرشيف ممثل مؤقتًا أثناء تشغيل التثبيت.
- لم تعد مرفقات subagent المضمنة تتمثل تحت
  `.openclaw/attachments/*` في مساحة العمل. يجهّز مسار spawn إدخالات بذور SQLite VFS،
  وتزرع عمليات التشغيل المضمنة تلك الإدخالات في مساحة scratch الخاصة بوقت تشغيل كل وكيل،
  وتضع الأدوات المدعومة بالقرص طبقة فوق SQLite scratch تلك لمسارات المرفقات. وقد أزيلت
  أعمدة سجل دليل مرفقات تشغيل subagent القديمة وخطافات التنظيف.
- لم تعد ترطيب صور CLI يحافظ على ملفات ذاكرة تخزين مؤقت ثابتة
  `openclaw-cli-images`. ما زالت خلفيات CLI الخارجية تتلقى مسارات ملفات، لكن تلك المسارات هي
  تمثيلات مؤقتة لكل تشغيل مع تنظيف.
- تكتب تشخيصات تتبع الذاكرة المؤقتة، وتشخيصات حمولة Anthropic، وتشخيصات تدفق النموذج الخام،
  وأحداث المخطط الزمني للتشخيصات، وحزم استقرار Gateway الآن
  صفوف SQLite بدلًا من ملفات `logs/*.jsonl` أو
  `logs/stability/*.json`.
  أزيلت أعلام تجاوز مسار وقت التشغيل ومتغيرات البيئة؛ ويمكن لأوامر التصدير/تصحيح الأخطاء
  تمثيل الملفات صراحة من صفوف قاعدة البيانات.
- لم يعد مرافق macOS يملك كاتب `diagnostics.jsonl` متداولًا. تنتقل سجلات التطبيق
  إلى التسجيل الموحد، وتبقى تشخيصات Gateway الدائمة مدعومة بـ SQLite.
- تستخدم قائمة سجلات حارس منفذ macOS الآن صفوف SQLite مشتركة مهيكلة
  `macos_port_guardian_records` بدلًا من ملف JSON في Application Support
  أو كتلة مفردة مبهمة.
- تستخدم أقفال Gateway المفردة الآن صفوف `state_leases` مشتركة مهيكلة تحت
  نطاق `gateway_locks` بدلًا من ملفات قفل دليل مؤقت. تشير مستندات استكشاف أخطاء Fly وOAuth
  الآن إلى قفل عقد SQLite/تحديث المصادقة بدلًا
  من تنظيف أقفال ملفات قديمة.
- تستخدم حالة مؤشر إعادة تشغيل Gateway الآن صفوف SQLite مشتركة مهيكلة
  `gateway_restart_sentinel` بدلًا من `restart-sentinel.json`؛ يقرأ وقت التشغيل
  نوع المؤشر، والحالة، والتوجيه، والرسالة، والاستمرار، والإحصاءات من
  الأعمدة المهيكلة. `payload_json` هو مجرد نسخة لإعادة التشغيل/تصحيح الأخطاء. يمسح كود وقت التشغيل
  صف SQLite مباشرة ولم يعد يحمل سباكة تنظيف الملفات.
- تستخدم نية إعادة تشغيل Gateway وحالة تسليم المشرف الآن صفوف SQLite مشتركة مهيكلة
  `gateway_restart_intent` و`gateway_restart_handoff` بدلًا من
  الملفات الجانبية `gateway-restart-intent.json` و
  `gateway-supervisor-restart-handoff.json`.
- يستخدم تنسيق Gateway المفرد الآن صفوف `state_leases` مهيكلة تحت
  `gateway_locks` بدل كتابة ملفات `gateway.<hash>.lock`. يمتلك صف العقد
  مالك القفل، والانتهاء، وHeartbeat، وحمولة تصحيح الأخطاء؛ وتمتلك SQLite
  حد الاكتساب/الإفراج الذري. أزيل خيار دليل أقفال الملفات المتقاعد؛
  وتستخدم الاختبارات هوية صف SQLite مباشرة.
- حُذف مساعد تقرير استخدام Cron القديم غير المشار إليه الذي كان يفحص ملفات `cron/runs/*.jsonl`.
  يجب أن تقرأ تقارير سجل تشغيل Cron صفوف SQLite المهيكلة
  `cron_run_logs`.
- يكتشف استرداد إعادة تشغيل الجلسة الرئيسية الآن الوكلاء المرشحين عبر
  سجل SQLite `agent_databases` بدل فحص أدلة
  `agents/*/sessions`.
- يحذف استرداد تلف جلسة Gemini الآن صف الجلسة في SQLite فقط؛
  ولم يعد يحتاج إلى بوابة `storePath` قديمة أو يحاول إلغاء ربط
  مسار JSONL مشتق للنص المنسوخ.
- يتعامل مسار تجاوز المسار الآن مع قيم البيئة الحرفية `undefined`/`null`
  كغير مضبوطة، مما يمنع قواعد بيانات `undefined/state/*.sqlite`
  العرضية في جذر المستودع أثناء الاختبارات أو تسليمات Shell.
- تستخدم بصمات صحة الإعداد الآن صفوف SQLite مشتركة مهيكلة `config_health_entries`
  بدلًا من `logs/config-health.json`، مما يبقي ملف الإعداد العادي
  وثيقة الإعداد الوحيدة غير الخاصة ببيانات الاعتماد. يحتفظ مرافق macOS بحالة صحة
  محلية للعملية فقط ولا يعيد إنشاء ملف JSON الجانبي القديم.
- لم يعد وقت تشغيل ملف تعريف المصادقة يستورد أو يكتب ملفات JSON لبيانات الاعتماد. مخزن بيانات الاعتماد
  القانوني هو SQLite؛ وتُعد `auth-profiles.json` و`auth.json` لكل وكيل
  و`credentials/oauth.json` المشتركة مدخلات ترحيل Doctor
  تُزال بعد الاستيراد.
- تؤكد اختبارات حفظ/حالة ملف تعريف المصادقة الآن جداول مصادقة SQLite المهيكلة مباشرة
  ولا تستخدم أسماء ملفات ملف تعريف المصادقة القديمة إلا كمدخلات لترحيل Doctor.
- ينظف `openclaw secrets apply` ملف الإعداد، وملف البيئة، ومخزن ملفات تعريف المصادقة
  في SQLite فقط. ولم يعد يحمل منطق توافق يحرر
  `auth.json` المتقاعد لكل وكيل؛ يمتلك Doctor استيراد ذلك الملف وحذفه.
- تخطط عمليات ترحيل أسرار Hermes وتطبق ملفات تعريف مفاتيح API المستوردة مباشرة
  في مخزن ملفات تعريف المصادقة في SQLite. ولم تعد تكتب أو تتحقق من
  `auth-profiles.json` كهدف وسيط.
- تصف مستندات المصادقة الموجهة للمستخدمين الآن
  `state/openclaw.sqlite#table/auth_profile_stores/<agentDir>` بدلًا من
  مطالبة المستخدمين بفحص أو نسخ `auth-profiles.json`؛ وتبقى أسماء JSON القديمة الخاصة بـ OAuth/auth
  موثقة فقط كمدخلات استيراد Doctor.
- لم تعد مساعدات مسار حالة core تعرض ملف `credentials/oauth.json`
  المتقاعد. اسم الملف القديم محلي لمسار استيراد مصادقة Doctor.
- تصف مستندات التثبيت، والأمان، والإعداد الأولي، ومصادقة النماذج، وSecretRef الآن
  صفوف ملفات تعريف المصادقة في SQLite والنسخ الاحتياطي/الترحيل للحالة كاملة بدلًا من
  ملفات JSON لملفات تعريف المصادقة لكل وكيل.
- يمرر اكتشاف نموذج PI الآن بيانات الاعتماد القانونية إلى تخزين مصادقة
  `pi-coding-agent` داخل الذاكرة. ولم يعد ينشئ أو ينظف أو يكتب
  `auth.json` لكل وكيل أثناء الاكتشاف.
- تستخدم إعدادات مشغل Voice Wake وتوجيهه الآن جداول SQLite مشتركة مهيكلة
  بدلًا من `settings/voicewake.json` أو `settings/voicewake-routing.json` أو
  صفوف عامة مبهمة؛ يستورد Doctor ملفات JSON القديمة ويزيلها بعد
  ترحيل ناجح.
- تستخدم حالة فحص التحديث الآن صفًا مشتركًا مهيكلًا `update_check_state` بدلًا من
  `update-check.json` أو كتلة عامة مبهمة؛ يستورد Doctor
  ملف JSON القديم ويزيله بعد ترحيل ناجح.
- تستخدم حالة صحة الإعداد الآن صفوفًا مشتركة مهيكلة `config_health_entries` بدلًا
  من `logs/config-health.json` أو كتلة عامة مبهمة؛ يستورد Doctor
  ملف JSON القديم ويزيله بعد ترحيل ناجح.
- تستخدم موافقات ربط محادثات Plugin الآن صفوفًا مهيكلة
  `plugin_binding_approvals` بدلًا من حالة SQLite مشتركة مبهمة أو
  `plugin-binding-approvals.json`؛ الملف القديم هو مُدخل ترحيل لـ doctor.
- تخزّن ارتباطات المحادثة الحالية العامة الآن صفوف
  `current_conversation_bindings` ذات أنواع محددة بدلاً من إعادة كتابة
  `bindings/current-conversations.json`؛ يستورد doctor ملف JSON القديم ويزيله
  بعد ترحيل ناجح.
- تخزّن سجلات مزامنة مصادر Memory Wiki المستوردة الآن صف SQLite لحالة Plugin
  واحدًا لكل مفتاح خزنة/مصدر بدلاً من إعادة كتابة `.openclaw-wiki/source-sync.json`؛
  يستورد مزوّد الترحيل سجل JSON القديم ويزيله.
- تخزّن سجلات تشغيل استيراد ChatGPT في Memory Wiki الآن صف SQLite لحالة Plugin
  واحدًا لكل معرّف خزنة/تشغيل بدلاً من كتابة `.openclaw-wiki/import-runs/*.json`.
  تبقى لقطات الاسترجاع ملفات خزنة صريحة إلى أن تُنقل أرشفة لقطات تشغيل الاستيراد
  إلى تخزين الكتل الثنائية.
- تخزّن الملخصات المجمّعة في Memory Wiki الآن صفوف كتل ثنائية لـ SQLite Plugin بدلاً من
  كتابة `.openclaw-wiki/cache/agent-digest.json` و
  `.openclaw-wiki/cache/claims.jsonl`. يستورد مزوّد الترحيل ملفات التخزين المؤقت
  القديمة ويزيل دليل التخزين المؤقت عندما يصبح فارغًا.
- يخزّن تتبع تثبيت مهارات ClawHub الآن صف SQLite لحالة Plugin واحدًا لكل
  مساحة عمل/مهارة بدلاً من كتابة أو قراءة الملفات الجانبية `.clawhub/lock.json` و
  `.clawhub/origin.json` وقت التشغيل. يستخدم كود وقت التشغيل كائنات حالة التثبيت
  المتتبعة بدلاً من تجريدات ملف القفل/الأصل ذات شكل الملف. يستورد doctor
  الملفات الجانبية القديمة من مساحات عمل الوكلاء المكوّنة ويزيلها
  بعد استيراد نظيف.
- يقرأ فهرس Plugin المثبّت الآن صف SQLite المشترك ذي النوع المحدد
  `installed_plugin_index` الوحيد ويكتبه بدلاً من `plugins/installs.json`؛ ملف
  JSON القديم ليس إلا مُدخل ترحيل لـ doctor ويُزال بعد الاستيراد.
- يعيش مساعد مسار `plugins/installs.json` القديم الآن في كود doctor القديم.
  تعرض وحدات فهرس Plugin وقت التشغيل خيارات استمرارية مدعومة بـ SQLite فقط،
  وليس مسار ملف JSON.
- تستخدم علامة إعادة تشغيل Gateway، ونيّة إعادة التشغيل، وحالة تسليم المشرف الآن
  صفوف SQLite مشتركة ذات أنواع محددة (`gateway_restart_sentinel` و
  `gateway_restart_intent` و `gateway_restart_handoff`) بدلاً من كتل عامة
  مبهمة. لا يحتوي كود إعادة التشغيل وقت التشغيل على عقد علامة/نية/تسليم
  ذي شكل ملف.
- تستخدم ذاكرة التخزين المؤقت لمزامنة Matrix، وبيانات التخزين الوصفية، وارتباطات السلاسل،
  وعلامات إزالة تكرار الوارد، وحالة تهدئة تحقق بدء التشغيل، ولقطات تشفير
  IndexedDB الخاصة بـ SDK، وبيانات الاعتماد، ومفاتيح الاسترداد الآن جداول
  حالة/كتل Plugin في SQLite المشتركة. لم تعد بُنى مسارات وقت التشغيل تعرض مسار
  بيانات وصفية `storage-meta.json`؛ اسم الملف هذا مُدخل ترحيل قديم فقط.
  تعيش خطة استيراد JSON القديمة الخاصة بها في سطح إعداد/ترحيل doctor الخاص بـ Matrix Plugin.
- لم يعد بدء تشغيل Matrix يفحص حالة ملفات Matrix القديمة أو يبلّغ عنها أو يكملها.
  كشف ملفات Matrix، وإنشاء لقطة التشفير القديمة، وحالة ترحيل استعادة مفاتيح الغرف،
  والاستيراد، وإزالة المصدر، كلها مملوكة لـ doctor.
- أُزيلت براميل ترحيل Matrix وقت التشغيل. تُستورد مساعدات كشف حالة/تشفير الحالة القديمة
  وتعديلها بواسطة Matrix doctor مباشرة بدلاً من أن تكون جزءًا من سطح API وقت التشغيل.
- تعيش علامات إعادة استخدام لقطة ترحيل Matrix الآن في حالة SQLite Plugin
  بدلاً من `matrix/migration-snapshot.json`؛ لا يزال بإمكان doctor إعادة استخدام
  الأرشيف نفسه المتحقق منه قبل الترحيل من دون كتابة ملف حالة جانبي.
- تستخدم مؤشرات ناقل Nostr وحالة نشر الملف الشخصي الآن حالة SQLite Plugin المشتركة.
  تعيش خطة استيراد JSON القديمة الخاصة بها في سطح إعداد/ترحيل doctor الخاص بـ Nostr Plugin.
- تستخدم مفاتيح تبديل جلسة Active Memory الآن حالة SQLite Plugin المشتركة بدلاً من
  `session-toggles.json`؛ يؤدي تشغيل الذاكرة مجددًا إلى حذف الصف بدلاً من
  إعادة كتابة كائن JSON.
- تستخدم مقترحات Skill Workshop وعدادات المراجعة الآن حالة SQLite Plugin المشتركة
  بدلاً من مخازن `skill-workshop/<workspace>.json` لكل مساحة عمل. كل
  مقترح هو صف منفصل تحت `skill-workshop/proposals`، وعدّاد المراجعة
  صف منفصل تحت `skill-workshop/reviews`.
- تستخدم تشغيلات الوكيل الفرعي لمراجع Skill Workshop الآن محلّل نص جلسة وقت التشغيل
  بدلاً من إنشاء مسارات جلسة جانبية `skill-workshop/<sessionId>.json`.
- تستخدم عقود عمليات ACPX الآن حالة SQLite Plugin المشتركة تحت
  `acpx/process-leases` بدلاً من سجل كامل الملف `process-leases.json`.
  يُخزّن كل عقد في صف خاص به، مع الحفاظ على إزالة العمليات القديمة عند بدء التشغيل
  من دون مسار إعادة كتابة JSON وقت التشغيل.
- تُنشأ سكربتات تغليف ACPX وبيت Codex المعزول في جذر OpenClaw المؤقت.
  يُعاد إنشاؤها حسب الحاجة وليست مُدخلات نسخ احتياطي أو ترحيل.
- تستخدم استمرارية سجل تشغيل الوكلاء الفرعيين صفوف `subagent_runs` مشتركة ذات أنواع محددة.
  أصبح مسار `subagents/runs.json` القديم الآن مُدخل ترحيل لـ doctor فقط، ولم تعد
  أسماء مساعدات وقت التشغيل تصف طبقة الحالة بأنها مدعومة بالقرص.
  لم تعد اختبارات وقت التشغيل تنشئ تجهيزات `runs.json` غير صالحة أو فارغة لإثبات
  سلوك السجل؛ بل تزرع/تقرأ صفوف SQLite مباشرة.
- يمرحّل النسخ الاحتياطي دليل الحالة قبل الأرشفة، وينسخ الملفات غير قواعد البيانات،
  ويلتقط قواعد بيانات `*.sqlite` باستخدام `VACUUM INTO`، ويحذف ملفات WAL/SHM
  الجانبية الحية، ويسجل بيانات اللقطة الوصفية في بيان الأرشيف، ويسجل
  تشغيلات النسخ الاحتياطي المكتملة في SQLite مع بيان الأرشيف. يتحقق `openclaw backup
create` من الأرشيف المكتوب افتراضيًا؛ `--no-verify` هو المسار السريع
  الصريح.
- يتحقق `openclaw backup restore` من الأرشيف قبل الاستخراج، ويعيد استخدام
  البيان المطبع الخاص بالمتحقق، ويستعيد أصول البيان المتحقق منها إلى
  مسارات المصدر المسجلة. يتطلب `--yes` للكتابة ويدعم `--dry-run`
  لخطة الاستعادة.
- حُذف مرشح مسارات النسخ الاحتياطي المتطايرة القديم. لم يعد النسخ الاحتياطي يحتاج
  إلى قائمة تخطي tar حية لملفات JSON/JSONL القديمة الخاصة بالجلسات أو cron لأن لقطات SQLite
  تُرحّل قبل إنشاء الأرشيف.
- لم تعد عملية إعداد مساحة العمل العادية والتهيئة تنشئ
  أدلة `agents/<agentId>/sessions/`. إنها تنشئ التكوين/مساحة العمل فقط؛
  تُنشأ صفوف جلسات SQLite وصفوف النصوص عند الطلب في
  قاعدة بيانات كل وكيل.
- يستهدف إصلاح أذونات الأمان الآن قواعد بيانات SQLite العامة وقواعد بيانات كل وكيل
  بالإضافة إلى ملفات WAL/SHM الجانبية بدلاً من `sessions.json` وملفات نصوص
  JSONL.
- تصف أسماء وقت تشغيل سجل sandbox الآن أنواع سجل SQLite مباشرة
  بدلاً من حمل مصطلحات سجل JSON القديمة عبر المخزن النشط.
- يزيل `openclaw reset --scope config+creds+sessions` قواعد بيانات
  `openclaw-agent.sqlite` لكل وكيل بالإضافة إلى ملفات WAL/SHM الجانبية، وليس فقط
  أدلة `sessions/` القديمة.
- تستخدم مساعدات جلسات Gateway المجمّعة الآن أسماء موجّهة للإدخالات:
  يعيد `loadCombinedSessionEntriesForGateway` القيمة `{ databasePath, entries }`.
  أُزيلت تسمية المخزن المجمّع القديمة من مستدعيات وقت التشغيل.
- تكتب عملية تهيئة قناة Docker MCP الآن صف الجلسة الرئيسي وأحداث النص
  في قاعدة بيانات SQLite لكل وكيل بدلاً من إنشاء
  `sessions.json` ونص JSONL.
- يحل خطاف ذاكرة الجلسة المضمّن الآن سياق الجلسة السابقة من
  SQLite بواسطة `{agentId, sessionId}`. لم يعد يفحص أو يخزن أو يصطنع
  مسارات النصوص أو أدلة `workspace/sessions`.
- يكتب خطاف مسجل الأوامر المضمّن الآن صفوف تدقيق الأوامر إلى جدول SQLite المشترك
  `command_log_entries` بدلاً من الإلحاق بـ
  `logs/commands.log`.
- تعرض قوائم السماح لإقران القنوات الآن مساعدات قراءة/كتابة مدعومة بـ SQLite فقط
  وقت التشغيل وفي Plugin SDK. يعيش محلّل مسار `*-allowFrom.json` القديم
  وقارئ الملفات فقط تحت كود استيراد doctor القديم.
- تسجّل `migration_runs` تنفيذات ترحيل الحالة القديمة مع الحالة،
  والطوابع الزمنية، وتقارير JSON.
- تسجّل `migration_sources` كل مصدر ملف قديم مستورد مع التجزئة، والحجم،
  وعدد السجلات، والجدول الهدف، ومعرّف التشغيل، والحالة، وحالة إزالة المصدر.
- تسجّل `backup_runs` مسارات أرشيف النسخ الاحتياطي، والحالة، وبيانات JSON.
- لا يحتفظ المخطط العام بجدول سجل `agents` غير مستخدم. اكتشاف
  قواعد بيانات الوكلاء هو سجل `agent_databases` القانوني إلى أن يصبح لدى وقت التشغيل
  مالك حقيقي لسجلات الوكلاء.
- يُخزّن تكوين كتالوج النماذج المولّد في صفوف SQLite عامة ذات أنواع محددة
  `agent_model_catalogs` مفهرسة بدليل الوكيل. يستخدم مستدعو وقت التشغيل
  `ensureOpenClawModelCatalog`؛ لا توجد API توافق `models.json` في
  كود وقت التشغيل. يكتب التنفيذ إلى SQLite ويُرطّب سجل PI المضمّن
  من تلك الحمولة المخزنة من دون إنشاء ملف `models.json`.
- أُزيل تصدير Markdown لنصوص جلسات QMD وتكوين `memory.qmd.sessions`.
  لا توجد مجموعة نصوص QMD، ولا مسار وقت تشغيل `qmd/sessions*`، ولا جسر
  ذاكرة جلسات مدعوم بالملفات.
- تستورد واجهة وقت تشغيل memory-core مساعدات فهرسة نصوص SQLite من
  `openclaw/plugin-sdk/memory-core-host-engine-session-transcripts`، وليس من
  مسار SDK الفرعي لـ QMD. يحتفظ المسار الفرعي لـ QMD بإعادة تصدير توافقية فقط
  للمستدعين الخارجيين إلى أن يمكن لإزالة تنظيف SDK كبرى حذفها.
- أصبحت `index.sqlite` الخاصة بـ QMD الآن تجسيدًا مؤقتًا وقت التشغيل مدعومًا
  بجدول SQLite الرئيسي `plugin_blob_entries`. لم يعد وقت التشغيل ينشئ
  ملفًا جانبيًا دائمًا `~/.openclaw/agents/<agentId>/qmd`.
- لم يعد Plugin الاختياري `memory-lancedb` ينشئ
  `~/.openclaw/memory/lancedb` كمخزن ضمني مُدار من OpenClaw. إنه
  خلفية LanceDB خارجية ويبقى معطلاً إلى أن يكوّن المشغّل
  `dbPath` صريحًا.
- يفشل `check:database-first-legacy-stores` عند وجود مصدر وقت تشغيل جديد يقرن
  أسماء المخازن القديمة مع واجهات API لنظام الملفات بأسلوب الكتابة. ويفشل أيضًا عند
  وجود مصدر وقت تشغيل يعيد إدخال علامات جسر النصوص المتقاعد
  `transcriptLocator` أو `sqlite-transcript://...`. يبقى كود الترحيل وdoctor والاستيراد
  والتصدير الصريح غير الخاص بالجلسات مسموحًا. لا تزال أسماء عقود قديمة أوسع
  مثل `sessionFile` و`storePath` وواجهات عصر الملفات القديمة `SessionManager`
  لها مالكون حاليون وتحتاج إلى عمل حراسة ترحيل منفصل
  قبل أن تصبح فحصًا تمهيديًا مطلوبًا. تغطي الحراسة الآن أيضًا
  مخازن `cache/*.json` وقت التشغيل، والملفات الجانبية العامة
  `thread-bindings.json`، وJSON حالة/سجل تشغيل cron، وJSON صحة التكوين،
  وملفات إعادة التشغيل والقفل الجانبية، وإعدادات Voice Wake، وموافقات ربط Plugin،
  وJSON فهرس Plugin المثبّت، وJSONL تدقيق File Transfer، وسجلات نشاط Memory Wiki،
  وسجل النص القديم `command-logger` المضمّن، ومفاتيح تشخيص JSONL للتدفق الخام
  في pi-mono. كما يحظر أسماء وحدات doctor القديمة على مستوى الجذر بحيث
  يبقى كود التوافق تحت `src/commands/doctor/`. تستخدم معالجات تصحيح Android
  أيضًا مخرجات logcat/داخل الذاكرة بدلاً من تجهيز ملفات تخزين مؤقت
  `camera_debug.log` أو `debug_logs.txt`.

## شكل المخطط الهدف

أبقِ المخططات صريحة. تستخدم حالة وقت التشغيل المملوكة للمضيف جداول ذات أنواع محددة. وتستخدم الحالة
المعتمة المملوكة لـ 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` تنفيذ ترحيل الحالة بعد الفحص التمهيدي العادي
للإعدادات وينشئ نسخة احتياطية متحققًا منها قبل الاستيراد. يجب ألا يستورد بدء تشغيل
وقت التشغيل ولا `openclaw migrate` ملفات حالة OpenClaw القديمة.

خصائص الترحيل:

- تكتشف جولة ترحيل واحدة جميع مصادر الملفات القديمة وتنتج خطة قبل تعديل أي شيء.
- ينشئ Doctor أرشيف نسخة احتياطية متحققًا منه قبل الترحيل، وذلك قبل استيراد
  الملفات القديمة.
- تكون عمليات الاستيراد idempotent ومفهرسة حسب مسار المصدر، وmtime، والحجم، والتجزئة، والجدول
  الهدف.
- تُزال ملفات المصدر الناجحة أو تُؤرشف بعد أن تلتزم قاعدة البيانات الهدف
  بالتغييرات.
- تترك عمليات الاستيراد الفاشلة المصدر دون تغيير وتسجل تحذيرًا في
  `migration_runs`.
- يقرأ كود وقت التشغيل من SQLite فقط بعد وجود الترحيل.
- لا يلزم مسار رجوع إلى إصدار أقدم أو تصدير إلى ملفات وقت التشغيل.

## مخزون الترحيل

انقل هذه إلى قاعدة البيانات العامة:

- تستخدم كتابات وقت تشغيل سجل المهام الآن قاعدة البيانات المشتركة؛ وحُذف مستورد الملف الجانبي غير المشحون
  `tasks/runs.sqlite`. تجري عمليات حفظ اللقطات upsert حسب معرّف المهمة
  وتحذف فقط صفوف المهمة/التسليم المفقودة.
- تستخدم كتابات وقت تشغيل تدفق المهام الآن قاعدة البيانات المشتركة؛ وحُذف مستورد الملف الجانبي غير المشحون
  `tasks/flows/registry.sqlite`. تجري عمليات حفظ اللقطات
  upsert حسب معرّف التدفق وتحذف فقط صفوف التدفق المفقودة.
- تستخدم كتابات وقت تشغيل حالة Plugin الآن قاعدة البيانات المشتركة؛ وحُذف مستورد الملف الجانبي غير المشحون
  `plugin-state/state.sqlite`.
- لم يعد بحث الذاكرة المضمن افتراضيًا إلى `memory/<agentId>.sqlite`؛ إذ
  تعيش جداول الفهرس الخاصة به في قاعدة بيانات الوكيل المالكة، وأُلغي الاشتراك الصريح
  في الملف الجانبي `memorySearch.store.path` لصالح ترحيل إعدادات doctor.
- تعيد إعادة فهرسة الذاكرة المضمنة ضبط الجداول المملوكة للذاكرة فقط في قاعدة بيانات الوكيل.
  يجب ألا تستبدل ملف SQLite كله، لأن قاعدة البيانات نفسها تملك
  الجلسات والنصوص المنسوخة وصفوف VFS والآثار وذاكرات التخزين المؤقت لوقت التشغيل.
- سجلات حاويات/متصفحات Sandbox من JSON أحادي ومجزأ. تستخدم كتابات
  وقت التشغيل الآن قاعدة البيانات المشتركة؛ ويبقى استيراد JSON القديم.
- تستخدم تعريفات وظائف Cron وحالة الجدولة وسجل التشغيل الآن SQLite المشترك؛
  يستورد doctor ملفات `jobs.json` و`jobs-state.json` و
  `cron/runs/*.jsonl` القديمة ويزيلها
- هوية/مصادقة الجهاز، والدفع، والتحقق من التحديث، والالتزامات، وذاكرة التخزين المؤقت لنماذج OpenRouter،
  وفهرس Plugin المثبتة، وارتباطات خادم التطبيق
- تستخدم سجلات إقران الجهاز/Node والتمهيد الآن جداول SQLite مطبوعة
- يستخدم مشتركو إشعارات إقران الجهاز وعلامات الطلبات المسلّمة الآن جدول
  حالة Plugin المشترك في SQLite بدلًا من `device-pair-notify.json`.
- تستخدم سجلات مكالمات الصوت الآن جدول حالة Plugin المشترك في SQLite ضمن
  مساحة الاسم `voice-call` / `calls` بدلًا من `calls.jsonl`؛ وتتابع CLI الخاصة بالـ Plugin
  سجل المكالمات المدعوم بـ SQLite وتلخصه.
- تستخدم جلسات QQBot gateway وسجلات المستخدمين المعروفين وذاكرة التخزين المؤقت لاقتباسات فهرس المراجع الآن
  حالة Plugin في SQLite ضمن مساحات أسماء `qqbot` (`sessions`, `known-users`,
  `ref-index`) بدلًا من `session-*.json` و`known-users.json` و
  `ref-index.jsonl`؛ يستورد ترحيل doctor/setup الخاص بـ QQBot الملفات القديمة ويزيلها.
- تستخدم تفضيلات منتقي النماذج في 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 وعلامات منع تكرار الوارد الآن حالة 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، وتعيينات معرّفات الرد القصيرة، وصفوف منع تكرار صدى الإرسال
  الآن حالة 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، وبيانات التخزين الوصفية، وارتباطات الخيوط، وعلامات منع تكرار الوارد،
  وحالة تبريد التحقق عند بدء التشغيل، وبيانات الاعتماد، ومفاتيح الاسترداد، ولقطات تشفير IndexedDB الخاصة بـ SDK
  الآن مساحات أسماء حالة/كائنات 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` لكل مساحة عمل.
- تشترك طوابير التسليم الصادر وتسليم الجلسات الآن في جدول SQLite العالمي
  `delivery_queue_entries` ضمن أسماء طوابير منفصلة
  (`outbound-delivery`, `session-delivery`) بدلًا من ملفات
  `delivery-queue/*.json` و`delivery-queue/failed/*.json` و
  `session-delivery-queue/*.json` المتينة. تستورد خطوة الحالة القديمة في doctor
  الصفوف المعلقة والفاشلة، وتزيل علامات التسليم الراكدة، وتحذف ملفات
  JSON القديمة بعد الاستيراد. حقول التوجيه السريع وإعادة المحاولة أعمدة مطبوعة؛ وتُحتفظ بحمولة JSON
  فقط لإعادة التشغيل/التصحيح.
- تستخدم إيجارات عمليات ACPX الآن حالة Plugin في SQLite ضمن `acpx/process-leases`
  بدلًا من `process-leases.json`.
- بيانات تعريف تشغيل النسخ الاحتياطي والترحيل

انقل هذه إلى قواعد بيانات الوكلاء:

- جذور جلسات الوكلاء وحمولات إدخالات الجلسة ذات شكل التوافق. تم ذلك لكتابات
  وقت التشغيل: بيانات تعريف الجلسة السريعة قابلة للاستعلام في `sessions`، بينما تبقى حمولة
  `SessionEntry` الكاملة ذات الشكل القديم في `session_entries`.
- أحداث نصوص الوكيل المنسوخة. تم ذلك لكتابات وقت التشغيل.
- نقاط تحقق Compaction ولقطات النص المنسوخ. تم ذلك لكتابات وقت التشغيل:
  نسخ نصوص نقاط التحقق هي صفوف نصوص منسوخة في SQLite وتُسجل بيانات تعريف نقاط التحقق
  في `transcript_snapshots`. أصبحت مساعدات نقاط تحقق Gateway
  تسمي هذه القيم لقطات نصوص منسوخة بدلًا من ملفات مصدرية.
- مساحات أسماء VFS المؤقتة/مساحات العمل للوكيل. تم ذلك لكتابات VFS وقت التشغيل.
- حمولات مرفقات الوكلاء الفرعيين. تم ذلك لكتابات وقت التشغيل: فهي مدخلات بذور VFS في SQLite
  وليست ملفات مساحة عمل متينة مطلقًا.
- آثار الأدوات. تم ذلك لكتابات وقت التشغيل.
- آثار التشغيل. تم ذلك لكتابات وقت تشغيل العامل عبر جدول
  `run_artifacts` لكل وكيل.
- ذاكرات التخزين المؤقت المحلية للوكيل في وقت التشغيل. تم ذلك لكتابات ذاكرة التخزين المؤقت ذات نطاق وقت تشغيل العامل
  عبر جدول `cache_entries` لكل وكيل. تبقى ذاكرات تخزين النماذج المؤقتة على نطاق Gateway
  في قاعدة البيانات العالمية ما لم تصبح خاصة بوكيل.
- سجلات تدفق أصل ACP. تم ذلك لكتابات وقت التشغيل.
- جلسات دفتر إعادة تشغيل ACP. تم ذلك لكتابات وقت التشغيل عبر
  `acp_replay_sessions` و`acp_replay_events`؛ يبقى `acp/event-ledger.json` القديم
  كمدخل doctor فقط.
- بيانات تعريف جلسة ACP. تم ذلك لكتابات وقت التشغيل عبر `acp_sessions`؛ كتل
  `entry.acp` القديمة في `sessions.json` هي مدخلات ترحيل doctor فقط.
- الملفات الجانبية للمسار عندما لا تكون ملفات تصدير صريحة. تم ذلك لكتابات وقت التشغيل:
  يكتب التقاط المسار صفوف `trajectory_runtime_events` في قاعدة بيانات الوكيل
  ويعكس الآثار ذات نطاق التشغيل إلى SQLite. الملفات الجانبية القديمة هي
  مدخلات استيراد doctor فقط؛ يمكن للتصدير إنتاج مخرجات حزمة دعم JSONL جديدة
  لكنه لا يقرأ أو يرحّل ملفات المسار/النص المنسوخ الجانبية القديمة في وقت التشغيل.
  يعرّض التقاط المسار في وقت التشغيل نطاق SQLite؛ ومساعدات مسار JSONL
  معزولة لدعم التصدير/التصحيح ولا يُعاد تصديرها من وحدة وقت التشغيل.
  تسجل بيانات تعريف مسار المشغّل المضمن هوية `{agentId, sessionId, sessionKey}`
  بدلًا من الاحتفاظ بمحدد موقع النص المنسوخ.

أبقِ هذه مدعومة بالملفات في الوقت الحالي:

- `openclaw.json`
- ملفات بيانات اعتماد المزوّد أو CLI
- بيانات تعريف Plugin/الحزم
- مساحات عمل المستخدم ومستودعات Git عند اختيار وضع القرص
- السجلات المقصودة لمتابعة المشغل، ما لم يُنقل سطح سجل محدد

## خطة الترحيل

### المرحلة 0: تجميد الحد

اجعل حد الحالة المتينة صريحًا قبل نقل المزيد من الصفوف:

- أضف جدول `migration_runs` إلى قاعدة البيانات العالمية.
  تم ذلك لتقارير تنفيذ ترحيل الحالة القديمة.
- أضف خدمة ترحيل حالة واحدة مملوكة لـ doctor للاستيراد من ملف إلى قاعدة بيانات.
  تم: يستخدم `openclaw doctor --fix` تنفيذ ترحيل الحالة القديمة.
- اجعل `plan` للقراءة فقط واجعل `apply` ينشئ نسخة احتياطية ويستورد ويتحقق،
  ثم يحذف الملفات القديمة أو يعزلها.
  تم: ينشئ doctor نسخة احتياطية موثقة قبل الترحيل، ويمرر مسار النسخة الاحتياطية
  إلى `migration_runs`، ويعيد استخدام مسارات المستورد/الإزالة.
- أضف حظرًا ثابتًا كي لا تتمكن شيفرة وقت التشغيل الجديدة من كتابة ملفات الحالة القديمة بينما
  لا يزال بإمكان شيفرة الترحيل والاختبارات زرعها/قراءتها.
  تم ذلك لمخازن الحالة القديمة المرحّلة حاليًا؛ كما يفحص الحارس
  الاختبارات المتداخلة بحثًا عن عقود محدد موقع النص المنسوخ المحظورة في وقت التشغيل.

### المرحلة 1: إنهاء مستوى التحكم العالمي

احتفظ بحالة التنسيق المشتركة في `state/openclaw.sqlite`:

- الوكلاء وسجل قواعد بيانات الوكلاء
- دفاتر المهام ودفاتر تدفق المهام
- حالة Plugin
- سجل حاويات/متصفحات Sandbox
- سجل تشغيل Cron/المجدول
- الإقران، والجهاز، والدفع، والتحقق من التحديث، وTUI، وذاكرات تخزين OpenRouter/النماذج المؤقتة، وحالات وقت التشغيل الصغيرة الأخرى ذات نطاق Gateway
- بيانات تعريف النسخ الاحتياطي والترحيل
- بايتات مرفقات الوسائط في Gateway. تم ذلك لكتابات وقت التشغيل؛ المسارات المباشرة للملفات
  هي تجسيدات مؤقتة للتوافق مع مرسلي القنوات وتجهيز Sandbox.
  تقبل قوائم السماح في وقت التشغيل مسارات تجسيد SQLite، لا جذور وسائط الحالة/الإعدادات القديمة.
  يستورد doctor ملفات الوسائط القديمة إلى `media_blobs` ويزيل الملفات المصدرية بعد نجاح كتابة الصفوف.
- جلسات التقاط وكيل التصحيح، والأحداث، وكائنات Blob للحمولات. تم: تعيش الالتقاطات
  في قاعدة بيانات الحالة المشتركة وتُفتح عبر تمهيد قاعدة بيانات الحالة المشتركة ومخططها
  وWAL وإعدادات مهلة الانشغال. تُضغط بايتات الحمولة باستخدام gzip في
  `capture_blobs.data`؛ لا يوجد تجاوز لقاعدة بيانات جانبية لوقت تشغيل وكيل التصحيح،
  ولا دليل Blob، ولا هدف مخطط/توليد شيفرة مخصص لالتقاط الوكيل فقط.
  يستورد ترحيل doctor/startup صفوف `debug-proxy/capture.sqlite` المشحونة
  وكائنات Blob المشار إليها، بما في ذلك تجاوزات بيئة قاعدة البيانات/Blob القديمة النشطة،
  ثم يؤرشف تلك المصادر مع ترك شهادات CA سليمة.

تحذف هذه المرحلة أيضًا فاتحات الملفات الجانبية المكررة، ومساعدات الأذونات، وإعداد WAL،
وتنظيف نظام الملفات، وكتّاب التوافق من تلك الأنظمة الفرعية.

### المرحلة 2: إدخال قواعد بيانات لكل وكيل

أنشئ قاعدة بيانات واحدة لكل وكيل وسجّلها من قاعدة البيانات العالمية:

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

يخزن صف `agent_databases` العالمي المسار، وإصدار المخطط، والطابع الزمني لآخر ظهور،
وبيانات تعريف أساسية للحجم/السلامة. تطلب شيفرة وقت التشغيل قاعدة بيانات الوكيل من السجل
بدلًا من اشتقاق مسارات الملفات مباشرة.

تملك قاعدة بيانات الوكيل:

- `sessions` بوصفه جذر الجلسة المعياري، مع `session_entries` بوصفه جدول الحمولة ذي شكل التوافق المرتبط بذلك الجذر، و
  `session_routes` بوصفه بحث `session_key` النشط الفريد
- `conversations` و`session_conversations` بوصفهما هوية توجيه المزوّد المطبّعة
  المرتبطة بالجلسات
- `transcript_events`
- لقطات النصوص ونقاط تحقق Compaction. تم ذلك لكتابات وقت التشغيل.
- `vfs_entries`
- `tool_artifacts` وآثار التشغيل
- صفوف وقت التشغيل/ذاكرة التخزين المؤقت المحلية للوكيل. تم ذلك لذاكرات التخزين المؤقت ذات النطاق الخاص بالعامل.
- أحداث دفق ACP الأصلية
- أحداث وقت تشغيل المسار عندما لا تكون آثار تصدير صريحة

### المرحلة 3: استبدال واجهات API لمخزن الجلسات

تم ذلك لوقت التشغيل. لم يعد سطح مخزن الجلسات ذي شكل الملفات عقد وقت تشغيل نشطًا:

- لم يعد وقت التشغيل يستدعي `loadSessionStore(storePath)` أو يتعامل مع `storePath` بوصفه
  هوية الجلسة.
- عمليات صفوف وقت التشغيل هي `getSessionEntry` و`upsertSessionEntry` و
  `patchSessionEntry` و`deleteSessionEntry` و`listSessionEntries`.
- أزيلت من وقت التشغيل مساعدات إعادة كتابة المخزن بالكامل، وكاتبات الملفات، واختبارات الصفوف، وتنقيح الأسماء المستعارة، ومعاملات حذف المفاتيح القديمة.
- ما زالت صادرات توافق حزمة الجذر المهملة تكيّف مسارات
  `sessions.json` المعيارية على واجهات API لصفوف SQLite.
- يبقى تحليل `sessions.json` فقط في كود ترحيل/استيراد doctor
  واختبارات doctor.
- تقرأ آلية الرجوع في دورة حياة وقت التشغيل ترويسات نصوص SQLite، لا الأسطر الأولى من JSONL.

استمر في حذف أي شيء يعيد إدخال معاملات قفل الملفات،
أو مفردات التنقيح/الاقتطاع بوصفها صيانة ملفات، أو هوية مسار المخزن، أو اختبارات
يكون تأكيدها الوحيد هو استمرارية JSON.

### المرحلة 4: نقل النصوص ودفقات ACP والمسارات وVFS

اجعل كل دفق بيانات وكيل أصليًا في قاعدة البيانات:

- تمر كتابات إلحاق النصوص عبر معاملة SQLite واحدة تضمن ترويسة
  الجلسة، وتتحقق من عدم تكرار معرّف الرسالة، وتحدد ذيل الأصل، وتدرج
  في `transcript_events`، وتسجل بيانات تعريف الهوية القابلة للاستعلام في
  `transcript_event_identities`. تم ذلك لإلحاقات رسائل النصوص المباشرة و
  إلحاقات `TranscriptSessionManager` المستمرة العادية؛ تحتفظ عمليات الفرع الصريحة
  باختيار الأصل الصريح لها وما زالت تكتب صفوف SQLite
  من دون اشتقاق أي محدد موقع ملف.
- تصبح سجلات دفق ACP الأصلية صفوفًا، لا ملفات `.acp-stream.jsonl`. تم.
- لم يعد إعداد إنتاج ACP يحفظ مسارات JSONL للنصوص. تم.
- تكتب عملية التقاط مسار وقت التشغيل صفوف/آثار الأحداث مباشرة. ما زال بإمكان
  أمر الدعم/التصدير الصريح إنتاج آثار JSONL لحزمة الدعم
  كتنسيق تصدير، لكن تصدير الجلسة لا يعيد إنشاء JSONL للجلسة. تم.
- تبقى مساحات عمل القرص على القرص عند تكوينها في وضع القرص.
- تستخدم مساحة VFS المؤقتة ووضع مساحة العمل التجريبي VFS-only قاعدة بيانات الوكيل.

يستورد الترحيل ملفات JSONL القديمة مرة واحدة، ويسجل الأعداد/التجزئات في
`migration_runs`، ويزيل الملفات المستوردة بعد فحوص السلامة.

### المرحلة 5: النسخ الاحتياطي والاستعادة والتنظيف والتحقق

تبقى النسخ الاحتياطية ملف أرشيف واحدًا:

- أنشئ نقطة تحقق لكل قاعدة بيانات عامة وقاعدة بيانات وكيل.
- التقط كل قاعدة بيانات بدلالات النسخ الاحتياطي في SQLite أو `VACUUM INTO`.
- أرشف لقطات قواعد البيانات المضغوطة، والتكوين، وبيانات الاعتماد الخارجية، وتصديرات
  مساحات العمل المطلوبة.
- احذف ملفات `*.sqlite-wal` و`*.sqlite-shm` الحية الخام.
- تحقق بفتح كل لقطة قاعدة بيانات وتشغيل `PRAGMA integrity_check`.
  ينفذ `openclaw backup create` تحقق الأرشيف هذا افتراضيًا؛
  يتجاوز `--no-verify` تمريرة الأرشيف بعد الكتابة فقط، لا فحص سلامة
  إنشاء اللقطة.
- تنسخ الاستعادة اللقطات مرة أخرى إلى مساراتها الهدف. يعيد هذا الفرع تعيين
  تخطيط SQLite غير المشحون إلى `user_version = 1`؛ يمكن لتغييرات المخطط المشحونة مستقبلًا
  إضافة ترحيلات صريحة عند الحاجة.

### المرحلة 6: وقت تشغيل العامل

أبق وضع العامل تجريبيًا أثناء وصول تقسيم قاعدة البيانات:

- يتلقى العمال معرّف الوكيل، ومعرّف التشغيل، ووضع نظام الملفات، وهوية سجل قاعدة البيانات.
- يفتح كل عامل اتصال SQLite خاصًا به.
- يحتفظ الأصل بسلطة تسليم القناة، والموافقات، والتكوين، والإلغاء.
- ابدأ بعامل واحد لكل تشغيل نشط؛ لا تضف التجميع إلا بعد استقرار دورة الحياة وملكية اتصال قاعدة البيانات.

### المرحلة 7: حذف العالم القديم

تم ذلك لإدارة جلسات وقت التشغيل. لا يُسمح بالعالم القديم إلا كمدخل doctor صريح أو مخرج دعم/تصدير:

- لا توجد كتابات وقت تشغيل إلى `sessions.json`، أو JSONL للنصوص، أو JSON لسجل sandbox، أو SQLite جانبي للمهام، أو SQLite جانبي لحالة Plugin.
- لا يوجد تنقيح لملف JSON/جلسة، أو اقتطاع نصوص ملفية، أو أقفال ملفات جلسات،
  أو اختبارات جلسات ذات شكل أقفال.
- لا توجد صادرات توافق وقت تشغيل يكون هدفها إبقاء ملفات الجلسات القديمة
  محدثة.
- تبقى صادرات الدعم الصريحة تنسيقات أرشفة/تجسيد يطلبها المستخدم
  ويجب ألا تغذي أسماء الملفات مرة أخرى في هوية وقت التشغيل.

## النسخ الاحتياطي والاستعادة

يجب أن تكون النسخ الاحتياطية ملف أرشيف واحدًا، لكن يجب أن يكون التقاط قاعدة البيانات
أصليًا في SQLite:

1. أوقف نشاط الكتابة طويل الأمد أو ادخل حاجز نسخ احتياطي قصيرًا.
2. لكل قاعدة بيانات عامة وقاعدة بيانات وكيل، شغّل نقطة تحقق.
3. التقط كل قاعدة بيانات باستخدام دلالات النسخ الاحتياطي في SQLite أو `VACUUM INTO` داخل
   دليل نسخ احتياطي مؤقت.
4. أرشف لقطات قواعد البيانات المضغوطة، وملف التكوين، ودليل بيانات الاعتماد،
   ومساحات العمل المحددة، وبيانًا.
5. تحقق من الأرشيف بفتح كل لقطة SQLite مضمنة وتشغيل
   `PRAGMA integrity_check`.
   ينفذ `openclaw backup create` ذلك افتراضيًا؛ `--no-verify` مخصص فقط
   لتجاوز تمريرة الأرشيف بعد الكتابة عمدًا.

لا تعتمد على نسخ `*.sqlite` و`*.sqlite-wal` و`*.sqlite-shm` الحية الخام بوصفها
تنسيق النسخ الاحتياطي الأساسي. يجب أن يسجل بيان الأرشيف دور قاعدة البيانات،
ومعرّف الوكيل، وإصدار المخطط، ومسار المصدر، ومسار اللقطة، وحجم البايت، وحالة السلامة.

يجب أن تعيد الاستعادة بناء قاعدة البيانات العامة وملفات قواعد بيانات الوكلاء من
لقطات الأرشيف. نظرًا لأن تخطيط SQLite لم يُشحن بعد، يحتفظ هذا التحسين
بمخطط الإصدار 1 فقط مع استيراد doctor من ملف إلى قاعدة بيانات. يتحقق أمر الاستعادة
من الأرشيف أولًا، ثم يستبدل كل أصل في البيان من الحمولة المستخرجة المتحقق منها.

## خطة تحسين وقت التشغيل

1. أضف واجهات API لسجل قاعدة البيانات.
   - حل مسارات قاعدة البيانات العامة وقواعد البيانات لكل وكيل.
   - أبق المخططات غير المشحونة عند `user_version = 1`؛ لا تضف كود مشغّل
     ترحيل المخططات حتى يحتاج مخطط مشحون إلى ذلك.
   - أضف مساعدات الإغلاق/نقاط التحقق/السلامة التي تستخدمها الاختبارات والنسخ الاحتياطي وdoctor.

2. ادمج مخازن SQLite الجانبية.
   - انقل جداول حالة Plugin إلى قاعدة البيانات العامة. تم ذلك لكتابات وقت التشغيل؛ حُذف مستورد المخزن الجانبي القديم غير المشحون.
   - انقل جداول سجل المهام إلى قاعدة البيانات العامة. تم ذلك لكتابات وقت التشغيل؛ حُذف مستورد المخزن الجانبي القديم غير المشحون.
   - انقل جداول Task Flow إلى قاعدة البيانات العامة. تم ذلك لكتابات وقت التشغيل؛
     حُذف مستورد المخزن الجانبي القديم غير المشحون.
   - انقل جداول البحث في الذاكرة المدمجة إلى قاعدة بيانات كل وكيل. تم؛ أصبح
     `memorySearch.store.path` المخصص الصريح يُزال الآن بترحيل تكوين doctor.
     تعمل إعادة الفهرسة الكاملة في مكانها مقابل جداول الذاكرة فقط؛ حُذف مسار
     تبديل الملف بالكامل القديم ومساعد تبديل الفهرس الجانبي.
   - احذف فاتحات قاعدة البيانات المكررة، وإعداد WAL، ومساعدات الأذونات،
     ومسارات الإغلاق من تلك الأنظمة الفرعية.

3. انقل الجداول المملوكة للوكيل إلى قواعد بيانات لكل وكيل.
   - أنشئ قاعدة بيانات الوكيل عند الطلب عبر سجل قاعدة البيانات العامة. تم.
   - انقل إدخالات جلسات وقت التشغيل، وأحداث النصوص، وصفوف VFS، وآثار الأدوات إلى قواعد بيانات الوكلاء. تم.
   - لا ترحّل إدخالات جلسات قاعدة البيانات المشتركة المحلية للفرع، أو أحداث النصوص،
     أو صفوف VFS، أو آثار الأدوات؛ لم يُشحن ذلك التخطيط مطلقًا. أبق فقط
     الاستيراد القديم من ملف إلى قاعدة بيانات في doctor.

4. استبدل واجهات API لمخزن الجلسات.
   - أزل `storePath` بوصفه هوية وقت التشغيل. تم ذلك لوقت التشغيل ومحمي بواسطة
     `check:database-first-legacy-stores`: أصبحت بيانات تعريف الجلسة، وتحديثات المسار،
     واستمرارية الأوامر، وتنظيف جلسات CLI، ومعاينات الاستدلال في Feishu،
     واستمرارية حالة النصوص، وعمق الوكيل الفرعي، وتجاوزات جلسة ملف المصادقة،
     ومنطق تفريع الأصل، وفحص QA-lab تحل الآن
     قاعدة البيانات من مفاتيح الوكيل/الجلسة المعيارية.
     تكشف استجابات قوائم الجلسات في Gateway/TUI/UI/macOS الآن `databasePath`
     بدلًا من `path` القديم؛ تعرض أسطح تصحيح macOS قاعدة البيانات لكل وكيل
     كحالة للقراءة فقط بدلًا من كتابة تكوين `session.store`.
     لم تعد `/status`، وتصدير المسار المدفوع بالمحادثة، ووكلاء اعتماديات CLI
     تنشر مسارات المخازن القديمة؛ تقرأ آلية رجوع استخدام النصوص
     SQLite بهوية الوكيل/الجلسة. لم تعد اختبارات وقت التشغيل والجسر تكشف
     `storePath`؛ تمتلك مدخلات doctor/الترحيل اسم الحقل القديم ذلك.
     لم يعد تحميل الجلسات المجمعة في Gateway يحتوي فرع وقت تشغيل خاصًا لقيم
     `session.store` غير القالبية؛ فهو يجمع صفوف SQLite لكل وكيل.
     أزيل مسار doctor القديم لقفل الجلسة ومساعد تنظيف `.jsonl.lock` الخاص به؛
     أصبحت SQLite الآن حد تزامن الجلسة.
     تستخدم مواقع استدعاء وقت التشغيل الساخنة أسماء مساعدات موجهة بالصفوف مثل
     `resolveSessionRowEntry`؛ أزيل الاسم المستعار القديم للتوافق
     `resolveSessionStoreEntry` من وقت التشغيل وصادرات SDK الخاصة بـ Plugin.

- استخدم عمليات الصفوف `{ agentId, sessionKey }`.
  تم: `getSessionEntry` و`upsertSessionEntry` و`deleteSessionEntry` و
  `patchSessionEntry` و`listSessionEntries` هي واجهات API تبدأ بـ SQLite ولا
  تتطلب مسار مخزن جلسة. أصبحت أوامر ملخص الحالة، وحالة الوكيل المحلي، والصحة،
  وأمر قائمة `openclaw sessions` تقرأ صفوف كل وكيل مباشرة
  وتعرض مسارات قاعدة بيانات SQLite لكل وكيل بدلًا من مسارات `sessions.json`.
- استبدل حذف/إدراج المخزن بالكامل بـ `upsertSessionEntry` و
  `deleteSessionEntry` و`listSessionEntries` واستعلامات تنظيف SQL.
  تم ذلك لوقت التشغيل: تستخدم المسارات الساخنة الآن واجهات API للصفوف وتصحيحات صفوف يعاد تجربتها عند التعارض؛
  تقتصر مساعدات استيراد/استبدال المخزن بالكامل المتبقية على كود استيراد الترحيل
  واختبارات خلفية SQLite.
  - احذف `store-writer.ts` واختبارات صف الكاتب. تم.
  - احذف من وقت التشغيل تنقيح المفاتيح القديمة ومعاملات حذف الأسماء المستعارة من عمليات upsert/patch لصفوف الجلسة. تم.

5. احذف سلوك سجل JSON في وقت التشغيل.
   - اجعل قراءات وكتابات سجل sandbox خاصة بـ SQLite فقط. تم.
   - استورد JSON الأحادي والمجزأ فقط من خطوة الترحيل. تم.
   - أزل أقفال السجل المجزأ وكتابات JSON. تم.

- احتفظ بجدول سجل واحد typed بدلًا من تخزين صفوف السجل كـ JSON معتم عام
  إذا بقي الشكل حالة تشغيلية في المسار الساخن. تم.

6. احذف تحوير الجلسات ذي شكل قفل الملفات.
   - تم ذلك لإنشاء أقفال وقت التشغيل وواجهات API لأقفال وقت التشغيل.
   - أزيل مسار تنظيف doctor المستقل القديم لـ `.jsonl.lock`.
   - `session.writeLock` هو تكوين قديم مرحّل بواسطة doctor، وليس إعداد وقت تشغيل typed.
   - لم تعد سلامة الحالة تملك مسار تنقيح منفصلًا لملفات نصوص يتيمة؛
     يستورد ترحيل doctor مصادر JSONL القديمة ويزيلها في مكان واحد.
   - يستخدم تنسيق Gateway singleton صفوف SQLite typed في `state_leases` تحت
     `gateway_locks` ولم يعد يكشف سطح دليل قفل ملفات.
   - لم تعد استمرارية إزالة التكرار العامة في SDK الخاصة بـ Plugin تستخدم أقفال ملفات أو ملفات JSON؛
     بل تكتب صفوف حالة Plugin مشتركة في SQLite. تم.
   - يستخدم تنسيق تضمين QMD عقد حالة SQLite بدلًا من
     `qmd/embed.lock`. تم.

7. اجعل العمال مدركين لقاعدة البيانات.
   - يفتح العمال اتصالات SQLite الخاصة بهم.
   - يمتلك الأصل التسليم، واستدعاءات القناة، والتكوين.
   - يتلقى العامل معرّف الوكيل، ومعرّف التشغيل، ووضع نظام الملفات، وهوية سجل قاعدة البيانات،
     لا مقابض حية.
   - يبقى `vfs-only` تجريبيًا ويستخدم قاعدة بيانات الوكيل بوصفها جذر التخزين الخاص به.
   - أبق عاملًا واحدًا لكل تشغيل نشط أولًا. يمكن أن ينتظر التجميع حتى تصبح مدة حياة اتصال قاعدة البيانات وسلوك الإلغاء اعتياديين.

8. تكامل النسخ الاحتياطي.
   - علّم النسخ الاحتياطي أخذ لقطات لقواعد البيانات العامة وقواعد بيانات الوكلاء عبر النسخ الاحتياطي في SQLite أو
     `VACUUM INTO`. تم ذلك لملفات `*.sqlite` المكتشفة ضمن أصل الحالة.
   - أضف تحقق النسخ الاحتياطي من سلامة SQLite وإصدار المخطط. تم ذلك لفحوصات السلامة عند إنشاء النسخة الاحتياطية والتحقق الافتراضي من الأرشيف.
   - سجّل بيانات تعريف تشغيل النسخ الاحتياطي في SQLite. تم ذلك عبر جدول `backup_runs` المشترك مع مسار الأرشيف والحالة وJSON البيان.
   - أضف الاستعادة من لقطات أرشيفية موثّقة. تم: يتحقق `openclaw backup
restore` قبل الاستخراج، ويستخدم البيان المطبع الخاص بأداة التحقق، ويدعم `--dry-run`، ويتطلب `--yes` قبل استبدال مسارات المصدر المسجلة.
   - ضمّن تصدير VFS/مساحة العمل فقط عند الطلب؛ لا تصدّر داخليات الجلسة بصيغة JSON أو JSONL.

9. احذف الاختبارات والكود المتقادمين. تم ذلك لأسطح جلسات وقت التشغيل المعروفة.

- أزل الاختبارات التي تؤكد إنشاء وقت التشغيل لملفات `sessions.json` أو ملفات نصوص JSONL. تم ذلك لمخزن جلسات النواة، والدردشة، وأحداث نصوص Gateway، والمعاينة، ودورة الحياة، وتحديثات إدخال جلسة الأوامر، وإعادة ضبط/تتبّع الرد التلقائي، وتركيبات Dreaming في memory-core، وتوجيه هدف الموافقة، وإصلاح نص الجلسة، وإصلاح أذونات الأمان، وتصدير المسار، وتصدير الجلسة.
  تؤكد اختبارات نصوص Active-memory الآن نطاقات SQLite وعدم إنشاء ملفات JSONL مؤقتة أو مستمرة.
  أُزيل تراجع تقليم نصوص Heartbeat القديم لأن وقت التشغيل لم يعد يقتطع نصوص JSONL.
  لم تعد اختبارات أداة قائمة جلسات الوكيل تمثل مسارات `sessions.json` القديمة بوصفها شكل استجابة Gateway؛ تستخدم اختبارات التطبيق/واجهة المستخدم/macOS `databasePath`.
  أصبحت اختبارات استخدام نصوص `/status` تزرع صفوف نصوص SQLite مباشرة بدلاً من كتابة ملفات JSONL.
  تستخدم اختبارات دورة حياة جلسات Gateway الآن مساعدين لزرع نصوص SQLite مباشرة؛ اختفى شكل تركيبة ملف الجلسة أحادي السطر القديم من تغطية إعادة الضبط والحذف.
  لم تعد `sessions.delete` تعيد حقل عصر الملفات `archived: []`؛ لا يبلغ الحذف إلا عن نتيجة تعديل الصف. اختفى خيار `deleteTranscript` القديم أيضاً: حذف جلسة يزيل جذر `sessions` القانوني ويترك SQLite يطبق الحذف المتسلسل على صفوف النصوص واللقطات والمسارات المملوكة للجلسة، لذلك لا يستطيع أي مستدعٍ ترك نصوص يتيمة خلفه أو نسيان فرع تنظيف.
  أصبحت اختبارات التقاط مسار context-engine تقرأ صفوف `trajectory_runtime_events` من قاعدة بيانات وكيل معزولة بدلاً من قراءة `session.trajectory.jsonl`.
  أصبحت سكربتات زرع قناة Docker MCP تزرع صفوف SQLite مباشرة. تقتصر الكتابات المباشرة إلى `sessions.json` على تركيبات doctor.
  يقرأ اختبار Tool Search Gateway E2E دليل استدعاء الأداة من صفوف نصوص SQLite بدلاً من فحص ملفات `agents/<agentId>/sessions/*.jsonl`.
  أصبحت أحداث مضيف memory-core وصفوف خدش مجموعة الجلسات تعيش الآن في حالة Plugin مشتركة في SQLite؛ `events.jsonl` و`session-corpus/*.txt` مدخلات ترحيل doctor قديمة فقط. تستخدم الصفوف النشطة مسارات افتراضية `memory/session-ingestion/`، وليس `.dreams/session-corpus`. أُزيلت وحدة إصلاح Dreaming القديمة في memory-core واختبارات CLI/Gateway الخاصة بها لأن وقت التشغيل لم يعد يملك إصلاح أرشيف الملفات لتلك المجموعة. لم تعد اختبارات الجسر/الأثر العام في memory-core تعرض `.dreams/events.jsonl`؛ تستخدم اسم أثر JSON افتراضي مدعومًا بـ SQLite.
  تقول وثائق اختبار SDK/Codex العامة الآن حالة جلسة SQLite بدلاً من ملفات الجلسة، ولم يعد مثال دور القناة يكشف وسيط `storePath`.
  تستخدم حالة مزامنة Matrix الآن مخزن حالة Plugin في SQLite مباشرة. تمرر عقود العميل/وقت التشغيل النشطة جذر تخزين حساب، وليس مسار `bot-storage.json`، ويستورد doctor ملف `bot-storage.json` القديم إلى SQLite قبل حذف المصدر. أصبحت سيناريوهات QA Matrix الخاصة بإعادة التشغيل/الإتلاف تعدّل صف مزامنة SQLite مباشرة بدلاً من إنشاء ملفات `bot-storage.json` وهمية أو حذفها، ويمرر أساس E2EE جذر مخزن مزامنة بدلاً من مسار `sync-store.json` وهمي.
  لم يعد اختيار جذر تخزين Matrix يقيّم الجذور حسب ملفات JSON القديمة للمزامنة/الخيوط؛ يستخدم بيانات تعريف الجذر المتينة إضافة إلى حالة التشفير الحقيقية.
  لم تعد حزمة اختبارات خلفية جلسات SQLite وقت التشغيل تختلق `sessions.json`؛ تعيش تركيبات المصدر القديمة الآن في اختبارات doctor التي تستوردها.
  لم تعد اختبارات جلسات Gateway تكشف مساعد `createSessionStoreDir` أو إعداد مسار مخزن جلسات مؤقت غير مستخدم؛ أدلة التركيبات صريحة، والإعداد المباشر للصفوف يستخدم تسمية صفوف جلسات SQLite.
  انتقلت تغطية محلل مخزن جلسات JSON5 المخصص لـ doctor فقط من اختبارات البنية التحتية إلى اختبارات ترحيل doctor، لذلك لم تعد حزم اختبارات وقت التشغيل تملك تحليل ملفات الجلسات القديمة.
  لم تعد اختبارات SSO/الرفع المعلق في وقت تشغيل Microsoft Teams تحمل تركيبات أو محللات JSON جانبية؛ يعيش تحليل رمز SSO القديم فقط في وحدة ترحيل Plugin. لم تعد اختبارات Telegram تزرع مسارات مخزن وهمية `/tmp/*.json`؛ فهي تعيد ضبط ذاكرة الرسائل المؤقتة المدعومة بـ SQLite مباشرة. لم يعد مساعد حالة اختبار OpenClaw العام يكشف كاتب `auth-profiles.json` القديم؛ تملك اختبارات ترحيل مصادقة doctor تلك التركيبة محلياً.
  لم تعد اختبارات وقت التشغيل لمؤشرات آخر جلسة في TUI، وموافقات exec، ومفاتيح Active-memory، وإزالة تكرار Matrix/تحقق بدء التشغيل، ومزامنة مصدر Memory Wiki، وروابط المحادثة الحالية، ومصادقة التهيئة، واستيراد أسرار Hermes، تصنع ملفات جانبية قديمة أو تؤكد غياب أسماء ملفات قديمة. تثبت السلوك عبر صفوف SQLite وواجهات API العامة للمخزن؛ اختبارات doctor/الترحيل هي المكان الوحيد الذي تنتمي إليه أسماء ملفات المصدر القديمة.
  لم تعد اختبارات وقت التشغيل لإقران الجهاز/العقدة، وallowFrom للقناة، ونوايا إعادة التشغيل، وتسليم إعادة التشغيل، ومدخلات طابور تسليم الجلسة، وصحة التكوين، وذاكرات iMessage المؤقتة، ومهام Cron، وترويسات نصوص PI، وسجلات الوكلاء الفرعيين، ومرفقات الصور المدارة، تنشئ ملفات JSON/JSONL متقاعدة لمجرد إثبات أنها متجاهلة أو غائبة.
  لم يعد استرداد فيضان PI يحتوي على احتياط إعادة كتابة/اقتطاع في SessionManager: يقتطع اقتطاع نتائج الأدوات وإعادات كتابة نصوص context-engine صفوف نصوص SQLite، ثم يحدّثان حالة الموجه النشط من قاعدة البيانات. تفوض إلحاقات رسائل SessionManager المستمرة إلى مساعد إلحاق نصوص SQLite الذري لاختيار الأصل وضمان التماثلية. كما تختار إلحاقات البيانات الوصفية/الإدخال المخصص العادية الأصل الحالي داخل SQLite، بحيث لا تعيد نسخ المدير القديمة إحياء سباقات سلسلة الأصل السابقة لـ SQLite.
  أصبح تنظيف ذيل PI الاصطناعي لفحوصات منتصف الدور المسبقة و`sessions_yield` يقلّم حالة نصوص SQLite مباشرة؛ حُذف جسر إزالة الذيل القديم في SessionManager واختباراته.
  كما يلتقط حفظ نقطة تحقق Compaction اللقطات من SQLite فقط؛ لم يعد المستدعون يمررون SessionManager حياً كمصدر نص بديل.
- أبقِ الاختبارات التي تزرع ملفات قديمة للترحيل فقط.
- استُبدل إثبات ملفات JSON بإثبات صفوف SQL لأسطح وقت التشغيل النشطة.

- أضف حظراً ثابتاً على كتابات وقت التشغيل إلى مسارات JSON القديمة للجلسات/الذاكرة المؤقتة.
  تم ذلك لحارس المستودع.

10. اجعل تقرير الترحيل قابلاً للتدقيق.
    - سجّل عمليات الترحيل في SQLite مع طوابع بدء/انتهاء زمنية، ومسارات المصدر، وتجزئات المصدر، والأعداد، والتحذيرات، ومسار النسخ الاحتياطي.
      تم: تستمر تنفيذات ترحيل الحالة القديمة الآن في تقرير `migration_runs` مع جرد مسار/جدول المصدر، وSHA-256 لملف المصدر، والأحجام، وأعداد السجلات، والتحذيرات، ومسار النسخ الاحتياطي.
      تم: تستمر تنفيذات ترحيل الحالة القديمة أيضاً في صفوف `migration_sources` للتدقيق على مستوى المصدر وقرارات التخطي/الملء الخلفي المستقبلية.
    - اجعل التطبيق متماثلاً. يجب أن تؤدي إعادة التشغيل بعد استيراد جزئي إما إلى تخطي مصدر مستورد بالفعل أو الدمج بمفتاح ثابت.
      تم: تستورد فهارس الجلسات، والنصوص، وطوابير التسليم، وحالة Plugin، ودفاتر المهام، وصفوف SQLite العامة المملوكة للوكيل عبر مفاتيح ثابتة أو دلالات upsert/replace، لذلك تندمج عمليات إعادة التشغيل دون تكرار الصفوف المتينة.
    - يجب أن تبقي عمليات الاستيراد الفاشلة ملف المصدر الأصلي في مكانه.
      تم: تترك عمليات استيراد النصوص الفاشلة الآن مصدر JSONL الأصلي في مساره المكتشف، ويسجل `migration_sources` المصدر بوصفه `warning` مع `removed_source=0` لتشغيل doctor التالي.

## قواعد الأداء

- اتصال واحد لكل خيط/عملية مقبول؛ لا تشارك المقابض بين العمال.
- استخدم WAL، و`foreign_keys=ON`، ومهلة انشغال 30 ثانية، ومعاملات كتابة قصيرة `BEGIN IMMEDIATE`.
- أبقِ مساعدي معاملات الكتابة متزامنين ما لم/حتى تضيف API معاملات غير متزامنة دلالات mutex/backpressure صريحة.
- أبقِ كتابات تسليم الأصل صغيرة ومعاملاتية.
- تجنب إعادة كتابة المخزن بأكمله؛ استخدم upsert/delete على مستوى الصف.
- أضف فهارس لمسارات القائمة حسب الوكيل، والقائمة حسب الجلسة، وupdated-at، ومعرّف التشغيل، والانتهاء قبل نقل الكود الساخن.
- خزّن الآثار الكبيرة، والوسائط، والمتجهات كـ BLOBs أو صفوف BLOB مجزأة، وليس JSON بصيغة base64 أو مصفوفات رقمية.
- أبقِ مدخلات حالة Plugin المعتمة صغيرة ومحددة النطاق.
- أضف تنظيف SQL لـ TTL/الانتهاء بدلاً من تقليم نظام الملفات.
  تم ذلك لمخازن وقت التشغيل المملوكة لقاعدة البيانات: الوسائط، وحالة Plugin، وكتل Plugin الثنائية، وإزالة التكرار المستمرة، وذاكرة الوكيل المؤقتة كلها تنتهي عبر صفوف SQLite. يقتصر تنظيف نظام الملفات المتبقي على التجسيدات المؤقتة أو أوامر الإزالة الصريحة.

## الحظر الثابت

أضف فحص مستودع يفشل الكتابات الجديدة في وقت التشغيل إلى مسارات الحالة القديمة:

- `sessions.json`
- `*.trajectory.jsonl` باستثناء مخرجات حزمة الدعم المادية
- `.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 لأجزاء سجل sandbox
- ملفات JSON لجسر `/tmp` الخاص بترحيل الخطاف الأصلي
- `plugin-state/state.sqlite`
- ملفات 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 لسجل sandbox أو
  ملفات SQLite المصاحبة للمهام أو ملفات SQLite المصاحبة لحالة Plugin. تُحذف مستوردات SQLite المصاحبة
  غير المشحونة للمهام وحالة Plugin.
- استيراد الملفات القديمة يقتصر على doctor فقط.
- تنتج النسخة الاحتياطية أرشيفا واحدا يتضمن لقطات SQLite مضغوطة وإثبات سلامة.
- يمكن لعمال الوكلاء العمل باستخدام القرص أو مساحة مؤقتة VFS أو تخزين
  VFS فقط التجريبي.
- تبقى ملفات الإعدادات وملفات بيانات الاعتماد الصريحة هي ملفات التحكم الدائمة
  الوحيدة المتوقعة غير المعتمدة على قاعدة بيانات.
- تمنع فحوصات المستودع إعادة إدخال مخازن ملفات وقت التشغيل القديمة.
