الانتقال إلى المحتوى الرئيسي
يتعامل Lousho مع حالات الفشل في طبقتين: الطبقة الأولى لا تغيّر الـ agent أبدًا. هي فقط تُكمل الـ runs أو توقفها. والطبقة الثانية تقترح تغييرات على الـ agent لكنها لا تُجريها أبدًا. هذه الصفحة نظرة عامة. كل قسم يربط بالصفحة التي فيها التفاصيل الكاملة.

استعادة الـ run الآن

أعطِ الـ agent مخزن checkpoints وشغّل agent.recover() مرة واحدة لكل process. كل intervalMs (الافتراضي 30 ثانية) تسرد agent.pending() وتستأنف كل run منقطع من آخر checkpoint له، فلا تُشغَّل الخطوات المكتملة مرة أخرى.
استدعِ recovery.stop()، أو ألغِ خيار signal، عند الإيقاف. ما تفعله الحلقة مع حالات الفشل:
  • التراجع (backoff). الـ run الذي فشل يُتخطّى حتى تنقضي مدة تراجعه: intervalMs مضاعفةً لكل محاولة فاشلة متتالية، حتى 15 دقيقة.
  • العزل (quarantine). بعد maxAttempts حالات فشل متتالية (الافتراضي 10)، تتوقف الحلقة عن استئناف الـ run وتستدعي onQuarantined(run) مرة واحدة. وتظل agent.pending() تسرده، وتظل agent.resume() تشغّله، حتى يقرّر شخص. حفظ التقدّم يصفّر العدّاد.
  • إعادة المحاولة مع تشخيص. مع retryWithDiagnosis: true (الافتراضي false)، يحصل الـ run الذي يبلغ الحد أولًا على محاولة أخرى: fork باسم <id>.heal، يُستأنَف من الخطوة نفسها، مع ملاحظة تقول لماذا فشل الـ run. تقتبس الملاحظة الخطأ كبيانات وتحدّ طوله. إذا اكتمل الـ fork، يُحذَف الأصلي ويُبلِّغ onRecovered بـ id الأصلي. وإذا بلغ الـ fork الحد هو أيضًا، يُعزَل الاثنان. ينطبق هذا على runs الـ send()، لا على دورات الجلسات، ويجب أن يحتفظ المخزن بـ سجل checkpoints.
  • الأخطاء التي لن تزول. الـ run الذي يحمل آخر خطأ له retryable: false، مثل 400 من المزوّد، يُترك وشأنه.
  • انقطاعات المزوّد. بعد 3 حالات فشل متتالية من المزوّد، عبر أي runs، تتوقف الحلقة مؤقتًا وتستدعي onOutage(true). ثم تجرّب run واحدًا في كل مرة، على فترات متزايدة، وتستدعي onOutage(false) بمجرد أن ينجح أحدها. ولا تُعزَل الـ runs بسبب فشل المزوّد أثناء التوقف المؤقت. ومفتاح API الخاطئ لا يُحسَب انقطاعًا.
  • الموافقات. الـ run المتوقف على موافقة أو سؤال يُترك لشخص.
يمكن لكل replica أن تشغّل recover(): تضمن run leases أن تستأنف واحدة منها فقط الـ run. راجع الاستعادة التلقائية للسلوك الكامل.

إيقاف الـ run الذي لا يحرز تقدّمًا

تعيد الاستعادة تشغيل الـ runs التي انقطعت. أما الـ run الذي ما زال يعمل لكنه عالق، مثل run يستدعي أداة فاشلة مرة بعد مرة، فيحتاج إلى hook بدلًا من ذلك. تضيف createProgressGuard() تلميحًا إلى نتيجة الأداة التي تظل تفشل بالطريقة نفسها، ثم ترفض الأداة أو الاستدعاء المتكرر. وبعد أن ترفض maxDenials استدعاءات (الافتراضي 3)، يوقف الرفض التالي الـ run بـ LOUSHO_RUN_NO_PROGRESS. يُسجَّل هذا الخطأ على أنه غير قابل لإعادة المحاولة، فلا تستأنف agent.recover() الـ run. كل تلميح ورفض وإيقاف يُبَث كحدث heal.action:
لفحص ما أنتجته الأداة، وليس فقط ما إذا كانت فشلت، أضف createOutputCheck(). راجع Hooks للاثنين، وأحداث البث لحقول heal.action.

مراقبتها

  • استدعاءات recover() الراجعة: onRecovered وonQuarantined وonOutage وonError. الاستدعاء الراجع الذي يرمي خطأ لا يوقف الحلقة.
  • تسرد agent.pending() كل run غير مكتمل مع lastError وattempts، بما في ذلك المعزولة.
  • النتيجة التي استبدلها حارس التقدّم تُعلَّم على span الأداة بـ lousho.tool.replaced_by_hook، ويُسجَّل الرفض كخطأ الـ span. راجع التتبّع والمراقبة للـ spans ولـ daemon الـ observe المحلي.

اقتراح تعديلات لاحقًا

تبحث improveAgent() من lousho/improve عن تعليمات ومهارات أفضل مستخدمةً حالات فاشلة تعطيها لها. وهي تجريبية.
ما تفعله وما لا تفعله:
  • تُرجع اقتراحًا فقط. الـ outcome بقيمة proposal يأتي مع diff. يراجعه شخص، مستعينًا بـ formatImproveResult() للحصول على بطاقة مقروءة، ثم يطبّقه بنفسه.
  • لا تستطيع تغيير إلا التعليمات والمهارات. لا تستطيع تغيير الأدوات أو الصلاحيات أو الحدود.
  • تختبر قبل أن تقترح. يُشغِّل كل مرشّح حالاتك مرة أخرى ويجب أن يحسّن حالة تدريب واحدة على الأقل دون أن يجعل أي حالة أسوأ، بما في ذلك الحالات المحجوزة (held-out) التي لا يراها المحرّرون أبدًا. وتفحص أيضًا التكلفة لكل run ناجح مقابل maxCostIncrease (الافتراضي 0.5).
  • الـ probe الخاص بك يشغّل الـ agent، فهو المسؤول عن الآثار الجانبية. أضف createShadowHook({ readOnly: [...] }) إلا إذا كانت كل أداة آمنة للتشغيل.
يمكن أن تأتي الحالات من traces الخاصة بك: تحوّل casesFromFailures(db) الـ runs الفاشلة في قاعدة بيانات observe المحلية لديك إلى حالات. وتصل نتائج الأدوات فيها إلى المحرّرين معلَّمة بأنها غير موثوقة. ومن سطر الأوامر، يفعل lousho improve <agent> --check <module> ذلك ويطبع الاقتراح للمراجعة؛ راجع CLI. راجع تحسين الـ agent للبوابة والنتائج وملاحظات الأمان.

كيف تتكامل الطبقتان

الـ run الذي تتخلّى عنه الطبقة الأولى، معزولًا أو موقوفًا بـ LOUSHO_RUN_NO_PROGRESS، علامة على أن شيئًا في الـ agent يحتاج إلى تغيير. أصلِح الأداة، أو غيّر التعليمات. وإذا كان السبب في التعليمات أو المهارات، فيمكن أن تصبح حالات الفشل تلك حالات لـ improveAgent()، ويقرّر شخص ما إذا كان سيطبّق ما تقترحه.

الأدلة الحيّة (S29 وS30)

في إصدارات الـ SDK الحالية، تطبّق حلقة التعافي الذاتي (lousho improve على مجلد agent) التعديلَ الذي يجتاز فحوصها تلقائيًا بشكل افتراضي (الوضع التلقائي)، أما الوضع اليدوي فيضعه في قائمة انتظار ليقرّر فيه شخص. في 2026-11-09 اختُبرت هذه الحلقة في تشغيل حيّ على حالات برمجية اصطناعية. عمل الـ agent على qwen/qwen3.7-flash، وعمل نموذج تحرير منفصل، stealth/crouton-alpha، على الحالات الاصطناعية فقط. شُغِّل كل سيناريو مرة واحدة، وشُغِّل planted-editor ثلاث مرات.
  • نجح كل سيناريو اختبر شيئًا فعلًا. نجح planted-editor في محاولتين من محاولتين، ولم تصل محاولة ثالثة إلى المحرّرين، فلم تُحتسَب.
  • تحقّق سجل التدقيق في كل مجلد محاولة.
  • حكم التقرير هو INCOMPLETE (غير مكتمل)، لأن معايير القرار تتطلب من 5 إلى 10 محاولات لكل سيناريو.
أبقت القراءة النهائية (S30) الوضع التلقائي افتراضيًا، وأبقت الحلقة تجريبية. راجع الـ harness ذاتي التعافي: التصميم والأدلة للاطلاع على التصميم وكل النتائج وحدودها.