Claude Code لإخفاقات CI: اطلب منه اقتباس مخرج الفشل، اقتراح أصغر إصلاح ممكن، وإضافة اختبار ارتدادي لمنع التكرار.

فشل CI عادةً ليس غامضًا. السجل يوضح أين توقف الأمر، أي أمر فشل، ورسالة الخطأ. تشغيل جيد يتضمن تتبّعًا للمكدس، أو خطأ للمجمّع مع ملف ورقم سطر، أو تقرير اختبار يبيّن أيّ تعبير تحقق فشل. أحيانًا تحصل حتى على تلميح على شكل diff مثل "expected X, got Y" أو خطوة فاشلة واضحة مثل "lint" أو "build" أو "migrate database".
المشكلة الحقيقية أن الناس (وأحيانًا الذكاء الاصطناعي) يعاملون السجل كضجيج خلفي. إذا ألصقت سجلًا طويلًا وطلبت "إصلاحًا"، الكثير من النماذج تقفز إلى تفسير مألوف بدل قراءة السطور الأخيرة المهمة. التخمين يزداد سوءًا عندما يبدو الخطأ شائعًا ("module not found"، "timeout"، "permission denied"). النتيجة قد تكون إعادة كتابة كبيرة، اعتماد جديد، أو إجابة "جرّب تحديث كل شيء" لا تتطابق مع الفشل الفعلي.
الهدف ليس "جعل الاختبارات تمر بطريقة ما". الهدف أبسط:
عمليًا، "الأصغر" عادةً ما يكون أحد ما يلي: تغيير من عدة أسطر في مكان واحد، استيراد مفقود أو مسار خاطئ، قيمة إعداد خاطئة واضحة لبيئة CI، أو التراجع عن تغييرٍ عارضٍ مكسر بدل إعادة تصميم الشيفرة.
اختبار متابعة أيضًا مهم. اجتياز CI مرة واحدة ليس مثل منع التكرار. إذا جاء الفشل من حالة طرفية (مدخل null، المنطقة الزمنية، تقريب، صلاحيات)، أضف اختبار ارتدادي يفشل قبل الإصلاح ويمر بعده. هذا يحوّل إنقاذًا لمرة واحدة إلى حاجز وقائي.
معظم التصحيحات السيئة تبدأ بسياق مفقود. إن ألصقت السطر الأحمر الأخير فقط، على النموذج التخمين عوضًا عن الفهم، وغالبًا ما تتحول التخمينات إلى إعادة كتابة.
حاول توفير قدر كافٍ من التفاصيل بحيث يمكن لشخص تتبّع الفشل من أول خط خطأ حقيقي حتى النهاية، ثم يُغيِّر أقل ما يمكن.
انسخ هذه العناصر في رسالتك (حرفيًا عندما تستطيع):
go test ./..., npm test, flutter test, golangci-lint run).أضف قيودًا بكلام واضح. إن أردت إصلاحًا صغيرًا، قل ذلك: لا إعادة تصميم، لا تغييرات سلوكية إلا إذا لزم، ابقِ الباتش محدودًا بمنطقة الفشل.
مثال بسيط: فشل CI في خطوة اللينت بعد ترقية اعتماديات. ألصق مخرجات اللينت بدءًا من التحذير الأول، أدرج الأمر الذي استخدمه CI واذكر تغيير نسخة الحزمة الوحيد. هذا يكفي لاقتراح تعديل إعداد من سطر واحد أو تغيير شيفرة صغير، بدل إعادة تنسيق نصف المستودع.
إن أردت شيئًا قابلاً للنسخ واللصق، هذا الهيكل عادةً يكفي:
CI command:
Failing output (full):
Recent changes:
Constraints (smallest fix, no refactor):
Flaky? (runs attached):
عندما يخطئ نموذج في تشخيص انهيار CI، غالبًا لأن مطالبتك تسمح له بالتخمين. عملك هو جعله يُظهر عمله باستخدام مخرجات الفشل بالضبط، ثم الالتزام بأصغر تغيير قد يجعل المهمة تمر.
اِطلب أدلة وخطة صغيرة. مطالبة جيدة تفرض خمسة أشياء:
الشك مقبول. الشك الخفي هو ما يهدر الوقت.
ألصق هذا في أعلى سؤالك عن CI:
Use ONLY the evidence in the CI output below.
1) Quote the exact failing lines you are using.
2) Give ONE sentence: the most likely cause.
3) Propose the smallest fix: 1-3 edits, with file paths.
4) Do NOT do formatting/renames/refactors or "cleanup".
5) List uncertainties + the one extra detail that would confirm the diagnosis.
إذا قال السجل "expected 200, got 500" بالإضافة إلى تتبّع مكدس في user_service.go:142، فإن هذا الهيكل يدفع الرد نحو تلك الدالة وتغيير حارس أو معالجة خطأ صغيرة، لا إعادة تصميم نقطة النهاية.
أسرع الحلول تأتي من مطالبة تجبر اقتباس السجلات، تبقى داخل القيود، وتوقف عندما شيء ناقص.
You are helping me fix a CI failure.
Repo context (short):
- Language/framework:
- Test/build command that failed: <PASTE THE EXACT COMMAND>
- CI environment (OS, Node/Go/Python versions, etc.):
Failing output (verbatim, include the first error and 20 lines above it):
<PASTE LOG>
Constraints:
- Propose the smallest possible code change that makes CI pass.
- Do NOT rewrite/refactor unrelated code.
- Do NOT touch files you do not need for the fix.
- If behavior changes, make it explicit and justify why it is correct.
Stop rule (no guessing):
- If the log is incomplete or you need more info (missing stack trace, config, versions, failing test name), STOP and ask only the minimum questions needed.
Your response format (follow exactly):
1) Evidence: Quote the exact log lines that matter.
2) Hypothesis: Explain the most likely cause in 2-4 sentences.
3) Smallest fix: Describe the minimal change and why it addresses the evidence.
4) Patch: Provide a unified diff.
5) Follow-up: Tell me the exact command(s) to rerun locally to confirm.
Then, write ONE regression test (or tweak an existing one) that would fail before this fix and pass after it, to prevent the same failure class.
- Keep the test focused. No broad test suites.
- If a test is not feasible, explain why and propose the next-best guardrail (lint rule, type check, assertion).
تفصيلان يقلّلان الحاجة للردود المتكررة:
أسرع طريقة لإضاعة الوقت هي قبول تغييرات "تنظيف" تعدل خمسة أمور مرة واحدة. حدّد "الأدنى" مقدمًا: أصغر diff يجعل المهمة الفاشلة تمر، بأقل مخاطرة وأسرع طريقة للتحقق.
قاعدة بسيطة تعمل جيدًا: أصلح العرض أولًا، ثم قرر إن كانت إعادة التصميم واسعة النطاق تستحق العناء. إن أشار السجل إلى ملف واحد، دالة واحدة، استيراد مفقود، أو حالة طرفية، اهدف إلى هناك. تجنّب تعديلات "وبينما نحن هنا".
إن احتجت فعلاً لبدائل، اطلب اثنين فقط: "الأكثر أمانًا" مقابل "الأسرع". تريد مقايضات، لا قائمة خيارات.
وألزم بالتحقق المحلي بما يوافق CI. اطلب الأمر نفسه الذي يشغله الخطّ (أو أقرب ما يكون له)، حتى تؤكّد في دقائق:
# run the same unit test target CI runs
make test
# or the exact script used in CI
npm test
إذا اقترح الرد تغييرًا كبيرًا، قاومه بقول: "أرِني أصغر باتش يصلح تحقق الفشل، دون تنسيق غير متعلق أو إعادة تسمية."
إصلاح من دون اختبار متابعة هو مقامرة بأن المشكلة لن تعود. اطلب دائمًا اختبار ارتدادي يفشل قبل التصحيح ويمر بعده.
كن محددًا بشأن ما يعنيه "جيد":
نمط مفيد يطلب أربع نقاط: أين تضع الاختبار، ماذا تسميه، أي سلوك يغطي، وملاحظة قصيرة تشرح لماذا يمنع هذا الاختبار تكرار الخطأ.
إضافة جاهزة للنسخ:
مثال: يظهر CI حدوث panic عند استقبال Handler قيمة ID فارغة. لا تطلب "اختبارًا لهذا السطر" فقط؛ اطلب اختبارًا يغطي معرفات غير صالحة متعددة (فارغ، فقط مسافات، صيغة خاطئة). قد يكون الإصلاح الأصغر عبارة عن شرط حارس يعيد 400. يجب أن يختبر الاختبار المتغيرات غير الصالحة المتعددة حتى يفشل CI فور إزالة الحارس.
إن كان مشروعك يتبع قواعد اختبار محددة، اذكرها. إن لم يفعل، اطلب منه تقليد الاختبارات المجاورة في نفس الحزمة أو المجلد، واجعل الاختبار جديدًا مختصرًا وقابلًا للقراءة.
ألصق مقطع سجل CI الذي يتضمن الخطأ و20–40 سطرًا أعلاه. كذلك ألصق الأمر الفاشل والبيئة الأساسية (نظام التشغيل، إصدارات Node/Go/Python، الأعلام المهمة).
ثم اطلب منه إعادة صياغة ما فشلِ باللغة البسيطة والإشارة إلى السطور في المخرجات التي تثبت ذلك. إن لم يستطع اقتباس السجل، فهو لم يقرأه فعلاً.
اطلب أصغر تعديل ممكن يجعل الأمر الفاشل يمر. قاوم عمليات إعادة الهيكلة. قبل تطبيق أي شيء، اجعله يسرد:
طبق الباتش وأعد تشغيل الأمر الفاشل محليًا (أو نفس مهمة CI إن كانت هي خيارك الوحيد). إن استمر الفشل، ألصق مخرجات الفشل الجديدة فقط وكرر. الحدّ من السياق يبقي الرد مركزًا.
بمجرد الخضرة، أضف اختبارًا واحدًا يتعرّض للفشل قبل الباتش ويمر بعده. اجعله مركزًا: اختبار واحد، سبب واحد.
أعد تشغيل الأمر مع الاختبار الجديد للتأكد أنك لم تغمّش الخطأ.
اطلب رسالة كوميت قصيرة ووصف PR يضم: ما فشل، ما تغيّر، كيف تحققت، وما الاختبار الذي يمنع التكرار. المراجِعون يسرّهم أن تكون الأسباب واضحة.
فشل شائع: كل شيء يعمل محليًا، ثم تغيير صغير يجعل الاختبارات تفشل على راجن CI. هنا مثال بسيط من API مكتوب بـGo حيث بدأ الـhandler يقبل قيمة تاريخ بصيغة 2026-01-09 ولكن الشيفرة ما تزال تُحلّل فقط طوابع RFC3339 كاملة.
هذا نوع المقتطف الذي يجب لصقه (اجعله قصيرًا، لكن أدرج سطر الخطأ):
--- FAIL: TestCreateInvoice_DueDate (0.01s)
invoice_test.go:48: expected 201, got 400
invoice_test.go:49: response: {"error":"invalid due_date: parsing time \"2026-01-09\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"\" as \"T\""}
FAIL
exit status 1
FAIL app/api 0.243s
الآن استخدم مطالبة تجبر الأدلة، إصلاحًا صغيرًا، واختبارًا:
You are fixing a CI failure. You MUST use the log to justify every claim.
Context:
- Language: Go
- Failing test: TestCreateInvoice_DueDate
- Log snippet:
<PASTE LOG>
Task:
1) Quote the exact failing line(s) from the log and explain the root cause in 1-2 sentences.
2) Propose the smallest possible code change (one function, one file) to accept both RFC3339 and YYYY-MM-DD.
3) Show the exact patch.
4) Add one regression test that fails before the fix and passes after.
Return your answer with headings: Evidence, Minimal Fix, Patch, Regression Test.
رد جيد سيشير إلى عدم تطابق تنسيق التحليل، ثم يجري تغييرًا صغيرًا في دالة واحدة مثل parseDueDate في invoice.go ليجرب RFC3339 أولًا ثم ينهض إلى 2006-01-02 كبديل. لا إعادة هيكلة، لا حزم جديدة.
اختبار الارتداد يحمي: أرسل due_date: "2026-01-09" وتوقّع 201. إن أزال أحدهم لاحقًا الـfallback، يكسر CI بنفس فئة الفشل.
أسرع طريقة لإضاعة ساعة هي إعطاء عرض مقطوع من المشكلة. سجلات CI صاخبة، لكن الجزء المفيد غالبًا هو 20 سطرًا فوق الخطأ النهائي.
فخ آخر هو لصق السطر الأحمر الوحيد (مثلاً "exit 1") وإخفاء السبب الحقيقي في الأعلى (متغيّر بيئة مفقود، snapshot فاشل، أو الاختبار الأول الذي انهار). الحل: أدرج الأمر الفاشل ومربع السجل حيث يظهر الخطأ الحقيقي أولًا.
مصدر آخر لهدر الوقت هو ترك النموذج "يرتب" الشيفرة أثناء الطريق. تنقيحات التنسيق، ترقيات الاعتماديات، أو إعادة الهيكلة تجعل المراجعة أصعب وتزيد احتمال كسر أمور أخرى. أصلح النطاق للأدنى ورفض أي شيء غير مرتبط.
بعض الأنماط التي تراقبها:
إن اشتبهت بعدم الثبات، لا تغطّه بمحاولات متكررة: أزل العشوائية (تثبيت الوقت، تهيئة RNG، عزلك للمجلدات المؤقتة) حتى يصبح الإشارة واضحة.
قبل الدفع، قم بتمرير تحقق سريع. الهدف هو التأكد أن التغيير حقيقي، صغير، وقابل للتكرار، لا مجرد تشغيل محظوظ.
أخيرًا، شغّل مجموعة أوسع قليلًا من المهام (مثلاً: اللينت بالإضافة إلى اختبارات الوحدة). فخ شائع هو إصلاح يمر الهدف الأصلي لكنه يكسر هدفًا آخر.
إن أردت أن يوفر هذا الوقت باستمرار، عامل مطالبتك وبنية الاستجابة كعملية فريق. الهدف هو مدخلات قابلة للتكرار، مخرجات قابلة للتكرار، وأخطاء "غريبة" أقل.
حوّل أفضل مطالبتك إلى مقتطف محلي وشاركه مع الفريق. عندما يستخدم الجميع نفس التنسيق، يصبح المراجعون أسرع لأنهم يعرفون أين ينظرون.
حلقة عادة خفيفة تعمل في معظم الفرق:
إن فضّلت سير عمل قائم على الدردشة للبناء والتكرار، يمكنك إجراء نفس حلقة الإصلاح والاختبار داخل Koder.ai، استخدام لقطات أثناء التجربة، وتصدير الشيفرة عندما تصبح جاهزة للدمج.
ابدأ بالخطأ الحقيقي الأول، لا بـexit 1 النهائي.
أجبر النموذج على إثبات أنه قرأ السجل.
استخدم قيدًا مثل:
افترض أن "الأصغر" هو أصغر تصحيح يجعل الخطوة الفاشلة تنجح.
عادةً يعني ذلك:
تجنّب تغييرات "تنظيف" حتى تصبح CI خضراء.
ألصق سياقًا كافيًا لإعادة إنتاج الفشل، لا السطر الأحمر الأخير فقط.
ضمن:
go test ./..., , , إلخ).نعم — حدد قيودًا باللغة الصافية وكرّرها.
أمثلة قيود:
هذا يبقي الرد مركزًا وقابلًا للمراجعة.
إصلاح أقدم فشل واقعي أولًا.
إن لم تكن متأكدًا، اطلب من النموذج تحديد أول خطوة فاشلة في السجل والتزم بها.
عامل الانعدام في الثبات (flakiness) كدافع لإزالة العشوائية، لا لإضافة محاولات متكررة.
مثاليات الاستقرار:
بمجرد أن يصبح السلوك حتميًا، يصبح الإصلاح الأصغر واضحًا.
اطلب الأمر الدقيق الذي شغله CI ثم شغّهه محليًا.
إذا كان إعادة الإنتاج محليًا صعبًا، اطلب مثالًا مصغرًا داخل المستودع (اختبار واحد أو هدف) يثير نفس الخطأ.
اكتب اختبار ارتدادي واحد مركز يفشل قبل الإصلاح ويمرّ بعده.
أهداف جيدة:
إذا كان فشلًا متعلقًا باللينت/البناء، فـ"الاختبار" المقابل قد يكون تشديد قاعدة لينت أو إضافة فحص يمنع نفس الخطأ.
استخدم لقطات/تراجع للحفاظ على قابلية التراجع عن التجارب.
حَلقة عملية:
إن كنت تستخدم Koder.ai، تساعد اللقطات على التجربة السريعة دون خلط التعديلات التجريبية في التصحيح النهائي.
npm testflutter test