הנדסה עם סוכנים

SwarmForge לעומק: איך נחיל הסוכנים של אנקל בוב עובד באמת

שישה סוכני AI, שישה worktrees של git, תור הודעות מתמיד, וסדרת שערי איכות שהם פקודות מעטפת ולא כוונות טובות. חלק ה-tmux הוא הדבר הפחות מעניין כאן.

הבעיה שבשבילה הוא נבנה

תנו לסוכן קוד אחד פיצ'ר אמיתי, והוא יכתוב את המימוש ואת הבדיקות באותה נשימה, מאותה הבנה, עם אותן נקודות עיוורות. אם הוא קרא את הדרישה לא נכון, הבדיקות מקודדות את הקריאה השגויה ועוברות. תבקשו מאותו סוכן לסקור את עבודתו והוא יסכים עם עצמו, כי ההיגיון שהוליד את הקוד עוד נמצא בהקשר שלו ועוד נראה סביר. הנפח מחמיר את זה ולא משפר: הפלט משכנע, שופע וזול, ולכן האדם שסוקר הופך לצוואר בקבוק ומתחיל לרפרף. SwarmForge מהמר על תשובה מסוימת לכך: איכות לא יכולה לבוא מהמחבר, ולכן כל דיסציפלינה סוקרת מקבלת סוכן משלה, הקשר משלה, עץ עבודה משלה, ובדיקה שמסתיימת באפס או שלא.

ההחלטה שנושאת את כל השאר היא לא מקביליות. היא שהתפקידים מתקשרים רק דרך קוד שנכנס ל-commit. סוכן סוקר לא רואה לעולם את הסבר המחבר למה הקוד בסדר — הוא רואה קומיט ושם משימה, ומריץ עליהם את הכלים שלו.

מה זה מבחינה מכניקה

SwarmForge היא מעטפת של שֶׁל ו-Babashka סביב מרכיבים שכבר יש לרוב הצוותים. כל תפקיד הוא חלון tmux שמריץ CLI של סוכן מול worktree משלו תחת .worktrees/, כך ששני סוכנים לא נוגעים באותה ספריית עבודה. ההתנהגות מגיעה מטקסט פשוט: constitution.prompt שטוענת לעליונות על כל השאר ואומרת לסוכן לקרוא ולציית לכל קובץ ב-swarmforge/constitution/articles/ בעלייה ובכל משימה, ובנוסף פרומפט תפקיד ב-swarmforge/roles/<role>.prompt. המאמרים המשותפים מכסים כללי הנדסה, כללי העברה וזרימת עבודה; המאמרים המקומיים הם המקום שבו פרויקט דורס אותם. התקשורת היא תור מבוסס קבצים בבעלות דמון, ושני סוגי ההודעות היחידים שסוכן יכול לשלוח הם העברת git והערה. הסקריפט ./swarm הוא רק אתחול דק: הוא מוריד את ארכיון הסקריפטים אם הספרייה חסרה, ואז מעביר את השרביט ל-swarmforge/scripts/swarmforge.sh.

שלוש צורות נחיל

כל ענף הוא תשובה אחרת לשאלה כמה תהליך מגיע למשימה. main הוא תיעודי; הטופולוגיות שרצות נמצאות בענפי ה-pack. הזרימה היא טבעת ולא תור.

two-pack

coder → cleaner → coder

coder שעובד קודם-כל-בדיקה ו-cleaner שמסדר, עושה סקירת CRAP ו-DRY ותיקוני ארכיטקטורה. הלופ הקטן ביותר שעוד מפריד בין כתיבה ובין שיפוט, והצורה היחידה שהעלות שלה קלה להצדקה בעבודה שגרתית.

four-pack

specifier → coder → refactorer → architect → specifier

מפרטי קבלה ב-Gherkin נכנסים בהתחלה. refactorer מנקה בלי לשנות התנהגות ומשפר כיסוי, ו-architect סוקר מבנה וכיוון תלויות לפני שהטבעת חוזרת אל המפרט.

six-pack

specifier → coder → cleaner → architect → hardener → QA

מוסיף מעבר הקשחה שמשנה את הקוד כדי למצוא איפה מערך הבדיקות עיוור, ותפקיד QA עצמאי שמאמת דרך ממשק המשתמש. ארבעה מששת התפקידים רצים במצב אצווה, כדי שהכלים ישתלמו על פני פס עדיפות שלם.

איך שינוי אחד עובר בפועל את הטבעת

זהו ה-six-pack, וכדאי לקרוא אותו כצינור של תנאי יציאה ולא כרשימת תפקידים. כל שורה היא פרומפט תפקיד במאגר, וכל תנאי יציאה הוא פקודה שחייבת להצליח.

1

specifier

→ coder
מקבל
בקשה מהאדם, ב-worktree של master
עושה
כותב מפרטי קבלה ב-Gherkin ואת מפרט מערך ה-QA מקצה לקצה, שואל שאלות במקומות שבהם הכוונה מעורפלת, ומקצץ את פרמטרי הדוגמה לערכים שמשפיעים בפועל על מוטציית הקבלה.
תנאי יציאה
לא מבצע commit עד שהאדם מאשר במפורש. זה השער האנושי היחיד בטבעת, והוא בחזית, שם הוא הזול ביותר.
2

coder

→ cleaner
מקבל
העברת git שמצביעה על קומיט ועל שם משימה יציב
עושה
כותב בדיקות יחידה ממוקדות שמבטאות את ההתנהגות המבוקשת ושבלשון פרומפט התפקיד עצמו היו נכשלות עבור מימוש שגוי סביר. אחר כך כותב רק את כמות קוד הייצור הדרושה כדי שיעברו. בדיקות קבלה מיוצרות אינן מקובלות במפורש כתחליף לבדיקות יחידה.
תנאי יציאה
האימות המקומי עובר. הוא לא מריץ מוטציה, CRAP או DRY — אלה שייכים לתפקידים מאוחרים יותר, כדי שה-coder לא יוכל לדרג את עבודתו.
3

cleaner

→ architect
מקבל
אצווה של העברות באותה עדיפות
עושה
מריץ קודם את כלי ה-CRAP ומוריד את המורכבות ל-6 ומטה, אחר כך את כלי ה-DRY לצמצום כפילויות, אחר כך את כלי המוטציה במצב סריקה וספירה בלבד — ומפצל כל קובץ עם יותר מ-100 נקודות מוטציה — ומעלה כיסוי היכן שסביר.
תנאי יציאה
ההתנהגות לא שונתה, הבדיקות עוד ירוקות, המורכבות והכפילות ירדו. אסור לו במפורש להריץ בדיקות מוטציה או להוסיף התנהגות.
4

architect

→ hardener
מקבל
אצווה של קומיטים מסודרים
עושה
מחלק את הקוד למודולים עם גבולות אמיתיים, שומר על תלויות שמצביעות פנימה, צד מחזורים ודליפות פריימוורק, ומבודד את מדיניות היישום מ-UI, ממערכת הקבצים, ממסד הנתונים ומהרשת. מוסיף בדיקות ארכיטקטורה אוטומטיות היכן שמעשי.
תנאי יציאה
ההתנהגות נשמרת והמערך ירוק. אסור להריץ git merge ביד: מיזוג נעשה רק דרך ready_for_next.sh.
5

hardener

→ QA
מקבל
אצווה של קומיטים שנסקרו מבנית
עושה
מריץ את כלי המוטציה של השפה קובץ אחר קובץ, דיפרנציאלית מול המניפסטים הקיימים, עם עד שמונה עובדים במקביל, ומטפל במוטנטים ששרדו לפני שממשיך. אחר כך מעבר מוטציית קבלה ב-Gherkin ברמת soft, אחר כך CRAP, אחר כך DRY, בדיוק בסדר הזה.
תנאי יציאה
כל כלי בשרשרת חייב להיות נקי לפני שהבא רץ. זה התפקיד שמחליט אם הבדיקות בודקות משהו בכלל.
6

QA

→ specifier
מקבל
אצווה של קומיטים מוקשחים
עושה
אימות סופי עצמאי: מפרט הקבלה, המערך מקצה לקצה שמונע דרך ממשק המשתמש בלי קיצורי API, בדיקות יחידה ותכונה, ובדיקות שחרור של הפרויקט. משחזר כל כשל לפני שהוא נוגע בקוד.
תנאי יציאה
מריץ CRAP ו-DRY שוב לפני סגירה. אם מערך ה-QA מתנגש ב-Gherkin או בבדיקות היחידה, הוא נעצר ושואל אדם במקום לבחור מנצח.

ההובלה היא החלק החריג

רוב מסגרות הסוכנים מאפשרות לסוכנים לדבר זה עם זה. SwarmForge מסרבת לזה במכוון: דמון מחזיק את המסירה, מערכת הקבצים היא התור, ו-tmux משמש רק כדי לדחוף חלון שאינו עסוק.

הטופולוגיה היא קובץ הגדרות אחד

conf

ה-six-pack שנשלח מציב כל תפקיד על אותו מנוע עם עקיפת הרשאות מופעלת, ומסמן את כל החצי האחורי של הטבעת כצרכני אצווה. שם התפקיד חייב להתאים לשם קובץ הפרומפט, שבמאגר הזה נכתב hardender.

# swarmforge/swarmforge.conf
# window-invisible <role> <agent> <worktree> [task|batch] [extra-cli-args...]
window-invisible specifier codex master           --yolo
window-invisible coder     codex coder            --yolo
window-invisible cleaner   codex cleaner    batch --yolo
window-invisible architect codex architect  batch --yolo
window-invisible hardender codex hardender  batch --yolo
window-invisible QA        codex QA         batch --yolo

התור הוא ספרייה, והמיקום הוא המצב

text

אין מסד נתונים ואין ברוקר בזיכרון. מקומה של העברה בעץ הוא הסטטוס שלה, שם הקובץ ממיין לפי עדיפות ואז זמן, והכותרות נושאות את שביל הביקורת. נחיל שקרס ממשיך מהמקום שבו הוא היה בכך שהוא קורא את הדיסק.

.swarmforge/handoffs/
  outbox/
    tmp/            # drafts land here, then get renamed in atomically
  sent/
  failed/           # malformed or undeliverable, with diagnostics
  inbox/
    new/
    in_process/
    completed/

# filename sorts the queue for you
<priority>_<timestamp>_<sequence>_from_<sender>_to_<recipients>.handoff
# priority 00-99, lower first; UTC YYYYMMDDTHHMMSSZ

סוכן יכול רק לבקש, לא למסור

sh

הסוכן כותב טיוטה עם ארבע כותרות וקורא לסקריפט השער. הוא לא יכול לכתוב id, from, recipient או חותמת זמן — אלה שמורות, כך שהמקוריות בשביל הביקורת לא ניתנת לזיוף בידי מי שנבדק. הוא גם לא מקליד SHA: הסקריפט מנרמל ומאמת שהקומיט הוא אובייקט אמיתי וחד-משמעי באורך עשרה תווים.

# ./tmp/handoff.txt — drafted inside the assigned worktree
type: git_handoff
to: hardender
priority: 00
task: task-1-cave-setup

# hand it to the protocol gate; the daemon does delivery
swarm_handoff.sh ./tmp/handoff.txt

# receiving side, driven by the role's mode in .swarmforge/roles.tsv
ready_for_next.sh     # -> TASK: / BATCH: / NO_TASK, plus the payload
done_with_current.sh  # -> stamps completed_at, then pulls the next item

השערים שה-hardener חייב לעבור, לפי הסדר

sh

זה מה שהופך את הנחיל למשהו יותר ממשחק תפקידים. החוקה מתקינה את הכלים האלה בעלייה, טרייים מהמאגרים של המחבר — crap4go, crap4java ו-crap4clj למורכבות, mutate4go, clj-mutate ו-mutate4java למוטציה, ומשפחת dry4* לכפילויות — ופרומפט התפקיד קובע את סדר ההרצה.

# hardener: nothing advances until the previous check is clean
mutate4go ./...            # one file at a time, differential, <= 8 workers
gherkin-mutator --level soft   # mutate the acceptance examples too
crap4go ./...              # complexity against coverage
dry4go ./...               # duplication

# then, and only then
swarm_handoff.sh ./tmp/handoff.txt   # to: QA

למה כל מנגנון מעוצב כך

בקריאה הנדסית, רוב ההחלטות שנראות מוזרות הן הגנות מפני כשלים ספציפיים של סוכנים.

ההודעה היא קומיט, לא הסבר

העברת git נושאת שם משימה וקומיט מאומת. היא לא יכולה לשאת את הטיעון של המחבר למה הקוד טוב, כי טיעון מזמין את הסוכן הבא להסכים איתו. קומיט מזמין אימות במקום זה. זו הרעיון הכי בר-העברה בפרויקט.

התראות ההעֵרה כלליות ומותר שיאבדו

הודעת ה-tmux של הדמון אומרת רק שהגיע דואר ושכדאי להריץ ready_for_next.sh אם אתה פנוי. היא לא נוקבת בשם קובץ, כך שסוכן לא יכול לבחור את הפריט המעניין ולדלג על סדר התור, וסוכן עסוק יכול להתעלם בבטחה, כי סיום משימה גם מביא את הבאה.

הערות מוגבלות לשמונים תווים ואינן מעודדות

סוכן יכול לשלוח הערה חופשית רק כשאדם, פרומפט התפקיד או החוקה אומרים זאת במפורש. מול עמימות או סתירה ההוראה היא להיעצר ולשאול אדם. זו סירוב מכוון לתת לסוכנים לנהל משא ומתן על דרישות ביניהם, וזה בדיוק המקום שבו מערכות מרובות סוכנים משתבשות בשקט.

לכל תפקיד worktree, לא רק ענף

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

החצי האחורי של הטבעת צורך אצוות

cleaner, architect, hardener ו-QA לוקחים את כל ההעברות באותה עדיפות כיחידה אחת. הרצות מוטציה, הרצות כיסוי ובדיקות ארכיטקטורה יקרות לכל הפעלה וזולות לכל קובץ נוסף, ולכן איגוד לאצווה הוא ההבדל בין שער שרץ ובין שער שמכבים.

התקן הוא עץ פרומפטים עם קדימות מוצהרת

constitution.prompt טוענת לסמכות, המאמרים נושאים את הכללים, מאמרים מקומיים דורסים אותם לפרויקט, פרומפטי התפקיד יושבים מעל, ולסוכן נאמר לקרוא את הכול מחדש בכל משימה. תקן הקוד שלכם מפסיק להיות מסמך על העבודה והופך לקלט שלה.

פסק הדין

החצי בעל הערך של SwarmForge הוא החוקה וסדר השערים: תפקידים בשם עם אחריות אחת, תנאי יציאה שהם פקודות ניתנות להרצה, וכלל קשה שהמחבר של שינוי לעולם לא מדרג אותו. החצי הזה טוב באמת, הוא ברוחו בלתי תלוי בשפה, ואפשר לממש אותו הרבעון הזה ב-CI שאתם מפעילים כבר — בלי שום tmux. החצי השני, הדמון ותור הקבצים המתמיד, בנוי להפליא ופותר בעיקר בעיה שאפשר להימנע ממנה: אם השערים שלכם רצים ב-CI על pull request, אתם מקבלים התמדה, שביל ביקורת וסדר עדיפויות בחינם מכלים שהצוות שלכם כבר מפעיל.

קראו את זה כמימוש הדגמה של זרימת עבודה, לא כפלטפורמה לאימוץ. התחילו ב-two-pack כדי להרגיש אם הפרדת תפקידים בכלל עוזרת לעבודה שלכם, קחו את שרשרת השערים בכל מקרה, ופנו לטבעת של שישה תפקידים רק כשעלות של פגם עולה בבירור על עלות של שש הרצות סוכן לכל שינוי.

מה הוא עושה נכון

  • + שערי איכות הם פקודות עם ערכי סף — מוטציה, CRAP, DRY, כיסוי — ולא שמות תואר במדריך סגנון
  • + הסוקר לא רואה לעולם את ההיגיון של המחבר אלא רק קומיט, וזו הדרך היחידה שסקירה בידי סוכן שווה משהו
  • + הסדר תואם רצף הנדסי אמיתי: לאפיין, לממש, לסדר, לשנות מבנה, להקשיח, לאמת באופן עצמאי
  • + בידוד ב-worktree מבטל שיבוש מעריכה מקבילה מתוך המבנה ולא באמצעות מנעולים
  • + מצב התור חי על הדיסק עם שביל ביקורת שסוכנים אינם מסוגלים מבנית לזייף, ולכן קריסה ממשיכה וניתן לשחזר הרצה
  • + שער האישור האנושי היחיד יושב בזמן האפיון, שם שינוי דעה זול ביותר
  • + הכול טקסט גלוי לעין — חלונות שאפשר לקרוא, פרומפטים שאפשר לערוך, תור שאפשר להציג עם ls

מה זה עולה לכם

  • התצורה שנשלחת מריצה כל סוכן עם עקיפת הרשאות, כך שכל העיצוב מניח שאתם מוכנים לתת לשישה סוכנים להריץ פקודות בלי השגחה במאגר שלכם
  • שש הרצות סוכן לכל שינוי הן אבסורד כלכלי בעבודה קטנה, ואין בטבעת דבר שמחליט שמשימה מסוימת ראויה לפחות תהליך
  • שרשרת הכלים הניתנת להרצה היא הפרויקטים crap4*, mutate4* ו-dry4* של המחבר עצמו ל-Go, Clojure ו-Java — מחוץ לשפות האלה חוזה העלייה של החוקה לא חל ואתם מספקים מקבילות משלכם
  • התקנה מחדש של הכלים האלה מ-GitHub בכל עלייה איטית, תלויה ברשת, ומהווה משטח שרשרת אספקה שעכשיו הוא שלכם
  • zsh, tmux ו-Babashka על macOS הם המסלול המאושר; ב-Windows זה אומר WSL ומתאם טרמינל
  • כלל ההעברה קדימה מחייב תפקיד להעביר במורד הזרם בין אם שינה משהו ובין אם לא, כך שהטבעת מייצרת תעבורה גם כששלב לא עשה כלום
  • פרומפטי תפקיד אינם אכיפה: שום דבר לא מונע מתפקיד לדלג על השער שלו מלבד המשפט שאוסר עליו, ולכן הערובות האמיתיות חזקות רק כמו העתק שלהן ב-CI
  • זה בעליל בעבודה — דשבורד, מחוון חום, שומר חלונות וענפי pack שמתפצלים, כאשר main בכוונה לא רץ

מה לקחת גם אם לא תריצו את זה

אל תיתנו למחבר לדרג את העבודה

  • - הריצו את כלי האיכות בשלב נפרד, עם הקשר נפרד מזה שכתב את הקוד
  • - תנו לשלב הסוקר את ה-diff ואת הכלים, לא את ההצדקה של המחבר
  • - בתהליכי עבודה עם סוכנים זו לא היגיינת תהליך אלא ההבדל בין סקירה לחתימת גומי

הפכו כל שער לקוד יציאה

  • - למורכבות, לכפילות, לכיסוי ולמוטנטים ששרדו יש כלים שמחזירים ערך שונה מאפס
  • - קבעו את סדר ההרצה ועצרו את הצינור בראשון שנכשל
  • - סוכן מגיב נכון לפקודה שנכשלה ובאופן מעורפל לפסקת עצות

העברות צרות, מאומתות וניתנות לביקורת

  • - הפניה לקומיט ועוד שורה קצרה דוחפות את הכוונה אל הקוד ואל ההודעה
  • - אמתו בגבול, כדי שבקשה שגויה תיפול לפני שהשלב הבא מבזבז עליה הרצה
  • - החזיקו את שדות המקוריות מחוץ להישג ידו של השולח אם אתם רוצים ששביל הביקורת יהיה שווה משהו

החזיקו את התקן במקום שבו העבודה קורית

  • - כללים שנכתבים כמאמרי פרומפט נקראים בכל משימה, בניגוד לדף ויקי שאף אחד לא פותח
  • - הפרידו כללים משותפים מדריסות מקומיות, כדי שהחריג של צוות אחד לא יהפוך לכלל של כולם
  • - נהלו אותם בגרסאות יחד עם הקוד וסקרו שינויים בהם כמו קוד

זרימת העבודה היא התרומה

אם מקלפים את tmux, את Babashka ואת ההתקנה מ-tarball, נשארת טענה על הנדסת תוכנה: הדיסציפלינות ששומרות על קוד ראוי למחיה ניתנות להפרדה, לכל אחת מגיע תור משלה עם הוראות משלה, ואף אחת מהן לא יכולה להתבצע באופן אמין בידי הצד שכתב את הקוד. זה היה נכון עוד לפני הסוכנים. מה שהסוכנים שינו הוא הסיכון, כי נפח הפלט עלה והאדם שסוקר לא נעשה מהיר יותר.

אז קחו את החלקים ששורדים את התרגום. תנו שם לכל מעבר ותפקיד אחד לכל אחד. הפכו כל תנאי יציאה לפקודה. שימו את השער האנושי בזמן האפיון. שללו מהמחבר של שינוי כל תפקיד בשיפוטו. אם הצינור הזה הוא שישה חלונות tmux, שני מהנדסים או קובץ CI עם חמש עבודות מסודרות — זה חשוב פחות בהרבה מהשאלה אם השערים קיימים ובאמת רצים.

שאלות נפוצות

מה צריך כדי להריץ את SwarmForge?

zsh, git, tmux ו-Babashka, ובנוסף CLI מוגדר של סוכן כמו Claude, Codex, Copilot או Grok. אין שירות ענן ואין שכבת אורקסטרציה להקים: הנחיל הוא חלונות tmux שאפשר להסתכל בהם, worktree לכל תפקיד על הדיסק, ותור של קבצי טקסט.

מאיזה ענף כדאי לצוות להתחיל?

two-pack. שני תפקידים מספיקים כדי לדעת אם הפרדת כתיבה משיפוט עוזרת לעבודה שלכם, ואת העלות של טבעת בשישה תפקידים קשה מאוד להצדיק לפני שיודעים זאת. main הוא תיעודי ולא מריץ נחיל.

האם בטוח להריץ סוכנים עם עקיפת הרשאות?

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

האם זה עובד רק ל-Go, Clojure ו-Java?

האורקסטרציה אינה תלויה בשפה, השערים הניתנים להרצה כן. החוקה נוקבת בכלי המוטציה, ה-CRAP וה-DRY של המחבר עצמו לשלוש השפות האלה. במערכות אחרות שומרים את מבנה התפקידים ומחליפים במקבילות, למשל Stryker או PIT למוטציה וכל דוח של מורכבות ועוד כיסוי לחישוב ה-CRAP.

האם נחיל סוכנים מייתר את ה-QA?

לא, והעיצוב גם לא מתיימר לכך. הוא מקדם את ה-QA לתפקיד עם שם, עם סקריפטים שרצים ועם כלל מפורש להיעצר ולשאול אדם כשמערך ה-QA מתנגש במפרט. עדיין צריך מישהו שיודע מה המוצר חייב למשתמשים שלו, ועדיין מישהו חותם על השחרור.

מה הרעיון הבודד ששווה להעתיק יותר מכל?

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

© 2026 - Ryware.