لإعادة الهيكلة لا أعراض — حين يخطئ Claude لا ترى ذلك. ثلاثة حواجز: اختبارات، commits ذرية، نقر يدوي.
إعادة الهيكلة هي المهمة التي يكون فيها Claude في أخطر حالاته. للأخطاء أعراض — زر لا يستجيب، قيمة undefined، stack trace — فتستطيع أن تحكم إن كان إصلاح Claude سليماً أم لا. إعادة الهيكلة لا أعراض لها. "لا يزال يعمل" قد يعني "الاختبارات لا تزال تمر" بينما السلوك تغيّر بصمت، ولم تنتبه، وبعد أسبوع يشتعل الإنتاج.
مؤخراً أجريت مع Claude إعادة هيكلة كبيرة نسبياً على how2claude: نقلت مدفوعات x402 من PaymentHandler + FacilitatorClient مكتوبتين يدوياً (139 سطراً) إلى gem x402-rails، وفي الوقت نفسه استخرجت تعيين الحقول لـ Purchase.create! / Subscription.create! — المكرر في كونترولرين — إلى دوال صنف على الموديل. commit واحد، 4 ملفات تغيرت، 2 حُذفت، 2 أُضيفت.
كان البرومبت كلمة واحدة: "refactor."
أمكن أن يكون بهذا القصر لأن الحواجز كانت موضوعة حوله.
حين وصل الفرع إلى تلك النقطة، كان لديه 221 اختباراً. كل المسارات الحرجة في تدفق الدفع مغطاة.
التصرف الافتراضي لـ Claude قبل إعادة الهيكلة ليس "انظر إلى الاختبارات أولاً." لذا أمرته أن يشغّل bin/rails test أولاً، ويتأكد من الأخضر، ثم يلمس أي شيء.
بعد إعادة الهيكلة، شغّلها مرة أخرى. لا تزال خضراء. هذا لا يعني غياب الانحدار — يعني أن السلوك المعروف لم يُكسر.
إذا كان مسار الكود غير مغطى بالاختبارات، اجعل Claude يكتب اختباراً أدنى يثبّت السلوك الحالي. شغّله، commit. ثم أعد الهيكلة. وإلا فما يفعله ليس إعادة هيكلة، بل إعادة كتابة — ولا طريقة للتحقق من التكافؤ.
هذه الإعادة كانت في الواقع شيئين:
Purchase / Subscription: controller → دوال صنف على الموديلفي الواجهة الأمامية شيء ثالث: إعادة كتابة تدفق التوقيع على جانب JS باستخدام viem + x402-fetch.
أجبرت Claude على التقسيم وفق الحدود الطبيعية: الخلفية + استخراج الموديل في commit واحد (9f3e239)، الواجهة الأمامية في commit منفصل (93746d8). كل commit يحمل وصفاً كاملاً، قائمة ملفات، وسبب التغيير.
الفوائد:
- الـ diff تبقى قابلة للقراءة. commit واحد، شيء واحد.
- دقة الـ rollback. إذا وقع خطأ واجهة أمامية في الإنتاج، git revert 93746d8 يعيد الواجهة فقط ويُبقي الخلفية.
- انتباه Claude نفسه يبقى مركّزاً. commit واحد شيء واحد — وانتباهه يغطي ذلك الشيء فقط.
حين تكتمل إعادة الهيكلة، أُوقف Claude وأجعله يُظهر لي git diff --staged. لا تشغّل الاختبارات. لا تشغّل التطبيق. اقرأ الـ diff أولاً.
الإشارات التي أفحصها:
app/services/x402/payment_handler.rb حُذف بالكامل — حسناً، هذا هو بيت القصيد من الانتقال إلى الـ gem. لكن إن حذف شيئاً لم أطلب لمسه، أتوقف وأسأل.Purchase.create!(wallet_address: verify_result["payer"], ...) → Purchase.record_x402!(payment:, settlement:) يقرأ الآن payment[:payer]. المصدر تغيّر (request.env الخاص بالـ gem مقابل قيمة الإرجاع من العميل القديم)، لكن يجب أن تتطابق الحقول واحداً بواحد.الفخ الأول: Stimulus controllers الخاصة بالـ gem لم تُحمَّل بصمت
gem x402-rails يُشحن مع Stimulus controllers خاصة به. كتب Claude الكود، مرّت الاختبارات خضراء. نقرتُ زر الدفع يدوياً — لا شيء.
السبب: config/importmap.rb كان فيه pin لـ @hotwired/stimulus يُشير إلى ملف vendor غير موجود، وimportmap أسقط ذلك الـ pin بصمت. فلم تُحمَّل controllers الـ gem أبداً. الاختبارات لا يمكنها التقاط هذا لأن bin/rails test لا ينفّذ JS.
الفخ الثاني: YAML حلّل 0x... كعدد صحيح
wallet_address: 0x833589... — بلا علامات اقتباس. رأى YAML البادئة 0x فقرأها كعدد صحيح ست عشري. استلم الـ facilitator قيمة غير نصية فرفض. لم يتوقف Claude للتفكير في قواعد تحليل YAML أثناء كتابة الإعدادات.
كلا الفخّين التُقطا لأنني نقرت الزر الفعلي. نجاح الاختبارات ليس كنجاح الميزة. التحقق اليدوي بعد إعادة الهيكلة ليس اختيارياً.
إعادة الهيكلة هي أعلى السيناريوهات خطراً في "اترك Claude يقود." الحواجز ليست من أجل Claude. هي من أجلك — لتلتقط أخطاء Claude في 5 دقائق، لا في حريق إنتاج.