
البرمجة الانسيابية المقيّدة
غالباً يبدأ الحديث عن Vibe Coding من نقطة واحدة: السرعة. كم يحتاج الذكاء الاصطناعي من الوقت حتى يحوّل وصفاً قصيراً إلى كود يعمل؟ هذا سؤال مهم، لكنه ليس كافياً. فالكود قد يعمل بسرعة، ومع ذلك يكون غير دقيق، أو مكلفاً على قاعدة البيانات، أو صعب الصيانة، أو غير مناسب لبيئة إنتاج حقيقية.
هذه الدراسة لا تنظر إلى الكود المولّد كأنه عرض سريع ومبهر. بل تتعامل معه كقطعة برمجية يجب اختبارها تحت شروط واضحة. المثال هنا مستورد منتجات مكتوب في Laravel، يقرأ ملف CSV مبنياً على بيانات منتجات من Amazon. نقارن ثلاث طرق لتنفيذ نفس الفكرة، ثم نحكم عليها بنتيجة معروفة مسبقاً، لا بمجرد الانطباع.
الفكرة الأساسية
المشكلة في الكود الذي يولّده الذكاء الاصطناعي ليست أنه قد يكون سيئاً. الكود السيئ كان موجوداً قبل الذكاء الاصطناعي بزمن طويل. المشكلة الجديدة أن الكود المولّد قد يبدو مكتملاً ومقنعاً قبل أن يثبت فعلاً أنه صحيح.
في مهام الاستيراد تحديداً، هذه نقطة خطرة. قد يقرأ المستورد ملف CSV، يضيف المنتجات إلى قاعدة البيانات، ثم يعرض ملخصاً يبدو مطمئناً. لكن بيئة الإنتاج تسأل أسئلة أدق: هل تم رفض الصفوف غير الصالحة؟ هل بقي استهلاك الذاكرة تحت السيطرة؟ هل تسبب كل صف بعدة استعلامات؟ هل يوجد سجل يشرح لماذا رُفض هذا الصف بعد أسبوع من التشغيل؟
النقاش العام حول برمجة الذكاء الاصطناعي يميل غالباً إلى أحكام كبيرة وسريعة. هناك من يرى أن الذكاء الاصطناعي صار أفضل من معظم المبرمجين، وهناك من يراه مجرد آلة لإنتاج كود رديء. لكن الدليل في الحالتين يكون غالباً تجربة شخصية، أو لقطة شاشة، أو دالة نجحت مرة وفشلت مرة. هذا يصلح كبداية للنقاش، لكنه لا يكفي كقياس.
سؤال هذه الدراسة أبسط وأكثر قابلية للاختبار: هل يتحسن الكود المولّد عندما يحتوي الطلب نفسه على القيود التي يفكر بها المهندس قبل كتابة الكود؟
السياق العام والأدلة السابقة
منشور Karpathy الذي انتشر معه مصطلح vibe coding مهم لأنه سمّى أسلوب عمل بدأ كثير من المطورين باستخدامه: تصف ما تريد، تقبل تغييرات كبيرة يولّدها النموذج، ثم توجه النتيجة بالحوار. هذا يشرح طريقة العمل، لكنه لا يثبت أن الكود الناتج جيد أو جاهز للإنتاج.
الطرف المتفائل لديه ما يستند إليه. في بحث GitHub حول Copilot تمت مقارنة مجموعة تستخدم Copilot مع مجموعة لا تستخدمه في مهمة JavaScript محددة لبناء HTTP server. المجموعة التي استخدمت Copilot أنجزت المهمة أسرع بشكل واضح. قوة هذه النتيجة أنها جاءت من تجربة منظمة، لا من انطباع. لكن حدودها واضحة أيضاً: المهمة صغيرة ومحددة، ومعيار النجاح معروف، والقياس كان حول إنهاء تلك المهمة، لا حول صمود الكود داخل مشروع طويل العمر.
في المقابل، الطرف الحذر لديه أسباب جدية أيضاً. دراسة METR لعام 2025 اختبرت مطورين خبراء على مشكلات حقيقية داخل مستودعات يعرفونها مسبقاً، ووجدت أن السماح باستخدام أدوات الذكاء الاصطناعي زاد زمن الإنجاز في ذلك السياق. الصفحة نفسها تشير الآن إلى أن هذه النتائج تاريخية وأن هناك نتائج أحدث في 2026، لذلك لا نستخدمها كحكم نهائي على الذكاء الاصطناعي. قيمتها هنا أنها تذكّرنا بأن العمل الحقيقي قد يعطي نتائج مختلفة تماماً عن العروض الصغيرة.
استطلاعات الثقة تعطي صورة قريبة من ذلك. استبيان Stack Overflow Developer Survey 2025 أشار إلى أن نسبة المطورين الذين لا يثقون بدقة مخرجات أدوات الذكاء الاصطناعي أعلى من نسبة الذين يثقون بها. هذا لا يعني أن المطورين يرفضون الأدوات، بل يعني أن التحقق من الناتج صار جزءاً أساسياً من العمل.
أقرب إطار لفكرة هذه المقالة يأتي من تقرير DORA 2025 حول تطوير البرمجيات بمساعدة الذكاء الاصطناعي. الفكرة هناك أن الذكاء الاصطناعي يضخّم ما هو موجود أصلاً في النظام. إذا كان لدى الفريق قواعد واضحة، اختبارات، سجلات، ومراجعة جيدة، فالنموذج يجد شيئاً مفيداً يبني عليه. أما إذا كان الطلب غامضاً، فالنتيجة غالباً ستكون شكلاً خارجياً يشبه الميزة، لا أكثر.
حتى أبحاث الأمان تدفعنا إلى نفس الحذر. دراسة Broken by Default عام 2026 استخدمت التحقق الشكلي على كود أمني مولّد، ووجدت ثغرات في مخرجات كل النماذج المختبرة. هذه الدراسة ليست عن مستوردات CSV، لكنها تضع نفس المبدأ أمامنا: لا تسأل فقط هل يبدو الكود مقنعاً، بل اسأل أي شروط يستطيع أن يتحمل.
لماذا السرعة وحدها مضللة؟
أسرع حل ليس بالضرورة أفضل حل. قد يظهر أمر في الطرفية، وتمتلئ قاعدة البيانات، ويظهر ملخص نهائي جميل. عندها يبدو أن المشروع تحرّك. لكن الحركة وحدها لا تعني أن العمل صحيح.
في المستوردات، هذا الخطر أكبر. الصف غير الصالح قد يدخل إلى قاعدة البيانات كأنه صف عادي. قد يقبل المستورد حالة مخزون غير معروفة، أو يحوّل كمية تالفة إلى صفر، أو يخزن JSON مكسوراً، أو يحدّث منتجاً موجوداً باستخدام هوية خاطئة. هذه الأخطاء لا تظهر دائماً فوراً. أحياناً تظهر لاحقاً في الفلاتر، أو المخزون، أو تقارير الدعم، أو في فقدان الثقة بالأرقام.
لذلك يعطي هذا الاختبار كل استراتيجية نفس البيانات غير النظيفة ونفس النتيجة المتوقعة. السؤال ليس: هل يعمل الأمر؟ بل: هل يترك قاعدة البيانات في الحالة الصحيحة؟ وهل يشرح بوضوح ما الذي رفضه ولماذا؟
شكل الاختبار
المصدر الخام هو بيانات منتجات من Amazon. هذه البيانات قريبة من الواقع: أسماء طويلة، أسعار مكتوبة كنصوص، تصنيفات مختلفة، حقول فارغة، وبيانات variants غير منتظمة. لكنها وحدها لا تكفي للاختبار، لأنها لا تخبرنا مسبقاً ما النتيجة الصحيحة التي يجب الوصول إليها.
هنا يظهر الفرق بين البيانات الواقعية والبيانات القابلة للقياس. البيانات الواقعية تعطي الاختبار طابعاً حقيقياً: أسماء طويلة، أوصاف غير مرتبة، حقول ناقصة، أسعار بصيغ مختلفة، وبيانات variants مزعجة. أما البيانات المضبوطة فتعطي الاختبار القدرة على الحكم: قبل تشغيل أي أمر، نعرف كم صفاً يجب إدخاله، وكم صفاً يجب تحديثه، وكم صفاً يجب رفضه.
لذلك تم بناء مجموعة اختبار تحافظ على فوضى البيانات الواقعية، لكنها تضيف نتيجة مرجعية قابلة للقياس: 930 صفاً في الإدخال، منها 600 صف يجب إدخاله، و250 صفاً يجب تحديثه، و80 صفاً يجب رفضه.
مسار الاختبار يكون كالتالي:
بيانات Amazon
بناء مجموعة اختبار مضبوطة
تشغيل أوامر Laravel Artisan
جمع النتائج المقاسة
حساب درجة VCPRI
إعداد التشغيل يتكون من ثلاثة أجزاء: ملف الإدخال، منتجات موجودة مسبقاً قبل الاستيراد، وملف حقيقة مرجعية نستخدمه بعد التشغيل فقط. المستورد يرى بيانات الإدخال والمنتجات الموجودة مسبقاً، لكنه لا يرى الإجابة المتوقعة أثناء التنفيذ. الإجابة تستخدم لاحقاً للحكم على النتيجة.
قواعد المستورد
الهدف ليس بناء نسخة كاملة من كتالوج Amazon. المطلوب هنا قواعد صغيرة وواضحة تكشف هل يتعامل المستورد مع البيانات كما يجب أم لا.
| الحقل الداخلي | حقل CSV | النوع | القاعدة |
|---|---|---|---|
source_id | Uniq Id | نص | معرّف الصف في المصدر الأصلي. |
sku | Sku | نص | المفتاح الأساسي للمنتج عند وجوده. |
asin | Asin | نص | مفتاح احتياطي إذا كان Sku غير موجود. |
name | Product Name | نص | حقل مطلوب، ولا يجوز أن يكون فارغاً. |
brand | Brand Name | نص | حقل اختياري. |
category | Category | نص | حقل اختياري. |
price | Selling Price | رقم عشري | مطلوب، ويجب أن يكون رقماً أكبر من الصفر. |
list_price | List Price | رقم عشري | اختياري، لكن يجب أن يكون رقماً إذا كان موجوداً. |
quantity | Quantity | عدد صحيح | مطلوب في هذا الاختبار، ولا يجوز أن يكون سالباً. |
status | Stock | نص | يجب أن تكون القيمة ضمن حالات المخزون المسموحة. |
variants | Variants | JSON | اختياري، لكن إذا وُجد يجب أن يكون JSON صالحاً. |
description | Product Description | نص | اختياري، مع حد أقصى للطول. |
هوية المنتج تتبع ترتيباً واضحاً: نستخدم Sku أولاً، ثم Asin، ثم Uniq Id. إذا لم نجد أي مفتاح صالح، نرفض الصف. بهذه الطريقة نحافظ على واقعية البيانات، لكننا لا نترك القرار عشوائياً.
هذه القواعد متواضعة عمداً. لا نحاول هنا تمثيل الصور، أو وزن الشحن، أو الأبعاد، أو كل تفاصيل السوق. الهدف هو عزل المشكلات التي تظهر سريعاً عندما ينتقل الكود المولّد من بيانات تجريبية نظيفة إلى بيانات مورّد حقيقية.
بروتوكول السيناريوهات
كل استراتيجية نُفذت كأمر Laravel Artisan داخل نفس التطبيق. كل الأوامر تقرأ نفس ملف الاستيراد ونفس حالة المنتجات الموجودة مسبقاً، وتعيد نفس الأرقام: عدد الإدخالات، عدد التحديثات، عدد الصفوف المرفوضة، عدد حالات الفشل، زمن التشغيل، أعلى استهلاك للذاكرة، وعدد الاستعلامات.
هذا البروتوكول مهم حتى لا تتحول المقارنة إلى عرض غير عادل. إذا أصلحنا نسخة raw بعد رؤية النتائج، فهي لم تعد raw. وإذا حسّنا نسخة Laravel الأساسية بصمت، فهي لم تعد تمثل الحل العادي المتوقع من Laravel. وإذا أعطينا النسخة المقيّدة اختباراً أسهل، فلن نعرف أثر القيود فعلاً.
يقارن الاختبار بين ثلاث استراتيجيات:
أساس Laravel متوسط المستوى: كود عملي مألوف يستخدم تحقق Laravel، يقرأ البيانات صفاً بصف، يسجل الرفض بشكل بسيط، ويعتمد على
updateOrCreate.Raw vibe coding: طلب عام للذكاء الاصطناعي مع تعديلات صغيرة فقط حتى يعمل داخل المشروع. هذه النسخة ليست مخربة، لكنها غير محددة بما يكفي.
Constraint-driven vibe coding: طلب يذكر القيود بوضوح: الذاكرة، التحقق، عدد الاستعلامات، سجلات الرفض، وقابلية الاختبار.
نسخة raw ليست سيئة عمداً. هي فقط ناقصة التحديد. كثير من الميزات المولّدة تفشل ليس لأننا طلبنا كوداً سيئاً، بل لأننا لم نذكر الضغط الحقيقي الذي يجب أن يتحمله الكود. ونسخة Laravel الأساسية ليست مثالاً ضعيفاً مصنوعاً للمقارنة؛ استخدام validation مع updateOrCreate حل واقعي يمكن أن يكتبه مطور في نسخة إنتاج أولى. أما النسخة المقيّدة، فهي أفضل تحديداً لأن الطلب نفسه يذكر ما يجب ضبطه قبل كتابة الكود.
ما الذي تغيّره القيود؟
الفرق لا يبدأ داخل الكود، بل قبل كتابة الكود. الطلب الخام يقول للنموذج: ابنِ هذه الميزة. أما الطلب المقيّد فيقول: ابنِ هذه الميزة، لكن لا نعتبرها منتهية إلا إذا احترمت هذه الشروط.
طلب خام:
Build a Laravel CSV importer for products. It should read the CSV,
insert new products, update existing products, reject invalid rows,
and return a summary.طلب مقيّد:
Build a Laravel product importer for the benchmark CSV. Do not load
the full dataset into memory. Use sku, then asin, then source_id as the
product-key fallback. Validate price, quantity, status, variants, and
description length. Reject duplicate product keys inside the import
input. Preload existing keys to reduce database queries. Log every
rejected row with row number and reason. Return measured counts,
runtime, memory, and query count.المهم هنا ليس أن الطلب الثاني أطول. المهم أنه يجعل الفشل واضحاً. الصف لا يُتجاهل بصمت، بل يُرفض بسبب محدد. وهذا السبب هو ما يجعل المقارنة ممكنة.
فرق التحقق عملياً:
// Raw-style validation: enough for a demo, not enough for the contract.
if ($productKey === '' || trim($row['name']) === '' || $row['price'] <= 0) {
reject($rowNumber);
}// Constraint-driven validation: every controlled failure has a rule.
if ($productKey === '') return reject($rowNumber, 'missing_product_key');
if (trim($row['name']) === '') return reject($rowNumber, 'empty_name');
if (! is_numeric($row['price']) || $row['price'] <= 0) return reject($rowNumber, 'invalid_price');
if (! preg_match('/^-?\d+$/', $row['quantity']) || $row['quantity'] < 0) return reject($rowNumber, 'invalid_quantity');
if (! in_array($row['status'], $allowedStatuses, true)) return reject($rowNumber, 'invalid_status');
if ($row['variants'] !== '' && json_decode($row['variants']) === null && json_last_error() !== JSON_ERROR_NONE) {
return reject($rowNumber, 'invalid_variants_json');
}طريقة التقييم
استخدمت الدراسة مؤشراً باسم VCPRI، أي مؤشر جاهزية كود Vibe Coding للإنتاج. الهدف منه جمع أكثر من جانب في رقم واحد: صحة النتيجة، استهلاك الذاكرة، زمن التشغيل، عدد الاستعلامات، الأمان، التعامل مع الأخطاء، وقابلية الصيانة.
VCPRI = 0.25C + 0.20M + 0.15R + 0.15Q + 0.10S + 0.10F + 0.05Tأخذت صحة النتيجة الوزن الأعلى لأن البيانات الخاطئة ليست مجرد مشكلة أداء، بل مشكلة ثقة. أما الذاكرة، والوقت، وعدد الاستعلامات، فهي مهمة لأن مستوردات البيانات غالباً لا تفشل في المثال الصغير، بل تفشل عندما يكبر حجم البيانات.
Checklist Score = Passed Checks / Total Checks x 100
Memory Score = Lowest Peak Memory / Current Peak Memory x 100
Runtime Score = Fastest Runtime / Current Runtime x 100
Query Score = Lowest Query Count / Current Query Count x 100| المعيار | الوزن | السبب |
|---|---|---|
| صحة النتيجة | 0.25 | يجب أن يطابق المستورد أعداد الإدخال والتحديث والرفض المتوقعة. |
| الذاكرة | 0.20 | ملفات CSV تكبر مع الوقت، ونفاد الذاكرة فشل واضح وخطير. |
| وقت التشغيل | 0.15 | الوقت مهم، لكن مستورداً صحيحاً وبطيئاً أفضل من مستورد سريع يفسد البيانات. |
| عدد الاستعلامات | 0.15 | كثرة الاستعلامات هي كلفة مخفية شائعة في منطق الاستيراد صفاً بصف. |
| الأمان | 0.10 | الاستيراد يتعامل مع بيانات خارجية، لذلك لا يجب الوثوق بها مباشرة. |
| التعامل مع الفشل | 0.10 | الصفوف المرفوضة يجب أن تكون واضحة ومصنفة وقابلة للتتبع. |
| قابلية الاختبار والصيانة | 0.05 | الكود يجب أن يكون مفهوماً بما يكفي لتعديله بأمان لاحقاً. |
النتائج المقاسة
شُغّل الاختبار عبر أوامر Laravel Artisan حقيقية، وباستخدام SQLite لتسهيل إعادة القياس محلياً. كل استراتيجية شُغلت ثلاث مرات، والأرقام المعروضة هي المتوسطات.
| الاستراتيجية | Inserted | Updated | Rejected | Memory MB | Runtime s | Queries |
|---|---|---|---|---|---|---|
| أساس Laravel متوسط المستوى | 600 | 250 | 80 | 28.0 | 12.0625 | 1700 |
| Raw vibe coding | 640 | 258 | 32 | 30.0 | 13.2861 | 1796 |
| Constraint-driven vibe coding | 600 | 250 | 80 | 26.0 | 3.1975 | 851 |
درجات VCPRI كانت كالتالي:
| الاستراتيجية | C | M | R | Q | S | F | T | VCPRI |
|---|---|---|---|---|---|---|---|---|
| أساس Laravel متوسط المستوى | 100.00 | 92.86 | 26.51 | 50.06 | 100.00 | 100.00 | 60.00 | 78.06 |
| Raw vibe coding | 25.00 | 86.67 | 24.07 | 47.38 | 40.00 | 40.00 | 20.00 | 43.30 |
| Constraint-driven vibe coding | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 |
قراءة النتائج
نسخة raw انتهت من التشغيل، لكنها لم تلتزم بالقواعد المتوقعة. أدخلت 640 صفاً بدلاً من 600، وحدّثت 258 بدلاً من 250، ورفضت 32 صفاً فقط من أصل 80 صفاً غير صالح. هذا النوع من الفشل خطير لأنه لا يبدو كفشل واضح. الأمر يعمل، والجدول يمتلئ، لكن الخطأ يبقى مخفياً داخل البيانات المقبولة.
أساس Laravel كان صحيحاً من ناحية النتيجة. أدخل الصفوف التي يجب إدخالها، وحدّث الصفوف التي يجب تحديثها، ورفض الصفوف التي يجب رفضها. مشكلته كانت في طريقة التنفيذ: القراءة صفاً بصف مع updateOrCreate أدت إلى 1700 عملية قاعدة بيانات، وجعلته أبطأ تنفيذ صحيح في الاختبار.
النسخة المقيّدة غيّرت طريقة التفكير قبل التنفيذ. قرأت البيانات بشكل تدريجي، تحققت من الحقول بوضوح، حمّلت مفاتيح المنتجات الموجودة مسبقاً، رفضت المفاتيح المكررة داخل الملف، وسجلت أسباب الرفض بشكل منظم. وصلت إلى نفس النتيجة الصحيحة، لكن مع 851 استعلاماً وزمن أقل بكثير.
هنا يظهر الفرق بين طلب ميزة وطلب هندسي. عبارة “ابنِ مستورداً” تصف ما نريد رؤيته في النهاية. أما “ابنِ مستورداً يقرأ تدريجياً، يتحقق من قواعد ثابتة، يقلل فحص قاعدة البيانات صفاً بصف، يرفض التكرار، ويسجل أسباب الفشل” فهي تصف الشروط التي تجعلنا نثق أن الميزة انتهت فعلاً.
نتيجة raw مهمة لأنها واقعية. لم ينهَر الكود، ولم ينتج جدولاً فارغاً، ولم يعرض خطأ واضحاً. بل أعطى أرقاماً قد تمر في مراجعة سطحية إذا لم يقارنها أحد بالحقيقة المرجعية. لهذا نحتاج إلى اختبارات واضحة في البرمجة بمساعدة الذكاء الاصطناعي: لأنها تستبدل شعور “الكود يبدو مكتملاً” بسؤال أدق: ماذا حدث فعلاً؟
ماذا تقول الدراسة عن برمجة الذكاء الاصطناعي؟
هذه الدراسة لا تثبت أن الذكاء الاصطناعي أفضل من المطور، ولا تثبت أن الطلب المقيّد سينتصر دائماً. لكنها تثبت شيئاً عملياً: شكل الطلب يؤثر بقوة على شكل الكود الناتج. عندما يكون الطلب عاماً، يميل الكود إلى تحقيق الشكل الظاهر للميزة. وعندما يحتوي الطلب على قيود قابلة للقياس، يصبح الناتج أقرب إلى كود يمكن اختباره ومحاسبته.
هذا لا يلغي دور المهندس. بالعكس، يجعله أوضح. دور المهندس هنا ليس فقط كتابة كل سطر بنفسه، بل تحديد الحدود التي تجعل الكود قابلاً للحكم: ما الذي يجب رفضه، ما الذي يجب تسجيله، ما الذي لا يجوز تحميله في الذاكرة، وما النتيجة التي نعتبرها صحيحة.
الحدود
هذه دراسة حالة مقاسة، وليست قانوناً عاماً. استخدم الاختبار SQLite، لذلك قد تختلف الأرقام المطلقة عند استخدام MySQL أو PostgreSQL. كما أن مجموعة الاختبار تحتوي 930 صفاً، وهو حجم مناسب لكشف مشكلات التحقق وعدد الاستعلامات، لكنه لا يكفي وحده للحكم على ملفات ضخمة جداً.
زمن التشغيل قيس كزمن كامل لتنفيذ أمر Laravel Artisan. هذا يشمل تكلفة بدء Laravel نفسه: تحميل Composer autoload، تشغيل service providers، قراءة الإعدادات، تجهيز الأمر، وفتح اتصال قاعدة البيانات. هذه التكلفة عادلة داخل المقارنة لأن كل السيناريوهات تعمل داخل نفس التطبيق ونفس البيئة. قد تؤثر على الرقم المطلق، لكنها لا تعطي استراتيجية واحدة أفضلية خاصة.
مع ذلك، تبقى الدراسة مفيدة لأن أنماط الفشل التي ظهرت فيها شائعة جداً. بيانات المورّدين ليست نظيفة دائماً. مفاتيح المنتجات قد تكون ناقصة. JSON قد يكون مكسوراً. والمستورد الذي يبدو “عاملاً” قد يقبل صفوفاً كان يجب رفضها. هذه بالضبط الحالات التي يحتاج فيها الكود المولّد إلى قيود واضحة قبل أن نثق به.
النسخة التالية من الدراسة يجب أن تختبر نفس السيناريوهات على حجم بيانات أكبر، وقاعدة بيانات عبر الشبكة، واختبارات أدق لأسباب الرفض. ومن المفيد أيضاً فصل زمن بدء Laravel عن زمن حلقة الاستيراد نفسها.
الخلاصة
الخلاصة ليست أن كود الذكاء الاصطناعي جيد أو سيئ بشكل مطلق. الخلاصة أن الكود المولّد بدون قيود قد يكون مقنعاً أكثر مما يستحق. نسخة raw أعطت شكلاً يشبه المستورد، لكنها فشلت في القواعد. أساس Laravel كان صحيحاً لكنه ثقيل. أما النسخة المقيّدة فكانت صحيحة وأخف لأنها بدأت من شروط واضحة، لا من وصف عام للميزة فقط.
في العمل الإنتاجي، لا يكفي أن نقول: ابنِ الميزة. يجب أن نحدد حجم البيانات، قواعد التحقق، حدود الاستعلامات، سلوك الذاكرة، سجلات الفشل، حدود الأمان، وبنية قابلة للاختبار. عندها يصبح Vibe Coding أقرب إلى ممارسة هندسية حقيقية، لا مجرد اختصار سريع.
لمن يرغب في التعمق أكثر، أرفقت هنا ملف PDF يضم الدراسة كاملة بكل تفاصيلها.
