أساسيات الهندسة الوكيلة: دورة مكثفة في 45 دقيقة
8 مفاهيم، و80% من الاستخدام الحقيقي
المتطلب السابق: الدورة المكثفة في البرمجة الوكيلة. تعلمك تلك الصفحة الأدوات (Claude Code، وOpenCode، وplan mode، وCLAUDE.md، والمهارات، وMCP، وhooks). أما هذه الصفحة فتعلمك الانضباط الذي تستخدم به تلك الأدوات. كلاهما يكمل الآخر: الأدوات بلا انضباط تنتج vibe code؛ والانضباط بلا أدوات يبقى نظرية.
"الكود ليس رخيصا. الكود السيئ أغلى مما كان في أي وقت مضى." مات بوكوك
"تدور vibe coding حول رفع الحد الأدنى لما يستطيع الجميع فعله في البرمجيات. أما agentic engineering فتدور حول الحفاظ على معيار الجودة الذي كان قائما من قبل في البرمجيات المهنية." أندريه كارباثي
تدور في الصناعة حكاية سائبة: الذكاء الاصطناعي نموذج جديد، لذلك لم تعد قواعد الهندسة القديمة تنطبق؛ والمواصفات هي الكود المصدري الجديد؛ والنموذج هو المترجم؛ ولا يهم الفرق ما دام البرنامج يعمل. هذه حكاية مريحة، لكنها خاطئة.
أطروحة هذا الفصل، والخيط الممتد في كل موظف رقمي بدوام كامل في هذا الكتاب، هي العكس. تزداد أهمية أساسيات البرمجيات في عصر الذكاء الاصطناعي عما كانت عليه قبله. والسبب آلي لا عاطفي. الواجهة التي تصممها هي الواجهة التي يتعلم منها الوكيل؛ والأسماء التي تختارها هي الأسماء التي يعيد استخدامها؛ والحدود التي ترسمها هي الحدود التي يحترمها. ينتج الوكيل داخل قاعدة كود نظيفة ومختبرة جيدا كودا أعلى بعدة درجات من الوكيل نفسه داخل قاعدة كود متشابكة. لم تعد البنية خاصية في الكود وحده؛ بل صارت مدخلا إلى الوكيل. الكود السيئ ينتج وكلاء سيئين. والكود الجيد ينتج وكلاء يبدون أكفاء على نحو لافت.
يعلمك هذا الفصل سير العمل الذي يجعل تلك الكفاءة قابلة للتكرار: مسارا من سبع مراحل (idea → grilling → PRD → issues → implementation → review → QA) منفذا عبر مهارات صغيرة وقابلة للتركيب تعمل بالطريقة نفسها في Claude Code وOpenCode. تنتقل المهارات والمواصفات والأنماط المعمارية المكتوبة لأحدهما إلى الآخر بلا تغيير. المنهج هو الثابت. والأداة هي المتغير.
بنهاية هذا الفصل ستكون قادرا على:
- تحديد موقعك على طيف vibe coding ↔ agentic engineering واختيار الانضباط الذي يناسب مخاطر عملك.
- تشخيص أنماط الفشل الستة في البرمجة بالذكاء الاصطناعي وتطبيق علاج كل واحد منها.
- تشغيل حلقة كاملة grill → PRD → vertical-slice issues → AFK implementation في Claude Code أو OpenCode.
- كتابة
SKILL.mdلا يحمّله الوكيل إلا عند الحاجة، بدلا من حرق tokens في كل دور. - إعادة هيكلة قاعدة كود من "shallow modules" إلى "deep modules" كي تعمل حلقات تغذية AI الراجعة فعلا.
- استخدام مفردات العمل بطلاقة: smart zone، dumb zone، clearing، compaction، handoff، AFK، tracer bullet، design concept، grilling، jagged intelligence.
لمحة عن مسار العمل
قبل أي نظرية، إليك الشكل التشغيلي الذي يعلمه الفصل. سبع مراحل، وخمس مهارات، واتجاه تدفق واحد. كل قسم لاحق إما يشرح صفا من الجدول أو يريه في الكود.
| # | المرحلة | ما الذي يحدث | المدخل → المخرج | المهارة | القسم |
|---|---|---|---|---|---|
| 1 | الفكرة → مفهوم متفق عليه | يحاورك الوكيل سقراطيا حتى يصبح التصميم مشتركا بينكما | رغبة → مفهوم تصميم | grill-me | §6.1 |
| 2 | المفهوم → الوجهة | يلخص المحادثة في PRD | محادثة → PRD | to-prd | §6.2 |
| 3 | PRD → قائمة عمل | يقسم PRD إلى تذاكر شرائح عمودية | PRD → tracer-bullet issues | to-issues | §6.3 |
| 4 | المسألة → شريحة | ينفذ شريحة واحدة مع الاختبار أولا | issue → reviewable diff | tdd | §6.4 |
| 5 | الشرائح → قائمة مستنزفة | تستنزف حلقة AFK الطابور داخل sandboxes | issues → PRs | (orchestrator) | §6.5 |
| 6 | الفرق → قرار | يقرأ الإنسان الفرق ويجري QA | PR → merge or new issue | (ذوق، لا أتمتة) | §6.6 |
| 7 | صحة قاعدة الكود باستمرار | يعثر على الوحدات السطحية ويقترح تعميقها | codebase → RFC | improve-codebase-architecture | §7.4 |
المراحل 1-3 هي وردية النهار: الإنسان داخل الحلقة. والمراحل 4-5 هي وردية الليل: يعمل الوكيل AFK داخل sandbox. المرحلة 6 تعود إلى وردية النهار. أما المرحلة 7 فتعمل وفق cron أسبوعي وتغذي مسائل جديدة إلى المرحلة 3. يعمل المسار كله بالطريقة نفسها في Claude Code وOpenCode.
هل أنت جديد في البرمجة؟ اقرأ هذا أولا.
يفترض هذا الفصل أنك كتبت كودا من قبل، واستخدمت
git، وشغلت حزمة اختبارات، وفتحت طلب دمج. إذا كانت هذه الأمور مألوفة، فتجاوز هذا المربع وتابع.أما إذا لم تكن مألوفة بعد، فسيبقى الفصل قابلا للقراءة بوصفه خريطة مفاهيمية. ستحصل على شكل سير العمل، والمفردات التي تحتاج إليها لفهم محادثات البرمجة بالذكاء الاصطناعي، وفهرس تشخيصي للفشل الشائع، والفلسفة المعمارية التي تجعل الوكلاء يعملون جيدا داخل قواعد كود حقيقية. لكنك لن تستطيع تشغيل أمثلة الكود بعد؛ فهذا يحتاج أولا إلى بضعة أسابيع من أساسيات البرمجة. المسار الصادق هو: اقرأ الفصل مرة كي تحصل على الخريطة، وتعلم المتطلبات السابقة، ثم عد واتبع الكود.
الحد الأدنى من المفردات اللازمة لمتابعة الأقسام المفاهيمية:
- مصطلح Repo (اختصار repository): مجلد كود المشروع، يتتبعه
git.- مصطلح Branch: نسخة موازية من المستودع تستطيع التجربة فيها من دون التأثير في الكود الرئيسي. Worktree مفهوم قريب: نسخة من المستودع على القرص مرتبطة بفرع.
- مصطلح Commit: لقطة محفوظة من التغييرات، معها رسالة قصيرة تصفها.
- مصطلح Pull request (PR): تغيير مقترح يرسل للمراجعة قبل دمجه في الفرع الرئيسي. وهو ما يراجعه البشر في المرحلة 6 من هذا الفصل.
- مصطلح Test / test suite: كود يفحص صحة كود آخر ويعمل آليا. تعني عبارة "Tests pass" أن كل الفحوص خرجت خضراء.
- مصطلح Sandbox (أو container): بيئة معزولة، كأنها حاسوب صغير محكم الإغلاق، يستطيع الوكيل أن يعمل داخله ويكتب الملفات ويكسر الأشياء من دون لمس بقية نظامك.
- مصطلح Token: وحدة النص التي يعالجها النموذج اللغوي. تعادل تقريبا ثلاثة أرباع كلمة في المتوسط. تسع نافذة سياق من 100k-token نحو 75,000 كلمة.
- مصطلح Terminal / shell / bash: الطريقة النصية لتشغيل الأوامر على الحاسوب. الأسطر التي تبدأ بعلامة
$في هذا الفصل هي أوامر تكتبها في الطرفية.
1. من Vibe Coding إلى الهندسة الوكيلة
تغير أمران في تتابع قريب. الأول جعل الثاني ضروريا.
1.1 البرمجيات 3.0: نموذج حوسبة جديد
يصف أندريه كارباثي البرمجيات عبر ثلاثة عصور. Software 1.0 هو ما قضى معظم المهندسين مسيرتهم في كتابته: كود صريح، تنفذه CPU، ويعمل على بيانات منظمة. Software 2.0 هو عصر الأوزان المتعلمة: البرمجة عبر تنسيق مجموعات البيانات وتدريب الشبكات العصبية بدلا من كتابة منطق تفريعي. Software 3.0 هو العصر الذي نعيشه الآن: البرمجة عبر prompting، حيث يكون LLM نوعا من الحاسوب القابل للبرمجة، وما تضعه في نافذة السياق هو الذراع الذي تحركه به.
ما يتغير بين العصور هو الأثر الذي تنتجه. في 1.0 كان الأثر كودا قابلا للتنفيذ. وفي 3.0 صار الأثر على نحو متزايد قطعة نص موجهة إلى وكيل. عندما يشحن OpenCode مثبته، فهو لا يشحن سكربت bash؛ بل يشحن فقرة بلغة طبيعية مخصصة للصقها في وكيل برمجة. يقرأ الوكيل البيئة، وينقح داخل الحلقة، ويصل إلى تثبيت عامل. لم يعد المثبت برنامجا؛ صار مهارة.
يتسع هذا النمط. فالتوثيق المكتوب للبشر ("اذهب إلى هذا الرابط، واضغط Settings...") يتحول إلى توثيق مكتوب للوكلاء ("أعط هذا لوكيل البرمجة لديك وسيضبط مشروعك"). لم تعد واجهات المستخدم هي الواجهة الوحيدة؛ صار الوكيل مستخدما من الدرجة الثانية لكل نظام تبنيه، ولكل نظام تعتمد عليه. البنية التحتية المهيأة للوكلاء (واجهات API، والتوثيق، والأدوات، ومسارات النشر المصممة للوكلاء أولا) هي طبقة المنصة التالية.
يتناول هذا الفصل العمل داخل Software 3.0. فالمهارات (§5) آثار من 3.0. وPRDs والتذاكر (§6) آثار من 3.0. وملفا AGENTS.md وCONTEXT.md (§3، الفشل 2) أثران من 3.0. والكود نفسه صار على نحو متزايد تابعا لكل ذلك.
1.2 يرفع Vibe Coding الأرضية؛ وتحفظ الهندسة الوكيلة السقف
صاغ كارباثي أيضا مصطلح vibe coding: أن تترك الوكيل يكتب الكود، وتقبل مخرجه من دون قراءة الفرق، وتحكم عليه بحسب ما إذا كان البرنامج يعمل. هذه ممارسة حقيقية ومفيدة وباقية. بها يستطيع غير المبرمج أن يشحن أداة نافعة في عطلة نهاية أسبوع؛ وبها يصف كارباثي بناء MenuGen، مشروعه الجانبي الذي يحول صور قوائم المطاعم إلى قوائم تعرض صور الأطباق. يرفع vibe coding أرضية ما يستطيع الفرد إنتاجه في البرمجيات. وآثار رفع تلك الأرضية الاقتصادية كبيرة، وغالبا جيدة.
لكن انضباطا ثانيا يظهر الآن فوق ذلك: agentic engineering. حيث يرفع vibe coding الأرضية، تحفظ agentic engineering السقف: معيار جودة البرمجيات المهنية. ينجز الوكيل معظم الكتابة؛ لكنك تبقى مسؤولا عن الأمان، وسلامة البيانات، وقابلية الصيانة، والعقود، وتجربة المستخدم. لا يقدم vibe coding الثغرات من تلقاء نفسه؛ المهندس الذي يستخدمه بإهمال هو من يفعل ذلك. لا يتحرك المعيار لمجرد أن الكاتب تغير.
| Vibe coding | Agentic engineering | |
|---|---|---|
| الهدف | رفع أرضية ما يمكن بناؤه | حفظ سقف ما يعد مهنيا |
| المراجع | غالبا لا يوجد؛ الحكم بحسب هل يعمل | يقرأ الإنسان الفرق؛ وفوقه مراجعة آلية |
| البنية | ما يخرجه الوكيل | يصممها المهندس؛ وينفذها الوكيل |
| الاختبارات | اختيارية | غير قابلة للتفاوض؛ TDD على المسار الحرج |
| صحة قاعدة الكود | يقبل الانجراف | إعادة هيكلة وفق جدول؛ وتعميق الوحدات |
| التعامل مع الفشل | "يعمل عندي" | قابل للإعادة؛ مختبر؛ ومفسر |
| الموضع المناسب | مشاريع جانبية، نماذج أولية، أدوات مؤقتة | أنظمة إنتاج، عمل منظم، وأي شيء متعدد المستخدمين |
المبادئ وسير العمل في هذا الفصل هي انضباط الهندسة الوكيلة، لا حرية vibe coding. عندما تبني موظفا رقميا بدوام كامل ستثق به مؤسسة في كشوف الرواتب، أو تصعيدات العملاء، أو التسويات المالية، فvibe coding يعد سوء ممارسة. تحتاج إلى الأرضية والسقف: إنتاجية أعلى وجودة محفوظة.
الفجوة بين مهندس وكيلي متوسط ومهندس قوي أوسع بكثير من فجوة "10× engineer" القديمة. يقول كارباثي: "ليست 10× هي التسريع الذي تحصل عليه. الناس البارعون جدا في هذا يبلغون ذروة أعلى بكثير من 10× من وجهة نظري الآن." وإغلاق تلك الفجوة هو عمل هذا الفصل.
2. ثلاثة قيود يرثها كل وكيل برمجة
وكيل البرمجة ليس مهندسا سحريا؛ بل هو نموذج ملفوف داخل harness. تشكل ثلاث خصائص لهذا الزوج كل سير عمل نبنيه فوقه: ميزانية انتباه محدودة، ولا حالة دائمة، وملف قدرات متعرج.
2.1 المنطقة الذكية والمنطقة الغبية
عندما يتنبأ النموذج بالرمز التالي (قطعة نص تعادل تقريبا ثلاثة أرباع كلمة إنجليزية)، يزن كل رمز آخر موجودا بالفعل في نافذة السياق. لكل رمز ميزانية انتباه محدودة: نصيب ثابت من التأثير ينفقه على البقية. نافذة من N رمزا فيها تقريبا N² علاقة انتباه تتنافس على تلك الميزانية الثابتة.
النتيجة غير قابلة للتفاوض. في بدايات الجلسة يكون الوكيل في المنطقة الذكية: حادا، مركزا، وتذكره جيد. ومع نمو الجلسة، تضعف إشارة كل رمز بسبب المنافسين. ينجرف الوكيل إلى المنطقة الغبية: ينسى المخطط الذي لصقته في الأعلى، ويخترع حقولا غير موجودة في ملف الأنواع، ويربط متغيرين لهما الاسم نفسه ربطا خاطئا، ويناقض استدلاله السابق. النموذج نفسه، والمعاملات نفسها؛ لكن أفواها أكثر تأكل من الطبق نفسه.
يقع السقف العملي في أعمال البرمجة، عبر نماذج الطليعة الحالية، أدنى بكثير من النافذة المعلنة بصرف النظر عما إذا قالت الدعاية 200k أو 1M. تتقارب تقارير الممارسين حول نحو 100k tokens كخط ماء تقريبي قبل أن يبدأ الانجراف بالظهور، لكن الرقم الدقيق أقل أهمية من الشكل: بعد جزء ما من النافذة المعلنة، لم تحصل على قدرة أكثر؛ بل حصلت على منطقة غبية أكبر تنفق فيها المال. تساعد النوافذ الأكبر في retrieval عبر المستندات الطويلة؛ لكنها لا تمد reasoning في الكود بالمعامل نفسه.
Token usage: 0k ────────── 50k ────── 100k ────── 200k ────── 1M
Quality: ████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░
↑ ↑
smart zone dumb zone begins
كيف يبدو الانتقال في جلسة حقيقية؟ تقريبا هكذا:
turn 5 → you paste users.ts schema (8 fields: id, email, name, ...)
turn 9 → agent uses User.email correctly
turn 23 → agent builds a route, refers to User.id, all good
turn 47 → context is now ~80k tokens
turn 52 → agent writes user.emailAddress ← field doesn't exist
turn 55 → agent invents user.preferences ← also not in the schema
⇒ smart zone exited.
⇒ /clear, re-paste schema in a fresh session, continue.
النموذج نفسه، والتعليمة نفسها عند الدور 52 كما عند الدور 9. الشيء الوحيد الذي تغير هو ميزانية الانتباه. العلاج ليس الدفع إلى الأمام. اجعل حجم كل وحدة عمل مناسبا للمنطقة الذكية، وعندما تنتهي الوحدة، ارم الجلسة وابدأ جلسة جديدة.
2.2 مشكلة Memento
النماذج عديمة الحالة. لا تحمل شيئا عبر طلبات مزود النموذج. الاستمرارية داخل الجلسة هي أن يعيد harness تغذية السياق في كل دور؛ أما الاستمرارية بين الجلسات فهي شيء كتبه نظام ذاكرة إلى القرص وأعاد تحميله عند بداية الجلسة التالية.
هذه ميزة. أكثر ما يمكن الاعتماد عليه في الوكيل هو أن مسح السياق يعيده إلى حالة معروفة وجيدة. الوكيل الذي قضى أربعين دورا ينزلق إلى المنطقة الغبية هو الوكيل نفسه الذي سيقرأ تعليمتك الجديدة، بعد خمس ثوان من /clear، بميزانية انتباه جديدة وينتج عملا ممتازا.
توجد طريقتان للتعافي عندما تنتفخ الجلسة:
- المسح (Clearing): إنهاء الجلسة وبدء جلسة جديدة. إعادة ضبط كاملة.
- الضغط (Compaction): تلخيص الجلسة السابقة وبذر جلسة جديدة بالملخص. عملية فاقدة.
يميل معظم المطورين إلى compaction أولا لأنه يبدو أقل تدميرا. عامل هذا الحدس بريبة: يحفظ compaction بعض استدلال المنطقة الغبية الذي أوقعك في المشكلة. أما clearing، إذا اقترن بأثر تسليم صغير مكتوب (PRD، أو تذكرة، أو AGENTS.md)، فيمنح الجلسة التالية حالة بدء واحدة في كل مرة. البدايات المتوقعة تنتج نهايات متوقعة.
مبدأ العمل. عامل الوكيل مثل بطل Memento. خطط حول نسيانه. اجعل كل حقيقة مهمة تبقى في البيئة (
AGENTS.md، أوCONTEXT.md، أو مهارة، أو تذكرة)، لا في سجل المحادثة.
2.3 الذكاء المتعرج
يتعلق القيدان الأولان ب_مقدار_ ما يستطيع الوكيل الانتباه إليه. أما القيد الثالث فيتعلق ب_ما_ يجيده، وهو القيد الذي يفاجئ المهندسين أكثر من غيره.
النماذج اللغوية الكبيرة متعرجة. فهي ليست ذكية بالتساوي؛ تبلغ قمما حادة في مجالات معينة وتتجمد في أخرى، مع ارتباط ضعيف بمدى صعوبة المهمة كما يراها الإنسان. يستطيع نموذج حديث جدا إعادة هيكلة قاعدة كود من مئة ألف سطر أو العثور على ثغرة zero-day، وفي الجلسة نفسها أن ينصحك بالمشي إلى مغسلة سيارات تبعد خمسين مترا بدلا من القيادة إليها. لا يصل بين القدرتين إلا نوع بيئات RL التي صادف أن دربتها المختبرات عليها.
تدرّب نماذج الطليعة بكثافة عبر التعلم المعزز على مهام يكون مخرجها قابلا للتحقق: مسائل رياضيات لها إجابات قابلة للفحص، وكود يترجم ويمرر الاختبارات، وبراهين شكلية. يتعلم النموذج ببراعة داخل تلك الدوائر لأن إشارة المكافأة نظيفة. وخارجها يعمل بحدس ما قبل التدريب بلا تغذية راجعة مماثلة تصقله. يبدو ملف القدرات كسلسلة جبال بواد عميقة: قمم عند البرمجة التنافسية وإعادة هيكلة الكود، وواد عند التخطيط المنطقي لمسافات العالم الفيزيائي.
capability
│
│ ╱╲ ╱╲
│ ╱ ╲ ╱╲ ╱ ╲
│ ╱ ╲ ╱ ╲ ╱ ╲ ╱╲
│ ╱ ╲╱ ╲╱ ╲ ╱ ╲
│ ╱ ╲ ╱ ╲___
└────────────────────────────────────────► task
code refactor math car-wash common-sense
walking physical reasoning
لقيد الذكاء المتعرج أربع نتائج تشغيلية.
أولا، الكود هو المجال المحظوظ. أنت تعمل داخل إحدى أعمق القمم على السطح كله، لا لأن البرمجة أسهل بطبيعتها، بل لأن المختبرات أعطتها أولوية اقتصادية ودربت النماذج عليها بكثافة. تعامل مع ذلك بوصفه حظا جيدا، لا دليلا على أن النموذج "ذكي". خارج هذه القمة، قد يكون النموذج نفسه واثقا وخاطئا في أمور يصيبها طفل.
ثانيا، تبقيك حلقات التغذية الراجعة داخل الدوائر القابلة للتحقق. الأنواع الساكنة، والاختبارات الآلية، والlint، وأخطاء الترجمة هي إشارة المكافأة نفسها التي تدرب النموذج عليها. عندما يشغل الوكيل اختباراتك ويراها تفشل، فهو يعمل داخل شكل التغذية الراجعة الذي أنتج أقوى سلوكياته أثناء التدريب. ومن دون تلك الإشارات يعود إلى حدس ما قبل التدريب بلا تصحيح. هذا هو السبب الأعمق وراء الفشل 3 ومهارة tdd: لا تكتفي الاختبارات بالتقاط الأخطاء؛ بل تبقي الوكيل على القمة.
ثالثا، عليك أن تعرف أي دائرة أنت داخلها. عندما يفعل الوكيل شيئا لا يفعله مهندس مبتدئ، فغالبا لأنك غادرت القمة ودخلت منطقة لم تدربها المختبرات جيدا. يسأل كارباثي: "لماذا تراجع المستخدمين بالبريد الإلكتروني بدلا من user_id صريح؟" بعد أن رأى وكيله يفعل ذلك بالضبط في مشروع MenuGen. كان الوكيل خارج أقوى دوائره في نمذجة الهوية عبر خدمات خارجية. لم يكن العلاج تعليمة أفضل؛ بل كان تدخل كارباثي بتوجيه معماري صريح.
رابعا، عندما تبدأ من الصفر، اختر مكدسك بحيث يقع داخل قمة. ليست خريطة التعرج متماثلة عبر اللغات والأطر. يتحدث بوريس تشيرني بوضوح عن سبب بناء Claude Code بTypeScript وReact: "إنه on distribution جدا بالنسبة إلى النموذج." عندما تسمح القيود الأخرى، فضل الخيارات السائدة: Python وTypeScript على اللغات النادرة، وPostgres على المخازن الغريبة، والأطر الشائعة على الحلول اليدوية. أنت لا تختار التقنية التي كنت ستكتب بها وحدك؛ بل تختار ما تكتبه قوة عملك الوكيلة جيدا. ستلحق الذيل الطويل لاحقا؛ وحتى ذلك الحين، تشتري الخيارات on-distribution سنوات من الرفع الفعال.
حيوانات أم أشباح. يصف كارباثي النماذج اللغوية الكبيرة بأنها أشباح لا حيوانات: محاكاة إحصائية شكلتها البيانات والمكافأة، لا ذكاءات بيولوجية شكلها التطور. النتيجة: الصراخ على الوكيل لا يحسنه؛ والتعاطف معه لا يحسنه؛ و_"think step by step"_ لا يوقظ إدراكا نائما. ما يعمل هو وضع الوكيل على قمة (سياق واضح، وتغذية راجعة قابلة للتحقق، وكود حسن التسمية، ومواصفة دقيقة) ثم ترك السلوك المدرب يعمل. عامل نفسية الوكيل كفيزياء، لا كشخصية.
3. أنماط الفشل الستة في البرمجة بالذكاء الاصطناعي
تنتج القيود الثلاثة فشلا متوقعا. تظهر ستة أنماط منها كثيرا بما يكفي للتعامل معها كفهرس مغلق. الجدول التالي هو أداة التشخيص؛ وتوسع الفقرات اللاحقة كل صف إلى العرض، والسبب الجذري، والعلاج الذي يشفّره بقية الفصل كمهارة.
| # | العرض | السبب الجذري | العلاج | المهارة | أين |
|---|---|---|---|---|---|
| 1 | "لم يفعل الوكيل ما أردته." | لا يوجد مفهوم تصميم مشترك بينك وبين الوكيل | فرض التوافق قبل كتابة أي أثر، عبر مقابلة سقراطية | grill-me | §5، §6.1 |
| 2 | "الوكيل كثير الكلام جدا." | لا توجد لغة مشتركة؛ تسمي أنت والوكيل الشيء نفسه بأسماء مختلفة | حفظ CONTEXT.md لمصطلحات المجال وتحميله في كل جلسة | grill-with-docs | §5، §6.1 |
| 3 | "الكود لا يعمل." | حلقات تغذية راجعة ضعيفة؛ الوكيل يبرمج أعمى | بيئة صاخبة (أنواع، اختبارات، lints) + TDD red-green-refactor | tdd | §5، §6.4 |
| 4 | "بنينا كرة طين." | وحدات سطحية؛ ينتجها الوكلاء أسرع مما ينظفها البشر | الاستثمار يوميا في تصميم الوحدات؛ وتمرير تعميق دوري | improve-codebase-architecture | §7 |
| 5 | "ذهني لا يلحق." | تقرأ كل سطر بسرعة 5× من الوتيرة الطبيعية | مبدأ gray-box: صمم الواجهات وفوض التنفيذ | (عادة معمارية) | §7.3 |
| 6 | "أراجع كودا أكثر مما أبني." | انتقل عنق الزجاجة إلى المراجعة بعد ارتفاع الإنتاجية | قسّم المراجعة إلى طبقتين آلية وبشرية؛ تحافظ الشرائح العمودية على صغر الفروق | automated-review (وصفة في §6.5؛ ليست في الحزمة upstream) | §6.5، §7 |
الفشل 1: "لم يفعل الوكيل ما أردته."
أكثر الفشل شيوعا هو سوء التوافق. كانت لديك صورة واضحة للميزة؛ وبنى الوكيل شيئا مختلفا قليلا؛ ثم اختلفتما حتى على معنى "انتهى". هذه مشكلة تواصل، لا مشكلة نموذج. سمى فريدريك بروكس الشيء المفقود في The Design of Design: مفهوم التصميم، أي الفكرة المشتركة والمؤقتة لما يبنى. PRDs والمواصفات والمحادثات آثار تحاول التقاط مفهوم التصميم؛ لكنها ليست هو.
العلاج: أجبر مفهوم التصميم على الاستقرار قبل كتابة أي كود أو أثر رسمي. التقنية هي grilling: يحاورك الوكيل سقراطيا، قرارا بعد قرار، ويمشي عبر كل فرع من شجرة التصميم، ويقترح توصيته لكل سؤال، حتى يتوافق الطرفان. يبين القسم 5 المهارة.
الفشل 2: "الوكيل كثير الكلام جدا."
الوكيل الجديد الذي يهبط في مشروعك لا يعرف مصطلحاتك. تسمي قاعدة الكود عندك الأشياء lessons ويسميها الوكيل course units. يقول فريقك materialisation cascade فيكتب الوكيل فقرة تصف الفكرة نفسها. أنتما تتكلمان حول بعضكما وتحرِقان tokens في ذلك.
هذه هي المشكلة نفسها التي حلها التصميم المدفوع بالمجال قبل أكثر من عشرين عاما: اللغة الشاملة. يحتاج المشروع إلى مفردات مشتركة واحدة يستمد منها الكود والاختبارات والمحادثة والتوثيق. ومع الوكلاء لها فائدة ثانية: المفردات الأدق تعني tokens تفكير أقل في فك الالتباس، وانتباه أكثر للمهمة.
العلاج: حافظ على CONTEXT.md في جذر المستودع، وفيه مصطلحات مجال المشروع، وحمّله في كل جلسة. يبين القسم 5 كيف يقترن grilling وCONTEXT.md في المهارة نفسها.
الفشل 3: "الكود لا يعمل."
توافقت مع الوكيل. كتبت مواصفة نظيفة. أنتج الوكيل كودا، والكود مكسور، أحيانا بوضوح، وأحيانا بصمت. التشخيص شبه الدائم هو ضعف حلقات التغذية الراجعة. الوكيل يبرمج أعمى.
يحذر كتاب The Pragmatic Programmer من تجاوز مدى المصابيح الأمامية: أخذ مهام أكبر مما تستطيع سرعة التغذية الراجعة إنارته. يفعل الوكلاء ذلك باستمرار، وبأسوأ من البشر، لأنهم سيكتبون بسرور ألف سطر قبل فحص ما إذا كان أي منها يترجم. تحدد جودة التغذية الراجعة التي توفرها البيئة الذكاء الفعال لوكيل البرمجة.
العلاج: اجعل البيئة صاخبة: أنواع ساكنة، واستيرادات مفحوصة بالأنواع، واختبارات آلية، وlints سريعة، وhook قبل commit، ووصولا إلى المتصفح عندما يكون العمل بصريا. ثم افرض التطوير المدفوع بالاختبارات كي يأخذ الوكيل خطوات صغيرة ومقصودة: اختبار فاشل، اجعله ينجح، أعد الهيكلة، وكرر. تشفر مهارة tdd في §5 ذلك.
الفشل 4: "بنينا كرة طين."
يسرع الوكلاء كل شيء، بما في ذلك سرعة تحول قاعدة الكود إلى شيء غير قابل للصيانة. من دون تدخل ينتجون وحدات سطحية (كثير من الملفات الصغيرة التي تعرض كثيرا من الدوال الصغيرة، مع اعتماديات ضمنية تمتد بينها)، لأن توليد الوحدات السطحية واحدة تلو الأخرى أسهل. والوكيل الذي لا يستطيع التنقل داخل قاعدة كوده ينتج كودا أسوأ مع كل تمريرة. تصبح قاعدة الكود حلقة سم.
يقدم جون أوسترهاوت، في A Philosophy of Software Design، البديل: الوحدات العميقة. وحدات قليلة كبيرة بواجهات بسيطة وكثير من الوظائف مخبأة خلفها. الوحدات العميقة أسهل على الوكلاء في الاختبار (حد الاختبار هو الواجهة)، وأسهل في الفهم (لا يحتاج المستدعون إلى معرفة التنفيذ)، وأسهل في التفويض (أنت تصمم الواجهة، والوكيل يكتب التنفيذ).
العلاج: استثمر في تصميم الوحدات كل يوم (كنت بك)، وشغل improve-codebase-architecture دوريا للعثور على الوحدات السطحية واقتراح تعميقها. يغطي القسم 7 المبادئ بعمق.
الفشل 5: "ذهني لا يلحق."
هذا نمط فشل مفاجئ وجاد. كثيرا ما يذكر المهندسون الكبار عند العمل مع الوكلاء لأول مرة أنهم صاروا أكثر تعبا، لا أقل، رغم أنهم يشحنون كودا أكثر. عندما ينتج الوكيل الكود بثلاث إلى خمس مرات الوتيرة الطبيعية، يحمل المهندس النظام كله في رأسه بال_وتيرة الجديدة_. ومن دون انضباط معماري، تتضاعف الحمولة المعرفية بدلا من أن تنقسم.
العلاج: مبدأ gray box. صمم واجهات الوحدات بكل انتباهك؛ وفوض التنفيذ إلى الوكيل؛ وتحقق من الوحدة من الخارج عبر اختباراتها، لا بقراءة كل سطر داخلها. أنت تحمل الخريطة المعمارية؛ والوكيل يملأ الطوب. يوسع القسم 7.3 ذلك.
الفشل 6: "أراجع كودا أكثر مما أبني."
هذا الوجه الآخر للإنتاجية. بمجرد أن يشحن الوكيل بسرعة، ينتقل عنق الزجاجة إلى مراجعة الكود، ويتمدد عمل المراجعة حتى يملأ المساحة. العلاج هو تقسيم المراجعة إلى طبقتين: طبقة آلية عالية الإنتاجية تلتقط معظم القضايا الروتينية، وطبقة بشرية منخفضة الإنتاجية تركز على ما لا تستطيع الطبقة الآلية التقاطه.
العلاج: مهارة automated-review تعمل في جلسة جديدة، ولا تتلقى إلا الفرق، ومعايير ترميز المشروع، وقائمة تحقق أمنية، ثم تنتج تعليقا منظما على PR قبل أن يفتحه الإنسان. شغلها قبل الدمج كخطوة CI؛ فهي تلتقط تراجعات العقود، والاختبارات الناقصة، وأنماط الأمان المضادة الشائعة، ومخالفات أعراف المشروع. يصل المراجع البشري إلى PR مفروز مسبقا، وقد تحرر انتباهه للذوق، وملاءمة المنتج، والقرارات الغامضة التي رفعتها الطبقة الآلية. تحافظ الشرائح العمودية (§6) على صغر كل فرق؛ وتسمح حلقات المراجعة المستمرة (§6.5.3) للمراجع الآلي بالعمل وفق جدول بدلا من وقت الدمج فقط. لا يلغي أي من ذلك المراجعة البشرية؛ بل ينقل انتباه الإنسان إلى الموضع الذي لا يمكن استبدال الحكم فيه.
هذه هي أنماط الفشل الستة التي يزيلها بقية الفصل، بالترتيب.
4. سير العمل من البداية إلى النهاية
كل ما يلي يتدلى من هذا الهيكل: شكل المسار كله، مثبتا في الذهن قبل النزول إلى المهارات والكود.
4.1 نموذج وردية النهار ووردية الليل
هناك نوعان من العمل. يتطلب عمل الإنسان داخل الحلقة شخصا على لوحة المفاتيح يجيب عن الأسئلة ويتخذ أحكاما: التوافق، والتصميم، والذوق، وQA. أما عمل AFK ("away from keyboard") فيعمل بلا حضور داخل sandbox ويريك الفرق في الصباح: التنفيذ، وإعادة الهيكلة، وملء الاختبارات.
يتناوب المسار:
كل انتقال هو handoff. وكل handoff يتوسطه أثر صغير ودائم (CONTEXT.md، أو PRD، أو تذكرة، أو فرق)، لا جلسة طويلة مستمرة. تموت الجلسات الطويلة في المنطقة الغبية؛ أما الآثار الدائمة فتعيش إلى الأبد. هذه هي البصيرة المعمارية التي تجعل البقية تعمل.
4.2 حدود "من المواصفات إلى الكود"
المواصفات مفيدة. PRDs في §6.2 مواصفات. والمسائل في §6.3 مواصفات مصغرة. وCONTEXT.md مواصفة. لكن الحجة هنا أضيق من رفض عام: إنها ضد التعامل مع المواصفات كأنها سير العمل كله، حيث تكتب مواصفة، وتترجمها عبر وكيل، وتتجاهل الكود الناتج، وإذا حدث خطأ تعدل المواصفة وتعيد الترجمة. بوصفها مرحلة من المسار، المواصفات أساسية. وبوصفها حلقة مغلقة تستبدل بقية المسار، تنهار لسببين.
الكود هو ساحة المعركة. تختبئ داخل الكود قيود لم تتوقعها المواصفة: الوحدة الحالية التي يجب أن تندمج معها الميزة، وشكل البيانات الذي تعيده قاعدة البيانات فعلا، والخطأ الذي لا يظهر إلا عندما تكون الذاكرة المؤقتة باردة. المواصفة التي لا تستجيب لهذه القيود تبتعد أكثر عن الواقع مع كل إعادة ترجمة، وكل جولة تنتج كودا أسوأ من السابقة لأن الوكيل يرث تاريخا أطول من الاقتراحات غير المتجذرة.
تتقادم المواصفات. ملف gamification-prd.md المكتوب في مارس يصبح، بحلول يوليو، مستندا عن نظام لم يعد موجودا: تغيرت الأسماء، وتحركت الحدود، وتطورت المتطلبات. الوكيل الذي يحمّل تلك المواصفة كي "يوسع" النظام يرث مشكلة faithfulness قبل أن يكتب سطرا واحدا.
النموذج الصحيح هو نموذج §4.1: المواصفات آثار handoff في مرحلة واحدة من المسار، لا مصدر الحقيقة للنظام. توجه جلسة أو جلستين من التنفيذ، ثم تتقاعد. ما يبقى هو الكود، والاختبارات، وCONTEXT.md.
يشير كارباثي إلى الملاحظة نفسها حول plan mode: يسرع إلى إنتاج أثر قبل أن يستقر الاستدلال، بينما الخطوة الصحيحة هي أن "تعمل مع وكيلك لتصميم مواصفة مفصلة جدا" قبل كتابة أي كود. مسار grilling ثم PRD ثم issues هو شكل ذلك: يندفع plan mode إلى الأثر؛ أما المسار فيصل أولا إلى مفهوم تصميم ثم يترك الأثر يخرج منه.
4.3 الشرائح العمودية وTracer Bullets
أهم قرار شكلي في §4.1 هو كيفية تقسيم PRD إلى مسائل. الإغراء هو التقسيم الأفقي: مسألة لقاعدة البيانات، وأخرى لAPI، وثالثة للواجهة. هذا خطأ. مع التقسيم الأفقي لا يحصل الوكيل على تغذية راجعة من البداية إلى النهاية حتى تهبط المسألة الثالثة؛ وتتراكم الأخطاء عند الحدود؛ وقد توقف أي مسألة المسائل الأخرى.
الشكل الصحيح هو الشريحة العمودية، أي tracer bullet، بعد تشبيه The Pragmatic Programmer بالطلقات المضيئة التي تسمح لرامي المدافع المضادة للطائرات برؤية اتجاه النيران. أطلق tracer لترى هل التصويب صحيح، ثم أطلق بالكامل وأنت تعرف أنك ستصيب.
يمر القسم 6.3 بما تبدو عليه الشرائح العمودية في المثال العملي، بما في ذلك كيف يسمح رسم الاعتماديات بين الشرائح بالتنفيذ المتوازي. أما الآن، فيكفي المفهوم: تشحن كل مسألة مسارا من البداية إلى النهاية؛ ويخرج التسلسل من الاعتماديات، لا من المراحل.
5. المهارات كعملية مشفرة
يحتاج كل علاج إلى تشفيره كأثر قابل لإعادة الاستخدام والتحميل من الوكيل. هذا الأثر هو مهارة.
المبدأ مقابل النسخة. تدير هذا المسار خمسة مبادئ: grilling، وتلخيص PRD، والتقسيم إلى شرائح عمودية، وTDD، والتعميق. لكل مبدأ تنفيذ حالي من الدرجة الأولى في حزمة مهارات أحدهم. تتطور التنفيذات؛ أما المبادئ فلا. السجل الحي لمهارات المجتمع هو skills.sh؛ وتعيش حزمة مات بوكوك في skills.sh/mattpocock، وهي تمد الأمثلة العملية أدناه. عندما تظهر نسخة أفضل من
grill-meفي الربع القادم، بدّل النسخة؛ مبدأ grilling في مسارك لا يتحرك. الثابت المعماري هو نفسه الذي يعلمه §7.3 على مستوى الكود: الواجهة مستقرة؛ والتنفيذ قابل للتغيير.
5.1 ما المهارة، وما ليست عليه
مهارة (اسم): قدرة قابلة للتعليم ومجمعة كوحدة واحدة (تعليمات وموارد لأداء مهمة واحدة جيدا)، محفوظة في البيئة، ولا تحمّل إلى نافذة السياق إلا عندما تكون ذات صلة. إنها وحدة الإفصاح التدريجي في harness.
المهارة هي ما يقرأه الوكيل؛ أما الأداة فهي ما يستدعيه الوكيل. قد تقول مهارة: "عندما يطلب المستخدم نشرا، شغل bash deploy.sh وتحقق بأداة gh": المهارة هي النثر؛ وbash وgh هما الأداتان.
والمهارة أيضا عند الطلب. يحمّل AGENTS.md في كل دور، ويدفع تكلفة tokens في كل طلب إلى مزود النموذج؛ أما المهارة فلا تحمّل إلا عندما يقرر الوكيل أنها لازمة. كل ما لا يحتاج أن يكون في السياق كل دور مكانه مهارة، لا AGENTS.md. هذا هو الإفصاح التدريجي عمليا.
والمهارة قابلة للنقل. يعمل SKILL.md نفسه في Claude Code وOpenCode بلا تغيير. يسافر الانضباط مع الملف؛ أما harness فمتبادل.
5.2 أين تعيش المهارات
يفحص كلا harnesses أدلة معروفة عند بدء الجلسة، ويقرآن YAML frontmatter لكل SKILL.md، ويعرضان الأسماء والأوصاف على الوكيل. لا يحمّل المتن إلا عندما يقرر الوكيل أن المهارة ذات صلة.
يثبت skills CLI حزمة مجتمع داخل .agents/skills/، وهو الموضع القياسي العابر للأدوات. يبدو دليل المهارات المثبتة هكذا:
project/
└── .agents/
└── skills/
└── grill-me/
└── SKILL.md
يعمل تنسيق SKILL.md نفسه في كلا harnesses بلا تغيير. الاختلاف هو الأدلة التي يفحصها كل harness، وهذا يغير خطوة واحدة من التثبيت.
يفحص Claude Code 2.1.141 المسار .claude/skills/<name>/SKILL.md (وعالميا ~/.claude/skills/). ولا يفحص .agents/skills/. يثبت skills CLI في .agents/skills/، ولا يربط التثبيت إلى .claude/skills/ إلا عندما يكون ذلك الدليل موجودا سلفا. لذلك أنشئه أولا، ثم ثبت:
mkdir -p .claude/skills
npx skills@latest add mattpocock/skills
عندما يكون .claude/skills/ موجودا قبل التثبيت، ترتبط كل مهارة داخله ويكتشف Claude Code الحزمة. (إذا ثبت أولا ولم يجد Claude Code الأمر /grill-me، فالسبب هو الدليل المفقود: أنشئ .claude/skills/، ثم أعد التثبيت.)
استدع المهارة بأن تطلب ذلك بلغة طبيعية ("grill me on this plan")، فيحمّلها الوكيل عند مطابقة وصف frontmatter. ويقبل Claude Code أيضا استدعاء صريحا بشرطة مائلة: اكتب /grill-me لتحميل تلك المهارة بالاسم.
يفحص OpenCode المسار .agents/skills/ مباشرة، لذلك لا يحتاج التثبيت إلى خطوة إضافية:
npx skills@latest add mattpocock/skills
يفحص OpenCode أيضا .opencode/skills/<name>/SKILL.md (موضعه الخاص والأعلى أولوية) و.claude/skills/<name>/SKILL.md (متوافقا مع Claude)، إضافة إلى المواضع العالمية ~/.config/opencode/skills/ و~/.claude/skills/ و~/.agents/skills/. يسقط SKILL.md المكتوب لClaude Code في أي من هذه المواضع ويعمل بلا تغيير. يصعد OpenCode من الدليل الحالي إلى جذر git worktree ويلتقط المهارات على الطريق؛ وهذا مفيد في monorepos حيث يمكن لحزمة فرعية أن تملك مهاراتها الخاصة.
استدع المهارة بأن تطلب ذلك بلغة طبيعية. يعرض OpenCode كل مهارة متاحة للوكيل كأداة skill يستدعيها عندما يطابق وصف frontmatter الطلب، لذلك يقود جودة الوصف التحميل كما في Claude Code.
تنسيق واحد، وكلا harnesses، ولا خطوة ترجمة. مسار التثبيت هو الشيء الوحيد الذي يختلف، ويختلف بأمر mkdir واحد.
5.3 تشريح ملف SKILL.md
يتكون SKILL.md من جزأين: YAML frontmatter (البيانات الوصفية التي يفحصها harness) ومتن markdown (التعليمات التي يقرأها الوكيل عند التحميل).
أكثر مهارة حصولا على النجوم في حزمة مات بوكوك، grill-me، موجودة هنا كاملة: سبعة أسطر من المتن.
---
name: grill-me
description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
---
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
Ask the questions one at a time.
If a question can be answered by exploring the codebase, explore the codebase instead.
هذه هي المهارة كلها، وgrill-me هي أكثر مهارة استخداما في حزمة جذبت عشرات الآلاف من نجوم GitHub. تعمم ثلاث ملاحظات:
- لا تحتاج المهارات إلى الطول كي تكون مؤثرة. هذه المهارة في جوهرها ثلاث جمل، لكنها تغير محادثة التخطيط. لا تضف طولا إلا عندما يستحق الطول مكانه.
- يبذل frontmatter عملا حقيقيا. يعرض harness للوكيل
descriptionلا المتن، لذلك يجب أن يكون الوصف محددا بما يكفي كي يحمّله الوكيل في اللحظات الصحيحة. عبارة "Use when user wants to stress-test a plan, get grilled on their design, or mentions 'grill me'" أفضل بكثير من "for grilling." - يخاطب المتن الوكيل بضمير المخاطب، بالنبرة نفسها التي تستخدمها مع متعاون مبتدئ. "Interview me relentlessly." "Ask the questions one at a time." مباشر، خبري، بلا تردد.
تمدد مهارة أعقد (to-prd، أو to-issues، أو tdd، أو improve-codebase-architecture) الشكل نفسه بخطوات مرقمة، وقالب، وإشارات إلى مهارات أخرى. يبقى المبدأ: شفّر العملية؛ لا تشفر الجواب.
5.4 المبادئ اليومية الخمسة (وأفضل مهارات اليوم لكل منها)
تقابل خمسة مبادئ مراحل المسار في §4.1 واحدا لواحد. ولكل مبدأ تنفيذ حالي من الدرجة الأولى: ملف SKILL.md قابل للتثبيت اليوم. يشير الجدول أدناه إلى أكثر الحزم استخداما (حزمة مات بوكوك، في skills.sh/mattpocock). يرتبط اسم كل مهارة بملف SKILL.md القانوني لها؛ والمتون قصيرة وتستحق القراءة.
| المرحلة | المهارة | ما الذي تفعله |
|---|---|---|
| الفكرة → مفهوم تصميم متفق عليه | grill-me | مقابلة سقراطية حتى الوصول إلى التوافق. |
| المفهوم المتفق عليه → وثيقة وجهة | to-prd | تلخص المحادثة في PRD مع قصص مستخدم، وقرارات تنفيذ، وقائمة وحدات ستتغير. |
| PRD → قائمة مسائل | to-issues | تقسم PRD إلى تذاكر شرائح عمودية ذات علاقات حظر صريحة. |
| المسألة → شريحة منفذة | tdd | red–green–refactor على شريحة واحدة كل مرة. |
| صحة قاعدة الكود، باستمرار | improve-codebase-architecture | يجد الوحدات السطحية، ويقترح تعميقها، ويفتح مسألة RFC. |
قبل تشغيل أي من هذه المهارات. تتوقع حزمة مات خطوة bootstrap واحدة لكل مستودع، هي
setup-matt-pocock-skills، وتبني إعداد متتبع المسائل في المستودع، وكتلة## Agent skillsفيAGENTS.md/CLAUDE.md، وتجهز دليلdocs/agents/. تقرأ المهارات الهندسية من هذا الهيكل (كما يعتمدto-prdوto-issuesعلىdocs/adr/إن كان موجودا)، لذلك شغل الإعداد مرة بعد تثبيت الحزمة وقبل أول استدعاء لto-issuesأوtdd.
يمثل description: في frontmatter لكل مهارة السطر الذي يفحصه harness عند بدء الجلسة ليقرر ما الذي يعرضه على الوكيل. يحدد ذلك الوصف هل سيحمّل الوكيل المهارة في اللحظة المناسبة، لذلك يحمل الوزن الحقيقي. يظهر grill-me كاملا في SKILL.md في §5.3؛ أما المهارات الأخرى، فإليك ما تفعله كل واحدة منها (بصياغة من المهارات المثبتة، لا اقتباسا حرفيا):
to-prdيحول المحادثة الحالية إلى PRD وينشره إلى متتبع مسائل المشروع. لا يعيد مقابلتك؛ بل يلخص ما هو موجود بالفعل في السياق.to-issuesيقسم خطة أو مواصفة أو PRD إلى مسائل قابلة للالتقاط مستقلة على متتبع مسائل المشروع، مقسمة عموديا وبعلاقات حظر صريحة، ويضع لكل واحدة وسما يجعلها جاهزة لوكيل يلتقطها.tddيشغل حلقة red-green-refactor صارمة لبناء ميزة أو إصلاح خطأ: اختبار فاشل واحد أولا، ثم كود بالقدر الكافي لتمريره، ثم إعادة هيكلة، ثم تكرار، مع اختبارات عند واجهات الوحدات لا عند المساعدات الداخلية.improve-codebase-architectureيجد فرص تعميق في قاعدة الكود، مسترشدا بلغة المجال فيCONTEXT.mdوالقرارات فيdocs/adr/، ويقترحها من دون تعديل الكود.
يمكن للقارئ الذي يريد frontmatter الدقيق أن يشغل cat على ملفات SKILL.md المثبتة أو يفتح المصادر المرتبطة؛ الصياغة أعلاه تلخيص أمين، لا اقتباس. لاحظ سلوكا تجعله الملخصات صريحا وسيراه القارئ مباشرة: يكتب كل من to-prd وto-issues إلى متتبع المسائل لديك، لا إلى ملف محلي فقط.
تعمم ثلاث خصائص عبر المهارات الخمس كلها:
- يقوم
descriptionبعمل التحميل. يجب أن يكون محددا بما يكفي كي يعرف الوكيل متى يحمّل المهارة، لا ما موضوعها فقط. عبارات "Use when..." والنطاق السلبي الصريح هما موضع تلك الدقة. - تسمي المهارات حدودها. لا يجري
to-prdمقابلة أخرى؛ ولا يعدلimprove-codebase-architectureقاعدة الكود. هذه العبارات السلبية هي ما يسمح للمهارات بالتركيب من دون أن تدوس بعضها. - تسمي المهارات أزواجها. يقترن
tddضمنيا بالمسألة التي ينفذها؛ ويقترنto-issuesبPRD الذي يقسمه. المسار سلسلة مهارات، تسلم كل واحدة إلى التالية.
بنية هذا المسار المعمارية (المهارات، والشرائح العمودية، والوحدات العميقة، وsandboxes) لا تعتمد على نموذج بعينه. أما موثوقيته التشغيلية فليست كذلك. نموذج طليعة قوي في اتباع التعليمات (Claude Sonnet/Opus، أو نموذج من فئة GPT-5، أو Gemini 2.5 Pro) يحمّل المهارة الصحيحة عند مطابقة الوصف، وينفذ متن مهارة متعددة الخطوات بالترتيب، وينهي مقابلة grilling ذاتيا عندما يصل إلى التوافق. أما على نموذج اقتصادي أو محلي (deepseek-chat، أو فئة Haiku، أو Llama-70B، أو معظم النماذج المحلية)، فتتدهور تلك السلوكيات: تفوت المهارات trigger، وينزلق التسلسل متعدد الخطوات، وتنكسر عقود الخرج الحرفية (إشارة NO_MORE_TASKS في §6.5). العلاج هو نفسه من §2.3: إذا كان النموذج أضعف، فابن السقالات بقوة أكبر. استدع المهارات صراحة بالاسم بدلا من الاعتماد على مطابقة الوصف، واجعل متون المهارات قصيرة وخبرية، وقل ما يجب ألا يفعله النموذج، لا ما يجب أن يفعله فقط.
تغلق مهارة سادسة في حزمة مات بوكوك حلقة الفشل 2 (وكيل كثير الكلام / لا مفردات مشتركة): grill-with-docs. إنها المقابلة السقراطية نفسها في grill-me، لكنها تحدّث أيضا CONTEXT.md وسجلات قرارات البنية docs/adr/ أثناء تبلور القرارات داخل المحادثة. في حديث مات Software Fundamentals Matter More Than Ever بدأت كمهارة مستقلة ل"اللغة الشاملة" تمسح قاعدة الكود وتكتب مسرد مجال؛ ثم اندمجت في مهارة grilling نفسها، وفق مبدأ أن المصطلحات تحسم في لحظة اتخاذ القرار، لا في تمريرة لاحقة منفصلة. استخدم grill-me في محادثات تصميم greenfield التي لا يوجد فيها سياق مشروع بعد؛ واستخدم grill-with-docs عندما يملك المستودع CONTEXT.md وADRs تريد إبقاءها حديثة.
ابن مهاراتك أولا؛ ثم الجأ إلى حزمة غيرك ثانيا. أفضل مهارة هي التي تلتقط عملية فريقك. يعد fork لحزمة
mattpocock/skillsبداية ممتازة. امتلاك المكدس، والقدرة على قراءة كل مهارة تحمّلها، هو ما يمنحك قابلية الملاحظة عندما يحدث خطأ.
6. المسار في التطبيق
يشغل هذا القسم سير العمل من البداية إلى النهاية على مثال عملي: إضافة خدمة gamification إلى منصة دورات. يبنى المثال نفسه مرة بPython ومرة بTypeScript؛ وتعمل كل خطوة في Claude Code وOpenCode. ليست نقطة الفصل هي المثال؛ بل الشكل. استوعب الشكل مرة واحدة، فتصبح اللغة وharness تفاصيل.
6.1 المرحلة 1: مساءلة الفكرة
رسالة Slack من صاحب مصلحة:
"أرقام الاحتفاظ لدينا ليست جيدة. يسجل الطلاب، وينجزون بضعة دروس، ثم ينسحبون. أريد أن نضيف بعض gamification إلى المنصة: نقاطا، وسلاسل إنجاز، ومستويات."
هذه ليست مواصفة؛ إنها رغبة. أعطها لوكيل وقل "ابنها" وستحصل على شيء لا يطابق ما في ذهن صاحب المصلحة، لأن أيا منكما لا يعرف بعد ما في ذهنه. استدع grill-me.
$ claude
> /grill-me
> Read the Slack message in client-brief.md and grill me on adding gamification.
$ opencode
> Use the grill-me skill. Read client-brief.md and grill me on adding gamification.
يقرأ الوكيل الموجز، ويستكشف قاعدة الكود لفهم النماذج الموجودة (Lesson، وQuiz، وEnrollment)، ثم يبدأ بطرح الأسئلة، واحدا كل مرة، ومع كل سؤال توصيته:
Q1. What earns points? My recommendation: lesson completion + quiz pass.
Skip video-watch events (too noisy, gameable).
Q2. Are points retroactive for existing lesson_progress records?
My recommendation: yes, backfill once on migration, then live going forward.
Q3. Streak granularity? My recommendation: daily, with a 1-day grace period.
Q4. Level thresholds: linear, quadratic, or hand-tuned?
My recommendation: quadratic, capped at level 50.
...
تتوقف الجلسات في أي موضع بين خمسة عشر سؤالا ومئة سؤال. تنتهي الجلسة عندما يعلن الوكيل أنه لم تبق قرارات غير محسومة وأن لديك مفهوم تصميم مستقرا. لا كود، ولا PRD. مخرج grilling هو سجل محادثة؛ وسجل المحادثة هو مفهوم التصميم وقد صار صريحا.
6.2 المرحلة 2: من المحادثة إلى PRD
بعد أن يستقر مفهوم التصميم، استدع to-prd. لا تعيد المهارة مقابلتك؛ بل تلخص ما قلته بالفعل في مستند متطلبات منتج.
> /to-prd
> Use the to-prd skill on this conversation.
المخرج مستند markdown يتبع قالبا ثابتا:
# PRD: Course Platform Gamification
## Problem Statement
Students drop off after a handful of lessons. Retention metrics
indicate completion rates ... [synthesised from the brief]
## Solution
Add a points/streaks/levels gamification layer ...
## User Stories
1. As a student, I earn 10 points when I complete a lesson.
2. As a student, I earn 25 points when I pass a quiz.
3. As a student, I see my current streak on the dashboard.
4. As a student, I see my level on my profile.
5. As an admin, I can see aggregate engagement metrics.
... [12-20 more, each independently verifiable]
## Modules Touched
- NEW: gamification_service (deep module, owns points + streaks + levels)
- MODIFIED: lesson_progress_service (emits events on completion)
- MODIFIED: dashboard route (reads from gamification_service)
- NEW DB: point_events table, streak_state table
## Implementation Decisions
- Level formula: floor(sqrt(total_points / 50))
- Streak grace: 1 missed day allowed
- Backfill: one-time job at deploy
## Out of Scope
- Leaderboards (separate PRD)
- Push notifications (separate PRD)
ما الذي تقرؤه في PRD قبل الموافقة عليه. تصفح بحثا عن الانجراف، ولا تدقق لغويا. أنت والوكيل تشتركان بالفعل في مفهوم التصميم من جلسة grilling، والوكيل ممتاز في التلخيص؛ القراءة سطرا بسطر عمل من أعمال المنطقة الغبية. ركز انتباهك على أربعة مواضع يمكن أن ينحرف فيها التلخيص: قصص المستخدم (هل أسقط شيئا أو اخترع شيئا؟)، و_الوحدات التي ستتغير_ (هل ما زالت الحدود تطابق ما ناقشتموه؟)، و_قرارات التنفيذ_ (هل تطابق القرارات التي اتخذتها أثناء grilling؟)، و_خارج النطاق_ (هل تمددت الحدود؟). دقيقتان من التصفح المركز تلتقطان معظم الإخفاقات؛ أما قراءة المستند كله فتلتقط الإخفاقات نفسها وتكلف عشرة أضعاف الانتباه.
6.3 المرحلة 3: من PRD إلى مسائل شرائح عمودية
يصف PRD الوجهة. وتصف المهارة التالية الرحلة: كيف تقسم PRD إلى مسائل قابلة للالتقاط مستقلة، مقطعة عموديا، وبينها علاقات حظر.
شغل to-issues. بالنسبة إلى PRD الخاص بgamification، ينتج لوحة Kanban صغيرة:
┌────────────────────────────────────────────────────────────┐
│ Issue #1 - Award points for lesson completion (E2E) │
│ blocked by: nothing. Type: AFK. │
│ Touches: schema, service, lesson route, dashboard widget │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ Issue #2 - Award points for quiz pass (E2E) │
│ blocked by: #1. Type: AFK. │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ Issue #3 - Streak counter (E2E) │
│ blocked by: #1. Type: AFK. │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ Issue #4 - Level threshold + UI badge │
│ blocked by: #2. Type: AFK. │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ Issue #5 - Retroactive backfill of historical lessons │
│ blocked by: #1. Type: human-in-the-loop. │
└────────────────────────────────────────────────────────────┘
هناك خصائص عدة ليست مصادفة:
- تشحن المسألة #1 شريحة عاملة. لو دمج الفريق #1 فقط ثم توقف، فستملك المنصة ميزة gamification عاملة ولو بحدها الأدنى. في التقسيم الأفقي كانت "المرحلة 1" ستنتج جدول قاعدة بيانات لا يفعل شيئا.
- يسمح DAG بالتوازي. بعد دمج #1 يمكن تشغيل #2 و#3 في جلسات متوازية على فروع متوازية. وكيلان AFK، وPRان في الصباح.
- تعلّم #5 كعمل human-in-the-loop، لا AFK. تمس backfills البيانات التاريخية؛ لذلك يراقب الإنسان كل خطوة. يخبر حقل
Typeحلقة AFK في §6.5 أن تتجاوزه.
6.4 المرحلة 4: التنفيذ: TDD على شريحة واحدة
اختر أعلى الطابور غير المحظور: المسألة #1. استدع tdd. تفرض المهارة red-green-refactor صارما: اكتب اختبارا واحدا فاشلا، شاهده يفشل، اكتب بالقدر الكافي من الكود ليجتاز، شاهده يجتاز، أعد الهيكلة مع بقاء كل الاختبارات خضراء، وكرر.
لماذا TDD تحديدا؟ لسببين.
- يفرض الخطوات الصغيرة. من دون TDD، ينتج الوكيل ستة ملفات كود ثم يكتب طبقة اختبارات حولها لاحقا. تميل تلك الاختبارات إلى الغش؛ فهي تختبر التنفيذ، لا السلوك. مع TDD يكتب الاختبار أولا، قبل وجود التنفيذ، لذلك لا يمكن تشكيله كي يلائم ما كتبه الوكيل.
- يوفر تغذية راجعة كل دقيقة. كل اجتياز اختبار نقطة فحص. إذا انجرف الوكيل، يلتقطه الاختبار الفاشل التالي قبل أن ينتج مئة سطر من القمامة.
إليك شريحة المسألة #1 باللغتين: وحدة GamificationService عميقة بواجهة صغيرة، وتنفيذ واسع، وملف اختبار مركز. تفترض مهارة tdd وجود مشغل اختبارات عامل: ثبّت واحدا قبل أن تبدأ، pip install pytest لشريحة Python أو npm install -D vitest لشريحة TypeScript، وإلا فستفشل خطوة red الأولى على مشغل مفقود بدلا من تنفيذ مفقود.
ما يهم هنا. يبين المثال أدناه شيئين يمكن رؤيتهما من دون قراءة الصياغة:
- للخدمة واجهة عامة ضيقة جدا: طريقتان فقط (
award_lesson_completionوtotal_points). كل شيء آخر مخبأ داخل الصنف. لا يستطيع المستدعون الوصول إلى الداخل.- ينادي الاختبار هاتين الطريقتين فقط. لا يعبث الاختبار بالمساعدات الداخلية. إنه يفحص السلوك الذي سيراه المستدعي ("بعد ثلاث إكمالات، يكون المجموع 30")، لا كيفية حساب الخدمة له.
ذلك الشكل (واجهة صغيرة، وتنفيذ واسع، واختبارات عند الحد) هو ما يسميه §7 وحدة عميقة. نسختا Python وTypeScript متكافئتان سطرا بسطر.
- Python
- TypeScript
# gamification/service.py - the deep module's interface
from dataclasses import dataclass
from datetime import datetime
from typing import Protocol
@dataclass(frozen=True)
class PointAward:
student_id: str
points: int
reason: str
awarded_at: datetime
class PointEventStore(Protocol):
def append(self, award: PointAward) -> None: ...
def total_for_student(self, student_id: str) -> int: ...
class GamificationService:
"""Awards and totals points. Streaks and levels live here too,
but in the same module, so the interface stays small."""
LESSON_COMPLETION_POINTS = 10
def __init__(self, store: PointEventStore, clock=datetime.utcnow) -> None:
self._store = store
self._clock = clock
def award_lesson_completion(self, student_id: str) -> PointAward:
award = PointAward(
student_id=student_id,
points=self.LESSON_COMPLETION_POINTS,
reason="lesson_completion",
awarded_at=self._clock(),
)
self._store.append(award)
return award
def total_points(self, student_id: str) -> int:
return self._store.total_for_student(student_id)
# gamification/test_service.py - written FIRST
from datetime import datetime
from gamification.service import GamificationService, PointAward
class InMemoryStore:
def __init__(self) -> None:
self._events: list[PointAward] = []
def append(self, award: PointAward) -> None:
self._events.append(award)
def total_for_student(self, student_id: str) -> int:
return sum(a.points for a in self._events if a.student_id == student_id)
def test_lesson_completion_awards_ten_points():
store = InMemoryStore()
fixed_clock = lambda: datetime(2026, 5, 10, 12, 0, 0)
svc = GamificationService(store, clock=fixed_clock)
award = svc.award_lesson_completion("student-42")
assert award.points == 10
assert award.reason == "lesson_completion"
assert svc.total_points("student-42") == 10
def test_multiple_completions_accumulate():
svc = GamificationService(InMemoryStore())
for _ in range(3):
svc.award_lesson_completion("student-42")
assert svc.total_points("student-42") == 30
// gamification/service.ts - the deep module's interface
export interface PointAward {
readonly studentId: string;
readonly points: number;
readonly reason: string;
readonly awardedAt: Date;
}
export interface PointEventStore {
append(award: PointAward): void;
totalForStudent(studentId: string): number;
}
export class GamificationService {
static readonly LESSON_COMPLETION_POINTS = 10;
constructor(
private readonly store: PointEventStore,
private readonly clock: () => Date = () => new Date(),
) {}
awardLessonCompletion(studentId: string): PointAward {
const award: PointAward = {
studentId,
points: GamificationService.LESSON_COMPLETION_POINTS,
reason: "lesson_completion",
awardedAt: this.clock(),
};
this.store.append(award);
return award;
}
totalPoints(studentId: string): number {
return this.store.totalForStudent(studentId);
}
}
// gamification/service.test.ts - written FIRST
import { describe, it, expect } from "vitest";
import { GamificationService, PointAward, PointEventStore } from "./service";
class InMemoryStore implements PointEventStore {
private events: PointAward[] = [];
append(a: PointAward) {
this.events.push(a);
}
totalForStudent(id: string) {
return this.events
.filter((e) => e.studentId === id)
.reduce((sum, e) => sum + e.points, 0);
}
}
describe("GamificationService", () => {
it("awards ten points on lesson completion", () => {
const fixedClock = () => new Date("2026-05-10T12:00:00Z");
const svc = new GamificationService(new InMemoryStore(), fixedClock);
const award = svc.awardLessonCompletion("student-42");
expect(award.points).toBe(10);
expect(award.reason).toBe("lesson_completion");
expect(svc.totalPoints("student-42")).toBe(10);
});
it("accumulates across multiple completions", () => {
const svc = new GamificationService(new InMemoryStore());
for (let i = 0; i < 3; i++) svc.awardLessonCompletion("student-42");
expect(svc.totalPoints("student-42")).toBe(30);
});
});
هذه وحدة عميقة تعمل: واجهة عامة بطريقتين (awardLessonCompletion، وtotalPoints) فوق تنفيذ حر في أن ينمو إلى آلاف الأسطر. ولإثبات الادعاء بدلا من تقريره، إليك ما يحدث عندما تهبط المسألة #3 (عداد السلسلة).
ما يهم هنا. راقب الواجهة العامة، لا عدد الأسطر. قبل هذه الشريحة كانت للخدمة طريقتان (
awardLessonCompletion، وtotalPoints). بعدها أصبحت لها ثلاث طرق (الاثنتان نفسيهما إضافة إلىcurrentStreak). نما التنفيذ كثيرا، مع مخزن للسلاسل، وسجل نشاط، ومساعد تاريخ، لكن لا شيء من ذلك يتسرب. يرى المستدعون طريقة جديدة واحدة. لا يغير المستدعون الحاليون شيئا. تبقى الاختبارات الحالية خضراء. وينادي الاختبار الجديد الطريقة الجديدة فقط. هذا معنى "عميق" عمليا: ينمو السلوك؛ ويكاد السطح لا يتحرك.
- Python
- TypeScript
# gamification/service.py - interface gains ONE method, nothing else changes
class GamificationService:
LESSON_COMPLETION_POINTS = 10
def __init__(self, store, streaks=None, clock=datetime.utcnow):
self._store = store
self._streaks = streaks or InMemoryStreakStore() # internal detail
self._clock = clock
def award_lesson_completion(self, student_id: str) -> PointAward:
# unchanged signature; internally also updates streak state
award = PointAward(...)
self._store.append(award)
self._streaks.record_activity(student_id, self._clock().date())
return award
def total_points(self, student_id: str) -> int: # unchanged
return self._store.total_for_student(student_id)
def current_streak(self, student_id: str) -> int: # NEW - only addition
return self._streaks.streak_length(student_id, today=self._clock().date())
# gamification/test_service.py - existing tests untouched; ONE new test added
def test_streak_grows_with_consecutive_daily_completions():
days = [date(2026, 5, 8), date(2026, 5, 9), date(2026, 5, 10)]
clock = iter(datetime.combine(d, time()) for d in days)
svc = GamificationService(InMemoryStore(), clock=lambda: next(clock))
for _ in days:
svc.award_lesson_completion("student-42")
assert svc.current_streak("student-42") == 3
// gamification/service.ts - interface gains ONE method, nothing else changes
export class GamificationService {
static readonly LESSON_COMPLETION_POINTS = 10;
constructor(
private readonly store: PointEventStore,
private readonly streaks: StreakStore = new InMemoryStreakStore(),
private readonly clock: () => Date = () => new Date(),
) {}
awardLessonCompletion(studentId: string): PointAward {
// unchanged signature; internally also updates streak state
const award: PointAward = {
/* ... */
};
this.store.append(award);
this.streaks.recordActivity(studentId, this.clock());
return award;
}
totalPoints(studentId: string): number {
// unchanged
return this.store.totalForStudent(studentId);
}
currentStreak(studentId: string): number {
// NEW - only addition
return this.streaks.streakLength(studentId, this.clock());
}
}
// gamification/service.test.ts - existing tests untouched; ONE new test added
it("grows the streak across consecutive daily completions", () => {
const days = [
new Date("2026-05-08T12:00:00Z"),
new Date("2026-05-09T12:00:00Z"),
new Date("2026-05-10T12:00:00Z"),
];
let i = 0;
const svc = new GamificationService(
new InMemoryStore(),
undefined,
() => days[i],
);
for (i = 0; i < days.length; i++) svc.awardLessonCompletion("student-42");
expect(svc.currentStreak("student-42")).toBe(3);
});
حدثت ثلاثة أشياء، وكلها تشخيصية لوحدة عميقة صحيحة:
- كبرت الواجهة بطريقة واحدة، لا خمس. كان البديل السطحي سيعرض
recordActivity، وstreakLength، وstreakStore، وsetActivityCalendar: آليات داخلية تتسرب إلى الحد. النسخة العميقة تعطي المستدعين ما يحتاجونه بالضبط (currentStreak) ولا شيء آخر. - لم تتغير الاختبارات الحالية. ما تثبته من سلوك ما زال صحيحا؛ ملف الاختبار إضافي فقط. هذا ما تشتريه لك الاختبارات عند الواجهة.
- حصل السلوك الجديد على اختبار واحد عند الحد نفسه. لا تختبر streak store، ولا سجل النشاط، ولا مساعد التاريخ مباشرة؛ بل تختبرها ضمنا عبر عقد
currentStreak، وهو المستوى الصحيح.
تتبع الشريحة التالية (المسألة #4، عتبة المستوى) النمط نفسه: طريقة واحدة مضافة، واختبارات موجودة بلا تغيير، واختبار سلوك جديد واحد عند الحد.
6.5 المرحلة 5: حلقة AFK
لديك خمس مسائل في قائمة العمل ومهارة tdd مثبتة. لا تريد الجلوس على لوحة المفاتيح بينما يطحن الوكيل عبرها. تريد دفع خمس tracer bullets عبر النظام بالتوازي، ثم تناول العشاء ومراجعة خمسة PRs في الصباح.
حلقة AFK سكربت shell: اجمع مسائل AFK غير المحظورة، وسلّمها إلى الوكيل بتعليمة واضحة، وشغّل داخل حاوية sandboxed، وكرر حتى يفرغ الطابور. يلي ذلك تنفيذان: نسخة bash دنيا (تعمل مع أي harness) وorchestrator TypeScript منظم يشغل الشرائح بالتوازي.
6.5.1 حلقة AFK دنيا (bash)
ما يهم هنا. يفعل السكربت خمسة أشياء في حلقة حتى لا يبقى شيء ينجز: (1) يقرأ كل المسائل المفتوحة من مجلد؛ (2) يقرأ سجل commits الحديثة؛ (3) يسلم الاثنين إلى الوكيل بتعليمة واضحة؛ (4) يختار الوكيل مسألة واحدة وينفذها؛ (5) يفحص هل فرغ الطابور، فإن فرغ توقف. لا يكون الإنسان على لوحة المفاتيح أثناء أي من ذلك. يبدأ السكربت ويمشي بنفسه.
#!/usr/bin/env bash
# ralph.sh - the simplest AFK loop. Works with either harness.
# Loops over /issues/*.md, picks the highest-priority AFK issue,
# implements it inside a sandbox, commits, repeats until done.
set -euo pipefail # bash safety: exit on any error, undefined var, or failed pipe
PROMPT_FILE="${1:-prompts/implement.md}"
ISSUES_DIR="${2:-issues}"
# Two env vars carry the harness difference. AGENT_CMD is the binary;
# AGENT_PERM_FLAG is its skip-approvals flag, which is NOT the same
# string in both harnesses (see the tool-tabs below). Everything else
# in this script is byte-identical across Claude Code and OpenCode.
CMD="${AGENT_CMD:-claude}"
PERM_FLAG="${AGENT_PERM_FLAG:---permission-mode acceptEdits}"
while :; do
ISSUES=$(cat "$ISSUES_DIR"/*.md 2>/dev/null || true)
COMMITS=$(git log --oneline -5)
PROMPT=$(cat "$PROMPT_FILE")
RESULT=$($CMD $PERM_FLAG <<EOF
$PROMPT
## Open issues
$ISSUES
## Recent commits
$COMMITS
EOF
)
# Exit only on a line that is *exactly* the sentinel, so the loop
# does not stop if the agent merely quotes the token in prose.
if echo "$RESULT" | grep -qx "NO_MORE_TASKS"; then
echo "queue drained - exiting"
break
fi
done
<!-- prompts/implement.md - fed to the agent on every iteration -->
You are operating AFK on the gamification project.
1. From the open issues, pick the highest-priority issue whose
`Type:` is `AFK` and whose blockers are all closed.
If none, reply with a line containing only `NO_MORE_TASKS` and stop.
2. Read the PRD it references.
3. Use the `tdd` skill to implement one vertical slice.
4. Run the project feedback loops (typecheck, tests, lint).
Do not commit if any fail.
5. Commit referencing the issue number and close the issue.
المهارات، والتعليمة، والمسائل، كلها byte-identical عبر harnesses. ما يختلف هو ثنائية harness وعلامة تجاوز الموافقات فيه: يستخدم Claude Code العلامة --permission-mode acceptEdits، ويستخدم OpenCode العلامة --dangerously-skip-permissions للأثر نفسه. يحمل المتغيران البيئيان أدناه ذلك الفرق؛ أما heredoc على stdin فيعمل لكليهما.
AGENT_CMD="claude" \
AGENT_PERM_FLAG="--permission-mode acceptEdits" ./ralph.sh
AGENT_CMD="opencode run" \
AGENT_PERM_FLAG="--dangerously-skip-permissions" ./ralph.sh
6.5.2 مشغل AFK متواز (TypeScript)
تشغل نسخة bash الشرائح بالتسلسل. بعد أن تثق بالحلقة، تكون نقطة الرفع التالية هي التنفيذ المتوازي: اختر كل المسائل غير المحظورة، وأنشئ worktree معزولا لكل مسألة، وشغلها معا، ثم ادمج. يرسم orchestrator أدناه النمط؛ وتوجد تنفيذات جاهزة للإنتاج كمكتبات sandboxing مخصصة في منظومتي Claude Code وOpenCode.
ما يهم هنا. ثلاث أفكار؛ كل شيء آخر سباكة:
- بالتوازي، لا بالتسلسل. بدلا من تنفيذ الشريحة 1 ثم 2 ثم 3، ينفذ orchestrator الشرائح الثلاث كلها في الوقت نفسه، كل واحدة في مساحة عمل معزولة. في الصباح لديك ثلاثة طلبات دمج بدلا من واحد.
- كل تشغيل متواز معزول. "sandboxed worktree" نسخة منفصلة من قاعدة الكود (
git worktreeطريقة git المدمجة لامتلاك نسخ checked-out متعددة) تعمل داخل حاوية لا تستطيع إتلاف حاسوبك. إذا فعل الوكيل شيئا خطأ، فنطاق الضرر worktree واحد.- المراجع وكيل منفصل في جلسة جديدة. وكيل مختلف، وبنموذج مختلف (وأرخص)، ينظر إلى الفرق فقط ويقارنه بمعايير الترميز في المشروع. المراجعة في المحادثة نفسها التي كتبت الكود تعني المراجعة داخل المنطقة الغبية.
الكود نفسه سكربت Node.js متوسط المستوى؛ وسطر
Promise.allهو موضع التوازي.
// orchestrator.ts - parallel AFK loop with sandboxed worktrees
import { spawn } from "node:child_process";
import { readdir, readFile } from "node:fs/promises";
interface Issue {
id: string; // e.g. "issue-001"
title: string;
type: "AFK" | "human-in-the-loop";
blockedBy: string[]; // ids of blocking issues
closed: boolean;
}
const HARNESS = process.env.AGENT_CMD ?? "claude"; // "claude" or "opencode run"
async function loadIssues(dir: string): Promise<Issue[]> {
const files = await readdir(dir);
return Promise.all(
files.map(async (f) => {
const raw = await readFile(`${dir}/${f}`, "utf8");
return parseIssue(f, raw); // omitted for brevity
}),
);
}
function unblocked(issues: Issue[]): Issue[] {
const closed = new Set(issues.filter((i) => i.closed).map((i) => i.id));
return issues.filter(
(i) =>
!i.closed && i.type === "AFK" && i.blockedBy.every((b) => closed.has(b)),
);
}
function runInSandbox(issue: Issue): Promise<{ ok: boolean; branch: string }> {
return new Promise((resolve) => {
const branch = `afk/${issue.id}`;
// 1. create a git worktree on a fresh branch
// 2. start a docker container with that worktree mounted r/w
// 3. run the harness inside, with the implement.md prompt
const proc = spawn("scripts/run-sandbox.sh", [HARNESS, branch, issue.id], {
stdio: "inherit",
});
proc.on("exit", (code) => resolve({ ok: code === 0, branch }));
});
}
async function main() {
let issues = await loadIssues("./issues");
while (true) {
const ready = unblocked(issues);
if (ready.length === 0) {
console.log("backlog drained or fully blocked - exiting");
break;
}
// run all unblocked issues in parallel, one sandbox each
const results = await Promise.all(ready.map(runInSandbox));
// automated review on each successful branch BEFORE merge
// (in a fresh session - smart-zone reviewer)
for (const r of results.filter((r) => r.ok)) {
await reviewBranch(r.branch);
}
// reload issues from disk; agents may have closed some and opened others
issues = await loadIssues("./issues");
}
}
async function reviewBranch(branch: string): Promise<void> {
// spawn a *separate* agent session, smaller model, with the
// diff and the coding-standards skill as input. Open a comment
// on the PR. Do NOT auto-merge.
}
main();
توجد ثلاثة مبادئ داخل orchestrator، وهي أهم من الكود:
- العزل إلزامي. تشغيل AFK مع
--permission-mode bypassPermissionsومن دون sandbox هو طريقة تدمير المستودعات. تحصل كل شريحة على حاوية جديدة، وworktree جديد، ولا بيانات اعتماد إنتاج، ولا خروج شبكي إلا لما تحتاجه. - المراجع وكيل منفصل. المراجع في الجلسة نفسها التي نفذت الكود يراجع في المنطقة الغبية. المراجع في جلسة جديدة، إذا أعطي الفرق والمعايير فقط، يرى العمل بوضوح. نموذج أصغر يكفي للمراجعة (وغالبا يكون أكثر نقدية)؛ استخدم الأكبر للتنفيذ.
- تعيد الحلقة تحميل المسائل من القرص في كل دورة. عندما ينتج QA مسائل جديدة في §6.6، تظهر تلقائيا في الطابور.
6.5.3 الحلقات المستمرة والوكلاء المحيطون
تعمل الحلقات أعلاه مرة واحدة لكل backlog. تبدأ، وتستنزف الطابور، وتتوقف. التطور التالي هو إبقاؤها تعمل.
الحلقة، بمعنى بوريس تشيرني، هي استدعاء وكيل مجدول بcron ليعمل كل دقيقة، أو كل خمس دقائق، أو كل ثلاثين دقيقة على مهمة صغيرة قائمة. كل استدعاء جلسة جديدة، لذلك يبدأ كل مرة في المنطقة الذكية ولا يراكم انجراف المنطقة الغبية. لا يبقى الوكيل حيا؛ المهمة هي التي تبقى حية، ويولد وكيل جديد لمعالجة كل tick.
قد تتضمن مجموعة حلقات عاملة في مشروع واحد:
- منظف PRs: يعيد تشغيل CI المتقلب، ويعيد الإسناد فوق
main، ويصلح تعليقات الأخطاء المطبعية وlint التي تركها المراجعون. - معالج CI: عندما يبدأ اختبار متقلب في الفشل تقطعا، يحقق فيه ويصلحه.
- مجمّع التغذية الراجعة: يجلب تعليقات المستخدمين الواردة كل ثلاثين دقيقة، ويجمعها حسب الموضوع، وينشر ملخصا في Slack.
هذه ليست أدوات. إنها وكلاء محيطون: قوة عمل ذكاء اصطناعي دائمة منخفضة الشدة تعمل بجانب المشروع، وتتولى الضريبة الخلفية التي كانت تلتهم ساعات الهندسة تاريخيا، مثل تنظيف PRs، وصحة CI، وفرز التذاكر، وتحديث الاعتماديات، وهضم السجلات، وملخصات المراقبة. لا تبرر مهمة واحدة منها تشغيل AFK كامل؛ لكنها معا تستهلك وقتا حقيقيا. شغلها كحلقات فتختفي من يوم المهندس.
الحلقة المستمرة الدنيا هي سطر cron واحد فوق ملف تعليمة:
ما يهم هنا. يشغل job في
cronأمرا وفق جدول: كل ثلاثاء عند التاسعة صباحا مثلا، أو كل 30 دقيقة. تعني الخانات الخمس*/30 * * * *عبارة "كل 30 دقيقة، في كل ساعة، في كل يوم" (crontab.guru يفك أي جدول). يخبر السطر أدناه نظام التشغيل: "كل نصف ساعة، اذهب إلى مجلد مشروعي وشغل وكيل PR-janitor tick واحدة." كل tick جلسة وكيل جديدة تستمر قدر ما يلزم للتعامل مع PRs التي تحتاج انتباها، ثم تخرج. يبقى job إلى الأبد؛ والوكلاء قابلون للرمي.
# crontab -e
# every 30 minutes, run the PR-janitor agent in the project
*/30 * * * * cd /home/me/project && \
AGENT_CMD="claude" ./scripts/run-once.sh prompts/pr-janitor.md
<!-- prompts/pr-janitor.md -->
You are the PR janitor for this project.
1. List my open PRs (`gh pr list --author @me`). # gh = GitHub's CLI
2. For each PR:
- If CI failed on a known-flaky test, retrigger only that job.
- If the PR has merge conflicts with main, attempt a clean rebase.
If the rebase is non-trivial, leave a comment and stop.
- If a reviewer left a typo / lint comment, fix it and push.
3. Commit only changes you can explain in one sentence.
4. Do nothing else. Output a one-line summary.
النمط الأثقل هو routine: الحلقة نفسها تنفذ من جهة الخادم بدلا من cron على حاسوبك، لذلك تنجو من النوم، وإعادة التشغيل، والسفر. تظهر ميزات الوكيل المجدول من جهة الخادم عبر منتجات وكلاء البرمجة؛ تعامل مع نسخة cron المحلية كشكل التطوير، ونسخة الخادم كشكل الإنتاج. التعليمة هي نفسها؛ لا يتغير إلا المجدول.
تحكم الحلقات المستمرة قاعدتان تصميميتان:
- كل tick جلسة جديدة. لا تبقى حالة بين ticks إلا ما يكتب إلى البيئة (PRs، وسجلات CI، وملف حالة صغير). الحلقة عديمة الحالة عمدا؛ التعليمة تحمل الدور.
- لكل حلقة وظيفة واحدة. الحلقة التي تنظف PRs وتعالج CI وتجمع التغذية الراجعة ستتدهور إلى جلسة لا تجيد أيا منها. حلقة واحدة لكل دور، مثل مهارة واحدة لكل دور.
صار نمط AFK الآن من البداية إلى النهاية: §6.5.1 يشغل شريحة واحدة بالتسلسل؛ و§6.5.2 يشغل شرائح كثيرة بالتوازي؛ و§6.5.3 يبقي قوة العمل تعمل إلى أجل غير مسمى على الإيقاعات التي يولدها المشروع نفسه. تضيف كل خطوة إنتاجية من دون إضافة أحد إلى الفريق: وهذا هو الشكل التشغيلي لقوة عمل الموظفين الرقميين بدوام كامل.
6.6 المرحلة 6: المراجعة البشرية وQA
في صباح اليوم التالي لتشغيل الحلقة، لديك N طلبات دمج. اقرأ الفروق، لا ملخص الوكيل للفروق. الملخص كلمة الوكيل عما فعله؛ أما الفرق فهو ما فعله فعلا. وغالبا يختلفان بطرق دقيقة لا تظهر أهميتها إلا على نطاق الإنتاج.
مثال ملموس من شريحة gamification في §6.4. قال ملخص PR الذي كتبه الوكيل: "أضيفت نقاط لإكمال الدرس. الاختبارات تمر. تعرض أداة لوحة التحكم المجموع الحالي." قال الفرق الشيء نفسه، إلا أن تمريرة QA وجدت أن فتح لوحة التحكم قبل إكمال أي درس ينهار مع TypeError: Cannot read property 'awarded_at' of null. كان الوكيل قد عالج الحالة الفارغة في الخدمة (بإرجاع 0 من total_points) لكن مكون React افترض وجود طابع زمني last_award_at. فحص null واحد، إصلاح سهل؛ لكن اختبارات الوكيل لم تغط عرض الواجهة في الحالة الفارغة، لأن قصة المستخدم في الشريحة افترضت ضمنيا وجود award واحد على الأقل. تعود تلك الملاحظة إلى backlog كمسألة جديدة ("add empty-state to dashboard widget; cover with a test") غير محظورة، من نوع AFK. يدمج PR؛ وتلتقط وردية الليل المسألة الجديدة غدا. هذه الحلقة، حيث يجد الإنسان الفجوة، وتعود التذكرة إلى الطابور، ويصلحها الوكيل AFK، هي ما يجعل المسار يحسن نفسه.
ينتج QA أثمن أثر في المسار: مسائل جديدة. كل خطأ يعثر عليه، وكل قلق UX، وكل edge case لم يتوقعه PRD الأصلي، يتحول إلى تذكرة جديدة على لوحة Kanban بعلاقات حظر مناسبة. لا تفرغ اللوحة؛ بل تواصل إنتاج الشرائح.
وهذه أيضا المرحلة التي يعيش فيها الذوق. أتمتة QA إغراء يستحق المقاومة: وكيل يراجع واجهة وكيل آخر يصل إلى رأي لا يملكه أحد بعينه، والنتيجة هي ذلك المخرج المشتق الناعم بلا حواف خشنة الذي يميز مخرجات الذكاء الاصطناعي غير الخاضعة للإشراف. الإنسان الذي يقرر "هذا padding خطأ" و_"هذا label طويل جدا"_ خطوة غير قابلة للاختزال. يشحن الوكيل بخمسة أضعاف الوتيرة الطبيعية؛ وعملك أن تتأكد أنه يشحن ذوقك أنت بخمسة أضعاف الوتيرة، لا ذوق أي أحد آخر.
7. مبادئ البنية لقواعد كود صديقة للذكاء الاصطناعي
لا ينفصل سير العمل عن قاعدة الكود: كلما كانت البنية أنظف، كان أداء الوكيل أفضل داخلها. لم تعد البنية غاية في ذاتها فقط؛ بل صارت مدخلا إلى قوة عملك الذكية.
7.1 الوحدات العميقة بدلا من الوحدات السطحية
تكون الوحدة عميقة عندما تملك واجهة صغيرة وسلوكا كثيرا خلفها؛ وتكون سطحية عندما تكون الواجهة والتنفيذ بحجم متقارب.
بالنسبة إلى الوكيل، الفرق حاسم. في قاعدة كود سطحية، يتتبع الوكيل اعتماديات زوجية كثيرة بين ملفات صغيرة كثيرة؛ وتتدهور نسبة الإشارة إلى الضجيج لكل token؛ وتتمدد الاختبارات عبر حدود الوحدات لأن لا حد واحدا يحتوي سلوكا كافيا ليستحق الاختبار منفردا. أما في قاعدة كود عميقة، فيقرأ الوكيل واجهة واحدة ويثق بالحد. تقف الاختبارات عند الواجهة. يمكن إضافة السلوك داخليا من دون إزعاج المستدعين، ومن دون إعادة اختبارهم.
لتجسيد الفرق، إليك كيف كانت ستبدو النسخة السطحية من GamificationService: الطريقة التي يميل وكيل بلا توجيه معماري إلى كتابة الميزة نفسها بها.
ما يهم هنا. عد عدد العناصر المصدرة في كل كتلة. تعرض النسخة السطحية تسع دوال top-level يجب أن يتذكر المستدعون استدعاءها بالترتيب والتركيب الصحيحين. وتعرض النسخة العميقة ثلاث طرق على صنف واحد؛ وكل ما يجب أن يحدث خلف الكواليس يحدث خلف الكواليس. الخطأ الذي يجب تجنبه: في النسخة السطحية يستطيع مستدع أن ينسى استدعاء
validateAntiCheatويفسد النظام بصمت. في النسخة العميقة لا يستطيع المستدعي الوصول إلىvalidateAntiCheatأصلا؛ إنها مخبأة داخلawardLessonCompletionالتي تستدعيها آليا. إخفاء الأشياء الصحيحة هو وظيفة الوحدة العميقة كلها.
// gamification/index.ts - SHALLOW: the interface IS the implementation
export function awardPoints(studentId: string, reason: string, n: number): void;
export function totalPoints(studentId: string): number;
export function recordStreakActivity(studentId: string, day: Date): void;
export function streakLength(studentId: string, today: Date): number;
export function computeLevel(totalPoints: number): number;
export function validateAntiCheat(
studentId: string,
event: PointEvent,
): boolean;
export function backfillHistorical(studentId: string, since: Date): void;
export function pointsForLessonCompletion(): number;
export function pointsForQuizPass(): number;
// ... + the data classes each function depends on
تسع دوال top-level، كل واحدة قابلة للاستدعاء من أي مكان، وكل واحدة تعتمد بصمت على الأخرى (awardPoints يجب أن تستدعي validateAntiCheat؛ ولوحة التحكم يجب أن تستدعي awardPoints و recordStreakActivity و computeLevel لإكمال درس واحد؛ وإذا نسي أي مستدع واحدة منها، ينجرف النظام بصمت خارج الاتساق).
قارن ذلك بالنسخة العميقة من §6.4:
// gamification/service.ts - DEEP: small interface, large hidden body
export class GamificationService {
awardLessonCompletion(studentId: string): PointAward; // does ALL of the above internally
totalPoints(studentId: string): number;
currentStreak(studentId: string): number;
// streak recording, anti-cheat, level calc, point amounts → all hidden
}
ثلاث طرق. داخليا، توجد الاهتمامات التسعة نفسها، لكنها ليست الواجهة. لا يستطيع المستدعون نسيان استدعاء validateAntiCheat، لأن المستدعين لا يستطيعون استدعاءها أصلا. تقف الاختبارات على ثلاث طرق، لا تسع. يضاف السلوك الجديد (recordStreak، وعتبة المستوى، وbackfill) داخليا من دون تغيير العقد: بالضبط الخاصية التي يبينها §6.4.
قاعدة عملية. إذا كان عرض Outline في IDE للوحدة أطول من واجهتها العامة، فالوحدة سطحية. عمقها.
7.2 اختبر عند الواجهة
هذه نتيجة مباشرة من §7.1. تقف الاختبارات على واجهات الوحدات، لا على الدوال الداخلية. الاختبار على دالة داخلية يثبت التنفيذ؛ فتكسر إعادة الهيكلة الاختبار حتى عندما يكون السلوك المرئي خارجيا صحيحا. أما الاختبار على الواجهة فيثبت السلوك؛ وتتحرك الأجزاء الداخلية بحرية ما دام العقد قائما.
هذا ما تفرضه مهارة tdd افتراضيا: تستهدف الاختبارات الواجهة؛ ويعيد الوكيل هيكلة الأجزاء الداخلية بين خطوات green؛ وتمنح الحزمة تغطية كاملة من مساحة سطح صغيرة.
7.3 صمم الواجهة وفوض التنفيذ
هذه أهم عادة لمهندس كبير يعمل مع الوكلاء.
أنت تقرر ما تعرضه الوحدة: العقد، والأسماء، والثوابت. تؤثر هذه القرارات في كل مستدع؛ وتشكل البنية؛ وتتطلب ذوقا وخريطة للنظام كله في الذهن.
أما الوكيل فيقرر كيف يحقق العقد: بنى البيانات الداخلية، وموضع المساعدات، وترتيب العمليات. تؤثر هذه داخل وحدة واحدة فقط؛ وأخطاؤها قابلة للتعافي؛ ولا تحتاج إلى الخريطة المعمارية.
هذا هو مبدأ gray box. من الخارج تكون الوحدة محددة بالكامل: الواجهة مرئية، والأجزاء الداخلية مخفية بالتصميم. ومن الداخل يكون الوكيل حرا في أداء عمل ممتاز، مقيدا بعقد الواجهة فقط. يستطيع المهندس الكبير حمل الخريطة المعمارية لقاعدة كود من مليون سطر في رأسه لأن الخريطة تحتوي الواجهات فقط.
هذا ما يجعل مشكلة تشبع الدماغ في الفشل 5 قابلة للإدارة. لا يمكنك قراءة كل سطر يكتبه الوكيل؛ ذلك طريق إلى الاحتراق. لكن يمكنك إبقاء خريطة الوحدات في رأسك وقراءة كل تغيير في الواجهة بعناية. مجموعة التغييرات في الواجهات صغيرة؛ ومجموعة التغييرات داخل الوحدات كبيرة. تركيز الانتباه على المجموعة الصغيرة هو ما يتسع.
7.4 مهارة improve-codebase-architecture
تنجرف قواعد الكود مع الوقت نحو السطحية، خصوصا عندما تعمل فيها الوكلاء. والعلاج تمريرة تعميق دورية.
حتى كارباثي، وهو يعمل عند الطليعة بأحدث النماذج، يصف التجربة بوضوح: "أحيانا أشعر بنوبة قلبية صغيرة لأن الكود منتفخ جدا وفيه الكثير من النسخ واللصق، وتجريدات محرجة وهشة. يعمل، لكنه قبيح حقا." هذا ليس فشلا عميقا للنموذج؛ بل هو أداء النموذج داخل دائرة قابلة للتحقق عنوانها "هل يعمل الكود" من دون مكافأة مقابلة لسؤال "هل الكود حسن التصميم". تمنح تمريرة التعميق المكافأة التي لم تمنحها المختبرات.
---
name: improve-codebase-architecture
description: Find shallow-module candidates in the codebase and propose deepenings. Run weekly, or after a burst of feature work.
---
You are an architecture reviewer. Walk the codebase and find places
where understanding one concept requires bouncing between many small
files; where pure functions have been extracted only for testability,
not behaviour; where modules are tightly coupled at the seams.
Surface a numbered list of deepening candidates. For each, briefly:
- which existing files would collapse into the new deep module
- what the new interface would be (3-5 method signatures, no more)
- what behaviour would move inside, freeing callers from knowing it
Do NOT make changes. Open a markdown RFC describing the highest-value
candidate as an issue, blocked by nothing, type AFK.
تنتج الجولة الأسبوعية RFC واحدا للتعميق. يدخل إلى لوحة Kanban نفسها التي يتدفق عبرها عمل الميزات. وينفذ عبر حلقة TDD على الشرائح العمودية نفسها. تتحسن قاعدة الكود وفق جدول، لا بالمصادفة.
8. مفردات العمل
تسرع المفردات الدقيقة الاستدلال. المرجع الكامل هو Dictionary of AI Coding؛ أما المجموعة أدناه فهي الحد الأدنى اللازم لقراءة بقية هذا الكتاب وكتابتها.
| المصطلح | المعنى |
|---|---|
| Model | المعاملات. عديم الحالة. يتنبأ بالرمز التالي؛ ولا يفعل شيئا آخر. |
| Harness | كل ما يحيط بالنموذج ليحوله إلى وكيل: الأدوات، وتعليمة النظام، وإدارة نافذة السياق، والصلاحيات. Claude Code هو harness؛ وOpenCode هو harness. |
| Agent | نموذج + harness يعملان في نافذة سياق مع أدوات. هذا هو الشيء الذي تتحدث إليه فعلا. |
| Context window | العرض الثابت الحجم بالبايتات الذي يراه النموذج في كل طلب. محدود. وهو السطح الوحيد الذي يدرك النموذج عبره أي شيء. |
| Smart zone / dumb zone | منطقة بداية الجلسة حيث يكون الانتباه حادا / منطقة آخر الجلسة حيث يضعف الانتباه بسبب الرموز المنافسة. |
| Hallucination | خرج واثق وخاطئ. تأتي هلوسات factuality من فجوات في المعرفة البارامترية؛ وتأتي هلوسات faithfulness من الانجراف في المنطقة الغبية. وتختلف العلاجات. |
| Clearing | إنهاء الجلسة وبدء جلسة جديدة. إعادة الضبط الصلبة. تعيد الوكيل إلى حالة معروفة. |
| Compaction | تلخيص الجلسة في الذاكرة لبذر جلسة جديدة. عملية فاقدة؛ تحفظ بعض استدلال المنطقة الغبية. |
| Handoff | نقل السياق من جلسة إلى أخرى عبر أثر (PRD، أو تذكرة، أو CONTEXT.md). |
| AFK | "Away from keyboard." يطلق المستخدم جلسة ويتركها تعمل بلا حضور داخل sandbox. |
| Skill | قدرة قابلة للتعليم مجمعة في ملف SKILL.md. تحمّل عند الطلب. وحدة الإفصاح التدريجي. |
| Tracer bullet / vertical slice | مسألة تشحن مسارا رفيعا عبر كل طبقة من النظام، من البداية إلى النهاية. |
| Deep module | وحدة بواجهة صغيرة وتنفيذ داخلي كبير. الشكل الذي يجعل قواعد كود AI قابلة للتوسع. |
| Design concept | الفكرة المشتركة والمؤقتة لما يبنى، والمحمولة بين المستخدم والوكيل. ليست أثرا. |
| Grilling | تقنية لتكوين مفهوم تصميم: يحاور الوكيل المستخدم سقراطيا، قرارا واحدا كل مرة. |
| Vibe coding | قبول كود الوكيل بلا مراجعة بشرية. يختلف عن "البرمجة منخفضة الجودة"؛ فالمصطلح يسمي موقف المراجعة، لا المخرج. |
| Agentic engineering | انضباط استخدام الوكلاء في العمل الإنتاجي مع الحفاظ على معيار جودة البرمجيات المهنية. الموقف المعاكس لvibe coding: الأرضية مرفوعة والسقف محفوظ. |
| Jagged intelligence | الحقيقة التجريبية أن قدرة LLM تبلغ قمما حادة في المهام التي دربتها المختبرات عبر RL قابل للتحقق (رياضيات، كود)، وتتجمد خارج تلك الدوائر. الوكيل الذي يعيد هيكلة 100k سطر قد يخبرك أيضا أن تمشي إلى مغسلة سيارات تبعد 50 m. |
| On distribution | خاصية أن يكون الشيء ممثلا جيدا في بيانات تدريب النموذج، وبالتالي يتعامل معه بكفاءة. عند البدء من الصفر، اختر المكدسات التي يكون النموذج قويا فيها بالفعل. |
| Loop / Routine | وكيل محيط مستمر: جلسة جديدة تستدعى وفق جدول (cron محليا؛ أو "routine" من جهة الخادم) على مهمة صغيرة قائمة. كل tick عديم الحالة؛ أما الدور فيبقى في التعليمة. |
ينبغي للمبرمج العامل أن يستخدم أيا من هذه بلا تردد. جمل مثل "سأعمل clear، ثم أشغل tdd على الشريحة العمودية التالية غير المحظورة" و_"هذه faithfulness hallucination؛ التوثيق ما زال في السياق، لكنه توقف عن قراءته قرب الدور الأربعين"_ هي ما يفرق بين محادثة ضبابية ومحادثة تنجز عملا فعليا.
9. تمارين عملية
ثلاثة تمارين. افعلها بالترتيب. يستغرق كل واحد بين ثلاثين دقيقة وساعتين.
التمرين 1: ثبّت grill-me وشغله على فكرة حقيقية.
اختر ميزة تؤجل تحديد نطاقها. ثبت حزمة المهارات في مستودع نظيف متبعا §5.2 (لقراء Claude Code: شغل mkdir -p .claude/skills أولا، ثم npx skills@latest add mattpocock/skills). افتح Claude Code (أو OpenCode)، واستدع /grill-me، وأجب عن الأسئلة حتى يتوقف الوكيل. لا تختصر. عد الأسئلة. ولاحظ القرارات التي لم تكن ستستخرجها وحدك.
كيف يبدو "الجيد". تميل جلسة grilling لميزة غير تافهة إلى أن تستغرق نحو 15-40 سؤالا و30-90 دقيقة قبل أن يبلغ الوكيل التوافق. أقل من نحو 10 أسئلة يعني غالبا أن الفكرة صغيرة جدا أو أنك أجبت بسخاء مبالغ فيه؛ وأكثر من 60 يعني غالبا أن الوكيل يصطاد، فاقطعه واطلب منه الالتزام بتوصية في كل سؤال. في النهاية يجب أن تستطيع إعادة صياغة ثلاثة قرارات على الأقل ظهرت ولم تكن قد فكرت فيها عند الدخول. إذا لم تستطع، فقد كانت استبيانا لا grilling. نسبة تشخيصية مفيدة: ينبغي أن يكشف نحو سؤال من كل خمسة قرارا لم تكن قد حسمته مسبقا.
التمرين 2: اكتب شريحة عمودية كtracer bullet.
خذ أي ميزة غير منتهية في قاعدة كودك. اكتب قصة مستخدم واحدة تتبع أصغر مسار ممكن من البداية إلى النهاية. نفذها تحت مهارة tdd. لاحظ قصر الشريحة. ولاحظ مقدار التبكير الذي تظهر به أخطاء التكامل مقارنة بالتقسيم الأفقي.
كيف يبدو "الجيد". تهبط الشريحة في أقل من جلسة واحدة ومعها الاختبار والتنفيذ وفرق قابل للمراجعة في PR واحد. إذا لم يحدث ذلك، فالشريحة سميكة جدا؛ قسمها. احتكاك التكامل الذي تواجهه أثناء الشريحة هو قيمة التمرين؛ سجله كمسائل جديدة، ولا توسع الشريحة الحالية كي تبتلعه.
التمرين 3: عمق وحدة.
شغل improve-codebase-architecture على قاعدة كود تعرفها جيدا. اختر المرشح الأعلى قيمة. لا تنفذه بعد؛ ارسم على الورق الواجهة الجديدة (3-5 method signatures، لا أكثر). قارن مساحة سطح الواجهة الجديدة بالقديمة (مجموع الرموز العامة عبر الملفات التي ستنطوي). النسبة هي قياسك الملموس لمدى سطحية قاعدة الكود.
كيف يبدو "الجيد". يطوي التعميق الحقيقي عادة عدة وحدات صغيرة (نحو 5 إلى 15) في وحدة عميقة واحدة، بنسبة رموز عامة (قديم : جديد) في حدود 3:1 أو أعلى. إذا كانت النسبة أقرب إلى 1:1، فالمرشح لم يكن سطحيا حقا؛ اختر غيره.
قائمة تحقق قصيرة للعمل اليومي:
- هل شغلت
/clearقبل بدء جلسة اليوم؟ - هل استخدمت
grill-meلأي تغيير غير تافه؟ - هل مسائلي شرائح عمودية، لا مراحل أفقية؟
- هل تمر كل شريحة تنفيذ عبر
tdd؟ - هل تعمل تشغيلات AFK داخل sandbox؟
- هل المراجع جلسة منفصلة عن المنفذ؟
- هل قرأت الفرق، لا الملخص؟
10. الخاتمة: المبرمج الاستراتيجي
هذه هي الصورة التي ينبغي أن تحملها معك.
وكيلك مبرمج تكتيكي ممتاز: رقيب على الأرض يستطيع أخذ أي تل محدد جيدا، بأي لغة، وفي أي إطار عمل، في منتصف الليل، ويعود بشريحة عاملة في الصباح. لا تحتاج إلى تعليمه كيف يكتب دالة أو اختبارا. لقد حل harness والنموذج والأدوات ذلك بالفعل.
ما لا يستطيع الرقيب فعله هو تحديد أي تل. لا يستطيع أن يخبرك هل النظام الذي يبنى هو النظام الذي تحتاجه الأعمال. ولا يستطيع أن يخبرك هل يجب أن تكون الوحدة الثالثة التي توشك أن تطلبها وحدة مستقلة أصلا، أم تطوى داخل وحدة عميقة موجودة. ولا يستطيع أن يخبرك أن الكود الذي طلبته ينتهك قيدا مجاليا لم يكتب في أي مكان. ولا يستطيع إبقاء الخريطة المعمارية للنظام في ذهنه عبر أشهر وسنوات؛ فهو لا يملك أشهرا ولا سنواتا؛ لديه الجلسة الحالية وبضعة ملفات على القرص.
كل ما فوق الرقيب هو دور المبرمج الاستراتيجي، وهو دورك. التوافق مع صاحب المصلحة. تكوين مفهوم التصميم. اختيار الشريحة. تصميم الواجهة. قراءة الفرق. حمل الخريطة. والاستثمار في تصميم النظام كل يوم، كما كتب Kent Beck قبل ثلاثين عاما للبشر، وهو ما ينطبق الآن على قوة العمل الهجينة من مهندسين بشريين وموظفين رقميين بدوام كامل ستبني برمجيات العقد القادم.
أدوات المبرمج الاستراتيجي موصوفة في هذا الفصل. المسار (§4). والفشل الستة (§3) وعلاجاتها. والمهارات (§5) التي تشفر العلاجات. والبنية (§7) التي تجعل الوكيل جيدا. والمفردات (§8) التي تسمح لك بالاستدلال حول ذلك كله. عبر Claude Code وOpenCode، الانضباط واحد. وعبر Python وTypeScript، الانضباط واحد. وعبر أي نموذج وharness سيكونان موجودين بعد خمس سنوات، سيبقى الانضباط نفسه.
الحكاية التي بدأ بها هذا الفصل، أن الذكاء الاصطناعي يستبدل أساسيات البرمجيات، خاطئة لأنها تخلط من يكتب الكود مع شكل الكود الجيد. تغير الكاتب؛ ولم يتغير المعيار. قواعد الكود التي كانت جيدة للبشر جيدة للوكلاء. وقواعد الكود التي كانت سيئة للبشر سيئة للوكلاء، بل أسوأ، لأن الوكلاء يضخمون السوء.
اقرأ الكتب القديمة. The Pragmatic Programmer. A Philosophy of Software Design. Domain-Driven Design. Extreme Programming Explained. The Design of Design. كل صفحة سبقت هذه التقنية، وكل صفحة تنطبق الآن بحدة أكبر مما كانت تنطبق عند كتابتها. هذه الكتب هي كيف يتعلم المبرمج الاستراتيجي التفكير على الأزمنة التي لا يستطيع الرقيب بلوغها.
تستحق جملة من كارباثي أن تحملها معك: "يمكنك الاستعانة بغيرك في التفكير، لكن لا يمكنك الاستعانة بغيرك في الفهم." سينجز الوكيل الكتابة، والبحث، والboilerplate، واسترجاع تفاصيل API، وإعادة الهيكلة المملة. وسيزداد إنجازه للتفكير أيضا: توليد الخيارات، ووزنها، وصياغة الحلول، وتشغيل التجارب. ما يبقى لك وحدك هو الفهم: لماذا يبنى هذا النظام، وما غرضه، ومن يعتمد عليه، وما الذي يجب ألا يفعله أبدا. الفهم هو ما يتيح لك توجيه الوكيل أصلا. من دونه لا يملك الوكيل وجهة، والوكيل السريع بلا وجهة مجرد طريقة مكلفة للضياع.
والنتيجة الملازمة، من بوريس تشيرني: عندما تحل البرمجة ويصبح علم المجال هو عنق الزجاجة، أفضل شخص يكتب البرمجيات هو من يفهم المجال أكثر، لا من اعتاد تاريخيا كتابة البرمجيات. أفضل مؤلف لبرمجيات المحاسبة محاسب ممتاز. التشبيه التاريخي هو المطبعة: قبل غوتنبرغ كانت القراءة مهنة متخصصة يمارسها أقلية متعلمة صغيرة؛ وخلال عقود من مطبعته انفجر الإنتاج المطبوع؛ وخلال القرون التالية أصبحت القراءة مهارة أغلبية واسعة مع أنها كفت عن كونها مهنة. يبدأ القوس نفسه الآن للبرمجيات. خلال جيل، سيكون بناء البرمجيات شيئا يمارسه المهنيون في كل مجال كجزء عادي من عملهم (محاسبون يكتبون دفاترهم، وأطباء يكتبون سير عملهم السريري، ومحامون يكتبون محللات عقودهم، ومعلمون يكتبون أدوات مناهجهم)، وسيعني الدور الذي نسميه "مهندسا" شيئا أضيق وأعمق: الشخص الذي يصمم الركيزة التي يبني عليها بقية قوة العمل.
هذا هو شكل قوة العمل الذي يتناوله هذا الكتاب. الموظف الرقمي بدوام كامل الذي ستصنعه في الفصول التالية أداة لخبير مجال: يبنيه مهندس وكيلي، لكنه يحدد ويحكم ويستخدم من المحاسب، أو المكتتب، أو المحلل، أو مدير الحالة الذي يملك العمل. مبادئ هذا الفصل وسير عمله هي ما يجعل أولئك الموظفين الرقميين بدوام كامل جديرين بالثقة بما يكفي لاستحقاق تلك الملكية. المسار، والمهارات، والوحدات العميقة، والحلقات المستمرة، وsandboxes، وانضباط المنطقة الذكية، والوعي بالذكاء المتعرج: كلها في خدمة برمجيات يستطيع خبير المجال الاعتماد عليها من دون قراءة سطر واحد من الكود. هذا هو عقد الهندسة الوكيلة مع الناس الذين تخدمهم.
هذا هو العمل. وهذا هو الفصل.
قراءات إضافية
- مات بوكوك، Software Fundamentals Matter More Than Ever: الكلمة الرئيسية التي تغذي أطروحة هذا الفصل.
- مات بوكوك، Full Walkthrough: Workflow for AI Coding: شرح حي مدته ساعتان للمسار في §4 و§5.
- مات بوكوك، 5 Claude Code Skills I Use Every Single Day: مرجع المهارات اليومية.
- مات بوكوك، Dictionary of AI Coding: المسرد القانوني؛ ومصدر §8.
- مات بوكوك، Skills for Real Engineers: حزمة المهارات القابلة للتثبيت المستخدمة في الفصل.
- أندريه كارباثي، From Vibe Coding to Agentic Engineering: الحديث الذي يسمي الانضباط، ويصوغ إطار Software 1.0/2.0/3.0، ويقدم jagged intelligence وعدسة animals vs. ghosts المستخدمة في §1 و§2.
- بوريس تشيرني (Anthropic)، Why Coding Is Solved, and What Comes Next: منشئ Claude Code عن سير عمله الشخصي، وحجة "on-distribution" في اختيار المكدس، والحلقات وroutines المستمرة، وتشبيه المطبعة المستخدم في §1.2 و§2.3 و§6.5.3 و§10.
- جون أوسترهاوت، A Philosophy of Software Design: الوحدات العميقة والوحدات السطحية.
- ديفيد توماس وأندرو هنت، The Pragmatic Programmer: tracer bullets والمصابيح الأمامية.
- إريك إيفانز، Domain-Driven Design: اللغة الشاملة.
- كنت بك، Extreme Programming Explained: الاستثمار في التصميم كل يوم.
- فريدريك ب. بروكس، The Design of Design: شجرة التصميم ومفهوم التصميم.
المهارات المرافقة لهذا الفصل
يمر مسار الفصل عبر ست مهارات من حزمة مات بوكوك، وكلها مرتبطة هنا للقراءة المباشرة:
grill-me: المقابلة السقراطية التي تنتج مفهوم التصميم.grill-with-docs: grilling يكتب أيضاCONTEXT.mdوADRs في السياق نفسه (سلالة "اللغة الشاملة" من §3 الفشل 2).to-prd: يلخص المحادثة في PRD.to-issues: يقسم PRD إلى تذاكر tracer-bullet.tdd: red-green-refactor، شريحة واحدة كل مرة.improve-codebase-architecture: يجد الوحدات السطحية، ويقترح التعميق، ويفتح RFC.
تعمل خطوة bootstrap واحدة، setup-matt-pocock-skills، أولا لكل مستودع، وتبني إعداد متتبع المسائل وتخطيط docs/agents/ الذي تعتمد عليه المهارات الهندسية.
تشحن حزمة مات أربع عشرة مهارة إجمالا (المستودع الكامل). إلى جانب المسار ذي المراحل السبع وsetup-matt-pocock-skills، تتضمن أيضا diagnose (تصحيح أخطاء منضبط)، وtriage (فرز تذاكر كآلة حالات)، وzoom-out (إعادة تأطير بسياق أوسع)، وprototype (نماذج تصميم أولية مؤقتة)، وwrite-a-skill (المهارة الفوقية لإنشاء مهارات جديدة)، وhandoff (انضباط أثر التسليم من جلسة إلى جلسة من §4.1)، وcaveman (وضع التعليمة المقتضبة). تقع هذه خارج المسار ذي المراحل السبع لكنها تتركب معه، وكل منها يعمل بالطريقة نفسها في Claude Code وOpenCode. انظر Part 5: Building OpenClaw Apps لمرجع حزمة مهارات Agent Factory والمهارات الإضافية الخاصة بالكتاب.
وسيلة دراسة بالبطاقات التعليمية
اختبار المعرفة
فحص ذاتي سريع ومشروط للأفكار التي مررت بها للتو.