דלגו לתוכן

סקירת AI

סקירת AI היא הרצה אחת של הפייפליין המובנה pr_review על בקשת משיכה פתוחה אחת. הפייפליין פותח את מרחב הסקירה של ה-PR, מפזר סוכני סקירה שקוראים את ה-diff בצ׳קאאוט המבודד של אותו מרחב, כל אחד מהם רושם את ממצאיו כצמתי סקירה מובנים, סוכן מוביל מאחד אותם לסיור מודרך, ומסיים מחשב הכרעה אחת: Ship, Hold או Block. מה שהפייפליין אף פעם לא עושה הוא לפרסם — פרסום ל-GitHub הוא צעד נפרד ומכוון שאדם עושה.

שאר העמוד הזה מסביר את החלקים ולמה הם מעוצבים כך.

הקשר הסקירה של PR הוא מרחב הודעות — במצב review ובסוג pr — שמקושר לבקשת המשיכה באמצעות שיוך מרחב סקירה. הוא נוצר באופן אידמפוטנטי: עמוד ה-PR, פייפליין הסקירה ומשטחי הצ׳אט כולם מפענחים את מרחב הבסיס ה_אחד_ של ה-PR דרך אותו מסלול קוד, כך שתבנית שסוקרת PR ואדם שפותח אותו לעולם לא יגיעו לשני חדרים שונים שמסתכלים על שני צ׳קאאוטים שונים.

עץ העבודה המבודד של המרחב מכיל את ה-PR ב-head ref שלו. חדר אחד פירושו גם צ׳קאאוט אחד: כל סוקר עובד באותו מרחב במקום שכל אחד יקבל שכפול משלו של סביבת העבודה.

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

השיוך נושא סולם סטטוסים — requested ← in progress ← awaiting approval ← completed — וזה מה שמשער את Publish to GitHub בלשונית הסקירה של ה-PR.

כמה עמוקה הסקירה היא מדיניות של סביבת עבודה עם שלוש רמות, שנקבעת בהגדרות ← סביבת עבודה ← כללי, בכרטיס מדיניות סביבת העבודה:

רמה סוקרים שמתפצלים דיווח
light מהנדס בלבד רק מה שמהותי
balanced מהנדס, QA, ארכיטקט (ברירת המחדל) המעבר הקבוע
thorough כל החמישה, כולל אבטחה וביצועים שום דבר לא מדורג מטה

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

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

צמתי סקירה: ממצאים כנתונים, לא כפרוזה

קטע בשם “צמתי סקירה: ממצאים כנתונים, לא כפרוזה”

ממצא שנרשם עם add_review_node הופך לצומת סקירה על ה-PR — זה מה שלשונית הסקירה מציגה, זה מה שממנו מחושבת ההכרעה, וזה מה ש“Publish to GitHub” הופך להערה מוטבעת. סוקר שמחזיר רק פרוזה מייצר הרצת פייפליין שנראית מוצלחת ומשטח סקירה ריק; הרישום הוא החלק הנושא.

כל צומת נושא:

שדה ערכים
סוג bug, suggestion, recommendation, question, ticket
עדיפות P0 (קריטי) ← P3 (זוטר)
שלשת הטריאז’ קטגוריה (security, stability, …), חומרה, מאמץ
עוגן נתיב הקובץ, שורת ההתחלה והסיום
נשיאת התיקון שורות החלפה מוצעות, diff אופציונלי, הנחיית תיקון אופציונלית
ביטחון ציון [0, 1]
הנמקה הניתוח, שנכתב לפני הממצא

שני פרטים הם מכוונים. הצעת GitHub בלחיצה אחת מוצעת רק כשהסוקר סיפק שורות החלפה מדויקות — הסקתן מ-diff מאוחד משתבשת בשקט, ו-commit בלחיצה אחת של הסקה שגויה גרוע מלא להציג כפתור בכלל. והסכמה של add_review_node מציגה את reasoning לפני הממצא, כך שמודל שממלא את האובייקט לפי סדר הסכמה כותב את הניתוח קודם. השדה אופציונלי: השמטתו לא דוחה את הצומת. צומת שהמטען שלו שגוי נעלם במקום לזהם את הסקירה.

צומת עובר דרך open ← consensus-ready ← resolved או dismissed. הצעד האמצעי הוא לב המודל: ממצא מסיים את דרכו רק כשסוקר עמית מאשר אותו, וסוכן לעולם לא יכול לאשר ממצא משלו. כלי ה-MCP ‏publish_review_to_github וברירת המחדל של ה-RPC עדיין מפרסמים ממצאים שאושרו על ידי עמיתים בלבד. לעומת זאת, הכפתור Publish to GitHub בלשונית הסקירה שולח כל ממצא פתוח שנותר.

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

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

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

קבוצות: מה שסביבו מקובצת הסקירה

קטע בשם “קבוצות: מה שסביבו מקובצת הסקירה”

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

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

לצד ממצאי הסוקרים, סקירה צוברת תוצאות ציר: שישה צירים, משני סוגים.

ציר סוג נגזר מ
correctness, security מונחה טוקנים הממצאים של הסוקרים עצמם
testGap מונחה טוקנים הממצאים של הסוקרים
visual, apiContract דטרמיניסטי מחושב בלי להוציא טוקנים
performance דטרמיניסטי ספירה בלבד — שום דבר במוצר לא מחשב תוצאה

הכרעת ציר היא pass, warn, fail, partial או unavailable — ורק pass או warn פותחים שער. ההבחנה בין fail, partial ו-unavailable נושאת משקל: ציר משעור שלא הצליח להשלים או שלא הצליח לרוץ בכלל מחזיק את ההכרעה הכוללת במקום להעביר אותה. היעדר ראיה לעולם לא הופך לשער ירוק.

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

מסיים הסקירה מחשב את ההכרעה על הממצאים בסטטוס open או consensus-ready:

  • כל ממצא P0 עם ביטחון ≥ 0.7 ← Block
  • אחרת, כל P0 (ביטחון נמוך) או כל P1 ← Hold
  • אחרת ← Ship

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

האיחוד של הסוכן המוביל (CEO) הוא מעבר עריכתי, לא רישום מחדש: העתק שני בכתב יד של הממצאים הוא בדיוק מה שסוטה מהממצא האמיתי. ממצאים כפולים מדורגים מטה ולא מוצגים שוב — כמה סוקרים מופנים לאותו diff עם תחומי אחריות חופפים בכוונה, כך שאותו פגם שמגיע למסיים שלוש פעמים הוא המערכת עובדת; פרסומו שלוש פעמים הוא המערכת שמדליפה את הארכיטקטורה של עצמה לתיבת הדואר הנכנס של הקורא. בסקירה חוזרת, ממצאים מקבלים טביעת אצבע ומושווים מול הסבב הקודם, כך שהשינוי הוא מה שמוצג.

לבסוף הצירים נכנסים לתמונה, והם יכולים רק להפוך את ההכרעה לחמורה יותר: ציר משעור שנכשל כופה Block — אי אפשר לגבור עליו בהצבעה של ממצאים — וציר משעור שלא הצליח להשלים כופה לפחות Hold.

הפייפליין בכוונה לא מפרסם ל-GitHub; הפרסום מותנה באישור משתמש כך שסקירה לעולם לא תפורסם פעמיים. כשאתם לוחצים על Publish to GitHub:

  • נשלחת סקירת GitHub אחת. ממצאים שכבר נפתרו או נדחו מדולגים. הכפתור מפרסם כל ממצא פתוח שנותר (selection: all_open). כלי ה-MCP ‏publish_review_to_github עדיין מגיע כברירת מחדל לממצאים שאושרו על ידי עמיתים בלבד (consensus).
  • ממצאים המעוגנים לקובץ ולשורה הופכים להערות מוטבעות; כל השאר נכנס לגוף הסיכום, כל אחד עם כותרת תחתונה “— Control Center AI review” כך שהמקור חד־משמעי.
  • עוגנים נבדקים מחדש מול ה-diff ה_נוכחי_ של ה-PR בזמן הפרסום. הערה על קוד שכבר נכתב מחדש היא הדבר שהכי הורס אמון שסוקר יכול להשאיר; אם GitHub בכל זאת דוחה עוגן מוטבע, הסקירה כולה נשלחת מחדש כשכל ממצא מקופל לגוף, כך ששום דבר לא נשמט בשקט.
  • הכרעת Block נשלחת כ-REQUEST_CHANGES; Hold כ-COMMENT; Ship כ-APPROVE מהכפתור (approve_on_ship: true). כלי ה-MCP משאיר את Ship כ-COMMENT אלא אם תעבירו approve_on_ship.
  • הסקירה מתפרסמת תחת זהות האפליקציה של השרת. מי לחץ על Publish נרשם עבור שער התפקיד ויומן הביקורת; הוא אינו מחבר ה-GitHub.

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

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