Free

3,000 שורות בקומיט אחד: מדוע פיצ'רים מורכבים מצריכים קודם plan mode

האינסטינקט מול פיצ'ר מורכב הוא "בוא אנסה משהו" — אבל ההחלטות הארכיטקטוניות מסתתרות במודל השלישי, ב-edge case החמישי. הערך האמיתי של plan mode הוא העברת השיחה ברמת הארכיטקטורה לטקסט לפני הקוד. מקרה אמיתי: מערכת המושבעים הקהילתית של Pickful — 3,032 שורות, 119 ספקים ירוקים, קומיט אחד, אפס עבודת ארכיטקטורה מחדש אחר כך.


מול פיצ'ר מורכב, האינסטינקט של רוב האנשים הוא "בוא אנסה משהו".

הבעיה: למערכות מורכבות יש מאפיין — ההחלטות הארכיטקטוניות מסתתרות במודל השלישי, ב-edge case החמישי, בחוק הנקודות השמיני. לצלול לתוך הקוד ולהיתקל בהחלטות האלה באמצע הדרך, ואז לחזור ולשנות אותן — עולה פי 10 יותר מאשר לדבר עליהן בטקסט מההתחלה.

השתמשתי ב-plan mode של Claude Code כדי לבנות את TopicReview, מערכת המושבעים הקהילתית ב-Pickful, וראיתי את הגרסה הקיצונית של אי-השוויון הזה: קומיט אחד, 3,032 שורות, 119 ספקים ירוקים, עלייה לאוויר בפעם אחת. אף אחד מעשרה-ומשהו הקומיטים שבאו אחר כך לא היה עיבוד ארכיטקטוני — כולם כיוון פרמטרים, ליטוש UI, טלאי edge cases. המערכת רצה בצורה יציבה מאז, והיא כעת מרכזית באופן שבו הקהילה עושה מודרציה לעצמה.

הפוסט הזה עוסק בלמה פיצ'רים מורכבים מצריכים קודם plan mode, במה שלב ה-plan באמת עושה, ומתי השיחה מספיק בשלה כדי להתחיל לכתוב קוד.

עד כמה מורכבת המערכת

TopicReview הוא הצבעה קהילתית שמחליטה אם פוסט באיכות נמוכה יוסר. משפט אחד לתיאור — אבל המפרט נפרש בשכבות:

  • 5 מצבים: open → voting → decided → appealed → closed
  • 3 פסקי דין: remove / warn / keep
  • 2 שלבים: בירור ראשוני על ידי 12 מושבעים; ערעור על ידי 5 שופטים (מוגרלים מתוך 20 המשתמשים עם הכי הרבה נקודות)
  • זרימת נקודות רב-ממדית: קנס זמני 10 pt, stake ערעור 10 pt, +5 למושבעים שהצביעו בהתאם לפסק הדין, +10 לשופטים שהצביעו בהתאם לפסק הדין, +3 למדווח שדיווחו אומת, החזר בניצחון ערעור = stake + בונוס + קנס זמני
  • 4 סוגי משימות מתוזמנות: חלון הצבעה ראשוני 24 שעות, חלון ערעור 24 שעות, חלון בירור ערעור 24 שעות, וגם — נקודות מושבעים נדחות ב-24 שעות לאחר פסק דין remove (כי הערעור עלול להפוך אותו)
  • זרימות מקביליות + rollback: אם הקולות מתהפכים במהלך הסרה זמנית, צריך לשחזר את הפוסט ולהחזיר את הקנס הזמני; אם הערעור הופך את הפסק, ה-stake מוחזר בתוספת בונוס, אולי יחד עם הקנס הזמני, והמושבעים מחושבים מחדש לפי פסק הדין החדש

לב המורכבות איננו בחוק יחיד — הוא באופן שבו החוקים מתקיימים יחד. כל חוק שמוסיפים עלול להפעיל rollback במקום אחר.

קירות שבהם תיתקל בלי plan

כשאתה כותב ברציפות, הבעיות הקשות ביותר אינן העובדות הגלויות — אלא השאלות שלא חשבת לשאול. אם קוראים את הקוד של TopicReview לאחור, יש לפחות ארבעה קירות שבהם תיתקל בוודאות אם תדלג על ה-plan:

חוקי זכאות מושבעים. נראה פשוט כמו User.jurors_and_judges.sample(12). אבל החוקים בפועל הם: להחריג את כותב הפוסט, להחריג את מי שדיווח עליו, להחריג את מי שכבר הצביע בסבב הראשוני (כדי שאותו אדם לא יצביע גם בערעור). שלוש שכבות של החרגה. אם כותבים את ה-model בבת אחת, נופל אחד או שניים.

תשלום נקודות נדחה. פסק דין remove מפעיל בדרך כלל תשלום למושבעים. אבל ערעור יכול להפוך remove — וכשהוא הופך, המושבעים שהצביעו עם פסק הדין הישן מוצאים את עצמם בצד הלא נכון, ולכן יש לחשב את התשלומים מחדש מול פסק הדין החדש. לכן פסק דין remove חייב לחכות לסגירת חלון הערעור בן 24 השעות לפני שמשלמים למושבעים. אם תדלג על כתיבת הכלל הזה, תשלם מוקדם, ותמצא את עצמך מנסה לשחזר נקודות — פי 10 יותר מציק מאשר לשלם באיחור.

עיצוב ממשק המשימה המתוזמנת. 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
  • לא → UX גרוע: הפוסט מוסתר והמשתמש צריך לחכות 24 שעות כדי לפחות למחות
  • הבחירה בפועל של TopicReview: כן, ערעור מותר במהלך הסרה זמנית — אבל ה-review חייב לעבור קודם finalize → decided לפני שנפתח ה-appeal

ההחלטה היחידה הזו מתפשטת אחורה ומשנה את בדיקות הפרמטרים בתוך open_appeal! ואת הלוגיקה של מכונת המצבים. להחליט באמצע הדרך = לכתוב מחדש חצי מהמערכת.

מה שלב ה-plan באמת עושה

plan mode של Claude Code הוא מצב שבו אסור לכתוב קוד — Claude יכול לקרוא את ה-repo, לחשוב על גישות, להתדיין איתך, אבל כל שינוי קובץ נחסם hard-block עד שתאשר plan.

האילוץ המכני הזה הוא הלב: הוא מכריח את השיחה ברמת הארכיטקטורה להתרחש בטקסט.

כמה דברים ששלב ה-plan עושה בפועל:

1. ציור מכונת המצבים והתפקידים. 5 מצבים, 4 תפקידים (מושבע / שופט / כותב פוסט / מדווח), מה כל תפקיד יכול ולא יכול לעשות בכל מצב — הכול בכמה שורות markdown. כמה שורות מול עשרות קבצים. עלות השינוי שונה בשני סדרי גודל.

2. הליכה בזרימה של כל תפקיד:

  • מושבע: מקבל התראה → פותח review → קורא פוסט וסיבה → מצביע עם reasoning → מקבל נקודות
  • כותב הפוסט: מקבל התראה → רואה פסק דין → אם remove שוקל ערעור → מפקיד stake → מחכה
  • שופט: מקבל ערעור מוגרל מתוך top-20 → מצביע → מקבל נקודות

היכן שההליכה נתקעת, צצה שאלה חבויה: "האם המושבעים רואים את הקולות של מושבעים אחרים?", "מה הכותב יכול לעשות במהלך הסרה זמנית?"

3. חקירת edge cases. שלב ה-plan לא מעצב את "המסלול הנורמלי" — הוא שואל במכוון את השאלות שבדרך כלל לא עולות:

  • מה אם החלון נסגר עם 0 קולות? (בחירה סופית: ברירת מחדל keep.)
  • מה אם הערעור נסגר עם 0 קולות? (dismissed; ה-stake נאבד.)
  • האם שופט יכול להצביע על פוסט שהוא בעצמו דיווח עליו? (לא — אותו חוק החרגה.)
  • כמה מושבעים מפעילים finalize בו-זמנית — האם ה-race יכפיל תשלום? (להוסיף שדה juror_points_awarded לאידמפוטנטיות.)

95% מהשאלות האלה לא צצות באופן טבעי בזמן כתיבת קוד. שלב ה-plan מכריח אותך לעבור עליהן אחת-אחת.

4. ספר הנקודות הראשי. מערכת הנקודות מספיק מורכבת כדי שדיון לא יספיק — צריך ממש לצייר טבלה: כל זרימת נקודות עם הטריגר שלה, הסכום, ונתיב ה-rollback. כשהספר מתאזן, כל ה-edge cases (החזר זמני, החזר ערעור, בונוסים) מתיישבים חשבונאית.

עד לאן צריך הדיון להגיע לפני שכותבים קוד

קריטריון קשוח:

  • אתה יכול לעבור בכל נתיב בלי להיתקע — כל צירוף מפתיחת ה-review ועד closed (keep / remove / warn × עם ערעור / בלי × זמני / לא זמני) — אתה מספר אותו מקצה לקצה
  • לכל edge case יש התנהגות מוגדרת — לא "נראה בהמשך", אלא "0 קולות ברירת מחדל keep", "זמני מתיר ערעור אבל קודם finalize"
  • אין "אה, על זה עוד לא חשבתי" — על כל שאלה שאתה יכול לנסח יש כבר תשובה

כשהגעת לרמה הזו, לכתוב קוד הוא לתרגם את ה-plan ל-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 ספקים ירוקים. נמסרו בפעם אחת.

עשרה-ומשהו הקומיטים שבאו אחר כך מוכיחים שהארכיטקטורה החזיקה:

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 כבר כיסה. אין "לא חשבתי על ה-edge case הזה" — שלב ה-plan שאל. אין "הממשק הזה צריך עיצוב מחדש" — ה-plan כבר סידר.

שעות של כתיבת קוד, עושים רק דבר אחד: לתרגם עיצוב ברור למקלדת.

מתי לא להשתמש ב-plan

לא כל משימה ראויה ל-plan:

  • תיקוני באגים פשוטים — לאתר + לתקן + להוסיף regression test; ללא דיון מקדים
  • ריפקטור מכני — שינוי שם, חילוץ, העברה; המסלול אחד, ה-plan הוא צעד מיותר
  • מסלול אחד ברור בלבד — הוספת endpoint GET, toggle ב-UI; אין על מה להתווכח
  • אב-טיפוסים חקרניים — אתה בעצמך לא יודע מה אתה רוצה; להריץ משהו גס עדיף על עוד חשיבה

הרווח מ-plan mode מגיע מהורדת עלות הכתיבה מחדש. אם במשימה אין סיכון לכתיבה מחדש, ה-plan הוא רק עודף.

לסיום

"תחשוב לפני שתעשה" נשמע כמו עצה אופיינית. plan mode הוא לא זה.

plan mode הוא לגרום לכך שהשיחה ברמת הארכיטקטורה תתרחש במקום שבו 10 מילים יכולות לשנות אותה — ולא במקום שבו 30 קבצים חייבים להשתנות.

תחת מורכבות, יש להפוך את הפתגם התעשייתי הישן "words are cheap, code is expensive" — הוא לא אומר "תכתוב קוד קודם ותראה" (זה עובד רק כשההפרש בעלות קטן), הוא אומר לנצל את ההפרש הזה: להעביר את השיחה היקרה קדימה, אל המדיום הזול.

3,000 שורות בקומיט אחד זו הרגשה מצוינת. לא כי כתבתי מהר — אלא כי ה-plan הפך את "הכתיבה" לאקט מכני טהור.