diff --git a/HANDOFF.md b/HANDOFF.md new file mode 100644 index 0000000..2afdb59 --- /dev/null +++ b/HANDOFF.md @@ -0,0 +1,78 @@ +# Hand-off — 2026-06-05 + +Snapshot of repo state for whoever picks up next. Pair with [CLAUDE.md](CLAUDE.md) for the architecture, dev rules, and command crib. + +## Where main is + +`main` is at **0.52.0** (commit `679abae`, `feat(chapter): preserve source-site order in chapter list`). + +Recently landed (in order): +- `0.52.0` — `feat(chapter)`: source-site order in chapter list; new `source_index` column + reverse-sort. Migration `0021_chapter_source_index.sql` runs on next backend start. +- `0.51.2` — `fix(reader)`: drop `Chapter N:` prefix from title display; `chapterLabel()` helper in `$lib/api/chapters`. +- `0.47.0` — `feat(crawler)`: honour `CRAWLER_LIMIT` in the in-process daemon (previously CLI-only). + +All three were authored this session. + +## In-flight branches (pushed, not yet on main) + +The remote now has 18 local-only branches. The ones most relevant to current work: + +| Branch | Tip ver | Notes | +| --- | --- | --- | +| `feat/crawler-observability-and-reliability` | 0.54.0 | Active dev branch — admin crawler dashboard, live status SSE, coordinated browser restart, dead-job requeue, runtime PHPSESSID refresh, reliability fixes. Now also carries the `restart_browser` clears-`session_expired` fix from this session (commit `fb4182f`, 0.53.1). | +| `feat/private-mode` | 0.48.0 | Site-wide auth gate via `PRIVATE_MODE`. Already merged into main during this session. Branch left around for reference. | +| `feat/cover-retry-and-force-resync` | 0.50.0 | Cover retry backfill + admin force-resync. Already merged into main. | + +The older `bugfix/*`, `chore/*`, and other `feat/*` branches are pre-0.40 era WIP — they predate this session and may be stale; verify before reviving. + +## Session-specific changes worth flagging + +### 1. `CRAWLER_LIMIT` now caps the daemon + +Before: `bin/crawler` honoured `CRAWLER_LIMIT`, but the in-process daemon called `pipeline::run_metadata_pass(..., 0, ...)` so it always swept the full catalog. + +Fix: `CrawlerConfig.manga_limit` reads `CRAWLER_LIMIT` (default `0` = no cap), threaded through `RealMetadataPass::run`. Same env var as the CLI. + +Tests: `backend/src/config.rs::tests::crawler_limit_env_populates_manga_limit` (and the unset default). + +### 2. Browser restart now drops the sticky `session_expired` flag + +On branch `feat/crawler-observability-and-reliability` only (not on main yet). + +Bug: hitting the admin "Restart browser" button ran `coordinated_restart` (which re-runs `on_launch` → re-injects PHPSESSID → re-probes), but `session_expired` stayed `true` regardless. UI continued to report Session Expired and chapter workers kept idling. + +Fix: on `Ok(())` from `coordinated_restart`, the handler now calls `c.session.clear_expired()`. Error path still leaves it set. See [backend/src/api/admin/crawler.rs:230-262](backend/src/api/admin/crawler.rs#L230-L262). + +Test: `backend/src/crawler/session_control.rs::tests::clear_expired_flips_sticky_flag_without_touching_session`. + +## Dev stack + +Compose ships db + tor (frontend runs natively). See `docker-compose.dev.yml`. + +```bash +docker compose -f docker-compose.dev.yml up -d +(cd frontend && npm run dev) # http://localhost:5175 +``` + +Backend dev command template (fill in ``): + +```bash +cd backend && \ + CRAWLER_START_URL="" \ + CRAWLER_LIMIT=96 \ + CRAWLER_DAEMON=true \ + CRAWLER_PROXY=socks5h://localhost:9050 \ + CRAWLER_TOR_CONTROL_URL=tcp://localhost:9051 \ + CRAWLER_TOR_CONTROL_PASSWORD=dev-tor-password \ + CRAWLER_ALLOW_ANY_HOST=true \ + ADMIN_USERNAME=admin ADMIN_PASSWORD=admin \ + cargo run --release +``` + +`backend/.env` already pins `DATABASE_URL`, `BIND_ADDRESS=0.0.0.0:18080`, `STORAGE_DIR`, `COOKIE_SECURE=false`. It also extends `RUST_LOG` to silence the noisy `chromiumoxide::conn` / `chromiumoxide::handler` WS-deserialize lines. + +## Open items / known nuance + +- **Vite generates `vite.config.ts.timestamp-*.mjs`** as a transient artifact when the dev server is running. It's not in `.gitignore`; consider adding `frontend/vite.config.ts.timestamp-*.mjs` to root `.gitignore` to stop it showing up in `git status`. Deleting the file is safe — Vite re-creates as needed. +- **Pre-bump drift.** Manifest versions have been hand-bumped ahead of commits a couple of times during this session (e.g. `0.53.0` sitting uncommitted in the working tree). When you land work on the active branches, double-check the `backend/Cargo.toml`, `backend/Cargo.lock`, `frontend/package.json` triplet are in lockstep before committing. +- **`feat/crawler-observability-and-reliability` is multi-feature.** It carries observability, reliability, runtime session control, dashboard, and now the session-expired-clear fix — landing it as one squash on main would be a sizeable diff. Consider whether to split it (e.g. split out the dashboard + dead-job requeue into its own slice) before merging.