Continue roadmap: local TLS and agent review preparation

This commit is contained in:
Hamza Ayed
2026-10-04 00:35:05 +03:00
parent 379098f3d6
commit d29275043a
28 changed files with 3226 additions and 47 deletions
+15 -7
View File
@@ -2,15 +2,21 @@
هذه خارطة تنفيذ تدريجية للمشروع الحالي. التطبيق اليوم Flutter، وواجهة الخدمة FastAPI، والتخزين SQLite، وتوليد النص عبر خادم Ollama محلي. لا نبدأ بتدريب نموذج من الصفر؛ نبني منتجًا قابلًا لتبديل النموذج ونقيس كل مرحلة قبل توسيع الصلاحيات.
## الحالة الحالية — 2026-10-03
## الحالة الحالية — 2026-10-04
- تحقق واجهة تسجيل المشاريع على Windows: كانت العملية المفتوحة تستخدم ملف Debug أقدم من مصدر Flutter، لذلك لم يظهر زر «تسجيل مشروع جديد». اختبارات الواجهة 12/12 واختبارات حالة حفظ/فتح/إزالة المشاريع 7/7، و`flutter analyze` بلا ملاحظات. أُعيد بناء Windows Debug من المصدر الحالي وشُغّل التطبيق من الملف الناتج؛ بقي FastAPI على `127.0.0.1:8000` بحالة `ok` وGemma 4 E2B. سجل «مشاريعي» يحفظ مسارات المجلدات محليًا؛ لا يعني ذلك بعدُ تنفيذ أوامر المشروع، وهو ما يظل مشروطًا بعزل نظام التشغيل.
- متابعة التقييم على ملفات المشروع الفعلية: أضيفت مرادفات `permission/permissions/صلاحية/صلاحيات` لرموز صلاحيات الأدوات، فأصبح المقطع العميق `tool_name not in selected_skill.allowed_tools` يظهر ضمن نتائج السؤال الذي كان يفشل سابقًا؛ تقييم الاسترجاع 9/9 أدلة (`evals/results/retrieval_project_permission_synonym_2026-10-03.json`). هذا يقيس العثور على المصدر لا جودة صياغة Gemma. أضيف حدّ سياق لأربع مقاطع وإزالة التكرار وتوزيع المقاطع على ملفات مختلفة. في 2026-10-03 أُعيد تشغيل FastAPI من الشفرة الحالية بعد اكتشاف أن الخدمة الحية كانت أقدم من تعديل السياق. على الخدمة الجديدة، أعاد التقييم الكامل 11/11 ملفًا مستهدفًا في المرتبة الأولى ووجد الدليل 11/11 (`evals/results/retrieval_project_agent_fresh_api_2026-10-03.json`). مراجعة يدوية أولية لإجابات الجولة وجدت 9/11 إجابات مباشرة؛ سؤال ترحيل الإجابات وسؤال توجيه الصور امتنعا رغم وجود الدليل، لكن إعادة كل حالة منفردة أجابت عنها مع اقتباس المصدر (`evals/results/retrieval_project_agent_migration_retry_2026-10-03.json` و`evals/results/retrieval_project_agent_routing_retry_2026-10-03.json`). هذا يكشف تذبذب جودة التوليد، ولا يعادل درجات مستقلة؛ مراجعة بشرية أوسع ما زالت مفتوحة. اختبارات Flutter الكاملة الآن 16/16، واختبارات Python الكاملة عبر `unittest` الآن 89/89 (2026-10-03). فحص `compileall` و`git diff --check` ناجحان.
- تحقق تشغيل حديث: أُعيد تشغيل 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 في هذه الخطوة.
- تحديث الخدمة والواجهة في هذه الجولة: اكتُشف أن مستمع 8000 كان عملية بدأت قبل آخر تعديل لـ`app/main.py`، فأُعيد تشغيل FastAPI من `start-api.ps1`؛ `/health` الآن `ok` وGemma 4، على PID 51376 بعد اكتشاف وإيقاف المستمع الأقدم. أُغلق خادما الاختبار المؤقتان 8131/8132 بعد التحقق من مالكيهما، وأكد فحص SQLite عدم بقاء أي سجلات لمساحات اختبار `sovereignai-rag-eval-*`. مجموعة Flutter الكاملة الآن 16/16. أُنجز ترجمة Dart للأصول الحالية وشُغّل `flutter_app.exe` للـDebug من حزمة مؤقتة خارج OneDrive (PID 31556) مع API الحالي. `flutter run` المعتاد لم يكتمل: CMake حاول استبدال `kernel_blob.bin` مولّدًا داخل build لكنه ملف OneDrive cloud reparse محمي؛ ومحاولة الحزمة المؤقتة النظيفة لم تجد مترجم C++ في CMake. تبقى إعادة بناء Windows القياسية من مصدر المشروع بندًا مفتوحًا؛ لم يُحذف ملف OneDrive المحمي.
- 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 ويطلب الموافقة قبل الكتابة؛ لا يخزّن الخادم الملفات ولا يشغل كودها. يبث الخادم مراحل التحقق واختيار الأداة والتنفيذ وصياغة الرد إلى واجهة Flutter. أضيف قسم «مشاريعي» في 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 غير مشغلة الآن.
@@ -73,14 +79,14 @@
- [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 دون تغيير أقراص الجهاز. نحتاج بيئة عزل نظامية قابلة للقياس أو صلاحية إعدادها قبل تفعيل أوامر الوكيل.
- [ ] عزل عملية FastAPI عن ملفات المضيف غير المصرح بها على مستوى نظام التشغيل قبل السماح بعميل شبكي أو خدمة مستضافة؛ القائمة البرمجية وحدها لا تحد صلاحيات العملية نفسها. فحص 2026-10-03: Docker وWindows Sandbox غير متاحين، ولم يمكن تأكيد وجود توزيعة WSL (الأمر المتاح يعرض تعليمات فقط)؛ فحص ميزات Windows يتطلب صلاحية مسؤول. حاجز loopback في FastAPI يخفف الخطر محليًا لكنه لا يحقق عزل الملفات. تجربة AppContainer لم تثبت حد مساحة قرص موثوقًا، وطلب إنشاء VHDX أُلغي عند UAC دون تغيير أقراص الجهاز. إعادة فحص 2026-10-03 أكدت أن جلسة Windows الحالية ليست Administrator، وأن تشغيل `diskpart /?` فشل بـ`0xc0000142` قبل أي تعديل؛ أظهر فحص الأقراص C: وقسم NTFS للنظام فقط، ولم ينشأ VHDX. إعادة فحص قراءة فقط 2026-10-04: `wsl --status` و`wsl --list --verbose` أعادا شاشة الاستخدام بدل حالة توزيعة، و`fsutil quota query C:` أعاد `Access is denied`. أظهر `whoami /groups` أن مجموعة Administrators بحالة deny-only ومستوى الجلسة Medium؛ لا تملك جلسة التنفيذ الحالية رمز مسؤول فعليًا. نحتاج بيئة عزل نظامية قابلة للقياس أو جلسة إعداد مسؤول قبل تفعيل أوامر الوكيل.
- [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] HTTPS محلي اختياري لعميل Windows/Dart والمتصفح: أضيف `scripts/setup_local_tls.ps1` لإنشاء جذر تطوير خاص بـ`CurrentUser\Root` وشهادة خادم SAN لـ`localhost` و`127.0.0.1`؛ يقيّد ACL لمفتاح الخادم للمستخدم و`SYSTEM` ويحذف مفتاح الجذر بعد التوقيع. أضيف `start-api-https.ps1` لمنفذ 8443 و`remove_local_tls.ps1` لإزالة الشهادات والملفات المحددة. في 2026-10-04 أعاد Windows PowerShell وDart `HttpClient` الحالة 200 عبر الاسمين؛ فتح Edge headless صفحة `/health` وأظهر JSON بالحالة 200. رفض HTTPX بمخزن CA الافتراضي الشهادة الخاصة. أُوقف خادم الاختبار وبقي HTTP 8000 كما هو. `curl.exe` احتاج `--ssl-no-revoke` بسبب غياب CRL لجذر التطوير؛ لا نعطل فحص الشهادات في التطبيق. الإعداد loopback للتطوير فقط وليس شهادة عامة أو وصولًا شبكيًا.
- [x] حد أولي دائم لتخمين كلمات المرور وإنشاء الحسابات في SQLite مع نافذة انتهاء و`Retry-After`؛ اختبرته مجموعة Python كاملة، وتبقى مراجعة الحدود تحت reverse proxy موثوق قبل أي نشر خارجي.
- [x] تعطيل حفظ رمز الجلسة الدائم في الويب؛ استخدام مخزن ذاكرة مؤقت وإظهار ذلك للمستخدم.
- [ ] التحقق من متطلبات Linux keyring وتشغيل تخزين الجلسة الأصلي، وبناء macOS وLinux على منصات فعلية.
@@ -106,7 +112,7 @@
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).)
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 وتشغيل وتنظيف مؤقت قابل للتكرار. إعادة الفحص الحالية: رمز الجلسة ليس مسؤولًا، و`diskpart /?` يفشل بـ`0xc0000142`؛ لم يحصل أي تعديل للأقراص. ما زال هذا prototype غير مدمج في الوكيل ولا توجد أوامر عامة قابلة للتنفيذ. التالي: توفير ساحة تخزين يفرض النظام حدها فعليًا عبر عزل نظامي عامل، ثم ربط ملفات Snapshot والمخرجات بها، قبل دمج قائمة أوامر وموافقة صريحة في 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).
@@ -135,7 +141,7 @@
- [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 صغيرة ومصطنعة؛ الدرجات تصف هذه الحالات ولا تثبت جودة عامة. مراجعة إجابات الوكيل محفوظة لكن لا توجد درجات مستقلة من المستخدم بعد.
- [ ] متابعة التقييم على ملفات طويلة وPDFات متنوعة وأسئلة جديدة، وجمع مراجعة مستقلة لجودة إجابات النموذج فوق السياق المسترجع. النتائج الحالية fixtures صغيرة ومصطنعة؛ الدرجات تصف هذه الحالات ولا تثبت جودة عامة. في 2026-10-04 جُمعت 14 إجابة محفوظة من المجموعة ذات 11 حالة ومجموعتي PDF الطويل/الممسوح في ورقة مراجعة `evals/HUMAN_REVIEW_2026-10.md` مع سلم موحد وخانات فارغة؛ لا توجد درجات بشرية بعد، فلا تُحسب مرحلة المراجعة مكتملة.
- [x] مهارات محلية أولية قابلة للاختيار من واجهة وضع الوكيل: شرح الكود، مراجعة الكود، وخطة اختبارات. تعرض `/v1/agent/skills` وصف كل مهارة وأدواتها؛ تُحقن التعليمات الموثوقة في سياق الوكيل وتُفلتر قائمة الأدوات، ويرفض الخادم استدعاء أداة خارج صلاحيات المهارة. لمهارة مراجعة الكود معاينة فقط ولا تطبيق مباشر. اجتازت اختبارات الصلاحيات والواجهة؛ يبقى تقييم دقة كل مهارة على أمثلة أكثر قبل اعتمادها افتراضيًا.
- [x] قراءة رابط عام محدد عبر `POST /v1/web/read`: استخراج نص HTML الثابت وتمريره إلى Gemma المحلية للإجابة مع إرجاع الرابط والعنوان.
- [x] بحث ويب متعدد المصادر تجريبي عبر DuckDuckGo بلا مفتاح API: اختيار نطاقات مختلفة، محاولة جلب الصفحات العامة، تلخيص بالنموذج المحلي مع روابط المصادر، ووسم المقتطفات عند تعذر فتح الصفحة. (2026-10-01: استجابة حية أعادت ملخصًا ومصدرين مختلفين عبر FastAPI/Gemma.) أضيف زمن جلب إجمالي وزمن لكل مصدر إلى الاستجابة لمساعدة تشخيص المصادر البطيئة؛ اختبارات الحجب ومزوّد رسمي اختياري ما زالت لاحقًا.
@@ -166,6 +172,7 @@
## إضافات قبل توسيع الوكيل
- [x] قسم «مشاريعي»: تسجيل مجلد كمشروع محلي، فتح مجلد محفوظ بعد إعادة تشغيل التطبيق، إزالة اختصار المشروع من القائمة دون حذف محتوياته. مجموعة Flutter الكاملة 16/16، ومنها اختبار الاستعادة واختبار ظهور القسم والزر (2026-10-03). المشروع يعني مجلد عمل يختاره المستخدم؛ التطبيق يستطيع استعراض الملفات المحددة وفهرستها والبحث فيها، واقتراح تغييرات عبر diff بعد موافقة المستخدم. لا ينفّذ أوامر المشروع أو اختباراته بعد.
- [x] إلغاء التوليد وإظهار المدة وحالة الاتصال ورسالة الخطأ (2026-10-01: اختبارات Cubit وواجهة ناجحة).
- [x] حفظ نسخ إعادة التوليد والتنقل بينها (2026-10-01: اختبار واجهة وAPI وقاعدة البيانات ناجح)؛ تجربة أفضل للأخطاء وإعادة المحاولة ما زالت لاحقة.
- [x] إكمال طبقة مزوّد Ollama وقائمة قدرات النماذج المثبتة قبل توسيع أدوات الوكيل؛ إضافة مزودين آخرين ما زالت لاحقة.
@@ -174,6 +181,7 @@
- [x] حزمة تقييم أولية بالعربية والبرمجة ونتائج baseline على نموذجين؛ تكرار التشغيل وقياس الذاكرة والتحقق البشري الأوسع ما زالت لاحقة.
- [x] نواة وكيل الملفات: تقدم الخطوات عبر SSE، ومعاينة diff وموافقة صريحة قبل تطبيق الكتابة داخل الجذر المخصص للحساب. اختبار API مباشر في 2026-10-03 أكد اختيار أداة الحاسبة وإرجاع النتيجة الصحيحة. الخطوة التالية للوكيل هي أوامر تطوير محددة داخل عزل نظام تشغيل قابل للتحقق؛ لم يُفعّل تشغيل الأوامر العامة.
- [x] توضيح تجربة المشاريع وإصلاح سياق الملف المحدد (2026-10-03): نقطة `/v1/agent/workspace/files` على الخدمة الحية سردت 121 ملفًا من مجلد المشروع المسموح. كشف الاختبار الأول أن Gemma قد تتجاهل سؤال الملف إذا وصلها مقتطف طويل؛ أضيف اختيار مقاطع مرتبطة بكلمات السؤال ضمن سقف 4,000 حرف، ورسالة موجزة بلا مخطط أدوات في مهارة «شرح الكود» عند إرفاق ملفات محددة، ودرجة حرارة 0. اختبارات مهارات الوكيل 20/20 ومجموعة Python الكاملة 90/90. بعد إعادة تشغيل FastAPI الحالي عبر `start-api.ps1` (PID 51376، مع قاعدة SQLite الفعلية نفسها)، أجاب `/v1/agent/run` عن `README.md` بـ`gemma4:e2b` مع الاستشهاد بالمصدر. تسجيل المجلد محلي؛ والأمر/الاختبار الآلي داخل المشروع ما زالا غير متاحين حتى اكتمال عزل نظام التشغيل.
## ترتيب التنفيذ القادم
1. [x] التحقق من إجراءات المحادثة الجديدة على Windows Debug (2026-10-01): تشغيل API وGemma وGroq، اختبار صوت من الميكروفون حتى التفريغ والرد والحفظ في SQLite، نجاح اختبار الواجهة على نافذة 800px ونجاح `flutter analyze`.
@@ -181,7 +189,7 @@
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 بصريًا.)
6. [x] تشغيل جلسة Windows Debug نظيفة بعد إصلاح مجلدي روابط إضافات `record` المؤقتة؛ تحقق التشغيل السابق بـ`flutter run -d windows --no-pub`. **ملاحظة الجولة الحالية:** أُعيد تشغيل واجهة Dart الحالية من حزمة Debug محلية مؤقتة وربطها بـFastAPI الحالي؛ إعادة البناء القياسية في مجلد OneDrive ما زالت تتعثر عند استبدال cloud placeholder، وتبقى بحاجة إلى مسار build محلي دائم والتحقق من نافذة التطبيق بصريًا.
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 مجددًا مع مسار التأكيد.)