From 803504360670fa5fbac234f3f07bdf9bacc60f58 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 20:21:59 +0000 Subject: [PATCH 1/4] =?UTF-8?q?feat(notes):=20=D7=9E=D7=90=D7=A8=D7=A7?= =?UTF-8?q?=D7=93=D7=90=D7=95=D7=9F=20=D7=9E=D7=A8=D7=95=D7=A0=D7=93=D7=A8?= =?UTF-8?q?=20=D7=9B=D7=91=D7=A8=D7=99=D7=A8=D7=AA=20=D7=9E=D7=97=D7=93?= =?UTF-8?q?=D7=9C=20=D7=91=D7=9B=D7=9C=20=D7=A9=D7=9C=D7=95=D7=A9=D7=AA=20?= =?UTF-8?q?=D7=99=D7=A2=D7=93=D7=99=20=D7=94=D7=A4=D7=AA=D7=A7=D7=99=D7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ברירת המחדל הייתה ``!!this.boardId`` — דלוקה בלוח בלבד, כבויה בפתקים שעל קובץ ב-CodeKeeper ועל קובץ בדפדפן הריפו. הנימוק שנרשם בזמנו היה שאין ליעדים האלה מתג כיבוי, ולכן רינדור אוטומטי הוא שינוי שקט שאין למשתמש דרך לבטל. בפועל הדגל לבדו אינו מרנדר כלום: ``_syncTaskView`` דורש גם אותו וגם ``_hasRenderableMarkdown``, ולכן פתק של טקסט רגיל נשאר תיבת עריכה ואינו משתנה. מה שהשתנה הוא רק פתקים שכבר מכילים ``**`` או ``#`` — כלומר בדיוק המקרה שבו הרינדור הוא מה שהמשתמש התכוון אליו. מתג הכיבוי נשאר בלוח בלבד, ו-``markdown`` מפורש ב-opts ממשיך לגבור על ברירת המחדל. תיעוד — ``docs/user/sticky_notes.rst``: - שתי ההצהרות על ברירת המחדל עודכנו לתיאור החדש. - **פסקת העיגון בפתקי ריפו תוקנה, והיא הייתה שגויה מאז שההתנהגות השתנתה תחתיה.** היא טענה ש-``surface`` מעוגן למסגרת התצוגה ושהפתק אינו נגלל עם שורות הקוד. בפועל ``surface`` ליעד ריפו מודד מראשית התוכן (``_surfaceScrollShift`` מחסיר את ``scrollTop``), מאזין גלילה ייעודי מחשב מחדש את המיקום, ו-``_updatePinnedVisibility`` מסתיר פתק שיצא מהתחום הנראה — כלומר הפתק כן נגלל עם הקוד. הטענה על ``anchored`` נבדקה ונשארה: ``_resolveMode`` חוסם אותו לכל יעד ``surface``. תיעוד — ``docs/dev/sticky_notes_extending.rst``: סעיף מודגש בסוף שקובע שכל פיצ'ר או שינוי התנהגות מעדכן את עמוד המשתמש באותו PR, עם הפרדה שמונעת כפילות בין השניים — התנהגות נראית בעמוד המשתמש, נימוק הנדסי כאן. טסטים: שני הטסטים שאכפו את ברירת המחדל הישנה עודכנו, ונוספו שני שומרים — פתק בלי מבנה מארקדאון נשאר תיבת עריכה, ו-``markdown`` מפורש גובר. שניהם נופלים בלי השינוי. אומת ב-Chromium מול שני היעדים: הפתק עם המבנה מרונדר בטעינה בלי נגיעה, ופתק הטקסט נשאר textarea. על הקוד הקודם הדגל הוא ``false`` ואין רינדור. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019YULCppaQRPYN1RgeY6NBu --- AI-MAP.md | 2 +- docs/dev/sticky_notes_extending.rst | 16 +++++++++++- docs/user/sticky_notes.rst | 8 +++--- tests/sticky-notes-target.test.js | 39 ++++++++++++++++++++++------- webapp/static/js/sticky-notes.js | 28 +++++++++++++-------- 5 files changed, 68 insertions(+), 25 deletions(-) diff --git a/AI-MAP.md b/AI-MAP.md index 215303337..7b9adc3d7 100644 --- a/AI-MAP.md +++ b/AI-MAP.md @@ -23,7 +23,7 @@ - `docs/whats-new.rst` — **What's New**: יומן השינויים של הבוט וה-WebApp לפי תאריך — מה נוסף, מה השתנה ומה תוקן בכל עדכון, עם קישורים ל-Issues הרלוונטיים. - `docs/architecture.rst` — **ארכיטקטורה**: המערכת מורכבת מבוט Telegram, שכבת שירותים (services), שכבת נתונים (MongoDB) ואפליקציית Web. הזרימה העיקרית: Handlers → Services → Database. - `docs/architecture/clean-architecture.rst` — **Clean Architecture ב-src**: ארכיטקטורה זו מפרידה בין לוגיקה עסקית, תזמור יישומי ותשתיות כך שניתן לבדוק יחידות קוד בנפרד, להחליף מקורות נתונים בלי לשבור את שאר המערכת ולרוץ גם בסביבות ללא MongoDB. -- `docs/dev/sticky_notes_extending.rst` — **עקרונות להוספת פיצ'ר לסטיקי-נוטס**: המלכודות החוזרות של הפתקים הדביקים: יעד יחיד ב-build_note_target, מכסה fail-closed והפטור-לאדמין שהורג מכסות, flush לפני פעולה הרסנית, אינדקס ממוספר שנבנה לפני שמפילים, נורמליזציה בשני הקצוות, ויתומים בקריאה. +- `docs/dev/sticky_notes_extending.rst` — **עקרונות להוספת פיצ'ר לסטיקי-נוטס**: המלכודות החוזרות של הפתקים הדביקים: יעד יחיד ב-build_note_target, מכסה fail-closed והפטור-לאדמין, flush לפני פעולה הרסנית, אינדקס ממוספר שנבנה לפני שמפילים, נורמליזציה בשני הקצוות, יתומים בקריאה, ועדכון עמוד המשתמש. - `docs/contributing.rst` — **מדריך תרומה**: לתת מסלול ברור לתרומות קוד, עם דגש על סוכני AI ו-CI. - `docs/branch-protection-and-pr-rules.rst` — **Branch Protection & PR Rules**: לרכז נהלים ברורים להגנה על ענפים (Branch Protection) ולחוקי PR בפרויקט. diff --git a/docs/dev/sticky_notes_extending.rst b/docs/dev/sticky_notes_extending.rst index c36317168..14e714052 100644 --- a/docs/dev/sticky_notes_extending.rst +++ b/docs/dev/sticky_notes_extending.rst @@ -1,6 +1,6 @@ עקרונות להוספת פיצ'ר לסטיקי-נוטס ================================== -:summary: המלכודות החוזרות של הפתקים הדביקים: יעד יחיד ב-build_note_target, מכסה fail-closed והפטור-לאדמין שהורג מכסות, flush לפני פעולה הרסנית, אינדקס ממוספר שנבנה לפני שמפילים, נורמליזציה בשני הקצוות, ויתומים בקריאה. +:summary: המלכודות החוזרות של הפתקים הדביקים: יעד יחיד ב-build_note_target, מכסה fail-closed והפטור-לאדמין, flush לפני פעולה הרסנית, אינדקס ממוספר שנבנה לפני שמפילים, נורמליזציה בשני הקצוות, יתומים בקריאה, ועדכון עמוד המשתמש. הפיצ'ר של הפתקים הדביקים צובר משטחים לאורך זמן — קובץ ב-CodeKeeper ← לוח ← רינדור מארקדאון ← קובץ בריפו ממורר. כל תוספת כזו נוטה לגלות מחדש את אותן מלכודות, כי הן אינן בקוד של פיצ'ר בודד אלא בחוזה המשותף. העמוד הזה מרכז אותן, כדי שהפיצ'ר הבא (או סוכן AI שממש אותו) יקרא אותן פעם אחת במקום לגלות אותן שוב בפרודקשן. @@ -85,3 +85,17 @@ - **מודל טהור** (יעד, נורמליזציה, מכסה): טסטי יחידה, בלי מסד. כל טסט חדש נבדק במוטציה — ביטול התיקון חייב להפילו. - **אינדקס ייחודי ופילטר חלקי**: מול מונגו אמיתי בלבד. סטאב מחזיר ``None`` מ-``create_index`` וכל בדיקת כפילות עוברת בו, גם אם האינדקס מעולם לא נוצר. - **חיווט הלקוח** (הרכבה, שמירה, החלפת יעד): מול דפדפן אמיתי. השוואת מחרוזות אינה מוכיחה שהפתק באמת נשמר ונטען. + +התיעוד למשתמש הוא חלק מהפיצ'ר +------------------------------ + +.. important:: + **כל פיצ'ר חדש בפתקים, וכל שינוי בהתנהגות קיימת, מעדכן את** :doc:`/user/sticky_notes` **באותו PR.** + + העמוד הזה מתאר **איך** לבנות — מלכודות, חוזים בין שכבות, מה לבדוק ובמה. העמוד למשתמש מתאר **מה קורה** — מה רואים, מה ברירת המחדל, איפה יש מתג ואיפה אין. שינוי בהתנהגות שייך לשם, גם כשהוא נראה קטן. + + מה נחשב שינוי בהתנהגות: ברירת מחדל שמתהפכת, מצב מיקום שמתחיל או מפסיק להיות זמין, יעד חדש לפתק, מגבלה או מכסה שמשתנה, ותוספת לתת-קבוצת המארקדאון. שינוי פנימי שאינו נראה מבחוץ — ריפקטור, אינדקס, סדר קריאות — אינו מצריך עדכון. + +**בלי כפילות בין שני העמודים.** עובדה שכתובה בשניהם מתיישנת באחד מהם, ואז שניהם אומרים דברים שונים על אותו קוד. הכלל הוא הפרדה לפי שאלה: התנהגות נראית נכתבת בעמוד המשתמש בלבד, והנימוק ההנדסי — למה זה בנוי ככה, מה נשבר בלי זה — נכתב כאן בלבד. כשצריך את שניהם, כותבים כל חצי במקומו ומקשרים ביניהם ב-``:doc:``, כפי שנעשה כבר בשתי ההפניות לעמוד הזה מתוך עמוד המשתמש. + +**התיעוד אינו סמכות על הקוד.** אם בזמן העדכון מתגלה שמה שכתוב בעמוד המשתמש כבר אינו נכון — זה ממצא לתקן, לא רקע להתעלם ממנו. פסקת העיגון בפתקי ריפו שרדה כך סבב שלם אחרי שההתנהגות השתנתה תחתיה. diff --git a/docs/user/sticky_notes.rst b/docs/user/sticky_notes.rst index f4ecc373a..a33d0ce26 100644 --- a/docs/user/sticky_notes.rst +++ b/docs/user/sticky_notes.rst @@ -115,14 +115,14 @@ עיצוב מארקדאון ~~~~~~~~~~~~~~~ -מלבד צ'קבוקסים, הפתק מרנדר תת-קבוצה קלילה של מארקדאון: **מודגש** (``**``), *נטוי* (``*``), ``קוד`` בשורה, קו חוצה (``~~``), כותרות (``#`` עד ``###``), רשימות (``-``/``*``/``1.``), ציטוט (``>``), קו מפריד (``---``), קישורים (``[טקסט](כתובת)``) ובלוקי קוד (שורת גדר של שלושה תווי backtick, מעל התוכן ומתחתיו). כשהעיצוב פעיל, התצוגה נפתחת בדיוק כמו עם צ'קבוקס — כשיש בפתק מבנה מארקדאון כלשהו — ופתק של טקסט רגיל נשאר תיבת עריכה ולא משתנה. (בפתקי לוח העיצוב דלוק כברירת מחדל; בפתקי קבצים כבוי — ראו למטה.) +מלבד צ'קבוקסים, הפתק מרנדר תת-קבוצה קלילה של מארקדאון: **מודגש** (``**``), *נטוי* (``*``), ``קוד`` בשורה, קו חוצה (``~~``), כותרות (``#`` עד ``###``), רשימות (``-``/``*``/``1.``), ציטוט (``>``), קו מפריד (``---``), קישורים (``[טקסט](כתובת)``) ובלוקי קוד (שורת גדר של שלושה תווי backtick, מעל התוכן ומתחתיו). כשהעיצוב פעיל, התצוגה נפתחת בדיוק כמו עם צ'קבוקס — כשיש בפתק מבנה מארקדאון כלשהו — ופתק של טקסט רגיל נשאר תיבת עריכה ולא משתנה. (העיצוב דלוק כברירת מחדל בכל סוגי הפתקים — ראו למטה.) .. important:: **טקסט של משתמש — או של סוכן דרך** ``codekeeper_create_note`` **— אינו יכול להפוך לתגית.** זריקת ``