127 lines
6.7 KiB
Markdown
127 lines
6.7 KiB
Markdown
# Bookmark — Agent & Developer Context
|
|
|
|
Bookmark is a camera-driven book intake and checkout inventory system built
|
|
for **Books in Hand**, a nonprofit that keeps books out of landfills and in
|
|
people's hands. It is a standalone client project — not part of the
|
|
CircuitForge product line, no BSL tiering, no CircuitForge license server
|
|
integration. Owned by / donated to the nonprofit.
|
|
|
|
This file is the entry point for any AI coding assistant (Claude Code,
|
|
Codex, Cursor, etc.) or human contributor picking up this codebase. Read it
|
|
before making changes.
|
|
|
|
## What This Project Does
|
|
|
|
Two physical stations, camera-driven:
|
|
|
|
1. **Intake station** — a volunteer places a book on a marked platform under
|
|
a downward-facing webcam. The system captures front and back photos in a
|
|
guided flow, determines a `small` / `medium` / `large` size bucket
|
|
**deterministically** (by checking which physical platform markers are
|
|
covered vs. exposed — no OCR, no ML), and writes a row to a CSV
|
|
catalogue. This size bucket feeds Books in Hand's year-end tax and
|
|
501(c)(3) reporting, including charitable write-off valuation — it must
|
|
stay deterministic because a wrong bucket has real financial
|
|
consequences.
|
|
2. **Checkout station** (later phase) — reuses the same camera +
|
|
identification pipeline (barcode decode, vision-LLM fallback) to mark
|
|
books as taken, updating the same CSV.
|
|
3. **Batch OCR/ISBN backfill** (later phase) — a separate pass, run on
|
|
demand on GPU-equipped hardware, decodes ISBN barcodes first and falls
|
|
back to a local vision-LLM (VLM) to read the cover when no barcode is
|
|
present, filling in title/author/ISBN for the catalogue and the future
|
|
public website. Low-confidence matches are flagged for human review —
|
|
never auto-published.
|
|
|
|
**Full design rationale and phase-by-phase build order live in:**
|
|
- Design spec: `circuitforge-plans/books-in-hand/superpowers/specs/2026-07-13-inventory-system-design.md`
|
|
- Phase 1 implementation plan: `circuitforge-plans/books-in-hand/superpowers/plans/2026-07-13-bookmark-intake-station-plan.md`
|
|
|
|
Those live in a separate private planning repo and won't always be
|
|
available to whoever is working in this repo — treat this file as the
|
|
self-contained summary; the sections below capture what those docs decided.
|
|
|
|
## Terminology
|
|
|
|
Never use the generic term "AI" in code, comments, docs, or UI copy. Name
|
|
the specific mechanism instead: "LLM", "VLM" (vision-LLM), "OCR", "barcode
|
|
decode". This keeps claims about what the system does precise and avoids
|
|
overstating capability.
|
|
|
|
## Architecture (Phase 1 — Intake, the only phase built so far)
|
|
|
|
- **Backend:** Python 3.11+, FastAPI + Uvicorn. `bookmark/main.py` exposes
|
|
`create_app(session, camera)`. Routes live in `bookmark/api/routes.py`.
|
|
- **State machine:** `bookmark/session.py`'s `IntakeSession` drives the
|
|
guided front → back → next-book flow, calling into:
|
|
- `bookmark/sizing.py` — pure, deterministic marker-occlusion check
|
|
(`determine_size_bucket`). No ML.
|
|
- `bookmark/image_processing.py` — pure crop-to-book function
|
|
(`crop_to_book`), contour-diff against a calibrated empty-platform
|
|
reference frame.
|
|
- `bookmark/catalogue.py` — CSV read/write layer (`Catalogue`,
|
|
`BookRecord`). The CSV (`catalogue.csv`) is the single source of truth
|
|
for Phase 1 — no database.
|
|
- `bookmark/capture_strategies/` — three swappable, interchangeable
|
|
trigger strategies behind one `CaptureStrategy` interface, selected via
|
|
config (never hardcode one): `manual_button.py` (button/key press),
|
|
`motion_stop.py` (frame-diff stabilization countdown),
|
|
`stable_centered.py` (auto-detect a book filling the guide box and
|
|
holding steady).
|
|
- **Camera:** `bookmark/camera.py`'s `CameraSource` wraps `cv2.VideoCapture`
|
|
behind a `FrameSource` protocol so tests can substitute a fake camera.
|
|
- **Frontend:** plain HTML/CSS/JS kiosk page in `bookmark/static/` — no
|
|
build step. `theme.css` is the central theme file (colors, spacing,
|
|
typography as CSS variables, light/dark aware); `style.css` holds
|
|
component styles that reference those variables. Keep all future
|
|
frontend work theme-aware and responsive through this same file — don't
|
|
hardcode colors/spacing in component CSS or inline styles.
|
|
- **Config/entrypoint:** `bookmark/config.py`'s `AppConfig.load()` reads
|
|
`config.json` (per-install, gitignored — copy from `config.example.json`
|
|
and fill in real marker/guide-box pixel coordinates from
|
|
`calibrate.py`'s output). `run.py` wires everything together for
|
|
production; `calibrate.py` is a one-time-per-install interactive script
|
|
that captures the empty-platform reference frame.
|
|
|
|
## Hardware Context (informs future phases, not code in this repo yet)
|
|
|
|
Donated hardware: a 3U server (AMD EPYC Rome 8-core, 32GB DDR4, nVidia A400
|
|
— upgradeable to RTX 4000, 512GB NVMe + 4TB SATA SSD) hosts the intake
|
|
station and, in Phase 2+, a shared local vision-LLM service that both
|
|
intake and the future checkout kiosk(s) call over the LAN. Up to 3 Intel
|
|
NUCs (mixed generation) are available for kiosk stations. Cameras are
|
|
**not** provided — a USB webcam per active station still needs sourcing.
|
|
|
|
## Global Constraints (binding across all phases)
|
|
|
|
- No cloud services anywhere in Phase 1. Phase 2's only outbound network
|
|
calls are ISBN/title lookups against Open Library / Google Books, made
|
|
only after barcode decode or local VLM inference has already run.
|
|
- Size-bucketing must stay deterministic (geometry/visibility only) —
|
|
never derive it from OCR, ML, or an LLM/VLM step.
|
|
- Both the wide (uncropped, shows platform markers) and cropped (book-only)
|
|
images are kept for every capture — the wide image is the audit trail
|
|
for size-bucketing.
|
|
- No authentication/login on either station (nonprofit, low-stakes,
|
|
kiosk-appropriate).
|
|
- LLM/VLM output (Phase 2+) assists; a human reviews and approves before
|
|
anything gets published to the future public site — never auto-publish.
|
|
|
|
## Development Workflow
|
|
|
|
- Python: `.venv/bin/pip install -e ".[dev]"` from repo root.
|
|
- Tests: `.venv/bin/pytest -v` — TDD throughout; every module has a test
|
|
file under `tests/` that exercises it without real camera hardware
|
|
(synthetic NumPy frames, mocked `cv2.VideoCapture`, `TestClient` for the
|
|
API).
|
|
- Run locally: see `README.md` for calibration → config → `run.py` steps.
|
|
- Commit frequently, one logical change per commit, conventional-commit-style
|
|
subjects (`feat:`, `fix:`, `docs:`, `chore:`, `test:`).
|
|
|
|
## Out of Scope Here
|
|
|
|
- Website redesign and site publishing/export of catalogue data — separate
|
|
effort, contingent on the client's own timeline.
|
|
- Checkout station and batch OCR/ISBN backfill — future phases, each gets
|
|
its own plan before implementation starts; don't build ahead of the
|
|
current phase's plan.
|