一键导入
debug-highlights
Debug incorrect Kobo→Calibre highlight conversions via ground-truth comparison
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Debug incorrect Kobo→Calibre highlight conversions via ground-truth comparison
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | debug-highlights |
| description | Debug incorrect Kobo→Calibre highlight conversions via ground-truth comparison |
| compatibility | opencode |
| metadata | {"workflow":"interactive","destructive":true,"requires_device":true} |
Debug CFI conversion issues by creating manual ground-truth highlights in both systems and comparing converter output.
Read paths.kobo_db and paths.calibre_db from .agents/config.yaml. If the file is missing, ask the user for paths and create it.
KoboReader.sqlite on mounted volume, Calibre metadata.db in library dir.agents/logs/debug-highlights-<timestamp>.lognew format, max verbosity (-vv)WARNING: Deletes all highlights for selected book (preserved in memory, but lost if skill crashes). User should have backups.
IMPORTANT Kobo and Calibre use different versions of the same book: Calibre has a original epub, while Kobo has a kepubified version. The source code of "kepubify" is available in "kepubify.py". If needed, lookup other source code of Calibre.
IMPORTANT Calibre's CFI encode/decode logic lives in cfi.pyj: https://raw.githubusercontent.com/kovidgoyal/calibre/master/src/pyj/read_book/cfi.pyj — key functions: encode(), adjust_node_for_text_offset(), decode(), node_for_text_offset().
IMPORTANT Calibre's kepubify logic (adds kobo spans to EPUB HTML): https://raw.githubusercontent.com/kovidgoyal/calibre/master/src/calibre/ebooks/oeb/polish/kepubify.py — local copy in kepubify.py. Key function: kepubify_html_data().
IMPORTANT Always run calibre-customize -b $(pwd) before calibre-debug -e. The dual import loads the installed plugin, not local files. Symptom of staleness: debug logging you added doesn't appear.
test -f /Volumes/KOBOeReader/.kobo/KoboReader.sqliteSELECT DISTINCT VolumeID, COUNT(*) FROM Bookmark WHERE VolumeID LIKE '%?%' AND text != '' GROUP BY VolumeIDDELETE FROM Bookmark WHERE VolumeID = ? and DELETE FROM annotations WHERE book = ?SELECT * FROM Bookmark WHERE VolumeID = ? ORDER BY DateCreated DESC LIMIT 1SELECT annot_data FROM annotations WHERE book = ? LIMIT 1.agents/logs/debug-highlights-$(date +%Y%m%d-%H%M%S).log--filter_booknamecalibre-debug -e kobo2calibre.py -- --filter_bookname "<title>" /Volumes/KOBOeReader /Volumes/Stuff/Calibre --kepub_format new --both_ways -vv 2>&1 | tee "$LOG_FILE"SELECT annot_data, timestamp FROM annotations WHERE book = ? ORDER BY timestampconverter.py| Type | Symptom | Root Cause | Location |
|---|---|---|---|
| A: Spine Path | Wrong chapter in CFI | Spine ordering/path resolution | get_spine_index_map() |
| B: Block Number | CFI block ≠ Kobo block | HTML tag counting mismatch | BLOCK_TAGS constant |
| C: Char Offset ⭐ | Correct block, wrong text position | Sentence splitting differs | get_block_offset_from_kepubify() |
| D: Sentence Number | Wrong sentence in block | Sentence counting differs | split_into_sentences() |
| E: Complete Failure | Missing or error | Various | convert_kobo_to_calibre_highlight() |
Kobo (Bookmark): VolumeID, ContentID, Start/EndContainerPath, Start/EndOffset, Text, Color
Format: #kobo.{block}.{sentence} (1-indexed)
Calibre (annotations): book (FK), annot_data (JSON)
CFI: /6/2[chapter1]!/4/12/1:0 = spine/DOM path/char offset
calibre-debug -e kobo2calibre.py -- --filter_bookname "Book" /Volumes/KOBOeReader /Volumes/Stuff/Calibre --kepub_format new -vvmake testtest/test_converter.py