Free

3٬000 سطر في إصدار واحد: لماذا تحتاج الميزات المعقدة إلى plan mode أولًا

الانطباع الأول عند مواجهة الميزات المعقدة هو «دعني أجرّب شيئًا» — لكن القرارات المعمارية تختبئ في النموذج الثالث والحالة الحدية الخامسة. القيمة الحقيقية لـ plan mode هي نقل الحوار ذي المستوى المعماري إلى النص قبل الشيفرة. مثال حقيقي: نظام هيئة المحلفين المجتمعي في Pickful — 3٬032 سطر، 119 spec خضراء، إصدار واحد، صفر إعادة هيكلة لاحقًا.


عند مواجهة ميزة معقدة، يكون ردّ الفعل الغريزي لدى أغلب الناس: "دعني أجرّب شيئًا".

المشكلة: الأنظمة المعقدة تتميّز بسمة — القرارات المعمارية تختبئ في النموذج الثالث وفي الحالة الحدية الخامسة وفي قاعدة النقاط الثامنة. الغوص في الشيفرة ثم الاصطدام بهذه القرارات في المنتصف، ثم العودة لتغييرها، يكلّف 10 أضعاف ما كان يكلّفه مناقشتها نصيًّا من البداية.

استخدمتُ plan mode في Claude Code لبناء نظام هيئة المحلفين المجتمعي TopicReview في Pickful، فرأيتُ النسخة المتطرفة من هذه المتباينة: إصدار واحد، 3٬032 سطرًا، 119 spec جميعها خضراء، شحن لمرة واحدة. لم يكن أيٌّ من العشرات من الإصدارات التي تلت إعادة هيكلة معمارية — كلها ضبط معاملات، وصقل واجهة، وترقيع حالات حدية. النظام يعمل بثبات منذ ذلك الحين، وهو اليوم محور الإشراف الذاتي للمجتمع.

هذا المقال يتحدث عن سبب ضرورة استخدام plan mode أولًا مع الميزات المعقدة، وما الذي تفعله مرحلة plan فعلًا، ومتى تنضج المحادثة بما يكفي للبدء بكتابة الشيفرة.

مدى تعقيد النظام

TopicReview هو تصويت مجتمعي لتحديد ما إذا كان يجب إزالة منشور منخفض الجودة. جملة واحدة للشرح — لكن المواصفات تتكشف طبقات:

  • 5 حالات: open → voting → decided → appealed → closed
  • 3 أحكام: remove / warn / keep
  • مرحلتان: المراجعة الأولية يقوم بها 12 محلّفًا؛ الاستئناف يقوم به 5 قضاة (يُسحبون من أعلى 20 مستخدمًا بالنقاط)
  • تدفق نقاط متعدد الأبعاد: عقوبة مؤقتة 10 pt، رسم استئناف 10 pt، +5 للمحلّفين الذين صوّتوا مع الحكم، +10 للقضاة الذين صوّتوا مع الحكم، +3 للمبلّغين إذا ثبت بلاغهم، استرداد عند ربح الاستئناف = الرسم + مكافأة + العقوبة المؤقتة
  • 4 أنواع من المهام المجدولة: نافذة التصويت الأولي 24 ساعة، نافذة الاستئناف 24 ساعة، نافذة مراجعة الاستئناف 24 ساعة، وكذلك — تأجيل نقاط المحلّفين 24 ساعة بعد حكم remove (لأن الاستئناف قد ينقضه)
  • تدفقات متوازية + rollback: إذا انقلبت الأصوات أثناء الإزالة المؤقتة، يجب استعادة المنشور وإعادة العقوبة المؤقتة؛ إذا نقض الاستئناف الحكم، يُعاد الرسم مع مكافأة، وربما العقوبة المؤقتة أيضًا، ويُعاد تقييم المحلّفين وفق الحكم الجديد

جوهر التعقيد ليس في أي قاعدة منفردة — بل في كيفية تفاعل القواعد فيما بينها. كل قاعدة تُضاف قد تُطلق rollback في مكان آخر.

الجدران التي تصطدم بها دون plan

عندما تكتب متدفّقًا، فإن أصعب المشكلات ليست الحقائق المرئية — بل الأسئلة التي لم يخطر لك طرحها. بقراءة شيفرة TopicReview عكسيًّا، ثمّة على الأقل أربعة جدران ستصطدم بها حتمًا إن تجاوزت plan:

قواعد أهلية المحلّفين. تبدو مجرد User.jurors_and_judges.sample(12). لكن القواعد الفعلية هي: استبعاد كاتب المنشور، استبعاد من أبلغ عن المنشور، استبعاد من صوّت في الجولة الأولى (حتى لا يصوّت مجددًا في الاستئناف). ثلاث طبقات من الاستبعاد. إذا كتبتَ النموذج دفعةً واحدة، ستفوتك طبقة أو اثنتان.

الدفع المؤجّل للنقاط. حكم remove يُطلق عادةً صرف نقاط المحلّفين. لكن الاستئناف قد ينقض remove — وعندما ينقضه، يصير المحلّفون الذين صوّتوا مع الحكم القديم على الجانب الخاطئ، فيجب إعادة حساب الصرف وفق الحكم الجديد. لذا على حكم remove أن ينتظر إغلاق نافذة الاستئناف 24 ساعة قبل دفع المحلّفين. إن تجاهلتَ كتابة هذه القاعدة ودفعتَ أولًا، ستجد نفسك تحاول سحب النقاط لاحقًا — أصعب بعشر مرات من الدفع المتأخر.

تصميم واجهة المهمة المجدولة. CloseTopicReviewJob يبدو وكأنه "إنهاء review". في الواقع، يعالج ثلاث حالات:

# انتهاء نافذة التصويت الأولي
CloseTopicReviewJob.set(wait_until: voting_ends_at).perform_later(review.id)
# دفع نقاط المحلّفين المؤجّل بعد حكم remove
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, award_juror_points: true)
# انتهاء نافذة الاستئناف
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, appeal_id: appeal.id)

دون تخطيط مسبق، ستكتب التوقيع الأول، ثم تُدرك في الحالة الثانية أن الواجهة يجب أن تتغير.

الجدار الأغلى: هل يمكن الاستئناف أثناء الإزالة المؤقتة؟ عندما تتجاوز أصوات remove العتبة، يُخفى المنشور على الفور (مؤقت)، لكن الـ review يبقى في حالة voting — ليس decided. هل يستطيع المستخدم الاستئناف الآن؟

  • نعم → يجب توسيع الانتقالات بين decided وappealed
  • لا → تجربة استخدام سيئة: المنشور مُخفى والمستخدم مضطر للانتظار 24 ساعة كي يعترض
  • اختيار TopicReview الفعلي: نعم، يُسمح بالاستئناف أثناء الإزالة المؤقتة — لكن الـ review يجب أن يمر عبر finalize → decided أولًا قبل فتح الاستئناف

هذا القرار الفردي يمتد عكسيًّا ويغيّر فحوصات المعاملات داخل open_appeal! وكذلك منطق آلة الحالات. تأخير القرار إلى منتصف الطريق = إعادة كتابة نصف النظام.

ماذا تفعل مرحلة plan فعلًا

plan mode في Claude Code هو وضع لا يُسمح فيه بكتابة الشيفرة — يستطيع Claude قراءة المستودع والتفكير في الأساليب والتحاور معك، لكن أي تعديل على الملفات يُمنع بشكل صارم حتى توافق على خطة.

هذا القيد الميكانيكي هو جوهر الأمر: يُجبر المحادثة على المستوى المعماري أن تحدث في النص.

بعض ما تفعله مرحلة plan في الواقع:

1. رسم آلة الحالات والأدوار. 5 حالات، 4 أدوار (محلّف / قاضٍ / كاتب المنشور / مُبلِّغ)، وما يستطيع ولا يستطيع فعله كل دور في كل حالة — كلّه في بضعة أسطر من markdown. بضعة أسطر مقابل عشرات الملفات. كلفة التعديل تختلف برتبتين.

2. السير في تدفق كل دور:

  • المحلّف: يتلقى إشعارًا → يفتح الـ review → يقرأ المنشور والسبب → يصوّت مع reasoning → يستلم النقاط
  • كاتب المنشور: يتلقى إشعارًا → يرى الحكم → إن كان remove يفكر في الاستئناف → يودع الرسم → ينتظر
  • القاضي: يستلم الاستئناف المُختار من أعلى 20 → يصوّت → يستلم النقاط

كلما توقّف السير، يبرز سؤال مخفي: "هل يرى المحلّفون أصوات بعضهم؟"، "ماذا يستطيع الكاتب أن يفعل أثناء الإزالة المؤقتة؟"

3. استجواب الحالات الحدية. مرحلة plan لا تصمم "المسار الطبيعي" — بل تطرح عمدًا الأسئلة التي لا تخطر عادةً:

  • ماذا لو انتهت النافذة بصفر أصوات؟ (الخيار النهائي: الافتراضي keep.)
  • ماذا لو انتهى الاستئناف بصفر أصوات؟ (dismissed؛ يُخسر الرسم.)
  • هل يستطيع قاضٍ التصويت على منشور أبلغ عنه بنفسه؟ (لا — قاعدة الاستبعاد ذاتها.)
  • إذا أطلق عدة محلّفين finalize في الوقت نفسه، هل يكرّر الـ race الصرف؟ (أضف حقل juror_points_awarded لتحقيق idempotency.)

95% من هذه الأسئلة لا تبرز طبيعيًّا أثناء كتابة الشيفرة. مرحلة plan تجبرك على تجاوزها واحدًا تلو الآخر.

4. دفتر النقاط. نظام النقاط معقّد إلى حدٍّ لا تكفي فيه المناقشة — يجب رسم الجدول فعلًا: كل تدفق نقاط مع شرط تفعيله ومبلغه ومسار rollback الخاص به. حين يتوازن الدفتر، تتصالح كل الحالات الحدية (استرداد العقوبة المؤقتة، استرداد الاستئناف، المكافآت) حسابيًّا.

متى تصبح المحادثة كافية للبدء بكتابة الشيفرة

معيار صارم:

  • تستطيع السير عبر كل مسار دون تعثّر — كل تركيبة من فتح الـ review حتى closed (keep / remove / warn × مع/بدون استئناف × مؤقت/غير مؤقت) — يمكنك سردها من البداية إلى النهاية
  • لكل حالة حدية سلوك محدّد — ليس "نرى لاحقًا"، بل "صفر أصوات = keep افتراضيًّا"، "المؤقت يسمح بالاستئناف لكن يجب finalize أولًا"
  • لا يوجد "آه، هذا لم أفكر فيه بعد" — كل سؤال تستطيع صياغته لديه جواب مُعدّ

حين تبلغ هذا المستوى، تتحول كتابة الشيفرة إلى ترجمة الخطة إلى Ruby.

كيف تبدو مرحلة التنفيذ المتواصل

أوّل شحن لهذا النظام:

d162f1e Add community moderation system with jury/judge review and appeals
  63 files changed, 3032 insertions(+)
  119 specs, 0 failures

63 ملفًّا، 3٬032 سطرًا، 119 spec خضراء. شُحن لمرة واحدة.

العشرات من الإصدارات التالية تُثبت أن المعمار صمد:

Apply legacy penalty (1pt) for posts created before 2026-03-26
Fix topic review appeal bugs: window mismatch and verdict not updated
Add topic_removed status for posts removed by community review
Default to keep verdict when review expires with zero votes
Reduce provisional removal penalty to 1pt during trial period
Allow topic creator to withdraw active reviews
Add handled tab to jury dashboard, fix tabs styling

كلٌّ منها ضبط / إصلاح / صقل / ميزة صغيرة. لا واحد منها "العودة وإعادة تصميم آلة الحالات" أو "نموذج النقاط يجب تغييره". الهيكل كان صحيحًا تمامًا.

هذه هي المكافأة الحقيقية لـ plan: يظل التنفيذ دون انقطاع. لا يوجد "انتظر، كيف يعمل هذا المسار" — الخطة غطّته. لا يوجد "لم أفكر في هذه الحالة الحدية" — مرحلة plan سألت عنها. لا يوجد "يجب إعادة تصميم هذه الواجهة" — الخطة رتّبتها.

ساعات من كتابة الشيفرة، تفعل فيها شيئًا واحدًا فقط: ترجمة تصميم واضح إلى لوحة المفاتيح.

متى لا تستخدم plan

ليست كل مهمة تستحق plan:

  • إصلاحات الثغرات البسيطة — تحديد + إصلاح + إضافة regression test؛ لا حاجة لنقاش مسبق
  • إعادة هيكلة ميكانيكية — إعادة تسمية، استخراج، نقل؛ المسار واحد، الخطة خطوة زائدة
  • طريق واحد واضح فقط — إضافة endpoint GET، toggle لواجهة؛ لا شيء للنقاش
  • نماذج أولية استكشافية — لا تعرف أنت نفسك ما تريد؛ تشغيل نسخة خام أفضل من المزيد من التفكير

ربح plan mode يأتي من خفض كلفة إعادة الكتابة. إذا لم يكن في المهمة خطر إعادة كتابة، فالخطة مجرد عبء.

الخاتمة

"فكّر قبل أن تتصرف" يبدو نصيحة شخصية. plan mode ليس كذلك.

plan mode هو جعل المحادثة على المستوى المعماري تحدث حيث تستطيع 10 كلمات تغييرها — لا حيث يجب تغيير 30 ملفًّا.

في ظل التعقيد، يجب قلب المأثور الصناعي القديم "words are cheap, code is expensive" — لا يعني "اكتب الشيفرة أولًا وانظر" (هذا صحيح فقط حين تكون فجوة التكلفة صغيرة)، بل يعني استغلال فجوة التكلفة: نقل المحادثة الغالية إلى الأمام، إلى الوسيط الرخيص.

3٬000 سطر في إصدار واحد شعور رائع. ليس لأنني كتبتُ بسرعة — بل لأن plan حوّلت "الكتابة" إلى فعل ميكانيكي بحت.