6 Commits
Author SHA1 Message Date
wesandClaude Opus 5 fc93fc3a45 Document snapshot mode and the Kobo portability constraints
The README still described the binary as a highlights extractor, which has not
been the primary mode since snapshot was added.

Records the two constraints that only real hardware surfaced, because both cost
real time and neither is discoverable from a host build: the Elipsa's 4.9 kernel
predates statx, so Zig's File.stat and getEndPos fail as a bare
error.Unexpected after the snapshot is already written; and usize is 32-bit on
armv7, so a u64 stat size will not coerce. Also pins Zig to 0.15.2 rather than
"or later", since the 0.16 in pacman breaks the build, and notes that the host
build fails on CachyOS for reasons unrelated to this code.

Points at c0smere_devops/kobo-sync for deployment and operations rather than
duplicating them here — this repo is just the binary; the ingest service,
schema, trigger, monitoring and recovery runbook live with the rest of the
infrastructure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 20:39:54 -04:00
wesandClaude Opus 5 32d7db1668 Arm the watchdog for every mode, not just snapshot
The watchdog was spawned inside snapshot.run, so legacy highlights mode ran
without it. That is the mode NickelMenu invokes, against the endpoint that
stopped responding and hung a run for 16 days — so the exact failure being
fixed was still reachable from the device's menu.

Moves the spawn into main, ahead of mode dispatch, so both paths are covered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 18:22:23 -04:00
wesandClaude Opus 5 f55e9d0253 Add whole-database snapshot mode
Adds `kb_exfiltrator snapshot <db> [endpoint] [timeout-secs]`, which uploads a
consistent copy of the whole database instead of just extracted highlights. The
server can then parse whatever it wants, so adding a new statistic never means
touching the device again.

Uses VACUUM INTO rather than copying the file. Nickel keeps the database in WAL
mode and recent commits live in KoboReader.sqlite-wal until a checkpoint, so
copying the bare .sqlite silently loses reading progress — measured at 19 hours
of drift on the live device. Copying all three files instead is non-atomic: a
checkpoint landing mid-copy yields a pre-checkpoint main file plus a post-reset
WAL, losing data with no error. VACUUM INTO runs in a read transaction, so it
sees WAL-resident commits and emits one compacted journal_mode=delete file.

Also fixes the failure mode that left a process hung for 16 days: the server
stopped responding and std.http.Client has no timeout, so the process blocked
forever while holding the SQLite handle open. Snapshot mode closes the database
before any network I/O, and a watchdog thread hard-exits after a deadline
covering the whole run (snapshotting can stall on a locked database too).

Two portability constraints, both specific to the Kobo Elipsa:

  - Linux 4.9.77 predates statx (4.11). Zig's File.stat() and getEndPos() both
    issue it, returning ENOSYS as a bare error.Unexpected — after the snapshot
    is already written, so it presents as a post-write failure. readToEndAlloc
    with no size hint uses plain read() calls instead.
  - usize is 32-bit on armv7, so a u64 stat size will not coerce. Only the ARM
    build catches this.

Legacy invocations are unchanged, so the existing NickelMenu item keeps working.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 18:10:33 -04:00
wesandClaude ff42d5c35c Add complete Kobo highlight sync system with NickelMenu integration
- Add text cleaning to remove page reference numbers (e.g., "10After" -> "After")
- Implement cleanHighlightText() function with boundary detection
- Add NickelMenu configuration for UI integration
- Create sync wrapper scripts (with and without FBInk notifications)
- Add installation guides for Kobo deployment
- Include pointer/slice explanation examples for learning

Features:
- Extracts highlights from Kobo SQLite database
- Cleans page references from academic texts
- Computes SHA-256 hashes for deduplication
- POSTs JSON to Flask API endpoint
- Supports ARM static linking for Kobo hardware
- Optional FBInk notifications for user feedback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:13:16 -05:00
wesandClaude 22602bebf9 Add Highlight struct with SHA-256 hashing and improve query
- Add Highlight struct to represent bookmarks with owned memory
- Implement SHA-256 hashing for text and book identification
- Update SQL query to extract clean book filenames (removes path and fragment)
- Remove unused Annotation column from query
- Add CLAUDE.md for repository documentation
- Update .gitignore to exclude SQLite WAL files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 16:42:58 -05:00
wes 39bbae4e73 intial commit 2025-12-01 12:36:35 -05:00