Skip to content

feat: חיפוש בפתקים בוובאפ — שם, תוכן, וסינון לפי צבע - #3408

Merged
amirbiron merged 1 commit into
mainfrom
claude/focused-keller-bld86i
Sep 16, 2026
Merged

amirbiron merged 1 commit into
mainfrom
claude/focused-keller-bld86i

Conversation

@amirbiron

@amirbiron amirbiron commented Sep 16, 2026 •

Copy link
Copy Markdown
Owner

✨ תיאור קצר

עמוד /notes/search שמחפש בכל הפתקים של המשתמש יחד — לוח, קובץ, וקובץ בריפו. מגיעים אליו מעמוד הקבצים ומהגדרות הלוח. ההתאמה משותפת עם ה-MCP: שני הצרכנים עוברים דרך note_search_filter ונבדלים רק במה שהם מציגים, כך שאותה מילה מחזירה את אותם פתקים בשניהם.

📦 שינויים עיקריים

  • קוד (Backend)
  • בוט טלגרם
  • מסד נתונים/מיגרציות (אינדקס חדש)
  • תיעוד (docs/)
  • DevOps/CI/CD

פירוט:

  • sticky_notes_target — ל-note_search_filter נוסף color_id אופציונלי (מצטרף כפרדיקט עצמאי, לא כענף ב-$or); נוספו note_color_query ו-NOTE_SEARCH_PREVIEW_CHARS.
  • webapp/sticky_notes_api — GET /api/sticky-notes/search עם @require_auth ו-@notes_rate_limit, תקרה ל-limit, ו-build_note_search_pipeline.
  • webapp/routes/notes_search.py — בלופרינט חדש לעמוד עצמו (HTML בלבד, בתבנית boards_ui).
  • תבנית, JS ו-CSS חדשים — כולל פונקציית הדגשה משלנו.
  • אינדקס (user_id, updated_at) — בוובאפ וב-MCP, עם קידום _INDEX_READY_CACHE_KEY.
  • שתי נקודות כניסה — אייקון בעמוד הקבצים (משמאל ל-➕) ושורה בהגדרות הלוח.

שלוש החלטות שנגזרו ממדידה, לא מהיגיון

$text נבחן ונפסל. אינדקס טקסט הוא הפתרון המתבקש, אבל מדידה על פתקים אמיתיים בעברית הראתה שהוא מפספס כ-18% מההתאמות שהרג'קס מוצא: חיפוש "שימוש" החזיר 2 פתקים מתוך 27. הסיבה מתועדת ולא באג — $text מתאים טוקנים שלמים ומתעלם מגזירת סיומות, ולכן "פתק" אינו מוצא "בפתק". רג'קס תת-מחרוזת מוצא את שניהם. מונגו מתירה אינדקס טקסט אחד לכל אוסף, כלומר זו החלטה שקשה לחזור ממנה — ולכן היא מתועדת ב-docs/dev/sticky_notes_extending.

האינדקס (user_id, updated_at) מתקן בעיה שכבר קיימת. הדוקסטרינג של note_search_filter טען ש-user_id כפרדיקט ראשון חוסם את הסריקה למכסת המשתמש "ואינו COLLSCAN". explain על השאילתה האמיתית הראה שהתוכנית הזוכה בוחרת ב-updated_desc — כלומר החיפוש שרץ היום ב-MCP סורק את הפתקים של כל המשתמשים. הדוקסטרינג תוקן לתאר את מה שנמדד.

סינון הצבע צריך את שתי הצורות. במסד 176 פתקים שמורים כ-#FFFFCC באותיות גדולות בעוד שהפלטה מחזיקה #ffffcc — כלומר סינון שמשווה למזהה בלבד היה מחזיר אפס, בלי שגיאה. note_color_query מחזירה $in של המזהה ורג'קס מעוגן חסר-רישיות. הרג'קס יורד בעריכה אחת אחרי ש-scripts/migrate_note_colors.py --apply רץ בכל הסביבות.

עברית, ולמה ההדגשה בצד הלקוח

חיתוך התצוגה המקדימה הוא $substrCP ולעולם לא $substrBytes — אות עברית היא שני בייטים, וחיתוך בבייטים על מספר שנספר בתווים מפיל את השאילתה (Location28657). מאותה סיבה השרת אינו שולח היסטים: הוא סופר תווים, מונגו נקודות-קוד ו-JS יחידות UTF-16. ההתאמה נעשית על 200 התווים שכבר הגיעו.

ההדגשה בנויה מצמתי DOM (createElement + textContent) ולא ממחרוזות HTML, ולכן אין ב-notes_search.js שום innerHTML.

🧪 בדיקות

  • Unit — 35 בדיקות פייתון + 8 בדיקות JS
  • Integration
  • Manual — מדידה בדפדפן

כל בדיקה מומתה. 18 מוטציות בפייתון ו-5 ב-JS, וכל אחת הפילה את הבדיקה שלה: הסרת הדירוג מהמיון, הסרת ה-$project, הזזתו אחרי ה-$sort, החלפת $substrCP ב-$substrBytes, הסרת user_id, שוויון במקום $in, רג'קס בלי i, הסרת re.escape, הסרת $ifNull, הסרת התקרה, הסרת שורת הסנטינל, ו-textContent שהופך ל-innerHTML.

שתי מוטציות חשפו חורים בבדיקות שלי עצמי ותוקנו: בדיקת המדידה בבייטים עברה על קוד שבור כי הפתק שנבחר היה קצר מ-200 גם בבייטים — הוחלף בפתק של 150 תווים (270 בייטים), שיושב בין שתי היחידות. ומוטציה שנייה לא הוחלה בכלל כי הדפוס הופיע פעמיים בקובץ.

מדידה בדפדפן (Chromium אמיתי, 1024 ו-390): אין שגיאות דף; הרמז "המילה מופיעה בהמשך הפתק" מופיע בדיוק כשאין התאמה בכותרת ואין בתקציר; מטען <img onerror> ומרכאות מופיעים כטקסט ולא נוצר מהם אלמנט; עיגולי הפלטה נדגמו בפיקסלים והחזירו בדיוק את גווני NOTE_COLORS; אין גלילה אופקית; הטקסט בתוך ההדגשה 10.57:1 מול רקע ההדגשה.

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

בנוסף, התנהגות העמוד בערכות מיובאות נבדקה חלקית בלבד. מה שכן אומת: הטוקנים של ערכה מיובאת חלים על הכרטיס כמצופה (--card-bg נקרא נכון), וניגודיות הכותרת גבוהה בשלוש הערכות שבשימוש. מה שלא הושלם: ניגודיות שורת התקציר, שנשענת על --text-secondary. [data-theme="custom"] a שב-dark-mode.css צובע כל <a> ב---primary ומנצח בספציפיות את המחלקה של הכרטיס — אותו דפוס שכבר קיבל וו דריסה ייעודי באוספים ובהצעות החיפוש. אם יידרש, זה תיקון ממוקד בעקבות שימוש ולא חוסם מיזוג.

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

🧪 בדיקות נדרשות ב‑PR

  • 🔍 Code Quality & Security
  • Unit Tests (3.11)
  • Unit Tests (3.12)

📝 סוג שינוי

  • feat: פיצ'ר חדש

✅ צ'קליסט

  • הקוד עוקב אחרי הסגנון של הקבצים שהוא יושב בהם
  • בדיקות רצות ועוברות
  • תיעוד עודכן
  • לא נוספו ג'ובים חדשים
  • לא נוספו/שונו משתני סביבה
  • לא נוספו/השתנו טוקנים — ה-CSS החדש נשען על טוקנים קיימים, ובדיקת rg "#[0-9a-fA-F]{3,6}" על notes-search.css מחזירה ריק
  • אין סודות/מפתחות בקוד
  • אין מחיקות מסוכנות
  • הודעת הקומיט תואמת Conventional Commits
  • עיינתי במסמכי אתר התיעוד — נתיב: docs/webapp/theming_and_css.rst | המשפט: "Sticky Notes, Reader Modes ו-theme_preview.html נשארים Hardcoded בכוונה לצורכי Preset/Brand"
    • וגם: docs/dev/sticky_notes_extending.rst, docs/performance-sticky-notes.rst, docs/database/indexing.rst, docs/webapp/commands-catalog.rst (ממנו נגזרה הדרישה שהמזהים בעמוד לא יהיו globalSearchInput/searchBtn, כי global_search.js נטען בכל עמוד ומתחבר לכל דף שמכיל את שניהם)

🧩 השפעות/סיכונים

הרשאות: העמוד מחזיר את הפתקים של המשתמש בכל שלושת הסוגים, בדיוק כמו codekeeper_search_notes — שאינו מגודר לאדמין. הפער בין הגייטים של פתקי ריפו ב-MCP ובוובאפ מדווח בנפרד ב-#3407 ולא שונה כאן.

אינדקס: נוסף אינדקס אחד לאוסף שכבר נושא אחד-עשר. הבנייה best-effort ואינה מפילה בקשה. _INDEX_READY_CACHE_KEY קודם ל-v4, ולכן תהליכים שמחזיקים דגל v3 חי ייבנו מחדש בפריסה.

מיגרציה: scripts/migrate_note_colors.py --apply לא הורץ כאן, וסינון הצבע עובד גם בלעדיו. הרצתו מיישרת את המסד ומאפשרת לפשט את note_color_query בהמשך.

ערכות מיובאות: ראו את סעיף הבדיקות — ייתכן שיידרש וו דריסה לצבע הטקסט בכרטיס, בתבנית שכבר קיימת ב-collections.css וב-global_search.css.

🔗 קישורים

🧯 סיכון / החזרה לאחור (Rollback)

השינוי אדיטיבי: אף מסלול קיים לא שינה התנהגות. note_search_filter קיבל פרמטר עם ברירת מחדל שמשמרת את ההתנהגות הקודמת, ושאר השינויים הם קבצים חדשים או תוספות. Revert מסיר את העמוד ואת נקודות הכניסה; האינדקס נשאר במסד ואינו מזיק (הוא עוזר גם לחיפוש של ה-MCP).

🤖 Generated with Claude Code

https://claude.ai/code/session_01PL3goRvy9ze5NrG5z68Awr

עמוד ‎/notes/search שמחפש בכל הפתקים של המשתמש יחד — לוח, קובץ, וקובץ
בריפו. מגיעים אליו מעמוד הקבצים ומהגדרות הלוח.

ההתאמה משותפת עם ה-MCP: שני הצרכנים עוברים דרך note_search_filter, ונבדלים
רק במה שהם מציגים. ‏$text נבחן ונפסל — מדידה על פתקים אמיתיים בעברית הראתה
שהוא מפספס כ-18% מההתאמות שהרג'קס מוצא, כי הוא מתאים טוקנים שלמים ומתעלם
מגזירת סיומות.

ההדגשה נעשית בצד הלקוח מצמתי DOM ולא ממחרוזות HTML, והשרת אינו שולח היסטים:
הוא סופר תווים, מונגו נקודות-קוד ו-JS יחידות UTF-16, וערבוב היחידות האלה הוא
הבאג שהפיל את חיפוש הקוד. החיתוך ל-200 תווים הוא $substrCP, לעולם לא
$substrBytes.

נוסף אינדקס ‎(user_id, updated_at)‎: explain על החיפוש שכבר רץ ב-MCP הראה
שמונגו בוחרת ב-updated_desc וסורקת את הפתקים של כל המשתמשים. דגל המוכנוּת
קודם ל-v4 בהתאם, והבדיקה נועלת את השניים יחד.

סינון הצבע עובר דרך note_color_query — מזהה ורג'קס מעוגן חסר-רישיות בתוך
‎$in — כי במסד 176 פתקים שמורים כ-#FFFFCC בעוד שהפלטה מחזיקה ‎#ffffcc.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PL3goRvy9ze5NrG5z68Awr
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @amirbiron, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 4 days and 12 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 15 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 0a98c0b7-08f1-41f8-8cb6-0115809ff3cb

📥 Commits

Reviewing files that changed from the base of the PR and between c092066 and 66a9af5.

📒 Files selected for processing (19)
  • docs/database/detailed-schema.rst
  • docs/dev/sticky_notes_extending.rst
  • docs/performance-sticky-notes.rst
  • docs/user/sticky_notes.rst
  • mcp_server/backend.py
  • sticky_notes_target.py
  • tests/notes-search-highlight.test.js
  • tests/test_mcp_backend_lazy_init.py
  • tests/test_mcp_notes_handlers.py
  • tests/test_note_boards_api.py
  • tests/test_notes_search.py
  • webapp/app.py
  • webapp/routes/notes_search.py
  • webapp/static/css/notes-search.css
  • webapp/static/js/notes_search.js
  • webapp/sticky_notes_api.py
  • webapp/templates/files.html
  • webapp/templates/note_board.html
  • webapp/templates/notes_search.html

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🧯 Dangerous deletes guard report

Policy: see .cursorrules — dangerous deletions are blocked unless wrapped safely.

Summary:

  • Flagged findings (blocking): 0
    0
  • Excluded matches (not blocking): 15
  • Total matches (all files): 129

Flagged findings (file:line:snippet):
(none)

Excluded matches (by path pattern)
./webapp/static/js/md_preview.bundle.js.map:4:  "sourcesContent": ["// Markdown-it plugin to render GitHub-style task lists; see\n//\n// https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments\n// https://github.com/blog/1825-t … [truncated]
./docs/DOCUMENTATION_GUIDE.md:453:rm -rf _build
./docs/Makefile:24:	rm -rf $(BUILDDIR)
./Dockerfile:42:    rm -rf /var/lib/apt/lists/*
./Dockerfile:121:    rm -rf /var/lib/apt/lists/*
./node_modules/katex/package.json:153:    "build": "rimraf dist/ && mkdirp dist && cp README.md dist && rollup -c --failAfterWarnings && webpack && node update-sri.js package dist/README.md",
./node_modules/katex/src/fonts/Makefile:139:	rm -rf pfa ff otf ttf woff woff2
./node_modules/mermaid/dist/mermaid.js.map:4:  "sourcesContent": ["/**\n* Default values for dimensions\n*/\nconst defaultIconDimensions = Object.freeze({\n\tleft: 0,\n\ttop: 0,\n\twidth: 16,\n\theight: 16\n});\n/**\n* Default values for tr … [truncated]
./node_modules/mermaid/dist/chunks/mermaid.esm/chunk-2M32CCKP.mjs.map:4:  "sourcesContent": ["{\n  \"name\": \"mermaid\",\n  \"version\": \"11.12.0\",\n  \"description\": \"Markdown-ish syntax for generating flowcharts, mindmaps, sequence d … [truncated]
./node_modules/mermaid/dist/chunks/mermaid.esm.min/chunk-4HFYJGYH.mjs.map:4:  "sourcesContent": ["{\n  \"name\": \"mermaid\",\n  \"version\": \"11.12.0\",\n  \"description\": \"Markdown-ish syntax for generating flowcharts, mindmaps, sequen … [truncated]
./node_modules/mermaid/dist/chunks/mermaid.esm.min/chunk-4HFYJGYH.mjs:1:var r={name:"mermaid",version:"11.12.0",description:"Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graph … [truncated]
./node_modules/mermaid/dist/chunks/mermaid.core/chunk-KS23V3DP.mjs.map:4:  "sourcesContent": ["{\n  \"name\": \"mermaid\",\n  \"version\": \"11.12.0\",\n  \"description\": \"Markdown-ish syntax for generating flowcharts, mindmaps, sequence  … [truncated]
./node_modules/mermaid/dist/mermaid.min.js:1524:`,"getStyles"),c1e=RQe});var h1e={};dr(h1e,{diagram:()=>NQe});var NQe,f1e=N(()=>{"use strict";$ge();a1e();l1e();u1e();NQe={parser:Fge,db:n1e,renderer:o1e,styles:c1e}});var m1e,g1e=N(()=>{"use  … [truncated]
./node_modules/mermaid/dist/mermaid.min.js.map:4:  "sourcesContent": ["/**\n* Default values for dimensions\n*/\nconst defaultIconDimensions = Object.freeze({\n\tleft: 0,\n\ttop: 0,\n\twidth: 16,\n\theight: 16\n});\n/**\n* Default values fo … [truncated]
./README.md:842:find . -name "__pycache__" -exec rm -rf {} +

@sourcery-ai

sourcery-ai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR adds a user-facing Hebrew-aware notes search page and API spanning boards, files, and repository notes, reusing the MCP’s matching filter while adding color filtering, safe previews/highlighting, ranking, limits, and ownership checks; it also introduces a compound performance index, synchronized MCP/webapp initialization, navigation entry points, tests, and documentation.

Sequence diagram for webapp notes search with color filtering

sequenceDiagram
    actor User
    participant Page as Notes search page
    participant API as GET /api/sticky-notes/search
    participant Filter as note_search_filter
    participant DB as sticky_notes

    User->>Page: Submit query and optional color
    Page->>API: Fetch q and color
    API->>API: _search_limit
    API->>Filter: note_search_filter(user_id, needle, color_id)
    Filter-->>API: User, text, and color predicates
    API->>DB: aggregate(build_note_search_pipeline)
    DB-->>API: Ranked preview results plus sentinel row
    API-->>Page: JSON results and truncated flag
    Page->>Page: highlightInto
    Page-->>User: Render safe highlighted results
Loading

Entity relationship diagram for notes search ownership and indexing

erDiagram
    USER ||--o{ STICKY_NOTE : owns
    STICKY_NOTE {
        int user_id
        string title
        string content
        string color
        datetime updated_at
    }
    STICKY_NOTE }o--|| NOTE_TARGET : references
    NOTE_TARGET {
        string target
        string file_name
        string repo_path
    }
    STICKY_NOTE }o..o{ SEARCH_INDEX : optimized_by
    SEARCH_INDEX {
        string user_id_updated_at
    }
Loading

Flow diagram for note search pipeline and result shaping

flowchart TD
    Request[Search request] --> Match[$match: shared note_search_filter]
    Match --> AddFields[$addFields: title ranking and $substrCP preview]
    AddFields --> Project[$project: remove content]
    Project --> Sort[$sort: title hits then updated_at]
    Sort --> Limit[$limit: requested limit plus sentinel]
    Limit --> Unset[$unset ranking helper]
    Unset --> Response[Safe result objects with preview only]
Loading

File-Level Changes

Change Details Files
Added a cross-target notes search backend with shared matching semantics, color filtering, bounded results, previews, ranking, and ownership enforcement.
  • Extended the shared note filter with content matching and an independent color predicate, including legacy color spellings.
  • Added an authenticated, rate-limited search API with input validation, limit caps, sentinel-based truncation, title-first ranking, and content-free responses.
  • Built an aggregation pipeline using code-point-safe preview truncation and early projection of note bodies.
sticky_notes_target.py
webapp/sticky_notes_api.py
tests/test_notes_search.py
Added indexed search support and synchronized index initialization across the webapp and MCP.
  • Added the compound (user_id, updated_at) index and bumped the readiness cache key.
  • Mirrored the query-index specification in MCP initialization and guarded concurrent lazy index creation.
  • Reworked index tests to derive expectations from the implementation/specification rather than hard-coded counts.
mcp_server/backend.py
webapp/sticky_notes_api.py
tests/test_mcp_backend_lazy_init.py
tests/test_mcp_notes_handlers.py
tests/test_note_boards_api.py
Introduced a server-rendered notes search page with client-side querying, filtering, highlighting, and safe result rendering.
  • Added the /notes/search page, palette-driven color controls, responsive styling, URL state restoration, and navigation entry points.
  • Implemented client-side highlighting with DOM nodes and textContent, including hinting when the match falls outside the preview.
  • Added JavaScript coverage for matching, escaping, highlighting, and XSS-safe rendering.
webapp/routes/notes_search.py
webapp/templates/notes_search.html
webapp/static/js/notes_search.js
webapp/static/css/notes-search.css
webapp/templates/files.html
webapp/templates/note_board.html
tests/notes-search-highlight.test.js
webapp/app.py
Documented the search behavior, indexing rationale, schema impact, and user-facing feature.
  • Documented why regex is used instead of MongoDB text search for Hebrew substring matching.
  • Documented code-point-safe previews, color migration compatibility, index performance findings, and extension guidance.
  • Updated database and user documentation for the new indexed search capability.
docs/database/detailed-schema.rst
docs/dev/sticky_notes_extending.rst
docs/performance-sticky-notes.rst
docs/user/sticky_notes.rst

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

Copy link
Copy Markdown
Contributor

⏱️ Performance report

(No performance test durations collected. Mark tests with @pytest.mark.performance.)

@github-actions

Copy link
Copy Markdown
Contributor

📖 Documentation Preview

The documentation has been built successfully!

To view locally:

  1. Download the artifacts
  2. Extract the zip file
  3. Open index.html in your browser

@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.14286% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
sticky_notes_target.py 77.14% 3 Missing and 5 partials ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants