كيف تجعل ملف AGENTS.md محدثاً تلقائياً باستخدام dox
يصبح ملف AGENTS.md قديماً ويضلل وكيل البرمجة مما يسبب أخطاء غير متوقعة. استخدم أداة dox لتوليد التوثيق من الكود مباشرة ومراجعة التغييرات كأنها جزء من الكود المصدري لمشروعك.
لماذا يصبح ملف AGENTS.md الخاص بك غير دقيق بعد ثلاثة أسابيع
يصبح ملف AGENTS.md قديماً لأن لا شيء يربطه بالكود المصدري. أنت تكتبه يدوياً لمرة واحدة في اليوم الذي يبدو فيه المستودع بحالة معينة. بعد ذلك، يتغير مشغل الاختبارات، أو يُعاد تسمية حزمة ما، أو تُحذف خدمة، بينما يظل الملف يصف حالة شهر يونيو. لا يفشل أي شيء، لأن لا توجد خطوة بناء تقرأ هذا الملف.
يقرأ الوكيل (Agent) الملف ويصدقه. هذا هو الجزء الذي يكلفك الكثير. المستودع الذي لا يحتوي على AGENTS.md يجعل وكيل البرمجة يبحث في الملفات قبل اتخاذ أي إجراء. أما المستودع الذي يحتوي على ملف AGENTS.md غير دقيق، فيجعله يتوقف عن البحث لأنه يظن أنه يملك الإجابة بالفعل. ينفذ الوكيل الأمر المذكور في ملفك، فيرد الغلاف (Shell) بـ Missing script: "test"، وهنا يبدأ الوكيل بالتخمين. غالباً ما يقوم بتعديل package.json لإضافة السكريبت الذي وعدت به في توثيقك. الملف القديم لم يفشل بصمت، بل تسبب في تعديل لم تكن تريده.
يُعد dox أحد الحلول لهذه المشكلة. إنه مجموعة من القواعد المكتوبة للوكيل، تجعل تحديث التوثيق جزءاً من إتمام العمل، بحيث يتغير الملف في نفس الالتزام (Commit) الذي تضمن الكود الذي جعل الملف غير دقيق.
ما هو dox، وما ليس هو
dox هو ملف Markdown واحد. المستودع هو agent0ai/dox، وهو مرخّص برخصة MIT، واعتباراً من 11 أغسطس 2026 يبلغ حجم المشروع بالكامل 3906 بايت AGENTS.md، ويحتوي على ملف README، وملف LICENSE، وصورتين. لا توجد حزمة للتثبيت ولا وقت تشغيل (runtime).
هذا الأمر مهم، لأن كلمة "مولّد" (generator) توحي ببرنامج يحلل الكود الخاص بك. لا شيء يحلل الكود الخاص بك. dox هو عقد يقرؤه وكيل البرمجة (coding agent) الخاص بك: وكيلك هو المولّد، وdox هو مجموعة التعليمات التي تخبره متى يقرأ الوثائق، ومتى يعيد كتابتها، وما هو الشكل الذي تتخذه كل وثيقة.
يحتوي الملف على عشرة أقسام، اثنان منها يقومان بالعمل. يخبر قسم "القراءة قبل التعديل" (Read Before Editing) الوكيل بأن يتجول من جذر المستودع إلى كل مسار يخطط للمسه، وأن يقرأ كل ملف AGENTS.md على طول كل مسار، في الجلسة الحالية، دون الاعتماد على الذاكرة. ويخبره قسم "التحديث بعد التعديل" (Update After Editing) أن كل تغيير ذي مغزى يتطلب تمريرة DOX، مما يعني خطوة تحديث للوثائق يتم تشغيلها قبل اعتبار المهمة منجزة. تقوم هذه التمريرة بتحديث أقرب وثيقة مالكة عندما يتغير الغرض، أو الهيكل، أو سير العمل، أو الصلاحيات، أو تفضيلات المستخدم.
بقية الملف تتعلق بالشكل. يحتوي ملف AGENTS.md الفرعي على ترتيب أقسام افتراضي: الغرض، والملكية، والعقود المحلية، وتوجيهات العمل، والتحقق، وفهرس DOX الفرعي. يحتوي الملف الجذري على قواعد المشروع بالكامل بالإضافة إلى فهرس DOX الفرعي للمستوى الأعلى، وهي الطريقة التي يكتشف بها الوكيل الوثائق الفرعية. "الإغلاق" (Closeout) هو قائمة المراجعة التي يشغلها الوكيل في نهاية المهمة: إعادة فحص المسارات المتغيرة مقابل السلسلة، وتحديث أقرب الوثائق المالكة، وتحديث كل فهرس متأثر، وحذف التناقضات، وتشغيل التحقق الموجود، والإبلاغ عن الوثائق التي تركها دون تغيير بشكل متعمد.
ثبّت التوثيق على commit محدد، لا على main
لا يحتوي المستودع على tags أو releases، لذا لا يوجد رقم إصدار للتثبيت. ثبّت الـcommit بدلاً من ذلك. ملف AGENTS.md الحالي هو الـcommit رقم f34ec7ad1055d3393887e5a2670e8cb7320c9165، بتاريخ 1 أغسطس 2026.
mkdir -p .agent
curl -fsSL -o .agent/dox-f34ec7a.md \
https://raw.githubusercontent.com/agent0ai/dox/f34ec7ad1055d3393887e5a2670e8cb7320c9165/AGENTS.md
wc -c .agent/dox-f34ec7a.mdيجب أن يطبع wc -c القيمة 3906. أي رقم مختلف يعني أنك لم تجلب الملف الذي يصفه هذا الدليل، لذا اقرأه قبل الوثوق به. إذا أخطأت في كتابة hash الـcommit، فإن -f سيجعل curl يتوقف مع curl: (22) The requested URL returned error: 404 ولن يكتب أي محتوى، ثم يطبع wc -c القيمة 0. الملف المبتور أسوأ من عدم وجود ملف، لأن الوكيل سيتبع نصف العقد دون أن يعلم بذلك.
cp .agent/dox-f34ec7a.md AGENTS.md
git add AGENTS.md .agent/dox-f34ec7a.md
git commit -m "Add DOX rules (agent0ai/dox @ f34ec7a)"هذا الـcp مخصص لمستودع لا يحتوي على AGENTS.md بعد. إذا كان لديك ملف بالفعل، فلا تستبدله. ضع أقسام التوثيق فوق محتواك الحالي، واحتفظ بقواعدك الخاصة في الأسفل، واقرأ النتيجة مرة واحدة من البداية إلى النهاية. وثيقتان متناقضتان تنتجان وكيلاً يتبع السطر الذي قرأه أخيراً.
ثم اطلب من وكيلك، داخل المستودع، إجراء التمريرة الأولى. يعطي ملف README الصيغة الدقيقة:
Initialize DOX tree for this project now.يقوم هذا بإنشاء ملفات AGENTS.md الفرعية والفهارس التي تشير إليها. تحقق مما فعله قبل أن تصدقه:
git status --short
find . -name AGENTS.md -not -path './.git/*' | sortيجب أن يظهر كل ملف في مخرجات find ضمن فهرس توثيق فرعي (Child DOX Index) في مكان ما فوقه. الوثيقة الفرعية التي لا يذكرها أي فهرس هي وثيقة قد يغفل عنها الوكيل، لأن الفهرس هو الوسيلة التي يعثر بها على الوثائق التي لا تقع مباشرة على المسار الذي يسلكه.
ما يمكن لـ dox رؤيته، وما لا يمكنه معرفته
يقرأ الوكيل الذي يبني شجرتك المستودع، لذا يمكن لأي شيء موجود في المستودع أن يدخل في الجرد: هيكل المجلدات، وملفات تعريف الحزم (manifests) وملفات القفل (lockfiles)، والسكربتات الموجودة في package.json أو Makefile أو pyproject.toml، وملفات سير عمل CI، وملفات Dockerfiles، ونقاط الدخول، وCODEOWNERS إذا كان لديك واحد. الجرد المبني من هذه المصادر يحافظ على نفسه ذاتياً بشكل حقيقي. عندما تنتقل حزمة ما، تقوم الدورة التالية بتحديث السطر الذي يصفها.
كل ما يلي هو من اختصاصك لتوضيحه، لأنه غير موجود في المستودع ليتم قراءته:
- سبب وجود قاعدة معينة، وهو ما يمنع الوكيل من إزالتها باعتبارها تعقيداً غير ضروري.
- أي المسارين العاملين هو المدعوم، وأيهما ينتظر الحذف.
- أي شيء خارج المستودع، مثل بيئة الاختبار (staging) أو سبب تثبيت إصدار معين من التبعيات (dependency) قبل إصدارين.
- ما تخطط للقيام به في الأسبوع القادم، وهو الفرق بين ملف حالي وملف مفيد.
يعرف dox هذه الحقيقة عن نفسه. تنص قواعده الخاصة على أن "توجيهات العمل" (Work Guidance) يجب أن تعكس المعايير الحالية للمشروع أو تعليمات المستخدم، وإذا لم تكن هناك معايير بعد، تترك القسم فارغاً. يجب أن يعكس "التحقق" (Verification) فحصاً موجوداً بالفعل، لذا في حال عدم وجود إطار عمل للاختبار في المستودع، يظل ذلك القسم فارغاً حتى يتم توفيره. الملف المولد الذي يبتكر معياراً من تلقاء نفسه هو أسوأ من القسم الفارغ، لأن الوكيل سيقوم حينها بفرض هذا الابتكار.
أبقِ القصد المكتوب يدوياً خارج الجرد المُولَّد
هذا هو الفشل الذي يجعل الأشخاص يتخلون عن الوثائق المُولَّدة. أنت تكتب فقرة تشرح فيها أن طابور المهام يجب أن يظل أحادي المستهلك. بعد ثلاثة أسابيع، يقوم إجراء بإعادة كتابة الملف وتختفي فقرتك، داخل فرق (diff) من أربعين سطراً تقوم في الغالب بتبديل أسماء الملفات، ولا يلاحظ أحد ذلك.
هناك آليتان، وأنت بحاجة لكلتيهما.
أولاً، انقل القصد الدائم إلى ملف مختلف. قرارات التصميم والمنطق الكامن وراءها تنتمي إلى ملف DESIGN.md مكتوب للوكيل، والملاحظات الموجودة للبشر تنتمي إلى المكان الذي فصلت فيه HUMAN.md عن AGENTS.md. عندها يحمل AGENTS.md الجرد والعقود المحلية، وهو بالضبط الجزء الذي يجب أن يتغير عند تغير الكود.
ثانياً، احمِ القصد الذي يجب أن يبقى داخل AGENTS.md. غلّفه بعلامات وتعامل مع الكتلة على أنها مملوكة للبشر:
## User Preferences
<!-- dox:keep start -->
The jobs queue stays single consumer. Ordering is the reason this service exists.
Deploys ship on Tuesday. A Friday deploy is a human decision, not an agent decision.
<!-- dox:keep end -->تعليقات Markdown لا تظهر في الصفحة، والوكيل لا يزال يقرؤها. الآن اجعل بقاء الكتلة قابلاً للتحقق، بحيث يفشل الإجراء الذي يمحوها بشكل صاخب. شغّل هذا في CI (التكامل المستمر) عند كل طلب سحب (pull request):
git fetch -q origin main
sed -n '/dox:keep start/,/dox:keep end/p' AGENTS.md > /tmp/keep.head
git show origin/main:AGENTS.md | sed -n '/dox:keep start/,/dox:keep end/p' > /tmp/keep.base
diff -u /tmp/keep.base /tmp/keep.headdiff لا يطبع شيئاً ويخرج بالقيمة 0 عندما تظل الكتلة دون تغيير. أي مخرجات تعني أن الإجراء قد أعاد كتابة نص مملوك للبشر، لذا يجب على شخص ما الموافقة عليه أو التراجع عنه. يستمر الفحص دون أن يضطر أحد لتذكره.
أعد الإنشاء عند طلب السحب، لا وفق مؤقت
أفضل لحظة لتحديث وثيقة هي عند إجراء الالتزام (commit) الذي يجعلها غير دقيقة. أدرج عملية DOX في نفس طلب السحب (pull request) الخاص بالتغيير الهيكلي، وسيبقى فرق الملفات (diff) صغيراً بما يكفي لقراءته فعلياً.
إليك فحص حظر يفرض ذلك:
#!/usr/bin/env bash
set -euo pipefail
git fetch -q origin main
base=$(git merge-base origin/main HEAD)
changed=$(git diff --name-only "$base" HEAD)
if grep -qE '^(src|apps|packages)/' <<<"$changed" && ! grep -q 'AGENTS\.md$' <<<"$changed"; then
echo "Code changed but no AGENTS.md was touched. Run a DOX pass, or say why not."
exit 1
fiعدّل المسارات لتناسب مستودعك. تكمن القيمة في أن الفحص يفشل على الفرع (branch)، حيث يكون الإصلاح غير مكلف، ويفشل لسبب يمكن للمراجع اتخاذ إجراء بشأنه.
الجدولة هي وسيلة احتياطية وليست الآلية الأساسية. تلتقط المهمة الأسبوعية ما لم يلاحظه أحد على الفرع: ملفات نُقلت بسبب إعادة التأسيس (rebase)، حزمة حُذفت أثناء الدمج، أو وثيقة تشير إلى دليل لم يعد موجوداً. شغّل المهمة على خادم صغير، وهو نفس الخادم الذي قد تستخدمه لـ تشغيل وكيل برمجي على VPS، واجعله يفتح طلب سحب بدلاً من الدفع (push) إلى الفرع الرئيسي.
#!/usr/bin/env bash
set -euo pipefail
cd /srv/src/myapp
git fetch -q origin
git switch -c "dox/refresh-$(date +%Y%m%d)" origin/main
# Your agent CLI goes on the next line, in whatever non-interactive mode it offers.
# Prompt: "Run a DOX pass over this repository. Change AGENTS.md files only."
git add '*AGENTS.md'
git commit -m "dox: refresh AGENTS.md tree" || { echo "nothing to refresh"; exit 0; }
git push -q -u origin HEAD
gh pr create --fillهذا التعليق هو عنصر نائب عن قصد. لكل وكيل واجهة سطر أوامر (CLI) خاصة به وعلامة (flag) خاصة للتشغيل غير التفاعلي، والأمر المنسوخ من صفحة ويب والذي لا يطابق إصدارك سيفشل داخل cron حيث لا يرى أحد الخطأ. املأ البيانات وشغّل البرنامج النصي يدوياً مرة واحدة قبل جدولته. الـ || exit 0 مهم أيضاً: git commit يخرج برمز غير صفري مع nothing to commit, working tree clean عندما تكون الشجرة محدثة بالفعل، وتحت set -e سيؤدي ذلك إلى الإبلاغ عن تشغيل سليم على أنه فشل.
كل عملية تستهلك رموزاً (tokens)، لأن "القراءة قبل التعديل" تجعل الوكيل يقرأ السلسلة بأكملها في كل مهمة. هذه هي المقايضة، وهي تستحق المراقبة إذا كنت بالفعل تحسب تكلفة تشغيل وكيلك.
المستودعات الموحدة (Monorepos): عقود متعددة، فهرس واحد
إن وجود ملف AGENTS.md جذري واحد في مستودع يحتوي على أربعين حزمة يؤدي إلى إنشاء فرق (diff) لإعادة التوليد لا يقرؤه أحد، ووثيقة تكون في الغالب غير ذات صلة بما يفعله الوكيل في الوقت الحالي. الحل الذي تقدمه dox هو فهرس الوثائق الفرعي (Child DOX Index): يحتفظ الجذر بالقواعد الخاصة بالمستودع ككل ويشير إلى توابعه، بينما يمتلك كل حدٍّ دائم ملفه الخاص. كيفية تصميم هذه الشجرة، والأدوات التي تقرأ الملفات المتداخلة، مشروحة في ملفات AGENTS.md المتداخلة للمستودعات الموحدة.
ما تغيره dox هو نطاق المراجعة. يجب أن يؤدي طلب السحب (pull request) الذي يمس packages/api إلى إنتاج فرق في الوثائق داخل packages/api وليس في أي مكان آخر:
git diff --stat -- '*AGENTS.md'إذا كان هذا الأمر يسرد ستة ملفات لتغيير في حزمة واحدة، فإن الشجرة خاطئة. إما أن الحدود واسعة جداً، أو أن قاعدة تنتمي إلى الجذر قد نُسخت في كل تابع. توضح dox الحل مباشرة: القواعد العامة توضع في وثائق الأصل، والتفاصيل المحددة توضع في وثائق التابع. القواعد المكررة هي ما يجعل المراجعة الروتينية تعيد كتابة كل شيء. إذا كانت القواعد نفسها تنطبق حقاً عبر مستودعات منفصلة، فهذه مشكلة مختلفة، وتعد مشاركة مهارات الوكيل عبر المستودعات الأداة الأفضل لذلك.
راجع فرق الملفات (diff) كما تراجع الكود
من السهل الموافقة على فرق توثيق مُنشأ آلياً دون قراءته، وهذا هو السبب في شحن ملف خاطئ. اقرأ الفرق بالشك الذي تعامل به الكود المصدري، وابحث عن أربعة أمور:
- أي أمر يذكره الملف الآن، والذي يجب عليك تشغيله بنفسك قبل الدمج. تعليمات البناء المخترعة هي أكثر أسباب الفشل شيوعاً.
- أي سطر محذوف كان يحمل غرضاً معيناً. الإضافات رخيصة، أما الحذف فهو حيث تقع الخسارة.
- أي مسار مطلق، أو اسم مضيف، أو رابط URL داخلي، أو أي شيء يشبه بيانات الاعتماد.
- أي إدخال في الجرد لشيء لم يعد موجوداً، وهو ما يقوم
lsبتسويته في ثانية.
ثم تحقق من الحجم باستخدام wc -l AGENTS.md. أي ملف root يتجاوز مائتي سطر هو إشارة لتقسيمه، لأن القيمة الكاملة للسلسلة تكمن في أن الوكيل يقرأ الجزء الصغير ذي الصلة بدلاً من قراءة كل شيء.
عند حدوث عطل
حذف التمرير كتلة القصد الخاصة بك. يقوم الفحص diff أعلاه بطباعة الأسطر المحذوفة. استعد الملف من نقطة الفرع باستخدام git restore --source=origin/main AGENTS.md، ثم أعد تشغيل التمرير بتعليمات أكثر دقة تحدد الأقسام التي قد تتأثر.
تمت إعادة إنشاء فرعين. ستحصل على CONFLICT (content): Merge conflict in AGENTS.md وعلامات تعارض <<<<<<< HEAD داخل الملف. لا تقم بتعديل العلامات يدوياً. الملف مُنشأ آلياً، لذا فإن الحل الصحيح هو إجراء تمرير جديد على الشجرة المدمجة.
يتجاهل الوكيل الملف تماماً. تحقق من اسم الملف الذي تقرؤه أداتك فعلياً. إذا كانت تقرأ ملفاً مختلفاً، وجّهها إلى نفس المحتوى باستخدام ln -s AGENTS.md CLAUDE.md وقم بعمل commit للرابط الرمزي (symlink)، لكي تحتفظ بمصدر واحد بدلاً من وثيقتين تتباعدان عن بعضهما. إذا كان اسم الملف صحيحاً بالفعل ولا تزال القواعد تُتجاهل، قم بتشغيل التشخيص الخاص بـ لماذا تتجاهل وكلاء البرمجة تعليماتك قبل إعادة كتابة الوثيقة مرة أخرى.
نمت الشجرة بفروع لم يقم أحد بفهرستها. قارن مخرجات find . -name AGENTS.md بمدخلات الفهرس في الوثائق الأصلية. الفرع الذي لا يذكره أي فهرس هو فرع يمكن للوكيل تجاوزه مباشرة.
متى يكون استخدام المولد (Generator) مبالغاً فيه
عندما يكون لديك حزمة واحدة، وأمر اختبار واحد، وشخصان يعرفان المستودع جيداً: اكتب العشرين سطراً يدوياً. ملف AGENTS.md المكون من عشرين سطراً لا يتقادم بالسرعة التي تبرر وجود شجرة ملفات، وفهرس، وفحص CI، ومهمة دورية أسبوعية. أعد قراءته عند تغيير عملية البناء. هذه هي تكلفة الصيانة الكاملة، وهي أقل من تكلفة الآليات المحيطة بها.
تصبح أدوات التوثيق (dox) ذات قيمة عندما يحتوي المستودع على حدود لا يستوعبها شخص واحد في ذهنه: عدة حزم بقواعد مختلفة، أو مساهمون ينضمون دون خلفية مسبقة. القيمة ليست في النص المُولّد، بل في أن التوثيق يصبح شيئاً يمكن لطلب السحب (pull request) أن يفشل بسببه، وهذا هو السبب الوحيد الذي يجعل أي ملف في المستودع محدثاً.
FAQ
هل أحتاج إلى تثبيت أي شيء لاستخدام dox؟
لا. dox عبارة عن ملف Markdown واحد، مرخص بموجب رخصة MIT، واعتباراً من 11 أغسطس 2026 لا يشحن المستودع أي حزمة ولا يصدر أي نسخ (releases). انسخ محتوياته إلى ملف AGENTS.md الخاص بمشروعك، وسوف يتبع وكيل البرمجة الخاص بك القواعد الواردة فيه. ثبّت الـ commit الذي نسخته، وهو f34ec7ad1055d3393887e5a2670e8cb7320c9165 وقت كتابة هذا النص، واذكره في رسالة الـ commit الخاصة بك حتى تتمكن لاحقاً من معرفة الإصدار الذي بُنيت شجرة مشروعك بناءً عليه.
كيف أمنع عملية إعادة التوليد من حذف قواعدي المكتوبة يدوياً؟
افصل بين النوايا والمخزون. ضع التفكير المستدام في مستند منفصل، وأي شيء يجب أن يبقى داخل AGENTS.md ضعه داخل كتلة محددة. ثم تحقق من هذه الكتلة في نظام CI: استخرجها من الفرع ومن origin/main باستخدام sed، وقارن بينهما باستخدام diff، واجعل البناء يفشل عند وجود أي اختلاف. يقوم شخص ما بعد ذلك بالموافقة على التغيير أو التراجع عنه، بدلاً من تمريره دون ملاحظة داخل diff كبير.
كم مرة يجب أن أعيد توليد AGENTS.md؟
في طلب السحب (pull request) الذي يجعلها غير صحيحة. ينتمي التغيير الهيكلي وتوثيقه إلى diff واحد، لأن هذه هي اللحظة الوحيدة التي يمتلك فيها شخص ما السياق لمراجعة كليهما. التمرير المجدول أسبوعياً هو النسخة الاحتياطية للانحراف الذي قد يتسرب خارج الفرع، ويجب أن يفتح طلب سحب بدلاً من الالتزام (commit) مباشرة في الفرع الرئيسي main.
هل يجب أن توضع أوامر البناء في ملف AGENTS.md الجذري أم في ملف فرعي؟
في أقرب مستند يمتلكها. توضع القواعد الخاصة بالمستودع بالكامل وفهرس الأبناء في الجذر. أما الأمر الذي ينطبق على حزمة واحدة فيوضع في ملف AGENTS.md الخاص بتلك الحزمة. يحل dox التعارضات بناءً على المسافة: المستند الأقرب هو الذي يتحكم في التفاصيل المحلية، ولا يجوز لأي مستند فرعي إضعاف قاعدة أصلية. إن نسخ الأمر نفسه في كل مستند فرعي هو ما يجعل عملية التمرير الروتينية تعيد كتابة الشجرة بأكملها.
هل يستحق dox العناء بالنسبة لمستودع صغير؟
غالباً لا. الحزمة الواحدة التي تحتوي على أمر اختبار واحد وملف AGENTS.md بطول عشرين سطراً تتدهور ببطء، ويمكنك إصلاحها في الدقيقة التي تلاحظ فيها ذلك. يكتسب dox قيمته عندما يحتوي المستودع على عدة حدود بقواعد مختلفة، أو مساهمين يفتقرون إلى الخلفية المعرفية، لأن سلسلة المستندات تقوم حينها بعمل لا يقوم به شخص واحد بمفرده.