From 46de9128b89edf21bdae01627022ee3fc64e9d78 Mon Sep 17 00:00:00 2001 From: Hamza Ayed Date: Sun, 4 Oct 2026 16:44:05 +0300 Subject: [PATCH] test project picker to agent review flow --- SovereignAI-Starter/ROADMAP.md | 2 +- .../flutter_app/test/widget_test.dart | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/SovereignAI-Starter/ROADMAP.md b/SovereignAI-Starter/ROADMAP.md index 79b7909..688aa10 100644 --- a/SovereignAI-Starter/ROADMAP.md +++ b/SovereignAI-Starter/ROADMAP.md @@ -226,7 +226,7 @@ 4. [x] إضافة طبقة مزود النموذج واكتشاف النماذج (2026-10-01): عقد موحد للطلب الكامل والبث والقائمة، واستخدامه في المحادثة والوكيل وقراءة مساحة العمل والويب؛ Ollama هو المزوّد المنفذ حاليًا. تحقق حي من `/health` و`/v1/models` وطلب محادثة باستخدام Gemma. 5. [x] إكمال Markdown للمرحلة 1: جداول قابلة للتمرير، قوائم متداخلة، ومربعات مهام GFM؛ التحليل واختبارات الواجهة الثلاثة ناجحة وبناء Windows Debug نجح. 6. [x] تشغيل جلسة Windows Debug بعد إصلاح مجلدي روابط إضافات `record` المؤقتة. بناء OneDrive يفشل عند cloud placeholders وMSBuild `FTK1011`. في 2026-10-04 نجح بناء وتشغيل نسخة `%TEMP%` (PID 33624) مع API/Gemma؛ ثم أضيف `scripts/run_windows_debug_local.ps1` لمسار ثابت خارج OneDrive. `-BuildOnly` في `%LOCALAPPDATA%\SovereignAI-Starter\windows-dev\flutter_app` نجح أول مرة في 336 ثانية، وإعادة البناء بالـcache نجحت في 55 ثانية. وفي 2026-10-04 شُغلت أيضًا نسخة Debug الأحدث التي تتضمن زر إنشاء المشروع (PID 35400) وأعادت API `/health` حالة `ok` مع Gemma 4 وSQLite والوكيل. في محاولة 2026-10-04 لبناء تغييرات heartbeat/فهرسة PDF لم يكتمل البناء: إضافة `flutter_secure_storage_windows` لم تجد الرأس C++ عبر مسار الرابط الرمزي؛ ترجمت الإضافة منفردة بعد توجيه MSBuild إلى مسار الكاش الحقيقي، لكن البناء الكامل اصطدم بصلاحيات سجلات MSBuild في النسخة المؤقتة. كانت المحاولة السابقة غير ناجحة؛ لكن بناء لاحق من SDK معزول نجح، ونافذة التطبيق استجابت واتصلت بالخدمة كما هو مسجل أعلاه. تفاعل الأزرار ما زال مفتوحًا. - - [ ] تحقق مرئي ووظيفي كامل من زر فتح/إنشاء المشروع، ثم تسجيل مجلد وقراءة ملف وطلب معاينة تعديل من داخل نافذة Windows. أدلة الواجهة الآلية: اختبارات Flutter على أحدث مصدر بعد مزامنته إلى نسخة LocalAppData نجحت 22/22، واختبار `widget_test.dart` المستهدف نجح 7/7 بعد إضافة تأكيدات أن إرسال المستخدم يمرر مسار المشروع و`src/hello.py` للوكيل، وأن معاينة التعديل لا تطبق دون موافقة؛ وتشمل الاختبارات ظهور إجراء المشروع على المقاسات الضيقة والواسعة، واستمرار تسجيل المجلدات، وإنشاء مجلد مشروع آمن، ومعاينة diff؛ `flutter analyze --no-pub` بلا ملاحظات. أعيدت مزامنة أحدث المصدر وبناؤه في `LocalAppData\SovereignAI-Starter\windows-dev\ui-verify-20261004` باستخدام SDK معزول؛ نجح Windows Debug خلال 389.6 ثانية. اجتازت النسخة نفسها `flutter test --no-pub` 22/22 و`flutter analyze --no-pub` بلا ملاحظات (146 ثانية). شُغّل exe الحالي PID 55860، HWND 182911482، و`Responding=True`؛ أكد `/health` API 8000 الحالة `ok` مع Gemma 4 وSQLite. لم أتحقق بصريًا: `Computer Use list_windows` لم يعرض نافذة PID 55860، وأظهر نافذتين من مسار Debug قديم؛ التقاط النافذة القديمة انتهى بمهلة مرتين. لم أنفذ نقرات أو إدخالًا، وما زال تدفق فتح/تسجيل/قراءة/معاينة المشروع داخل نافذة حديثة مطلوبًا. +- [ ] تحقق مرئي ووظيفي كامل من زر فتح/إنشاء المشروع، ثم تسجيل مجلد وقراءة ملف وطلب معاينة تعديل من داخل نافذة Windows. أدلة الواجهة الآلية: اختبارات Flutter على أحدث مصدر بعد مزامنته إلى نسخة LocalAppData نجحت 22/22، واختبار `widget_test.dart` المستهدف نجح 7/7 بعد إضافة تأكيدات أن إرسال المستخدم يمرر مسار المشروع و`src/hello.py` للوكيل، وأن معاينة التعديل لا تطبق دون موافقة؛ وتشمل الاختبارات ظهور إجراء المشروع على المقاسات الضيقة والواسعة، واستمرار تسجيل المجلدات، وإنشاء مجلد مشروع آمن، ومعاينة diff؛ `flutter analyze --no-pub` بلا ملاحظات. أعيدت مزامنة أحدث المصدر وبناؤه في `LocalAppData\SovereignAI-Starter\windows-dev\ui-verify-20261004` باستخدام SDK معزول؛ نجح Windows Debug خلال 389.6 ثانية. اجتازت النسخة نفسها `flutter test --no-pub` 22/22 و`flutter analyze --no-pub` بلا ملاحظات (146 ثانية). شُغّل exe الحالي PID 55860، HWND 182911482، و`Responding=True`؛ أكد `/health` API 8000 الحالة `ok` مع Gemma 4 وSQLite. لم أتحقق بصريًا: `Computer Use list_windows` لم يعرض نافذة PID 55860، وأظهر نافذتين من مسار Debug قديم؛ التقاط النافذة القديمة انتهى بمهلة مرتين. في 2026-10-04 أضيف Widget Test يحاكي استجابة `file_selector` ثم ينقر تسجيل المشروع، يختار `src/hello.py`، ويرسل السياق للوكيل حتى معاينة diff مع تأكيد عدم التطبيق دون موافقة؛ الاختبارات الكاملة صارت 23/23 و`flutter analyze --no-pub` بلا ملاحظات. هذا لا يغني عن اختبار النافذة الأصلية؛ ما زال فتح/تسجيل/قراءة/معاينة المشروع يدويًا على Windows مطلوبًا. - [ ] تجربة `flutter run` التفاعلية عبر السكريبت المحلي ما زالت معلقة. أعيد بناء Debug بنجاح باستخدام SDK معزول، لكن توجد عدة عمليات `flutter_app` من جلسات ومسارات مختلفة؛ لم أغلقها، والسكريبت يرفض `flutter run` عندما تكون هذه النسخ مفتوحة. البناء والتحليل واختبارات Flutter ليست بديلًا عن التشغيل التفاعلي؛ يلزم إغلاق جلسات Debug بعد حفظ ما يلزم ثم تشغيل السكريبت. 7. [x] اختيار مساحة عمل وعرض الملفات المدعومة وتحديد ملفات للسؤال؛ التحقق من المجلدات والملفات على الخادم. 8. [x] إظهار انتقالات تقدم الوكيل أثناء العمل وربطها بحالات التنفيذ الفعلية عبر SSE؛ اختبار API حي لمسار الحاسبة. (2026-10-03: عبر FastAPI على 8100 وجلسة loopback، اختار Gemma 4 أداة `calculator` لمهمة 17×23، سجّل خطوة واحدة `completed` وأعاد 391.) diff --git a/SovereignAI-Starter/flutter_app/test/widget_test.dart b/SovereignAI-Starter/flutter_app/test/widget_test.dart index 66ad71d..09192f9 100644 --- a/SovereignAI-Starter/flutter_app/test/widget_test.dart +++ b/SovereignAI-Starter/flutter_app/test/widget_test.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:record/record.dart'; import 'dart:async'; @@ -260,6 +261,70 @@ void main() { await chatCubit.close(); }); + testWidgets('project picker selection reaches the agent review flow', ( + tester, + ) async { + tester.view.physicalSize = const Size(1500, 900); + tester.view.devicePixelRatio = 1; + addTearDown(tester.view.resetPhysicalSize); + addTearDown(tester.view.resetDevicePixelRatio); + + const selectorChannel = MethodChannel('plugins.flutter.io/file_selector'); + final messenger = + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; + messenger.setMockMethodCallHandler(selectorChannel, (call) async { + expect(call.method, 'getDirectoryPath'); + expect( + (call.arguments as Map)['confirmButtonText'], + 'تسجيل هذا المشروع', + ); + return r'C:\Projects\sample'; + }); + addTearDown( + () => messenger.setMockMethodCallHandler(selectorChannel, null), + ); + + final api = _ProposalWidgetApi(); + final cubit = ChatCubit(api, settingsStore: LocalSettingsStore.inMemory()); + await tester.pumpWidget( + MultiRepositoryProvider( + providers: [RepositoryProvider.value(value: api)], + child: MultiBlocProvider( + providers: [ + BlocProvider.value(value: cubit), + BlocProvider(create: (_) => VoiceCubit(api, AudioRecorder())), + ], + child: const SovereignApp(), + ), + ), + ); + await tester.pumpAndSettle(); + + await tester.tap(find.text('تسجيل مجلد مشروع موجود')); + await tester.pumpAndSettle(); + expect(find.text('ملفات مساحة العمل'), findsOneWidget); + await tester.tap(find.byType(CheckboxListTile)); + await tester.pumpAndSettle(); + await tester.tap(find.text('متابعة (1)')); + await tester.pumpAndSettle(); + + expect(cubit.state.selectedWorkspacePath, r'C:\Projects\sample'); + expect(cubit.state.selectedWorkspaceFiles, ['src/hello.py']); + await tester.enterText(find.byType(TextField), 'أنشئ ملف Python'); + await tester.tap(find.byTooltip('إرسال')); + await tester.pumpAndSettle(); + + expect(api.lastWorkspacePath, r'C:\Projects\sample'); + expect(api.lastWorkspaceFiles, ['src/hello.py']); + expect(find.text('مراجعة إنشاء الملف'), findsOneWidget); + expect(api.applyCount, 0); + await tester.tap(find.text('إلغاء')); + await tester.pumpAndSettle(); + expect(api.applyCount, 0); + expect(tester.takeException(), isNull); + await cubit.close(); + }); + testWidgets('model selector displays capabilities reported by Ollama', ( tester, ) async {