fix: ארבעה תיקונים מדוח האימות של #3394 — -B בתת-תהליך, כפילות ב-configuration, מספר תלוי-סביבה, ו-.pyc בגיט
✨ תיאור קצר
ארבעה תיקונים נפרדים שעלו מדוח אימות בלתי-תלוי של PR #3394 (squash dea1b9e). אין שינוי התנהגות בקוד ייצור: שניים מהם תיעוד, אחד מוסכמת טסטים, ואחד היגיינת גיט. כל אחד נמדד לפני ואחרי ולא הונח.
📦 שינויים עיקריים
- קוד (Backend)
- בוט טלגרם
- מסד נתונים/מיגרציות
- תיעוד (docs/)
- DevOps/CI/CD
פירוט נקודות:
tests/test_doc_sections.py— התת-תהליך יוצא מעץ המקור.test_doc_sections_pulls_no_heavy_modulesהריץsubprocess.run([sys.executable, "-c", code], cwd=_ROOT), כלומר תת-תהליך שכותב__pycache__לתוךservices/. השורש היה שהייבוא נשען על ה-cwd— הוא עבד רק מפני שהתהליך רץ בשורש הריפו, ולכן-Bלבדו לא הספיק:sys.path.insertעם נתיב מוחלט מנתק את המדידה מעץ העבודה, ורק אזcwd=tmp_pathאפשרי. זה בדיוק החיווט שכבר קיים ב-tests/test_rst_parser.py, וההערה שם מנמקת אותו.docs/configuration.rst— הסרת בלוק כפול. שלושת הסעיפים "Databases and Cache (Pooling/Timeouts)", "HTTP Clients" ו-"שימוש ב-http_sync" הופיעו פעמיים.mcp_server/outline_scanners/__init__.py— מספר תלוי-סביבה יוצא מה-docstring. הוא קבע "ארבעה מודולים מהריפו" ומנה אותם בשמם; בסביבה עםstructlogהם שבעה.__pycache__/*.pyc— יוצאים מניהול גיט. אחד-עשר קבצים שנכנסו ב-8098b67e(#3239) למרות ש-.gitignoreחוסם אותם.git rm --cachedבלבד — הם נשארים על הדיסק.
הכפילות ב-configuration.rst — מה נמצא ומה הוכרע
שני העותקים נכנסו בקומיט אחד, 171d8f66 (#1015, 23.10.2025), שהכניס את אותו בלוק פעם אחרי "Environment variables" ופעם אחרי "Security". לפניו הכותרות לא היו בקובץ כלל.
שני העותקים הושוו שורה-שורה לפני המחיקה, והם אינם זהים — אבל אף הבדל אינו הבדל בתוכן:
| עותק א' (13–58) | עותק ב' (85–111) | סוג |
|---|---|---|
Redis connection string. Use ``rediss://`` … | Redis connection string (use ``rediss://`` …) | פיסוק |
ע״י (U+05F4) + "לא להשתמש" | ע"י (ASCII) + "אל תשתמשו" | ניסוח |
שימוש ב‑http_sync (U+2011) | שימוש ב-http_sync (ASCII) | מקף |
נשאר עותק א' מילה במילה, כי הוא במקום הנכון מבנית — עם שאר סעיפי הקונפיגורציה — והוא היחיד שמלווה ב-"שימוש ב-http_async", שאין לו כפילות כלל. שבע-עשרה מתוך תשע-עשרה השורות שנמחקו קיימות בעותק ששרד כלשונן, והשתיים הנותרות הן שתי וריאציות הניסוח שבטבלה.
עוגנים — נבדק ולא הונח. autosectionlabel אינו מופעל ב-docs/conf.py, ולכן לכותרות אין לייבלים אוטומטיים ואף :ref: לא יכול להצביע עליהן. העוגן המפורש היחיד בקובץ הוא .. _config-error-signatures:, שיושב הרבה מתחת לבלוק שנמחק ואליו מפנה docs/observability/log-aggregator.rst. שאר ההפניות הנכנסות הן :doc: לעמוד כולו. לא נשבר אף עוגן, ולכן לפי docs/versioning-stable-anchors.rst אין כאן שינוי שובר-תיעוד שמחייב רשומה ב-whats-new.
משקל הייבוא — המדידה שהחליפה את המספר
| סביבה | סה"כ מודולים | מהריפו | כבדים |
|---|---|---|---|
בלי structlog | 73 | ארבעה — שרשרת ה-services | 0 |
עם structlog | 330 | שבעה — ועוד observability, monitoring, monitoring.error_signatures | 0 |
השרשרת: services/__init__.py מייבא state מ-backoff_state, ששורה 16 בו מנסה לייבא observability; ו-observability.py מייבא structlog בקשיחות בשורה 22 ומנסה monitoring.error_signatures בשורה 28. כלומר הזנב תלוי במה שמותקן בסביבה ולא בשורת קוד — וזה בדיוק המבחן ב-docs/doc-authoring.rst: מספר שיכול להשתנות בלי שאף שורת קוד תשתנה אינו ערך שנאכף, ואין לכתוב אותו. הניסוח החדש מתאר חלק קבוע וזנב מותנה, בלי מספר ובלי רשימה סגורה. האינווריאנט הנושא נשאר וזה מה שנמדד בשתי הסביבות: אפס מודולים כבדים.
תוקן גם דיוק שני באותו docstring: הטסט שאוכף את האינווריאנט מודד את services.doc_sections, לא את rst_parser. זה נכתב עכשיו כפער מוצהר במקום להשתמע ככיסוי.
🧪 בדיקות
- Unit
- Integration
- Manual
413 טסטים עברו, אפס נכשלו — test_doc_sections, test_rst_parser, test_mcp_docs_handlers, test_mcp_outline, test_doc_summary_style, test_docs_literalinclude_anchors. flake8 נקי על שני קובצי הפייתון שהשתנו.
בקרה שמוכיחה שתיקון ה--B אינו no-op. התת-תהליך הורץ מבודד, בלי pytest, על services/__pycache__ ריק:
| צורה | נכתב ל-services/__pycache__ |
|---|---|
ישנה — בלי -B, cwd= שורש הריפו | 3 קבצים (__init__, backoff_state, doc_sections) |
חדשה — עם -B, cwd=tmp_path | 0, ותיקיית ה-tmp נשארת ריקה גם היא |
ומה שלא השתנה, כדי שלא ייקרא אחרת: בריצת pytest רגילה הדלתא הייתה אפס גם לפני התיקון, כי האיסוף עצמו מייבא את אותם מודולים וכותב את אותם קבצים. נמדד אחרי התיקון: איסוף=4, הטסט לבדו=4, דלתא=0. כלומר זו הפרה של מוסכמה ולא באג נצפה, והערך שלה הוא ביום שבו עץ המקור יהיה לקריאה בלבד — כלל 8 ב-CLAUDE.md.
ambiguous_section — הורץ מחדש על כל 208 קובצי ה-RST:
| קובץ | לפני | אחרי |
|---|---|---|
docs/configuration.rst | 25 | 0 |
docs/development/tools.rst | 12 | 12 |
docs/observability/query-performance-profiler.rst | 8 | 8 |
| סה"כ | 45 | 20 |
שני הקבצים הנותרים לא נגענו בהם, והם כפילויות נפרדות.
בניית תיעוד: python -m sphinx -b html -W --keep-going על כל האתר — build succeeded, קוד יציאה 0, אפס אזהרות. בניית עמוד בודד הוחלפה בבנייה מלאה בכוונה: היא מייצרת אזהרה search index couldn't be loaded שהיא ארטיפקט של הבנייה החלקית עצמה ולא ממצא, והבנייה המלאה היא ממילא מה ש-RTD מריץ.
.pyc — נבדק שאין תלות: כל עשרת האזכורים של __pycache__ בריפו הם החרגות בלבד (.ruff.toml, bandit.yaml, .yamllint.yaml, services/code_indexer.py, scripts/audit_config_definitions.py, scripts/find_duplicates.py, github_menu_handler.py, repo_analyzer.py ושני טסטים). אף אחד אינו קורא מהתיקייה. אחרי git rm --cached הם נשארו על הדיסק ואינם מופיעים כ-untracked, כי .gitignore:2 חוסם אותם.
🧪 בדיקות נדרשות ב‑PR
- 🔍 Code Quality & Security
- Unit Tests (3.11)
- Unit Tests (3.12)
📝 סוג שינוי
- feat
- fix: תיקון באג
- docs: שינוי תיעוד בלבד
- refactor
- perf
- chore/ci: תשתית
- breaking change
✅ צ'קליסט
- הקוד עוקב אחרי הסגנון (flake8 נקי)
- בדיקות רצות ועוברות
- תיעוד עודכן
- ג'ובים חדשים — לא רלוונטי
- משתני סביבה — לא נוספו ולא שונו. הבלוק שנמחק מ-
configuration.rstהוא כפילות מדויקת של בלוק ששורד באותו קובץ, ולכן אף משתנה לא ירד מהתיעוד - טוקנים/ערכות נושא — לא רלוונטי
- אין סודות/מפתחות בקוד
- אין מחיקות מסוכנות — כל מחיקה זמנית בסשן עברה דרך מעטפת שמאמתת
readlink -fמול allowlist, לפיCLAUDE.md - הודעות הקומיט תואמות Conventional Commits
- CHANGELOG — אין קובץ כזה בשורש
- עיינתי במסמכי אתר התיעוד — נתיב:
docs/doc-authoring.rst,docs/versioning-stable-anchors.rst| המשפט: "אם המספר יכול להשתנות בלי שאף שורת קוד תשתנה — הוא ספירת מופעים, ואין לכתוב אותו" ו-"לא לשבור מזהי עוגנים קיימים (refs) בין גרסאות"
🧩 השפעות/סיכונים
אפס שינוי בקוד ייצור. שני קבצי התיעוד הם פרוזה, קובץ הטסט הוא מוסכמת בידוד, וה-.pyc הם היגיינת גיט. הסיכון היחיד שנשקל הוא אובדן תוכן מ-configuration.rst, והוא נסגר במדידה: 17 מ-19 השורות שנמחקו קיימות כלשונן בעותק ששרד, והשתיים הנותרות הן ניסוח חלופי של אותו מידע.
סטייה מהמוסכמה, מדווחת: CLAUDE.md ו-docs/doc-authoring.rst אומרים לא לבנות את התיעוד מקומית עבור פרוזה בעמוד קיים, כי RTD תופס. נתבקשתי לבנות עם אזהרות כשגיאות, ולכן בניתי — ובניתי את האתר המלא ולא עמוד בודד, כי הצורה החלקית מייצרת אזהרת שווא משלה.
🔗 קישורים
- מקור: דוח אימות בלתי-תלוי של #3394 (squash
dea1b9e, בסיס06983a8) - Issues קשורים: #
- מסמכים רלוונטיים:
docs/doc-authoring.rst,docs/versioning-stable-anchors.rst
🧯 סיכון / החזרה לאחור (Rollback)
git revert לכל אחד מארבעת הקומיטים בנפרד — הם עצמאיים לגמרי ואינם נוגעים באותם קבצים. ה-.pyc שיחזרו ב-revert יהיו זהים לאלה שעל הדיסק.
🤖 Generated with Claude Code
https://claude.ai/code/session_01P1AYmWhLGtpsr7sSdRZVD3
Generated by Claude Code
Summary by Sourcery
Clean up documentation, test isolation, and repository artifacts identified during validation without changing production behavior.
Bug Fixes:
- Prevent the documentation import test from writing bytecode into the source tree by isolating its subprocess and disabling bytecode generation.
Enhancements:
- Make outline scanner documentation describe the stable no-heavy-import invariant without environment-dependent module counts or incomplete module lists.
Documentation:
- Remove the duplicated configuration guidance while retaining the complete canonical section.
Tests:
- Update the subprocess-based import test to use an isolated working directory and repository path.
Chores:
- Remove tracked Python bytecode artifacts from Git while preserving the files locally.