build: add repeatable local Windows debug runner

This commit is contained in:
Hamza Ayed
2026-10-04 02:58:54 +03:00
parent 83199c1b78
commit 3e978d44ba
2 changed files with 112 additions and 2 deletions
+4 -2
View File
@@ -10,7 +10,9 @@
- تهيئة Linux: وُحّد `APPLICATION_ID` مع اسم سطح المكتب والأيقونة إلى `com.mithqal.ai`، وأضيف دليل اعتماديات البناء والتشغيل الآمن مع Libsecret وخدمة Secret Service في `flutter_app/linux/packaging/README.md`. لم يُنفذ بناء أو اختبار Linux أصلي على هذا المضيف Windows؛ بند Linux/macOS لا يزال مفتوحًا حتى يتحقق البناء ومخزن الجلسة على المنصات نفسها.
- وضوح تسجيل المشروع في النافذة الضيقة: أضيف إجراء دائم في الشريط العلوي بعنوان وصولي «تسجيل مشروع من مجلد موجود»، لأن القائمة الجانبية تختفي عند عرض 760px أو أقل. يحتفظ بسلوك اختيار مجلد موجود وتسجيله. تحقق اختبار واجهة عند عرض 700px من ظهور الإجراء رغم اختفاء القائمة؛ مجموعة `widget_test.dart` نجحت 6/6 و`flutter analyze --no-pub` بلا ملاحظات (2026-10-04). لم يُستبدل التطبيق المفتوح ببناء جديد: بناء Windows معزول فشل بعد 315 ثانية برسائل MSBuild `FTK1011` عن تعذر إنشاء ملفات تتبع إضافة `flutter_secure_storage_windows` تحت OneDrive؛ أُعيد إعداد مجلد بناء Flutter إلى الافتراضي وحُذف مجلد التحقق المؤقت.
- وضوح تسجيل المشروع في النافذة الضيقة: أضيف إجراء دائم في الشريط العلوي بعنوان وصولي «تسجيل مشروع من مجلد موجود»، لأن القائمة الجانبية تختفي عند عرض 760px أو أقل. يحتفظ بسلوك اختيار مجلد موجود وتسجيله. تحقق اختبار واجهة عند عرض 700px من ظهور الإجراء رغم اختفاء القائمة؛ مجموعة `widget_test.dart` نجحت 6/6 و`flutter analyze --no-pub` بلا ملاحظات (2026-10-04). فشل البناء داخل OneDrive برسائل MSBuild `FTK1011`، لكن نجح حل عملي بنسخ مصدر Flutter (9.4 MiB، دون build/cache) إلى نسخة محلية ثم بناء Debug كامل. شُغلت النسخة الجديدة في نافذة `Mithqal AI` تستجيب (PID 33624، HWND صالح)، بينما بقيت النافذة القديمة PID 1328 كما هي؛ API أعاد 200 وGemma 4.
- تكرار بناء Windows خارج OneDrive: أضيف `scripts/run_windows_debug_local.ps1`؛ يزامن المصدر إلى `%LOCALAPPDATA%\SovereignAI-Starter\windows-dev\flutter_app` ويحافظ على `build` و`.dart_tool` لتسريع الدورات التالية، ويدعم `-BuildOnly` و`-SyncOnly`. فُحصت صياغته، واختُبر SyncOnly مع الحفاظ على build cache، وشُغّل BuildOnly من المسار الثابت مرتين: أول بناء 336 ثانية، والثاني 55 ثانية في Flutter بعد استعادة الحزم offline. ملف Debug موجود في المسار المحلي الثابت. التشغيل التفاعلي من السكريبت لم يُختبر بعد لأن نوافذ التطبيق الحالية مفتوحة؛ افتح السكريبت بعد إغلاقها. تحذير OneDrive الأصلي ومسار البناء في المؤقت لم يعودا حاجزًا لبناء Debug.
- متابعة التقييم على ملفات المشروع الفعلية: أضيفت مرادفات `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` ناجحان.
@@ -195,7 +197,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` المؤقتة؛ تحقق التشغيل السابق بـ`flutter run -d windows --no-pub`. **ملاحظة الجولة الحالية:** أُعيد تشغيل واجهة Dart الحالية من حزمة Debug محلية مؤقتة وربطها بـFastAPI الحالي؛ إعادة البناء القياسية في مجلد OneDrive ما زالت تتعثر عند استبدال cloud placeholder. في 2026-10-04 فشل أيضًا بناء بمجلد إخراج Flutter مؤقت برسائل MSBuild `FTK1011` عند إنشاء سجلات تتبع `flutter_secure_storage_windows` في شجرة OneDrive. إعداد Flutter عاد إلى الافتراضي ونُظف مجلد المحاولة؛ بقيت واجهة PID 1328 القديمة مفتوحة. المطلوب مسار build محلي دائم والتحقق بصريًا من نافذة التطبيق.
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 ثانية. تبقى تجربة `flutter run` التفاعلية من السكريبت بعد إغلاق النوافذ الحالية، والتحقق البصري من زر المشروع.
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 مجددًا مع مسار التأكيد.)
@@ -0,0 +1,108 @@
[CmdletBinding()]
param(
[switch]$BuildOnly,
[switch]$SyncOnly,
[string]$WorkRoot
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$repositoryRoot = Split-Path -Parent $PSScriptRoot
$sourceApp = Join-Path $repositoryRoot 'flutter_app'
if (-not (Test-Path -LiteralPath (Join-Path $sourceApp 'pubspec.yaml') -PathType Leaf)) {
throw "Flutter project was not found under '$sourceApp'."
}
$localAppData = [IO.Path]::GetFullPath($env:LOCALAPPDATA).TrimEnd('\')
$tempDirectory = [IO.Path]::GetFullPath($env:TEMP).TrimEnd('\')
if ([string]::IsNullOrWhiteSpace($WorkRoot)) {
$WorkRoot = Join-Path $localAppData 'SovereignAI-Starter\windows-dev\flutter_app'
}
$workRootPath = [IO.Path]::GetFullPath($WorkRoot).TrimEnd('\')
$allowedRoots = @($localAppData, $tempDirectory)
$isAllowedRoot = $false
foreach ($allowedRoot in $allowedRoots) {
if ($workRootPath.StartsWith($allowedRoot + '\', [StringComparison]::OrdinalIgnoreCase)) {
$isAllowedRoot = $true
break
}
}
if (-not $isAllowedRoot) {
throw 'WorkRoot must be a child directory of LOCALAPPDATA or TEMP.'
}
if (Test-Path -LiteralPath $workRootPath) {
$workRootItem = Get-Item -LiteralPath $workRootPath -Force
if (($workRootItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
throw "Refusing to use a reparse-point work directory: $workRootPath"
}
} else {
New-Item -ItemType Directory -Path $workRootPath | Out-Null
}
$destinationAppPath = $workRootPath
if (-not (Test-Path -LiteralPath $destinationAppPath)) {
New-Item -ItemType Directory -Path $destinationAppPath | Out-Null
}
$destinationAppPath = (Resolve-Path -LiteralPath $destinationAppPath).Path
$destinationItem = Get-Item -LiteralPath $destinationAppPath -Force
if (($destinationItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
throw "Refusing to mirror source into a reparse-point directory: $destinationAppPath"
}
if (-not $SyncOnly) {
$runningApps = @(Get-Process -Name 'flutter_app' -ErrorAction SilentlyContinue)
if ($BuildOnly) {
$runningApps = @($runningApps | Where-Object { $_.Path -and $_.Path.StartsWith($workRootPath + '\', [StringComparison]::OrdinalIgnoreCase) })
}
if ($runningApps.Count -gt 0) {
$processIds = ($runningApps | ForEach-Object Id) -join ', '
throw "Close the running Mithqal AI Debug window(s) from this build workspace first (PID: $processIds), then run this script again."
}
}
# Keep native build outputs and package caches in the local copy for fast,
# incremental rebuilds. They are deliberately excluded from mirroring.
$excludedDirectories = @(
(Join-Path $sourceApp 'build'),
(Join-Path $sourceApp '.dart_tool'),
(Join-Path $sourceApp 'windows\flutter\ephemeral'),
(Join-Path $sourceApp 'linux\flutter\ephemeral'),
(Join-Path $sourceApp 'macos\Flutter\ephemeral')
)
$excludedFiles = @(
'.flutter-plugins',
'.flutter-plugins-dependencies',
'.packages',
'.env',
'.env.*'
)
& robocopy $sourceApp $destinationAppPath /MIR /XJ /R:1 /W:1 /NFL /NDL /NJH /NJS /NP /XD $excludedDirectories /XF $excludedFiles
if ($LASTEXITCODE -ge 8) {
throw "Could not sync Flutter sources to the local build directory (robocopy $LASTEXITCODE)."
}
Write-Host "Local Windows build workspace: $destinationAppPath"
if ($SyncOnly) {
exit 0
}
Push-Location $destinationAppPath
try {
& flutter pub get --offline
if ($LASTEXITCODE -ne 0) {
throw 'Flutter dependencies are not available in the local pub cache. Run flutter pub get once with network access, then retry.'
}
if ($BuildOnly) {
& flutter build windows --debug --no-pub
} else {
& flutter run -d windows --debug --no-pub
}
if ($LASTEXITCODE -ne 0) {
throw "Flutter exited with code $LASTEXITCODE."
}
} finally {
Pop-Location
}