# خارطة تطوير SovereignAI هذه خارطة تنفيذ تدريجية للمشروع الحالي. التطبيق اليوم Flutter، وواجهة الخدمة FastAPI، والتخزين SQLite، وتوليد النص عبر خادم Ollama محلي. لا نبدأ بتدريب نموذج من الصفر؛ نبني منتجًا قابلًا لتبديل النموذج ونقيس كل مرحلة قبل توسيع الصلاحيات. ## الحالة الحالية — 2026-10-03 - تحقق تشغيل حديث: أُعيد تشغيل FastAPI على `127.0.0.1:8000` من نسخة المشروع الحالية مع Ollama وGemma 4؛ `/health` أعاد `ok`، والجلسة المحلية أكدت وضع الوكيل متعدد الخطوات وحده 3، وتجربة API حية اختارت `calculator` وأعادت `391.0` لـ17×23. في 2026-10-03 اختُبر أيضًا طلب بحث+حساب حي: `search_workspace` أعاد `MAX_AGENT_TOOL_CALLS = 3` من `app/main.py`، ثم الحاسبة أعادت `21` لـ3×7 في خطوتين. بقي تطبيق Windows Debug شغّالًا، وظل ملف SQLite المحلي موجودًا في مساره. اختبارات Python الكاملة 83/83؛ اختبارات Flutter 15/15 و`flutter analyze` بلا ملاحظات من الجولة السابقة، ولم تتغير واجهة Flutter في هذه الخطوة. - 2026-10-03: أعيد تقييم البحث الهجين على 9 أسئلة بملفات المشروع الفعلية. فُهرست 4 ملفات بنموذج `granite-embedding:278m`، وأعاد البحث الملف المقصود ضمن أول 3 نتائج في 9/9، وفي المركز الأول في 6/9، ووجد النص الداعم المتوقع في 8/9؛ `MRR=0.833`. صُحح توقع اختبار PDF من قيمة افتراضية قديمة إلى الثابت الحقيقي `MAX_PDF_PAGES = 30`. بقي سؤال صلاحيات الأداة دون المقطع الدقيق في `main.py`. التقرير `evals/results/retrieval_2026-10-03_145357.json`. التقييم صغير ويقيس الاسترجاع لا جودة إجابة Gemma؛ لم تحصل مراجعة بشرية بعد. أداة التقييم صارت تستخدم جلسة loopback مؤقتة وتلغيها، وتسجل نمط البحث والتضمين، مع مهلة أطول للفهرسة على CPU. - الأساس المحلي يعمل: Flutter Windows Debug ↔ FastAPI ↔ Ollama، مع سجل SQLite للمحادثات ونسخ الإجابات. Gemma 4 E2B هو الافتراضي للنصوص، وطلبات الصور وPDFات الممسوحة تتحول تلقائيًا إلى Ministral 3:3b المحلي عند توفره. أضيف عقد أدوات الوكيل وسجل تدقيق للبيانات الوصفية فقط؛ ينفذ الوكيل حتى ثلاث خطوات أدوات مسموحة بالتتابع ثم يعيد النتائج إلى Gemma لصياغة الرد. عند طلب المستخدم البحث صراحةً في المشروع، يجلب الخادم مقتطفات المساحة المخصصة أولًا ويمررها كبيانات غير موثوقة. توجد ثلاث مهارات محلية قابلة للاختيار مع قائمة أدوات مسموحة يتحقق منها الخادم في كل خطوة. فهرس SQLite يدعم FTS5 وتضمينات Granite محلية اختيارية لملفات النص والكود وPDF الرقمي والممسوح والمختلط؛ PDF الممسوح يفهرس أول 3 صفحات عبر OCR الاختياري. الوكيل يسترجع المقاطع نصيًا ودلاليًا ويهمل النتائج القديمة عند تغير الملف. تجربة تضمين API حقيقية أعادت الملف المقصود أولًا في 3/3 أسئلة عربية؛ بقي توسيع التقييم على ملفات واقعية ومعايرة OCR وترتيب الأعمدة. - اكتملت وظائف المحادثة الأساسية وطبقة مزوّد Ollama، بما فيها جداول Markdown القابلة للتمرير والقوائم المتداخلة ومربعات مهام GFM؛ اجتاز التطبيق تحليل Flutter و10 اختبارات واجهة وحالة. - الوكيل يقرأ ملفات يختارها المستخدم، ويمكنه اقتراح إنشاء/تحديث ملف داخل مساحة العمل فقط. يعرض التطبيق diff ويطلب الموافقة قبل الكتابة؛ لا يخزّن الخادم الملفات ولا يشغل كودها. يبث الخادم مراحل التحقق واختيار الأداة والتنفيذ وصياغة الرد إلى واجهة Flutter. - أضيف مسار كتابة أولي للوكيل: لا يكتب مباشرة؛ يعرض diff لمعاينة إنشاء/تحديث ملف داخل مساحة العمل، ثم يتطلب تأكيدًا صريحًا في التطبيق. الموافقة تستخدم رمزًا مؤقتًا لمرة واحدة وفحصًا لبصمة الملف لمنع تطبيق معاينة قديمة أو استبدال تعديل أحدث. - API يضيف `X-Request-ID` لكل استجابة، ويرجع أخطاء HTTP والتحقق في غلاف موحد مع `detail` متوافق مع العميل؛ لا يضمّن قيم المدخلات في تفاصيل أخطاء التحقق. يعرض انتهاء مهلة النموذج كـ504. تغطي الاختبارات الصحة والأخطاء والمهل والإلغاء. - التحقق الشامل الأحدث (2026-10-02): 51 اختبار Python و11 اختبار Flutter ناجحة. فحص Dart للـCubit واختباره بلا ملاحظات، و`compileall` و`git diff --check` ناجحان. يعمل FastAPI على 8000 و8001؛ اختبار الخدمة المنفصلة 8002 أُغلق بعد التحقق. واجهة 5302 غير مشغلة الآن. - 2026-10-03: أصبحت واجهة Flutter تعرض خطوات الأدوات التي أعادها الوكيل بالترتيب، مع أسماء عربية وحالة كل خطوة، وتستمر في دعم الردود القديمة التي لا تحتوي `steps`. فحص Dart بلا ملاحظات، ومجموعة Flutter كاملة 13/13 ناجحة. تحقق API حي على 8100 أن Gemma 4 اختارت الحاسبة لطلب 17×23 وأعادت 391 مع خطوة `completed`. - 2026-10-02: أضيف OCR محلي اختياري EasyOCR عربي/إنجليزي للصور وPDF الممسوح. طلب الصورة الحي عبر FastAPI أعاد HTTP 200، وحوّل Gemma تلقائيًا إلى Ministral المحلي، وعرض OCR وتحليل الصورة. OCR قرأ العنوانين والمكان والتاريخ والوقت؛ ترتيب الصفوف RTL/LTR جمع العنوان العربي، وبقي متوسط الثقة 0.625. على CPU: تهيئة الأوزان ~45 ثانية ثم OCR ~71 ثانية. الأوزان نحو 300MB وتُنزل أول مرة؛ الصور نفسها لا تغادر الجهاز. يمرر المساران OCR إلى نموذج الرؤية ويعرضان النص للمراجعة، ويرجعان للرؤية إن غابت الحزمة أو الأوزان. الاعتماد موثق في `requirements-ocr.txt`؛ يلزم مراجعة تراخيص الأوزان قبل التوزيع التجاري. - 2026-10-02: يدعم تحليل الملفات وفهرسة المعرفة PDF المختلط صفحةً بصفحة: النص الرقمي يستخرج محليًا والصفحات المصورة وحدها تمر إلى OCR/الرؤية، مع الحفاظ على أرقام الصفحات. نجحت اختبارات الاستخراج والتحليل (2/2) واختبار API متكامل لفهرسة PDF مختلط واسترجاع النص الرقمي وOCR والحذف (1/1). أُجري اختبار API بقاعدة SQLite داخل مجلد المشروع ليتوافق مع sandbox؛ اختبارات وحدات أخرى لا تزال تستخدم `TemporaryDirectory` المقيد. حالات OCR في API تميز النجاح الكامل والجزئي وغياب الأوزان وعدم العثور على نص مقروء. - 2026-10-02: حسّنت قابلية تشخيص Deep Search بإرجاع زمن الجلب الإجمالي ولكل مصدر، وأضفت اختبار API بمصادر ومحرك مزيفين وأربعة اختبارات لقواعد رفض الشبكات المحلية والمنافذ/الاعتمادات غير المسموحة وتنقية HTML من `script` و`style`. اجتازت الاختبارات الخمسة و`compileall` و`git diff --check`؛ لم تُجرّب اتصالات إنترنت فعلية في هذه الجولة. - 2026-10-02: نزلت واختبرت محليًا `granite-embedding:278m` (562MB، 768 بُعدًا، متعدد اللغات ويتضمن العربية، Apache 2.0). أضيفت متجهات FTS الهجينة إلى SQLite، وإعادة التضمين وقت الفهرسة، وRRF عند البحث، والرجوع التلقائي إلى FTS5 عند غياب النموذج. تحقق API حي باستخدام Ollama الحقيقي: فهرسة وإجابة البحث الدلالي أعادتا HTTP 200 والنمط `hybrid` والملف الصحيح ثم حذف الفهرس. اختبار حقيقي موازٍ على 3 أسئلة عربية اختار الملف الصحيح أولًا في كل مرة (cosine 0.648–0.827). أضيف فلتر Flutter لمنع اختيار نماذج embedding-only للمحادثة؛ نجح اختبار Cubit لهذا السلوك لاحقًا. - 2026-10-02: عولجت حالة تعطيل التضمين صراحةً (`KNOWLEDGE_EMBEDDING_MODEL=`) لتعيد حالة اختيارية قابلة للمعالجة بدل خطأ داخلي، مع اختبارين لها. اجتازت 9 اختبارات Python مركزة و6 اختبارات `chat_cubit_test.dart`، و`dart analyze` للملفين المعدلين دون ملاحظات، و`compileall` و`git diff --check`. استدعاء Dart/Flutter من sandbox منع الكتابة/بدء خادم التحليل داخل Flutter SDK؛ بعد السماح المؤقت اللازم نجحت الفحوص، ولم يتغير كود SDK. فحص الصحة المحلي أعاد HTTP 200 للخدمتين على 8000 و8001؛ منفذ واجهة الويب 5302 لا يستمع الآن. - 2026-10-02: أضيف `--warmup` وملخص قياس الزمن إلى مشغل التقييم. تقييم تمهيدي بعد الإحماء: Gemma متوسط 20.47 ثانية (11.59–31.55)، وQwen متوسط 6.25 ثانية (4.85–9.30)، من 5 أسئلة لكل نموذج؛ Qwen أخفق في استدعاء الحاسبة قبل إصلاح تطبيع الرموز. تبقى المقارنة اتجاهية، بلا أخذ عينات متعددة أو قياس ذاكرة أو مراجعة مستخدم. كشف الاختبار أن Gemma تجاهلت طلب استخدام الحاسبة وQwen أرسل علامة الضرب `×`؛ صار التعبير المحدود يقبل `× ÷ −`، والطلب الصريح لاستخدام الحاسبة مع تعبير بسيط يمر الآن بالحاسبة المحلية المقيدة. إعادة تجربة حيّة على API اختبار منفصل 8002: النموذجان اجتازا فحصي الحاسبة (2/2 لكل واحد). اجتازت 10 اختبارات وكيل/مهارات بعد الإصلاح. - 2026-10-02: بعد اجتياز 51 اختبار Python و11 Flutter، أُعيد تشغيل Windows Debug من نسخة مصدر معزولة لأن التطبيق المفتوح قفل ملف exe الأصلي. عملية Flutter الجديدة بدأت مع API اختبار 8002؛ فحص الصحة وطلب محادثة حي عبر Gemma أعادا HTTP 200. بقيت قاعدة الخدمة في `.test-runtime` لحماية سجل المحادثات الأصلي. أداة فحص سطح المكتب لم تُرجع نوافذ أصلية و`MainWindowHandle` للعملية صفر، لذا لا أعتبر العرض المرئي مؤكدًا بعد. لم يُغلق التطبيق الأصلي أو يُستبدل. - تحقق حي من الفهرسة الممسوحة: PDF تجريبي 149KB، فُهرست صفحته عبر OCR ثم استُرجع نصه من FTS5، وأُزيل السجل والملف بعد الاختبار. - تشغيل FastAPI المحدث على `127.0.0.1:8001` نجح وفحص الصحة وOpenAPI صحيح. هذا خادم تجربة بقاعدة منفصلة `.live-api-data` وأوزان OCR من مجلد مؤقت؛ Swagger متاح على `http://127.0.0.1:8001/docs`. عملية 8000 القديمة لم تسمح جلسة Windows الحالية بإيقافها (`Stop-Process` أعاد Access Denied)، لذا لم تُستبدل قاعدة المحادثات أو تُنهَ العملية. التطبيق Flutter ما زال مضبوطًا على 8000 إلى أن يعاد تشغيل الخدمة الأصلية. - إعدادات عنوان API والنموذج المختار والإشعارات والمظهر الداكن تُحفظ محليًا: ملف إعدادات عبر `path_provider` للأجهزة و`localStorage` للويب. عند غياب plugin يُبلّغ التطبيق أن الإعداد لن يستمر بعد الجلسة. Windows Debug أنشأ ملف الإعدادات فعليًا؛ اختبار Cubit أكد الاستعادة بعد إعادة إنشائه، واختبار الواجهة أكد تبديل السمة، وبناء Flutter Web نجح (2026-10-02). - `/v1/models` يعرض القدرات التي يعلنها Ollama فعلًا لكل نموذج، مع علامة تحقق واضحة؛ قائمة Flutter تعرض النص/الصور/الصوت/الأدوات/التفكير/التضمينات دون تخمين. تحقق حي أظهر Gemma 4 E2B: نص، صور، صوت، أدوات، تفكير؛ Ministral 3:3b: نص، صور، أدوات. - أضيف زر البحث العميق متعدد المصادر وزرا اختيار الملفات إلى الواجهة؛ أضيف تقييم الإجابة بإعجاب/عدم إعجاب محفوظ لكل نسخة في SQLite. التقييم يجمع بيانات تقييم، ولا يدرّب أوزان Gemma تلقائيًا. - Flutter Windows Debug وFastAPI يعملان محليًا؛ مسار تحليل المرفقات يدعم PDF الرقمي، ويحوّل أول 3 صفحات من PDF الممسوح محليًا ثم يرسلها لنموذج الرؤية المحلي. تجربة حية على صورة اللقاء استخرجت العنوان والمكان عمان والتاريخ 15 تشرين الأول والوقت 6:30 مساءً دون ذكر سنة غير ظاهرة. اكتملت واجهة الحساب، وتحديد محاولات الدخول، وتعيين جذور ملفات منفصلة للحسابات بإعداد مسؤول الخادم. عزل عملية FastAPI على مستوى نظام التشغيل، واستعادة كلمة المرور، وTLS، والتخزين الآمن للويب ما زالت مفتوحة؛ لا يوجد نشر شبكي آمن بعد. الصوت يعتمد على Groq خارجي. - التدريب والضبط الدقيق وتوزيع Windows مراحل لاحقة، وليست مما يفعّله التطبيق حاليًا. - 2026-10-03: اكتمل فرض Bearer على كل عمليات `/v1` الخاصة (عدا الصحة وقائمة النماذج ومسارات بدء المصادقة العامة)، وربط Flutter بالجلسة لكل طلب محادثة/وكيل/ملف/معرفة/ويب/صوت. أصبحت ملكية فهرس المعرفة وسجل التدقيق حسب الحساب، ومعاينة تعديل الملف لا تُطبق إلا بجلسة صاحبها. تحقق OpenAPI وواجهات رفض الرمز وعزل حسابين وترحيل SQLite: 61 اختبار Python ناجح، و11 اختبار Flutter وتحليل Flutter بلا ملاحظات. يبقى قصر الوصول إلى مسارات نظام الملفات لكل مستخدم، وواجهة الدخول وتخزين الرمز الآمن وحدود محاولات الدخول؛ لذلك يظل التشغيل loopback فقط. - 2026-10-03: أضيفت شاشة Flutter للحساب (إنشاء/دخول/خروج)، وعند تبديل الهوية تمسح المحادثات المحملة ثم تعيد قراءتها تحت الجلسة الجديدة. رمز الحساب يمر عبر `flutter_secure_storage` ويُستعاد بالتحقق من `/v1/auth/me`؛ اختبار Flutter 11/11 و`flutter analyze` بلا ملاحظات. Android مضبوط على API 23. ثُبت مكوّن ATL ثم نجح `flutter build windows --debug`، وأُطلقت نسخة Windows Debug متصلة بخادم تجريبي على `127.0.0.1:8100` وقاعدة `.live-api-data`؛ فحص `/health` أعاد HTTP 200. لم أتحقق من التفاعل المرئي للشاشة بعد. - 2026-10-03: عُزلت مساحة العمل حسب الحساب عبر `SOVEREIGNAI_USER_WORKSPACES`؛ يتحقق الخادم من أن كل مسار داخل جذور المسؤول، ويرفض الجذور المتداخلة أو غير المخصصة، مع تحويل المنع إلى HTTP 403. أضيفت تغطية لحسابين وجذور منفصلة. تحقق API حي منفصل على 8100: إنشاء جلسة loopback ثم إرسال تحية عربية إلى `POST /v1/chat/completions` عبر Gemma 4 أعاد ردًا وHTTP 200. فحص `/health` أيضًا HTTP 200. هذا يثبت API والنموذج؛ اتصال نافذة Flutter بهذا المنفذ لم يُثبت، ولا تسجل الخدمة طلبًا صادرًا من التطبيق حتى الآن. تحديث الاختبارات الكامل لم يُعَد في هذه الجولة لأن `pytest` غير موجود في بيئة Python المتاحة، و`unittest discover` لا يشغل اختبارات pytest ويصطدم بإنشاء ملفات مؤقتة خارج مساحة العمل. الاختبار الكامل السابق كان 65 اختبارًا ناجحًا قبل هذا التغيير الصغير في معرّف المستخدم المحلي؛ يلزم إعادة تشغيل pytest في بيئة مناسبة. - 2026-10-03: حد الدخول محفوظ في SQLite: خمس كلمات مرور خاطئة لكل حساب أو اتصال خلال 15 دقيقة، وحدّ إنشاء 30 حسابًا لكل اتصال في الساعة. تُخزن بصمات SHA-256، ويرجع API حالة 429 و`Retry-After`. أضيفت الآن جذور منفصلة لكل حساب بإعداد `SOVEREIGNAI_USER_WORKSPACES`؛ طلب API أكد أن الحساب لا يختار مساحة حساب آخر، والجذور المتداخلة مرفوضة. مجموعة Python كاملة 65/65، و`compileall` و`git diff --check` ناجحان. ## المرحلة 1 — تجربة المحادثة - [x] نسخ إجابة المساعد. - [x] مشاركة نص الإجابة عبر نظام التشغيل. - [x] تعديل آخر سؤال وإعادة إرساله؛ تُستبدل الإجابة وما بعدها في سياق المحادثة. - [x] إعادة توليد آخر إجابة. - [x] إشعار داخل التطبيق عند اكتمال الإجابة أو انتهاء الطلب بخطأ. - [x] تجهيز تنبيهات نظام Windows/macOS/Linux/Android/iOS مع طلب إذن الهاتف عند ضغط المستخدم؛ الويب يعرض تنبيهًا داخل الصفحة في إصدار Flutter الحالي. - [x] إنشاء أصل أيقونة موحّد وإعداد توليد أيقونات Android/iOS/macOS/Windows/Web، وإضافة أصل تغليف Linux. - [x] اختيار نموذج Ollama مثبت من واجهة التطبيق، وتمريره صراحةً للطلب. - [x] وضع وكيل تجريبي للبحث وقراءة مقتطفات ملفات المشروع فقط، مع إرجاع مراجع الملفات. - [x] حفظ محاولات الإجابة كنسخ منفصلة بدل استبدالها، مع واجهة للتنقل بينها. (2026-10-01: اجتازت اختبارات Flutter التنقل والحفظ، واختبارات SQLite/API الترحيل والحفظ والاسترجاع.) - [x] إظهار حالة النموذج والوقت وسبب الخطأ، وتوفير إيقاف التوليد. (2026-10-01: اختبار زر الإيقاف في الواجهة، حفظ النص الجزئي، وحماية الإجابة القديمة أثناء إلغاء إعادة التوليد؛ `flutter analyze` بلا ملاحظات، وWindows Debug أُعيد تشغيله.) - [x] إضافة تقييم 👍/👎 لكل نسخة إجابة وحفظه في SQLite؛ اختبار واجهة حي نجح بعد إصلاح خطأ فهرسة الرسائل في قاعدة البيانات. يستخدم لاحقًا لبناء مجموعة تقييم/تفضيلات بمراجعة بشرية، ولا يغير أوزان النموذج بمفرده. - [x] عرض Markdown الأساسي الشائع: عناوين حتى المستوى السادس، غامق/مائل/شطب، قوائم أساسية، اقتباسات، كود داخل السطر وكتل كود ملوّنة حسب اللغة. لكل كتلة كود زر نسخ مستقل. - [x] فتح روابط Markdown الخارجية بصيغة HTTP أو HTTPS في المتصفح الافتراضي؛ تُرفض المخططات الأخرى. - [x] دعم جداول Markdown قابلة للتمرير أفقيًا، والقوائم المتداخلة، ومربعات مهام GFM؛ اجتاز اختبار الواجهة والتحليل، وأُعيد بناء وتشغيل Windows Debug بالتغييرات. ## المرحلة 2 — أساس موثوق للواجهة والـ API - [x] فصل عقد التطبيق عن تفاصيل Ollama عبر طبقة مزوّد موحدة (Model Provider)، مع بقاء Ollama أول تنفيذ للمزوّد. (2026-10-01: المحادثة والبث والوكيل وقراءة مساحة العمل والويب تستخدم العقد الموحدة؛ `MODEL_PROVIDER=ollama` هو التنفيذ المتاح حاليًا. بعد إعادة تشغيل FastAPI أكد `/health` المزوّد، وأعاد `/v1/models` ثلاثة نماذج، ونجح طلب محادثة حي عبر Gemma.) - [x] جلب قائمة النماذج المحلية والتحقق من اختيار النموذج قبل الإرسال؛ عرض قدرات كل نموذج التي يعلنها Ollama في API وقائمة Flutter، مع تمييز البيانات غير المتاحة عن عدم الدعم. تحقق حي على النماذج الأربعة المثبتة واختبار عقد Flutter/API (2026-10-02). - [x] مسار تحليل ملفات مرفقة نصية/برمجية وPDF عبر FastAPI، مع تحقق النوع والحجم وحد أقصى 3 ملفات. الملفات النصية حتى 256KB لكل ملف؛ PDF حتى 8MB لكل ملف، ومجموع المرفقات 16MB. PDF الرقمي حتى 30 صفحة و24 ألف محرف؛ PDF بلا طبقة نصية يحول أول 3 صفحات إلى JPEG محليًا ويرسلها إلى نموذج الرؤية المحلي. لا حفظ على القرص ولا تشغيل للكود. اجتاز اختبار API حقيقي على صورة عربية/إنجليزية، وأربعة اختبارات PDF. - [x] توحيد أخطاء HTTP والتحقق وإضافة `X-Request-ID` وربطه برسائل Flutter؛ الاختبارات الحية والوحدوية أكدت 200 و404 و422 ومعرّف الاستجابة وتنقية تفاصيل التحقق (2026-10-02). - [x] اختبارات تكامل لعقد API لحالات الصحة والأخطاء والقدرات، مع التحقق من استمرار اختبارات SQLite ومساحة العمل (14 اختبار Python ناجح، 2026-10-02). - [x] اختبار مهلة مزوّد النموذج وحد الطلب وإغلاق العميل عند الإلغاء، وإلغاء مهمة الوكيل عند إغلاق بث SSE؛ تظهر مهلة النموذج 504 (2026-10-02: 14 اختبار Python ناجح). - إبقاء الخدمة محلية افتراضيًا؛ لا تُعرض على الشبكة قبل مصادقة المستخدم ومراجعة إعدادات الأمان. - [x] حفظ عنوان API والنموذج والإشعارات في مخزن إعدادات محلي للأجهزة والويب؛ تعرض الواجهة فشل التخزين الدائم ولا توهم المستخدم بالحفظ. (2026-10-02: استعادة Cubit بعد إعادة إنشائه، إنشاء الملف على Windows، بناء الويب والتحليل واختبارات Flutter ناجحة.) - [x] إعداد تفضيل المظهر الداكن وحفظه محليًا؛ يبدّل سمة التطبيق وأسطح المحادثة الأساسية، واختبار واجهة على نافذة صغيرة. - [x] إظهار حالة الخادم والنموذج بوضوح في واجهة المحادثة. ## المرحلة 3 — الهوية والبيانات - [x] أساس مصادقة محلي في FastAPI: تسجيل/دخول بالبريد وكلمة مرور عبر API، تجزئة PBKDF2 مملحة، جلسات Bearer عشوائية قابلة للإلغاء وتنتهي بعد 7 أيام، وترحيل SQLite يحافظ على هويات OAuth القديمة. `X-User-ID` لم يعد يخول الوصول لسجل المحادثات؛ الجلسة المحلية التلقائية لا تصدر إلا لعميل loopback. اختبارات المصادقة والعزل والترحيل: 7 ناجحة (2026-10-03). - [x] ربط CRUD المحادثات والتقييم بهوية الجلسة، والتحقق من أن حسابًا ثانيًا لا يقرأ محادثة الحساب الأول. - [x] فرض Bearer على جميع عمليات `/v1` الخاصة وإرسال الجلسة من Flutter للمحادثة/الوكيل/الملفات/المعرفة/البحث والصوت؛ فحص OpenAPI يضمن ألا توجد عملية خاصة بلا HTTP Bearer. - [x] عزل فهرس المعرفة وسجل التدقيق بمعرّف الحساب، وربط رمز معاينة تعديل الملفات بصاحبها؛ اختبار API أثبت عدم استرجاع حساب لمحتوى فهرسه حساب آخر. - [x] ربط جذور مساحة العمل بالحساب عبر إعداد مسؤول الخدمة `SOVEREIGNAI_USER_WORKSPACES` (بريد الحساب ← مسارات مخصصة تحت القائمة العامة)؛ يرفض API الحساب الذي لا يملك تخصيصًا، ويرفض المسارات المتداخلة بين الحسابات. اختبار API أكد أن لكل حساب جذره فقط (2026-10-03). - [x] حاجز loopback داخل FastAPI: يرفض كل طلب peer ليس `127.0.0.1` أو `::1` بحالة 403 ومعرّف طلب، حتى لو رُبط Uvicorn خطأً على عنوان عام. اختبارات العميل المحلي/البعيد والمصادقة والمعرفة نجحت (23 اختبارًا). هذا يحد الوصول الشبكي على مستوى API لكنه لا يعزل ملفات العملية. - [ ] عزل عملية FastAPI عن ملفات المضيف غير المصرح بها على مستوى نظام التشغيل قبل السماح بعميل شبكي أو خدمة مستضافة؛ القائمة البرمجية وحدها لا تحد صلاحيات العملية نفسها. فحص 2026-10-03: Docker وWindows Sandbox غير متاحين، ولم يمكن تأكيد وجود توزيعة WSL (الأمر المتاح يعرض تعليمات فقط)؛ فحص ميزات Windows يتطلب صلاحية مسؤول. حاجز loopback في FastAPI يخفف الخطر محليًا لكنه لا يحقق عزل الملفات. تجربة AppContainer لم تثبت حد مساحة قرص موثوقًا، وطلب إنشاء VHDX أُلغي عند UAC دون تغيير أقراص الجهاز. نحتاج بيئة عزل نظامية قابلة للقياس أو صلاحية إعدادها قبل تفعيل أوامر الوكيل. - [x] إضافة قائمة سماح على مستوى الخادم عبر `SOVEREIGNAI_ALLOWED_WORKSPACES`؛ يرفض API أي مجلد خارج الجذور المعتمدة. مع `SOVEREIGNAI_USER_WORKSPACES` يطبق الخادم كذلك حدود جذور كل حساب. لا يغني ذلك عن عزل صلاحيات عملية FastAPI على مستوى نظام التشغيل. - [x] بناء واجهة إنشاء الحساب/الدخول والخروج وربطها بجلسات API؛ عند تبديل الحساب تمسح الواجهة الحالة المحلية ثم تعيد تحميل المحادثات والمهارات تحت الهوية الجديدة. - [x] حفظ رمز الحساب عبر `flutter_secure_storage` في مخزن النظام على المنصات الأصلية المدعومة، واستعادة `/v1/auth/me` عند بدء التطبيق؛ Android مضبوط على API 23 كحد أدنى. الويب لا يحفظ رمز الجلسة دائمًا، ويحتفظ به في الذاكرة فقط حتى إعادة التحميل أو إغلاق التبويب. - [x] اختبار مخزن جلسة الويب المؤقت (2/2) وبناء Flutter Web ناجح (2026-10-03). رسالة الدخول توضح انتهاء الجلسة عند إعادة تحميل الصفحة. - [x] إضافة استعادة كلمة المرور عبر SMTP: رمز عشوائي 30 دقيقة بصمة SHA-256، لمرة واحدة، تحديد طلبات حسب البريد والعميل، رسالة API عامة، وتسجيل خروج كل الجلسات القديمة بعد تغيير كلمة المرور. مسارات Flutter للطلب وإدخال الرمز وتغيير كلمة المرور مضافة؛ 12 اختبار مصادقة نجحت، و`flutter analyze` نظيف (2026-10-03). يتطلب الإرسال إعداد متغيرات SMTP الموثقة في README. - [x] اختبار FastAPI محليًا عبر TLS: `scripts/local_tls_smoke.py` ولّد شهادة اختبار مؤقتة، شغّل الخادم على `127.0.0.1`، تحقق من شهادة TLS صراحة وأعاد `/openapi.json` الحالة 200، ورفض شهادة غير موثوقة؛ أُغلق الخادم وحُذفت ملفات الشهادة بعد الاختبار (2026-10-03). - [ ] TLS: تحقق Windows Dart `HttpClient` المستخدم من عميل Flutter من `https://localhost/.../health` وأعاد 200 مع شهادة مؤقتة أضيفت إلى مخزن CurrentUser ثم حُذفت وتأكد غياب بصمتها (2026-10-03). أضيف لـ`start-api.ps1` خيار شهادة/مفتاح PEM عبر `SOVEREIGNAI_TLS_CERTFILE` و`SOVEREIGNAI_TLS_KEYFILE`، ويظل الإعداد الافتراضي HTTP على loopback؛ الزوج مطلوب معًا، ولا يثبت السكربت شهادةً في مخزن الثقة. (2026-10-03: اختبار تشغيل فعلي عبر السكربت على `127.0.0.1:8128` أعاد `/health` الحالة 200 باستخدام الشهادة المحددة، ورفضها عميل HTTPX عند استخدام مخزن الثقة الافتراضي. أوقفت الخدمة وحذفت الشهادة والمفتاح وقاعدة الاختبار المؤقتة.) محاولة Edge headless السابقة لم تنتهِ خلال 25 ثانية، لذلك ثقة المتصفح/واجهة Flutter على شهادة دائمة غير مؤكدة. إعداد إدارة شهادة محلية دائمة والتحقق من العميل/المتصفح قبل أي وصول شبكي ما زالا مفتوحين؛ شهادة smoke ليست شهادة نشر. - [x] حد أولي دائم لتخمين كلمات المرور وإنشاء الحسابات في SQLite مع نافذة انتهاء و`Retry-After`؛ اختبرته مجموعة Python كاملة، وتبقى مراجعة الحدود تحت reverse proxy موثوق قبل أي نشر خارجي. - [x] تعطيل حفظ رمز الجلسة الدائم في الويب؛ استخدام مخزن ذاكرة مؤقت وإظهار ذلك للمستخدم. - [ ] التحقق من متطلبات Linux keyring وتشغيل تخزين الجلسة الأصلي، وبناء macOS وLinux على منصات فعلية. - [x] تثبيت مكوّن C++ ATL في Visual Studio Build Tools؛ تحقق وجود `atlstr.h` ونجح `flutter build windows --debug` (2026-10-03). - تصميم بيانات المستخدمين والمحادثات والمرفقات ونسخ الإجابات مع ملكية واضحة وفهارس وترحيلات قاعدة بيانات. - SQLite مناسب لنسخة محلية أحادية الجهاز. عند تشغيل خدمة لعدة مستخدمين/أجهزة، ننتقل إلى PostgreSQL، مع نسخ احتياطية وسياسة حذف وتصدير. - تخزين الملفات الكبيرة في مساحة ملفات منظّمة، وحفظ بياناتها الوصفية ومراجعها في قاعدة البيانات، لا في سجل الرسائل ككتل ضخمة. ## المرحلة 4 — نواة الوكيل ### دورة التنفيذ 1. [x] يستقبل الوكيل هدفًا وسياقًا ومجموعة الأدوات المسموح بها. 2. [x] يقرر Gemma عبر استدعاء الأدوات الأصلي هل يجيب مباشرة أو يطلب الحاسبة/بحث مساحة العمل. 3. [x] يتحقق الخادم من اسم الأداة ومدخلاتها، وينفذ استدعاءً واحدًا فقط للحاسبة المحدودة أو البحث المقيد بمساحة العمل. 4. [x] يعيد الخادم نتيجة الأداة إلى Gemma لإنتاج الجواب النهائي، مع إظهار الأداة والملفات المقروءة في واجهة الوكيل. 5. [x] يسجل المسار والحالة والمدة ومعرّف العملية دون نص السؤال أو محتوى الملفات. 6. [x] إظهار انتقالات خطوات الوكيل أثناء التنفيذ، واختيار مساحة العمل من التطبيق قبل تفعيل الكتابة. (2026-10-02: بث SSE لمراحل التحقق، واختيار الأداة، والبحث، وصياغة الرد؛ تحقق API وFlutter.) ### سلم الأدوات والصلاحيات 1. [x] قراءة فقط أولية: الحاسبة والبحث النصي واسترجاع مقتطفات من مساحة العمل. يختار المستخدم مجلدًا من التطبيق أو يستخدم الخادم مجلده المضبوط؛ تمنع القائمة الملفات المخفية والمجلدات المستثناة. 2. [x] قراءة ملف كود محدد: عند ذكر مساره النسبي مثل `app/model_provider.py` في وضع الملفات، يقرأ الوكيل مقتطفًا أكبر (حتى 12,000 حرف) ويعيد اسم الملف. (2026-10-01: تجربة API حية أعادت جوابًا عن الملف المحدد وأعادت مساره وحده كمصدر.) 3. [x] اختيار مساحة العمل/الملف من نافذة التطبيق واستعراض قائمة الملفات قبل سؤال الوكيل. تعرض الواجهة الملفات النصية المدعومة وتسمح بتحديد 3 كحد أقصى؛ يرسل التطبيق المسارات النسبية، ويتحقق الخادم منها داخل المجلد المحدد. فُحص endpoint حيًا واستُبعد `.env`؛ ولا يرسل قائمة الملفات أو محتواها للتخزين. 4. [x] كتابة مضبوطة: إنشاء وتعديل ملفات داخل مساحة العمل فقط، مع معاينة diff وتأكيد المستخدم قبل التطبيق. (2026-10-02: لا كتابة عند المعاينة؛ الرمز مؤقت ولمرة واحدة، وفحص المسار والبصمة يعاد قبل التطبيق؛ اجتازت اختبارات Python واختبارات واجهة Flutter، وأُعيد تشغيل Windows Debug وFastAPI بالتغييرات.) 5. أوامر تطوير: تشغيل أوامر محددة في بيئة معزولة وبمهلة وحدود موارد، ومع موافقة لكل أمر في البداية. (2026-10-03: تحقق Windows 10 Pro 19045، Intel i7-6600U مع virtualization firmware مفعّل، RAM 15.9GB والمتاح وقت القياس 5.2GB، و40.8GB مساحة فارغة على C:. لا يوجد `WindowsSandbox.exe` أو Docker. استعلاما WSL أعادا شاشة المساعدة فلم يثبتا توفر توزيعة. فحص Windows Sandbox يحتاج مسؤولًا؛ محاولة DISM مرتفعة الصلاحية انتهت بخطأ `0xc0000142` ولم تغيّر إعدادًا. أُعدّ prototype محلي بـAppContainer وJob Object (`scripts/appcontainer_probe.cpp`): 512 MiB، حد 8 عمليات، مهلة 30 ثانية، وإنهاء شجرة العمليات عند إغلاق الـJob. في تشغيل Windows بأذونات مناسبة نجح smoke test: `cmd.exe` عمل داخل الحاوية؛ مُنع من قراءة ملف Temp للمضيف ومن إنشاء ملف خارجه، بينما نجح في الكتابة والقراءة من مجلد العمل المعزول. نُسخ `README.md` من المشروع إلى الحاوية ثم استخدم `curl.exe file://` لنسخه منها؛ النسخة تطابقت بايتًا ببايت. اختُبر `curl.exe` داخل الحاوية (`--version` exit 0)، وفشل الوصول إلى `/health` على `127.0.0.1:8100` بمهلة curl 28 رغم نجاح endpoint من المضيف؛ هذا فحص اتصال محلي فقط، وليس اختبارًا للإنترنت العام. إعداد AppContainer بلا قدرات شبكية. الجلسة المقيدة لدى Codex فشلت في إنشاء الملف الشخصي بـ`0x80070005`، بينما نجح الفاحص عبر جلسة التنفيذ المسموحة؛ يحتوي `scripts/run_appcontainer_probe.ps1` على build وتشغيل وتنظيف مؤقت قابل للتكرار. ما زال هذا prototype غير مدمج في الوكيل ولا توجد أوامر عامة قابلة للتنفيذ. التالي: تجربة نسخ ملفات محددة وآمنة من مساحة يختارها المستخدم مع حدود حجم واستثناء الأسرار والروابط الرمزية، ثم إرجاع المخرجات/diff والتحقق من الموارد والمهلة، وبعدها دمج قائمة أوامر مسموحة وموافقة صريحة في API والواجهة. [AppContainer isolation](https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-isolation)، [تنفيذ AppContainer](https://learn.microsoft.com/en-us/windows/win32/secauthz/implementing-an-appcontainer)، [Job Objects](https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects).) - [x] تجهيز Snapshot محدود لملفات يختارها المستخدم (`app/execution_snapshot.py`): يفرض جذر workspace المعتمد للحساب، حتى 50 ملفًا، 512KB لكل ملف و10MB إجماليًا، ويقبل الامتدادات المدعومة فقط. يرفض المسارات المخفية/المستثناة/الخارجة، والروابط الرمزية، وأسماء أجهزة Windows المحجوزة، وأسماء الملفات/المحتوى التي تكشف مفاتيح معروفة أو قيم اعتماد مباشرة؛ وينسخ إلى مجلد مؤقت مع SHA-256 لكل ملف. 7 اختبارات snapshot و7 اختبارات workspace ناجحة (2026-10-03). فحص الأسرار محافظ وليس ماسحًا شاملًا ولا يغني عن المراجعة. مرّ الـSnapshot عبر driver تطوير تجريبي إلى broker، لكنه غير مربوط بعد بطلب API أو منتقي ملفات المستخدم. - [x] تشغيل Python من ملفات Snapshot في AppContainer: نُسخت ملفات التشغيل القياسية وDLLs من Python 3.14 (33,627,970 بايت/631 ملفًا، دون `site-packages`)، وشغّل broker ملف `.py` الموجود داخل Snapshot وأعاد ملف نتيجة؛ تحقق الخروج `0`. يلتقط stdout/stderr عبر pipe ويخزن أول 64KB فقط: اختبار خرج 70KB أعاد 65,536 بايت وعلامة `truncated=true`. (2026-10-03: أعيد تشغيل probe كاملًا؛ fixture كتب بايتات stderr غير صالحة UTF-8، ونجح التحويل باستبدالها بـU+FFFD بدل فقد المخرجات. انتهى التشغيل `shell_exit=0`، وظلت نتيجة الملف داخل الحاوية.) الملف المشغل fixture فقط وليس كودًا اختاره المستخدم. - [x] اختبار مراقبة مساحة بيانات الحاوية، لكن النتيجة **غير صالحة كحد تخزين يفرضه النظام**: في تجربة تشخيصية أقدم تجاوز القياس الهدف ووصل إلى نحو 176MiB. (2026-10-03: كتابة متزامنة أوقفت العملية عند `ERROR_DISK_FULL` بعد رصد 134,273,312 بايت مقابل حد 134,217,728. إعادة تحقق على الحالة الحالية في 2026-10-03 تجاوزت الحد نفسه وسجلت 136,637,390 بايت، أي 2,419,662 بايت فوق الهدف قبل الإيقاف. توجد تجربة أقدم تجاوزت الهدف بنحو 645KB. هذه مراقبة دورية من broker وليست حصة قرص صلبة، فلا تكفي لتشغيل شيفرة عامة متعددة المستخدمين.) قاس probe مالك ملف النتيجة داخل الحاوية: `python_result_owner_is_host_user_sid=true` و`python_result_owner_is_appcontainer_sid=false`؛ لذلك حصة NTFS حسب المستخدم ستجمع ملفات المستخدم المضيف أيضًا، ولا تعزل مساحة كل تشغيل. توثيق Microsoft يربط رسوم الحصة بـSID مالك الملف، ويشرح أن الحصة الصلبة تمنع مساحة إضافية عند بلوغها. إرفاق VHD يتطلب `SE_MANAGE_VOLUME_PRIVILEGE`؛ تجربة VHDX المؤقتة السابقة أُلغيت عند UAC، ومحاولة تشغيل PowerShell المرتفع أخيرًا فشلت بـ`0xc0000142` قبل إنشاء القرص؛ لم يتغير أي قرص. فحص الحالة الحالية لم يجد `vmcompute`/`vmms` أو أدوات Hyper-V، وأوامر قراءة ميزات Windows فشلت بـCOMException. المسار التالي يحتاج تثبيت/تهيئة عزل نظامي أو عاملًا مخصصًا بحصة حقيقية؛ تبقى أوامر المستخدم العامة معطلة حتى يثبت حد قابل لإعادة الاستخدام. [NTFS disk quotas](https://learn.microsoft.com/en-us/windows/win32/fileio/disk-quota-limits)، [AttachVirtualDisk privileges](https://learn.microsoft.com/en-us/windows/win32/api/virtdisk/nf-virtdisk-attachvirtualdisk). - [ ] إكمال الربط الإنتاجي بعد تأمين حصة تخزين يفرضها نظام التشغيل: endpoint مصادق عليه لخطة أمر allowlist وموافقة مرة واحدة مرتبطة بالمستخدم والمساحة والبصمات والمهلة؛ نسخ الملفات المحددة من API إلى broker، capture موحد وآمن للنتيجة، عرض الموافقة والحالة والمخرجات في Flutter، ومعاينة diff قبل أي تطبيق. prototype لم يُدمج في API أو الواجهة ولا يسمح حاليًا بتنفيذ أوامر المستخدم. 6. لا وصول عام إلى القرص، ولا أوامر مدمرة أو نشر خارجي دون موافقة صريحة. كل أداة لها مخطط مدخلات ومخرجات واختبارات وسجل تدقيق. ### كودكس للبرمجة - مساحة مشروع يختارها المستخدم، مع فهرسة نصية أولًا ثم استرجاع المقاطع الملائمة للسؤال. - أدوات مقترحة: قراءة ملف، بحث نصي، قائمة ملفات، إنشاء/تعديل ملف عبر patch، عرض diff، تشغيل اختبارات وأوامر allowlist. - التنفيذ يتم في مجلد المشروع المحدد، مع حفظ التغييرات في Git وإظهارها للمستخدم قبل اعتمادها. - نبدأ بوكيل خطوة بخطوة (دورة واحدة واستدعاء أداة واحد)، ثم نرفع عدد الخطوات تدريجيًا بعد قياس الدقة والأمان. - [x] تعريف عقد JSON موحّد للأدوات الحالية عبر `GET /v1/agent/tools`، مع بيان صلاحية كل أداة وحدودها وآثارها الجانبية، وسجل تدقيق SQLite عبر `GET /v1/agent/audit` يسجل المسار والطريقة والحالة والمدة فقط دون السؤال أو محتوى الملف. أضيف معرّف تدقيق في `X-Agent-Audit-ID`. - [x] حلقة الوكيل عبر Ollama native tool calling: اختيار تلقائي بين إجابة مباشرة أو الحاسبة أو `search_workspace`؛ عند طلب البحث الصريح يقرأ الخادم أولًا من الجذر المخصص، ويتعامل مع المقتطفات كبيانات غير موثوقة. تحقق الخادم من قائمة الأدوات الفعلية والمدخلات وصلاحيات المهارة في كل خطوة، وينفذ حتى 3 أدوات بالتتابع ثم يعيد النتائج إلى Gemma لصياغة الإجابة. اقتراح تغيير الملف يوقف الأدوات عند معاينة diff، والكتابة ما زالت بموافقة صريحة. يعرض Flutter تسلسل الخطوات. تحقق 2026-10-03: اختبارات الوكيل 18/18 ومجموعة Python كاملة 83/83؛ تحليل Flutter بلا ملاحظات واختباراته 15/15 من الجولة السابقة. عند البحث الصريح لا يعرض الخادم أدوات بحث أخرى تكرر الإجراء، ويطلب من النموذج الإجابة مباشرة من المقتطفات؛ ويرفض أي أداة غير معروضة. النتيجة القرائية/الحسابية المطابقة تُعاد من مخبأ خاص بالطلب دون تنفيذ مجدد، ثم يطلب الخادم إنهاء الإجابة. إذا طلب المستخدم ضرب ثابت برمجي رقمي واحد جرى استخراجه من نتائج البحث، يحسب الخادم التعبير عبر المحلل الحسابي المحدود ويرجع الملف والخطوتين؛ الاختبار الحي أعاد `3 × 7 = 21` لـ`MAX_AGENT_TOOL_CALLS = 3`. اقتراح الملف لم يتغير: يتوقف عند معاينة diff، وتظل الموافقة مطلوبة قبل الكتابة. - [x] تنفيذ طلب الحاسبة الصريح بتعبير رياضي بسيط عبر المحلل المحلي المقيد، مع تطبيع `× ÷ −`؛ يمنع الاعتماد على قرار النموذج أو صيغة العامل وحدهما. اختبارات الوحدة وتجربتا API على Gemma وQwen تحققتا من الناتج واختيار الحاسبة (2026-10-02). هذا لا يضيف تنفيذ أوامر عامة. - [x] إعادة تشغيل جلسة Flutter Windows Debug على الواجهة المعدّلة: أُعيد تشغيل التطبيق بعد التغييرات وتأكدت رسالة `Restarted application` (2026-10-02). ما زال التوزيع كمثبت مستقل مرحلة لاحقة. ## المرحلة 5 — المعرفة والمهارات - [x] أساس RAG نصي/برمجي محلي: فهرسة ملفات UTF-8 التي يختارها المستخدم صراحةً من مساحة العمل، تقطيع مع تداخل، تخزين SQLite FTS5 ومتجهات محلية اختيارية، واسترجاع المقاطع مع المسار بدمج reciprocal-rank fusion. API يفرض حد 20 ملفًا و2 ميغابايت ويربط النتائج بمساحة العمل والمستخدم المحلي؛ زر Flutter يفهرس الملفات المحددة حتى 3 دفعةً واحدة. إذا غاب نموذج التضمين يبقى FTS5 عاملًا. تجربة API حقيقية بثلاثة أسئلة معاد صياغتها أعادت الملف الصحيح أولًا 3/3؛ العينة الصغيرة لا تكفي لقياس جودة عامة. - [x] تثبيت Granite Embedding 278M محليًا للاختبار (562MB من Ollama، متعدد اللغات بما فيها العربية، Apache 2.0)؛ تحقق `/api/embed` الفعلي أعاد 768 بُعدًا للنص العربي والإنجليزي. يضبط اسم النموذج بـ`KNOWLEDGE_EMBEDDING_MODEL`. - [x] فهرسة PDF الرقمي من مساحة العمل باستخدام محلّل pypdf المحدود ومراعاة أرقام الصفحات، وإدراجه في منتقي الملفات؛ اختبار تكاملي يثبت القائمة والفهرسة والبحث، وتجربة API حيّة على ملف مؤقت أثبتت الفهرسة والبحث والحذف. - [x] تحقق تكاملي لفهرسة PDF مختلط (صفحات رقمية وممسوحة)، واسترجاع نص كل نوع عبر FTS5، ثم حذف السجل؛ 1 اختبار API متكامل ناجح (2026-10-02). - [x] حذف مستندات محددة من فهرس SQLite عبر API وزر الواجهة. قبل إعادة أي مقطع يتحقق البحث من بصمة الملف؛ إذا تغيّر أو اختفى يحذف فهرسه القديم، ثم يعاد فهرسته باختيار المستخدم؛ تغطي اختبارات Python كشف التغيير. - [x] فحص استرجاع أولي من 11 سؤالًا عربيًا وإنجليزيًا على API حي. ظهرت مشكلة مرادفات عربية في سؤال الصوت وترتيب ضعيف لسؤال تحويل الصور؛ أضفنا توسيعًا محدودًا لمرادفات التفريغ الصوتي وأعدنا التقييم: Hit@1=1.0 وHit@3=1.0 وMRR=1.0 ومعدل ظهور الدليل=1.0. قبل التحسين كان Hit@1=0.818. حُذفت ملفات التقييم المؤقتة من الفهرس بعد القياس. النتائج: `retrieval_2026-10-02_140339.json` و`retrieval_2026-10-02_140538.json`. تبقى العينة مصطنعة وصغيرة، فلا تثبت جودة عامة. - [x] قياس إضافي على 9 أسئلة عن ملفات الكود الفعلية (`workspace.py`, `knowledge.py`, `pdf_documents.py`, `main.py`). كشف التقييم أن تكرار مقاطع الملف الواحد يزاحم مصادر أخرى؛ حدّثنا البحث لجلب مجموعة أوسع ثم توزيع حتى مقطعين لكل ملف. بعد التعديل: Hit@1=0.667، Hit@3=1.0، MRR=0.833، وظهور الدليل=1.0. النتائج في `retrieval_2026-10-02_141132.json` (قبل التعديل) و`retrieval_2026-10-02_141337.json` (بعده). العينة صغيرة واختبارها معجمي؛ الدقة الدلالية وجودة الإجابة لم تُقاسا. - [x] جولة تحسين استرجاع المقاطع العميقة على 11 سؤالًا من المجموعة المحلية (2026-10-03): توسيع محدود لمرادفات صلاحيات المهارات بالعربية والإنجليزية، ورفع سقف النتائج من 5 إلى 8 مع إبقاء حد 4 مقاطع لكل ملف لحماية تنوع المصادر. على API محلي تجريبي بقاعدة معزولة: `Hit@1=1.0`, `Hit@3=1.0`, `MRR=1.0`, وظهور الدليل `11/11`؛ تقرير `evals/results/retrieval_2026-10-03_160000.json`. اجتازت اختبارات قاعدة المعرفة `12/12`. - [x] توسيع الحزمة وإضافة جواب الوكيل من الأدلة المفهرسة (2026-10-03): أضيف دليل تقني بطول 15.7 كيلوبايت فيه المعلومة المستهدفة في المقطع 17 وPDF نصي؛ حفظ المشغّل اختياريًا إجابات الوكيل ومصادرها للمراجعة دون منح درجة آلية. الجولة الأولى على 13 حالة أعادت `Hit@1=1.0`, `Hit@3=1.0`, `MRR=1.0`, وظهور الدليل `13/13` (`evals/results/retrieval_extended_2026-10-03.json`). بعد إصلاح وزن OCR المحلي المعطوب وإعادة تشغيله دون تنزيل، أضيف PDF ممسوح فعلي إلى المجموعة؛ على API التطبيق الحالي بقاعدة SQLite الحية المؤقتة ثم حذف عناصرها بعد القياس: `Hit@1=1.0`, `Hit@3=1.0`, `MRR=1.0`, وظهور الدليل `14/14` (`evals/results/retrieval_extended_14_2026-10-03.json`). جواب الوكيل على PDF الممسوح استخرج الموعد `17 October 2026` وذكر مصدره (`evals/results/retrieval_scanned_pdf_agent_2026-10-03.json`). تجربة EasyOCR المباشرة والـAPI استخدمتا أوزانًا محلية فقط؛ النسخة التالفة محفوظة احتياطيًا بجانب الوزن المُصلح. - [ ] متابعة التقييم على ملفات طويلة وPDFات متنوعة وأسئلة جديدة، وجمع مراجعة مستقلة لجودة إجابات النموذج فوق السياق المسترجع. النتائج الحالية fixtures صغيرة ومصطنعة؛ الدرجات تصف هذه الحالات ولا تثبت جودة عامة. مراجعة إجابات الوكيل محفوظة لكن لا توجد درجات مستقلة من المستخدم بعد. - [x] مهارات محلية أولية قابلة للاختيار من واجهة وضع الوكيل: شرح الكود، مراجعة الكود، وخطة اختبارات. تعرض `/v1/agent/skills` وصف كل مهارة وأدواتها؛ تُحقن التعليمات الموثوقة في سياق الوكيل وتُفلتر قائمة الأدوات، ويرفض الخادم استدعاء أداة خارج صلاحيات المهارة. لمهارة مراجعة الكود معاينة فقط ولا تطبيق مباشر. اجتازت اختبارات الصلاحيات والواجهة؛ يبقى تقييم دقة كل مهارة على أمثلة أكثر قبل اعتمادها افتراضيًا. - [x] قراءة رابط عام محدد عبر `POST /v1/web/read`: استخراج نص HTML الثابت وتمريره إلى Gemma المحلية للإجابة مع إرجاع الرابط والعنوان. - [x] بحث ويب متعدد المصادر تجريبي عبر DuckDuckGo بلا مفتاح API: اختيار نطاقات مختلفة، محاولة جلب الصفحات العامة، تلخيص بالنموذج المحلي مع روابط المصادر، ووسم المقتطفات عند تعذر فتح الصفحة. (2026-10-01: استجابة حية أعادت ملخصًا ومصدرين مختلفين عبر FastAPI/Gemma.) أضيف زمن جلب إجمالي وزمن لكل مصدر إلى الاستجابة لمساعدة تشخيص المصادر البطيئة؛ اختبارات الحجب ومزوّد رسمي اختياري ما زالت لاحقًا. - [x] اختبار أولي لمخرجات المهارات وتقييد الأدوات، بما فيها محاولة مزود النموذج طلب أداة غير مسموحة؛ تحقق حي من API أعاد ملخص ملف مختار تحت مهارة شرح الكود. توسيع مجموعة التقييم والقياس عبر نماذج متعددة ما زال لاحقًا. ## المرحلة 6 — الوسائط - الصوت: حاليًا Groq خارجي للتفريغ. Gemma 4 E2B تدعم الصوت بحسب [بطاقة النموذج](https://ai.google.dev/gemma/docs/core/model_card_4)، لكن مسار إرسال الصوت إليها/نسخ محلي لم يُنفّذ؛ Whisper محلي لاحقًا. - [x] الصور: اختيار ورفع PNG/JPG/JPEG/WebP (حتى 3 صور) إلى `POST /v1/agent/images/analyze` محليًا. مع تثبيت `requirements-ocr.txt` يقرأ EasyOCR النص العربي/الإنجليزي ويغذي نصه والصورة معًا إلى نموذج الرؤية. تجربة اللقاء عبر FastAPI وMinistral المحلي أعادت HTTP 200 وتحليلًا لحقول الصورة؛ ترتيب صفوف RTL/LTR جمع العنوان العربي. بقي متوسط الثقة 0.625 وزمن OCR ~71 ثانية بعد تهيئة أولى ~45 ثانية على CPU. حد OCR مليونا بكسل للصورة، وتحليل الرؤية المحلي مسار رجوع عند غياب الحزمة أو الأوزان. راجع النص قبل استخدامه، وراجع ترخيص الأوزان قبل التوزيع التجاري. - [x] تحليل وفهرسة PDF رقمي أو ممسوح أو مختلط. يحدد الاستخراج حالة كل صفحة؛ النص الرقمي يحفظ ترتيب الصفحة، والممسوح يمر محليًا إلى OCR والرؤية. الحدود: 30 صفحة للملف، 3 صفحات ممسوحة للطلب، 2 مليون بكسل و4MB للصفحة، 8MB إجمالي صور، و8MB لملف PDF. في 2026-10-03، رفض EasyOCR الوزن المحلي `arabic.pth` لبصمة غير مطابقة؛ استُعيد الوزن الصحيح من أرشيف موجود مسبقًا مع حفظ النسخة القديمة، ثم نجح OCR محليًا والـAPI في قراءة موعد من PDF ممسوح دون تنزيل. عند التوزيع يجب إرفاق تراخيص PDFium ومراجعة تراخيص أوزان OCR. - تصميم الواجهة لتوضيح ما إذا عولج الملف محليًا أم أرسل إلى مزوّد خارجي. ## المرحلة 7 — تقييم النماذج والتدريب - [x] إنشاء مجموعة أولية من خمسة أسئلة عربية/برمجية مع معايير مراجعة بشرية وفحوص شكل/قيمة محدودة، ومشغّل يسجل الأجوبة ووقت كل طلب واسم أداة الوكيل في JSON. تجربة واحدة على Gemma 4 E2B وQwen 2.5 1.5B وحُفظت النتائج في `evals/results/` (2026-10-02). - تكرار التقييم مع إجابات مرجعية ومراجعين/درجات بشرية، وقياس استهلاك الذاكرة واعتماد مقارنة قابلة للتكرار. (2026-10-03: أُعيد التشغيل بمعايير أوسع: Gemma وQwen أكملتا 5/5 طلبات بلا أخطاء؛ Gemma مرّرت 9/9 فحوص شكلية، وQwen 8/9، ومتوسط الزمن 14.77 مقابل 6.25 ثانية. إجابة Qwen عن SQLite كانت غير دقيقة رغم اجتياز فحص وجود ثلاث نقاط، ما يثبت أن هذه الفحوص لا تقيس صحة المعنى. التقريرين النهائيين `evals/results/gemma4_e2b_2026-10-03_183058.json` و`evals/results/qwen2.5_1.5b-instruct-q4_K_M_2026-10-03_183140.json`. التقييمات السابقة المؤرخة `175827` و`180307` تستخدم فحوصًا أضيق. أُضيف `scripts/capture_ollama_runtime.ps1`: أظهر `/api/ps` حجم Gemma المحمّل 6,733,158,152 بايت وQwen 1,169,980,128 بايت، و`size_vram=0` لكليهما. اللقطتان `evals/results/ollama_runtime_2026-10-03_180846.json` و`...180934.json` لحظيتان وليستا peak؛ لا تربطان كل PID بالنموذج ولم تتوفر قراءة إجمالي/متاح RAM بسبب رفض CIM. لم تُسجل درجات بشرية بعد؛ تبقى مراجعة بشرية، قياس ذروة RAM/VRAM موثوق ومتكرر، وجولات إضافية للمقارنة.) الجولة السابقة كانت Gemma 8/10 بمتوسط 16.32 ثانية وQwen 5/10 بمتوسط 8.93 ثانية. أُصلحت منذها مشكلة الحساب المباشر مقابل الأداة وصيغة Qwen الرياضية؛ مشغّل التقييم يستخدم جلسة loopback مؤقتة ويلغيها. - اختيار النماذج حسب الرخصة، الجودة، اللغة، دعم الأدوات، كمية VRAM، وإمكانية التشغيل التجاري. لا نعتمد وصف «مفتوح» وحده كإثبات سماح تجاري؛ نراجع الرخصة الرسمية لكل إصدار. - تحسين أولي عبر prompts وRAG والأدوات؛ هذه غالبًا تعالج نقص المعرفة أو القدرة على الفعل دون تغيير أوزان النموذج. - عند توفر GPU مناسب: تجربة LoRA/QLoRA على بيانات مرخصة ومنقحة، ومقارنة النتائج بالمجموعة المرجعية قبل اعتماد adapter. - تدريب نموذج أساسي من الصفر خارج نطاق العتاد الشخصي المعتاد؛ يحتاج بيانات وحوسبة وبنية تدريب كبيرة، ولا يكون خطتنا الأولى. ## المرحلة 8 — تطبيق Windows ثم التوزيع - [x] تشغيل Flutter Windows في وضع Debug على الجهاز؛ أول بناء اكتمل، ثم أُعيد تشغيل التطبيق بعد تثبيت النموذج المحلي الجديد. لم تنتج بعد نسخة Windows قابلة للتثبيت. - حسم طريقة توزيع خدمة Python وOllama/النماذج وإدارتها، دون تضمين أوزان ضخمة داخل التطبيق نفسه. - توقيع التطبيق، تحديثات واضحة، سجلات تشخيص لا تكشف الأسرار، وإعدادات حذف البيانات والنسخ الاحتياطي. - قبل الاستخدام التجاري: مراجعة تراخيص النماذج والاعتماديات (بما فيها إشعارات PDFium المضمّنة)، الخصوصية، المصادقة، حدود الاستخدام، النسخ الاحتياطي، والتحديثات الأمنية. ## إضافات قبل توسيع الوكيل - [x] إلغاء التوليد وإظهار المدة وحالة الاتصال ورسالة الخطأ (2026-10-01: اختبارات Cubit وواجهة ناجحة). - [x] حفظ نسخ إعادة التوليد والتنقل بينها (2026-10-01: اختبار واجهة وAPI وقاعدة البيانات ناجح)؛ تجربة أفضل للأخطاء وإعادة المحاولة ما زالت لاحقة. - [x] إكمال طبقة مزوّد Ollama وقائمة قدرات النماذج المثبتة قبل توسيع أدوات الوكيل؛ إضافة مزودين آخرين ما زالت لاحقة. - [x] حفظ إعداد التنبيه وعنوان API والنموذج وتفضيل المظهر الداكن في إعدادات محلية على Windows والويب؛ لا تحفظ المفاتيح السرية. اختبار Cubit يثبت الاستعادة، واختبار واجهة يثبت تبديل السمة؛ تحليل Flutter و9 اختبارات وبناء الويب ناجحة (2026-10-02). - [x] إكمال امتدادات Markdown (جداول وقوائم متداخلة ومربعات مهام GFM)؛ الأساس والروابط الآمنة ونسخ كل كتلة منفردة أصبح جاهزًا. - [x] حزمة تقييم أولية بالعربية والبرمجة ونتائج baseline على نموذجين؛ تكرار التشغيل وقياس الذاكرة والتحقق البشري الأوسع ما زالت لاحقة. - [x] نواة وكيل الملفات: تقدم الخطوات عبر SSE، ومعاينة diff وموافقة صريحة قبل تطبيق الكتابة داخل الجذر المخصص للحساب. اختبار API مباشر في 2026-10-03 أكد اختيار أداة الحاسبة وإرجاع النتيجة الصحيحة. الخطوة التالية للوكيل هي أوامر تطوير محددة داخل عزل نظام تشغيل قابل للتحقق؛ لم يُفعّل تشغيل الأوامر العامة. ## ترتيب التنفيذ القادم 1. [x] التحقق من إجراءات المحادثة الجديدة على Windows Debug (2026-10-01): تشغيل API وGemma وGroq، اختبار صوت من الميكروفون حتى التفريغ والرد والحفظ في SQLite، نجاح اختبار الواجهة على نافذة 800px ونجاح `flutter analyze`. 2. [x] حفظ نسخ الإجابات وترحيل SQLite (2026-10-01): ترحيل قاعدة قديمة مع الحفاظ على الرسائل، وحفظ النسخ واسترجاع النسخة المختارة عبر PUT/GET؛ اجتاز اختبارا Python واختبار API حي على قاعدة التطبيق ثم حذف سجل الاختبار. اختبارا Flutter نجحا، و`flutter analyze` بلا ملاحظات. شُغّلت نسخة Windows Debug باسم Mithqal AI واتصلت الخدمة بـGemma؛ اختبار API للمحادثة أعاد ردًا عربيًا. 3. [x] حالة النموذج والمدة والخطأ وإيقاف التوليد (2026-10-01): اختبار إلغاء الرد الجزئي وإلغاء إعادة التوليد قبل أول رمز مع الحفاظ على الإجابة السابقة، واختبار زر الإيقاف بالواجهة؛ `flutter analyze` و5 اختبارات Flutter ناجحة، وWindows Debug يعمل بعد hot restart. 4. [x] إضافة طبقة مزود النموذج واكتشاف النماذج (2026-10-01): عقد موحد للطلب الكامل والبث والقائمة، واستخدامه في المحادثة والوكيل وقراءة مساحة العمل والويب؛ Ollama هو المزوّد المنفذ حاليًا. تحقق حي من `/health` و`/v1/models` وطلب محادثة باستخدام Gemma. 5. [x] إكمال Markdown للمرحلة 1: جداول قابلة للتمرير، قوائم متداخلة، ومربعات مهام GFM؛ التحليل واختبارات الواجهة الثلاثة ناجحة وبناء Windows Debug نجح. 6. [x] تشغيل جلسة Windows Debug نظيفة بعد إصلاح مجلدي روابط إضافات `record` المؤقتة؛ أُعيد بناء وتشغيل نسخة التطبيق الحالية. (2026-10-03: بعد تغييرات الحسابات والاستعادة اكتمل `flutter run -d windows --no-pub`، وبقيت جلسة Flutter متصلة؛ `/health` أعاد `ok` مع Gemma 4. لم تتوفر خدمة فحص نافذة Windows بصريًا.) 7. [x] اختيار مساحة عمل وعرض الملفات المدعومة وتحديد ملفات للسؤال؛ التحقق من المجلدات والملفات على الخادم. 8. [x] إظهار انتقالات تقدم الوكيل أثناء العمل وربطها بحالات التنفيذ الفعلية عبر SSE؛ اختبار API حي لمسار الحاسبة. (2026-10-03: عبر FastAPI على 8100 وجلسة loopback، اختار Gemma 4 أداة `calculator` لمهمة 17×23، سجّل خطوة واحدة `completed` وأعاد 391.) 9. [x] معاينة تغييرات الملفات عبر diff، ثم موافقة صريحة قبل الكتابة داخل مساحة العمل فقط (2026-10-02: endpoint ظهر في OpenAPI بعد إعادة تشغيل FastAPI؛ اختبارات Python وFlutter ناجحة، وشُغلت واجهة Windows Debug مجددًا مع مسار التأكيد.) 10. عزل أوامر التطوير المحددة وحدود مواردها وسجلها؛ لا تفعيلها قبل إعداد بيئة عزل قابلة للتحقق. 11. [x] توحيد أخطاء HTTP/التحقق ومعرّفات الطلبات، واختبارات عقد API والمهلات والإلغاء؛ 17 اختبار Python ناجح بعد إضافة اختبارات PDF (2026-10-02). [x] حفظ إعدادات API والنموذج والتنبيهات محليًا (اختبار استعادة وWindows Debug وWeb build). [x] عرض قدرات Ollama المثبتة في API والقائمة (تحقق حي من 4 نماذج). [x] تفضيل المظهر الداكن: محفوظ محليًا، واستعادة Cubit وتبديل السمة مختبران، وبناء الويب ناجح. 12. مصادقة وهوية متعددة المستخدمين قبل أي نشر شبكي، ثم PostgreSQL عند الحاجة إلى خدمة متعددة الأجهزة. 13. تحسين البحث والمهارات وRAG محلي للملفات وPDF الرقمي والممسوح والمختلط (حتى 3 صفحات ممسوحة في طلب الفهرسة) — منجز أساسًا. بقي تحسين الاسترجاع الدلالي ومعايرة OCR وخيار نسخ صوت محلي عند ملاءمة الموارد. 14. بناء مجموعة تقييم عربية/برمجية ثابتة، ثم دراسة LoRA/QLoRA فقط مع بيانات مرخصة وعتاد مناسب. 15. تجهيز وتوقيع مثبت Windows وإدارة Ollama والنماذج والتحديثات والنسخ الاحتياطي؛ مراجعة التراخيص والأمان قبل الاستخدام التجاري. ## شروط الانتقال بين المراحل - كل قدرة جديدة لها عرض واضح للمستخدم، حدود صلاحيات، وسجل مفهوم. - لا تُفعل أداة كتابة أو تنفيذ قبل وجود تحقق خادمي من المسارات والمدخلات. - لا نعتبر نجاح HTTP كافيًا: نتحقق من النتيجة في الواجهة ومن استمرار حفظ البيانات بعد إعادة فتح التطبيق. - قبل الإنتاج، نستبدل هوية التطوير ونراجع المصادقة والترخيص والأسرار والنسخ الاحتياطية.