Full-stack SSOT Orchestrator — أداة CLI تتحقق من اتساق 5 مصادر حقيقة وحيدة دفعة واحدة وتولّد الكود.
الشقوق في أسلوب Vibe Coding
مع انتشار أسلوب Vibe Coding، بدأت الأنماط تتكشف.
تقول للذكاء الاصطناعي “أنشئ ميزة الحجز” فينشئها. تقول “أضف ميزة الإلغاء” فيضيفها. عند إضافة الميزة الخامسة تنكسر الميزة الثانية. تغيّر مخطط API لكن الواجهة الأمامية لا تُحدَّث. تضيف عمودًا في قاعدة البيانات لكن طبقة الخدمة لا تعلم بذلك.
السبب بسيط: الذكاء الاصطناعي لا يستطيع تذكّر الكود بأكمله.
فيفعل الناس ما يلي: يكتشفون الجزء المكسور ويقولون للذكاء الاصطناعي “أصلح هذا أيضًا”. يصلحه فينكسر مكان آخر. “أصلح ذاك أيضًا.” تتكرر هذه الحلقة. كلما كبر المشروع طالت الحلقة، وعند نقطة ما يصبح “إعادة البناء من الصفر أسرع”.
لماذا يتضخم الكود؟
يمتزج في الكود شيئان:
القرارات: ماذا نعرض، أي API نستدعي، بأي ترتيب نعالج، ماذا نخزّن. التوصيلات: الكود الذي ينفّذ تلك القرارات في إطار عمل محدد.
لنفترض أننا نبني نظام حجز.
القرار: "عند إنشاء حجز، استعلم عن الغرفة؛ إن لم توجد أعد 404، وإن وُجدت أنشئ الحجز"
هذا السطر الواحد من القرار يتوزع على React hooks وGo handlers واستعلامات SQL ومخططات API وموارد Terraform. يُغلَّف كل جزء بصياغة الإطار الخاص به، ويُضاف إليه معالجة الأخطاء وتحويل الأنواع.
من بين 100,000 سطر من الكود، القرارات هي 12,500 سطر فقط. الباقي — 87,500 سطر — توصيلات.
وكلاء الذكاء الاصطناعي لديهم نافذة سياق محدودة. عند إضافة الميزة العاشرة لا يتذكرون التسع السابقة، لأنهم لا يستطيعون قراءة 100,000 سطر دفعة واحدة.
لو فصلنا القرارات فقط فهي 12,500 سطر — 55% من سياق 200K توكن. حجم يمكن للذكاء الاصطناعي قراءته دفعة واحدة.
5 مصادر SSOT
يُقابل Fullend كل طبقة من الطبقات الخمس المكوّنة للبرمجيات بلغة DSL واحدة. كل DSL تصبح مصدر الحقيقة الوحيد (SSOT) لتلك الطبقة.
| الطبقة | DSL | ما تصرّح به |
|---|---|---|
| الواجهة | STML (HTML5 + data-*) | ماذا نعرض وماذا نفعل |
| عقد API | OpenAPI 3.x | أي طلبات نستقبل وأي استجابات نعيد |
| تدفق الخدمة | SSaC (Go comment DSL) | بأي ترتيب نعالج |
| بنية البيانات | SQL DDL + sqlc | ماذا نخزّن |
| البنية التحتية | Terraform HCL | أين نشغّل |
OpenAPI وSQL DDL وTerraform معايير صناعية. أما الواجهة وتدفق الخدمة فلم يكن لهما DSL بمثابة SSOT. قرارات الواجهة الأمامية كانت مدفونة في React hooks، وتدفقات الخدمة متناثرة في Go handlers. لذلك صمّمنا STML وSSaC. هما لغتا DSL اللتان أنشأهما هذا المشروع.
specs/
├── frontend/*.html → STML
├── api/openapi.yaml → OpenAPI 3.x
├── service/*.go → SSaC
├── db/*.sql → SQL DDL + sqlc queries
└── terraform/*.tf → HCL
specs/ هي الحقيقة. artifacts/ يمكن إعادة توليدها في أي وقت.
التحقق الفردي موجود بالفعل
أدوات التحقق لثلاث طبقات موجودة بالفعل:
- sqlc يتحقق من اتساق DDL والاستعلامات.
- أدوات التحقق من OpenAPI تفحص صحة المخططات.
- Terraform يتحقق من صياغة HCL والتبعيات.
أنشأنا أيضًا أدوات تحقق مدمجة لكل من STML وSSaC. يتحقق SSaC من الاتساق الداخلي لتدفقات الخدمة، وتتحقق STML من تطابق تصريحات الواجهة مع OpenAPI.
كل طبقة من الخمس يمكنها التحقق من ذاتها داخليًا. المشكلة تحدث بين الطبقات.
الواجهة الأمامية تعرض حقلًا بـ data-bind="memo"، لكن مخطط استجابة API لا يحتوي على memo. يستدعي SSaC الدالة @model Reservation.SoftDelete، لكن استعلامات sqlc لا تحتوي على الطريقة SoftDelete. يُصرَّح في OpenAPI عن x-sort: [created_at]، لكن جدول DDL لا يملك فهرسًا على ذلك العمود.
الأدوات الفردية ترى طبقتها فقط. الشقوق بين الطبقات تبقى غير مرئية.
إخفاء البنية
“ولكن ألا يجب تعلّم 5 لغات DSL؟”
صحيح. لكن البنية لا يجب أن تُعرض على المستخدم.
إذا وضعنا مجموعة التقنيات وقواعد SSOT مسبقًا في موجّه نظام الوكيل، يكفي أن يقول المستخدم “أنشئ ميزة الحجز”. يقوم الوكيل تلقائيًا بإضافة نقطة نهاية في OpenAPI، وإنشاء جدول في DDL، وتصريح تدفق الخدمة في SSaC، ورسم الواجهة في STML، وتشغيل fullend validate للتحقق من الاتساق.
ما يراه المستخدم هو النتيجة فقط. البنية يستهلكها الوكيل، وليست شيئًا على المستخدم تعلّمه.
تجربة Vibe Coding تبقى كما هي. ما يتغيّر هو أن شيئًا لا ينكسر في الخلفية.
دور Fullend
Fullend هو أداة تحقق متبادل. لا يعيد اختراع الأدوات الفردية. يستدعي كل أداة ويفحص الحدود بين الطبقات.
fullend validate specs/
✓ DDL 3 tables, 18 columns
✓ OpenAPI 7 endpoints
✓ SSaC 7 service functions
✓ STML 4 pages, 6 bindings
✓ Cross 0 mismatches
All SSOT sources are consistent.
إذا فشل أي فحص:
✓ DDL 3 tables, 18 columns
✓ OpenAPI 7 endpoints
✗ SSaC CancelReservation
@model Reservation.SoftDelete — method not found in sqlc queries
✗ Cross 1 mismatch
FAILED: Fix errors before codegen.
عند نجاح التحقق يُولَّد الكود.
fullend gen specs/ artifacts/
sqlc يولّد نماذج قاعدة البيانات، وoapi-codegen يولّد أنواع API، وSSaC يولّد دوال الخدمة، وSTML يولّد مكوّنات React، وFullend يولّد كود الربط بينها.
قواعد التحقق المتبادل
القيمة الجوهرية لـ Fullend تكمن في التحقق المتبادل.
OpenAPI ↔ DDL
| هدف التحقق | القاعدة |
|---|---|
| x-sort.allowed | هل العمود المقابل موجود في الجدول؟ |
| x-filter.allowed | هل العمود المقابل موجود في الجدول؟ |
| x-include.allowed | هل هو جدول مرتبط عبر علاقة FK؟ |
SSaC ↔ DDL
| هدف التحقق | القاعدة |
|---|---|
| @model Model.Method | هل الطريقة المقابلة موجودة في استعلامات sqlc؟ |
| @result Type | هل يتطابق مع النوع المشتق من جدول DDL؟ |
| @param الاسم | هل يمكن تحويله إلى عمود DDL؟ |
SSaC ↔ OpenAPI
| هدف التحقق | القاعدة |
|---|---|
| اسم الدالة | هل يتطابق مع operationId؟ |
| @param request | هل الحقل موجود في مخطط الطلب؟ |
| @result + response | هل الحقل موجود في مخطط الاستجابة؟ |
STML ↔ SSaC — كلاهما يشير إلى نفس operationId في OpenAPI. عند نجاح التحقق من كليهما، يُضمن تلقائيًا تطابق API التي تستدعيها الواجهة الأمامية مع API التي تعالجها الخلفية.
تصميم موجّه للوكلاء
Fullend مصمَّم لوكلاء الذكاء الاصطناعي.
ليتمكن الوكيل من كتابة المواصفات، عليه معرفة أنواع التسلسل العشرة في SSaC، وسمات data-* الاثنتي عشرة في STML، وامتدادات x- في OpenAPI، وقواعد مطابقة الأسماء. لذلك نوفّر دليلًا للذكاء الاصطناعي من نحو 350 سطرًا. يُضاف مرة واحدة إلى موجّه نظام الوكيل.
حلقة التحقق بعد كتابة المواصفات بسيطة:
سير عمل الوكيل:
1. تعديل specs/
2. fullend validate specs/
3. إذا وُجدت أخطاء → إصلاح SSOT المعني → العودة إلى 2
4. صفر أخطاء → fullend gen specs/ artifacts/
لا حاجة لفهم النظام بأكمله. يكفي إصلاح ما يشير إليه validate لاستعادة الاتساق. النماذج الذكية تصيب من أول محاولة، والنماذج الأصغر تصيب من الثالثة. النتيجة واحدة.
حجم SSOT حسب المشروع
| الحجم | مثال | SSOT | كود التنفيذ | نسبة شغل السياق |
|---|---|---|---|---|
| صغير | حجز صالون تجميل | ~1,500 سطر | ~10,000 سطر | ~8% |
| متوسط | بمستوى Jira أو Notion | ~12,500 سطر | ~100,000 سطر | ~55% |
| كبير | بمستوى Shopify | ~30,000 سطر | ~300,000 سطر | ~90% |
بناءً على سياق 200K توكن. حتى تطبيقات SaaS المتوسطة يمكن للوكيل قراءة تصميمها بالكامل دفعة واحدة.
تحويل الاستثناءات إلى أنماط
ما لا يمكن التعبير عنه بأنواع التسلسل العشرة يُحال إلى call. وما لا يمكن التعبير عنه بسمات data-* يُحال إلى custom.ts. إذا تجاوزت مخارج الطوارئ هذه 20% من الإجمالي، تفقد الهيكلة معناها.
لكن الاستثناء لحظة عزله يصبح قابلًا للملاحظة. عندما تُهيكَل مشاريع كثيرة بـ Fullend، ستظهر أنماط متكررة في call وcustom.ts.
أنواع التسلسل العشرة في SSaC لم تُصمَّم من البداية. بل تقاربت إلى 10 بعد مراقبة مئات من أكواد الخدمة. نتوقع أن يتكرر المبدأ نفسه مع مخارج الطوارئ. أنماط call المتكررة تصبح أنواع تسلسل جديدة، وأنماط custom.ts المتكررة تصبح سمات data-* جديدة.
الاستثناءات لا تتقلص — بل تنمو منها البنية.
توسيع مجموعة التقنيات
حاليًا Fullend مُثبَّت على Go + React + PostgreSQL + Terraform. هذا مقصود. في مرحلة إثبات المفهوم، الأولوية هي اختراق مجموعة تقنية واحدة بالكامل.
لكن 3 من أصل 5 مصادر SSOT (OpenAPI، SQL DDL، Terraform) مستقلة عن اللغة بالفعل. أنواع التسلسل العشرة في SSaC أنماط غير مرتبطة بلغة محددة — تُعبَّر فقط بتعليقات Go. وSTML تستخدم سمات HTML5 data-* فهي مستقلة عن الإطار.
التوسيع مسألة إضافة واجهات خلفية لتوليد الكود. منطق التحقق وقواعد التحقق المتبادل تبقى كما هي.
العلاقة مع GEUL
5 لغات DSL تشكّل SSOT للبرمجيات. وSSOT بيانات مهيكلة. والبيانات المهيكلة رسم بياني. والرسم البياني يمكن ترميزه بـ GEUL.
data-fetch="ListReservations" في STML هو علاقة بين كيانات. @sequence get → @model → @guard → @response في SSaC هو تسلسل أحداث. تعريف نقطة النهاية في OpenAPI هو عقد. كلها بنى دلالية يمكن التعبير عنها بأضلاع الثلاثي وأضلاع الحدث6 وعقد الكيان في GEUL.
الطريقة التي يجري بها Fullend التحقق المتبادل بين 5 لغات DSL — المطابقة الرمزية، والتحقق من تطابق الأنواع، والتحقق من سلامة المراجع — هي نفس مبدأ التحقق الآلي في تدفقات GEUL.
الترخيص
MIT — GitHub