feat: מפת סימבולים ב-get_repo_file — ניווט בקבצים גדולים במקום ניחוש
✨ תיאור קצר
webapp/app.py הוא 20,035 שורות. סוכן שחיפש בו פונקציה קרא טווח וניחש. עם outline=true הכלי מחזיר את המפה — כל פונקציה וכל מחלקה עם שורת התחלה וסיום — וההמשך הוא lines=[start, end] מדויק במקום ניחוש.
📦 שינויים עיקריים
- קוד (Backend)
- בוט טלגרם
- מסד נתונים/מיגרציות
- תיעוד (docs/, מחרוזת התיאור)
- DevOps/CI/CD
כלל אחד מייצר את כל המפה
מרחב שמות בפייתון הוא פונקציה או מחלקה, ותו לא. התחילית גדלה רק בגבולות האלה — Class.method, _register_repo_tools.get_repo_file — ואילו if/try/with/for נחצים בלי להוסיף תחילית.
הכלל הזה הוא הפיצ'ר. ירידה רק לרמה העליונה החזירה 9 סימבולים ל-mcp_server/server.py במקום 38, והשאירה את build_mcp כבלוק אטום של 513 שורות שכל כלי ה-MCP חבויים בתוכו — כלומר בדיוק הכישלון שהפיצ'ר בא למנוע, בקובץ שמגדיר את הכלי.
וגרסת ביניים עדיין נכשלה: רקורסיה שירדה רק לתוך גופי פונקציות ומחלקות החמיצה 62 סימבולים ב-webapp/app.py, כי _Missing, _NoCache ו-_NativeThread יושבות בתוך except ImportError. חריג נקודתי למעטרים היה מייצר את אותו באג שכבה עמוק יותר.
| קובץ | לפני הכלל | אחריו | מונה בלתי תלוי |
|---|---|---|---|
mcp_server/server.py | 9 | 38 | 38 ✅ |
main.py | 89 | 190 | 190 ✅ |
github_menu_handler.py | 121 | 145 | 145 ✅ |
webapp/app.py | 413 | 530 | 530 ✅ |
database/manager.py | 122 | 176 | 176 ✅ |
חמש ההחלטות, וכל אחת נמדדה
שורת ההתחלה היא של המעטר. ב-webapp/app.py 203 מתוך 408 הפונקציות ברמה העליונה מעוטרות. טווח שהיה מתחיל ב-def היה מתחיל אחרי @app.route(...) — כלומר מחמיץ את השורה שמזהה את הנתיב.
symbol= מסנן על השם המלא, ללא רישיות. symbol="build_mcp" מחזיר את המרחב ואת כל מה שבתוכו — התנהגות מכוונת ומתועדת. total סופר את ההתאמות אחרי הסינון, כי עליו נשען העימוד. על app.py, symbol="api_db" מחזיר 5 סימבולים במקום 530.
שמות אינם ייחודיים. if/else אינם מרחב שמות, ולכן שתי הגדרות בשני ענפים חולקות שם מלא. קיימים שישה מקרים כאלה בריפו היום, למשל login_required.decorated_function בשורות 3448 ו-3465. שום שלב לא ממפתח לפי שם, והסדר הוא לפי שורת התחלה עם השם כשובר-שוויון יציב.
ה-except הרחב עוטף את ast.parse בלבד. סוג החריגה תלוי-גרסה — בייט אפס הוא SyntaxError ב-3.11 ו-ValueError במקומות אחרים, ו-surrogate לא חוקי הוא UnicodeEncodeError — ולכן מניית סוגים היא הגישה השברירית. מעבר העץ רץ מחוץ ל-try, עם מחסנית מפורשת: באג שלנו נופל בקול במקום להתחפש ל"אין אאוטליין", וקינון עמוק לא יכול לייצר RecursionError מהצד שלנו. error_type מוחזר בתשובה, כי except רחב בלעדיו הורג את היכולת לאבחן.
no_outline הוא status ולא error, בדיוק כמו binary: הקריאה הצליחה, פשוט אין תוכן מהסוג שביקשו. extract_outline מדווחת כשל בערך ההחזרה ולא בזריקה, וזה מוצהר ב-docstring לפי K11 — קורא שבודק רק חריגה היה מציג קובץ שבור כקובץ בלי סימבולים.
🧪 בדיקות
36 טסטים חדשים ב-tests/test_mcp_outline.py.
השלמות נבדקת מול tokenize, לא מול ast.walk. לקסר הוא מונה בלתי תלוי; השוואה לפונקציה אחרת באותה ספרייה שהמימוש בנוי עליה מוכיחה הרבה פחות. הבדיקה רצה על חמישה קבצים אמיתיים מהריפו, ויש טסט שמראה שהמונה עצמו מסוגל להפיל.
שמונה מוטציות, כולן הופלו — כל אחת מייצגת גרסה שבאמת נכתבה בדרך:
| מוטציה | נופלים |
|---|---|
| בלי ירידה לעומק | 19 |
| ירידה לגופי פונקציות בלבד | 11 |
| המעטר לא נספר | 3 |
| dedup לפי שם | 4 |
except SyntaxError בלבד | 2 |
ה-except עוטף גם את המעבר | 1 |
total סופר את הקובץ | 1 |
per_page מהודק לתקרת העץ | 1 |
- אימות מול mirror אמיתי: ארבעת הקבצים הגדולים מתלכדים עם המונה הבלתי תלוי, והמסלול המלא עובד —
symbol="api_db_collections"← שורות 5421–5481 ←lines=שמחזיר 61 שורות שמתחילות ב-@app.route. - טסט אינטגרציה עם
git init+clone --mirrorב-tmp_path, בלי נגיעה בעץ העבודה. - תוספתיות: בלי
outlineהתשובה זהה לזו של היום. - דרך ממשק ה-MCP ולא רק דרך הפונקציה, לפי
claude-md-snippets/testing.mdכלל 1. -
tests/test_mcp_*.py— 565 עוברים, אפס נופלים. - ⚠️ flake8 אינו מותקן בקונטיינר הזה. הרצתי
py_compileואורך שורות מולmax-line-length=120.
ובדרך תוקנה דמת בדיקה צרה: _RecordingRepoBackend.get_file קיבלה רק את החתימה הישנה. יושרה לחוזה האמיתי עם הפרמטרים בסוף, כמו שכבר נעשה שם ל-list_tree — זה הדפוס שמתועד ב-CLAUDE.md.
🧪 בדיקות נדרשות ב‑PR
- 🔍 Code Quality & Security
- Unit Tests (3.11)
- Unit Tests (3.12)
📝 סוג שינוי
- feat: פיצ'ר חדש
✅ צ'קליסט
- הקוד עוקב אחרי הסגנון
- בדיקות רצות ועוברות
- תיעוד עודכן — סעיף
mcp-outlineחדש ב-docs/mcp-server.rstומחרוזת התיאור של הכלי - לא נוספו ג'ובים חדשים
- לא נוספו משתני סביבה
- אין סודות/מפתחות בקוד
- אין מחיקות מסוכנות
- הודעת הקומיט תואמת Conventional Commits
- עיינתי במסמכי אתר התיעוד —
AI-MAP.mdבתחילת התכנון, ומשםdocs/mcp-server.rst,docs/observability/error_codes.rst(שקבע ש-E_*הם אוצר מילים אחר),docs/testing.rst,docs/doc-authoring.rst. וב-amir-bug-patterns:CRITICAL-PATTERNS.mdK11 ו-claude-md-snippets/testing.md
🧩 השפעות/סיכונים
קריאה קיימת אינה משתנה. בלי outline ההתנהגות זהה, ויש על זה טסט. אין נגיעה ב-services/git_mirror_service.py, בוובאפ, באינדקסר או ב-repo_files.
ast.parse אינו מריץ קוד — נבדק. אאוטליין נשפט מול תקרת ה-10MB כמו קריאת טווח, כי הוא קורא את הקובץ ומחזיר פלט זעיר. app.py עולה כ-250ms פרסינג, ורק כשמבקשים מפה.
האאוטליין מחושב מהבלוב ואינו נשמר. lines ב-repo_files כבר לימד שמידע שמור מתיישן ודרש lines_commit_sha; אאוטליין מיושן חמור יותר — הוא שולח לשורה שכבר לא שם.
לקוח MCP שהיה מחובר לפני הדיפלוי לא יראה את הפרמטרים החדשים עד שיתחבר מחדש.
🧯 סיכון / החזרה לאחור (Rollback)
revert של הקומיט מחזיר את המצב במלואו. אין מיגרציה ואין שינוי מצב. הפיצ'ר כבוי כברירת מחדל — מי שלא מעביר outline לא רואה שינוי.
🔗 קישורים
- ממשיך את #3320, שהוסיף את תקרת ה-10MB לקריאת טווח
- ואת #3316, שהוסיף את
lines=[start, end]שהמפה מזינה
🤖 Generated with Claude Code
https://claude.ai/code/session_0154RpRM1aCgLXCwUqDgywYp
Generated by Claude Code
Summary by Sourcery
Add opt-in symbol maps to repository file retrieval so agents can locate functions and classes in large Python files before requesting exact line ranges.
New Features:
- Add an optional Python symbol outline to repository file retrieval, including fully qualified function and class names with source ranges.
- Support case-insensitive symbol filtering and pagination for navigating large outlines.
Bug Fixes:
- Report unsupported files and parse failures explicitly without changing the existing non-outline read behavior.
- Prevent conflicting outline and line-range requests and reject outline pages that exceed the output byte budget.
Enhancements:
- Preserve decorator lines in symbol ranges, include nested definitions across control-flow blocks, and retain duplicate symbol names.
- Extend repository backend and MCP tool contracts with outline parameters and input normalization.
Documentation:
- Document outline usage, filtering, pagination, Python-only behavior, and size limits in the MCP server documentation and tool description.
Tests:
- Add comprehensive outline extraction, pagination, error handling, integration, and real-repository coverage, including independent definition counts and mirror-based MCP tests.
Chores:
- Update test backends to match the expanded repository file retrieval contract.