# TODO Durable backlog. Agents append here instead of leaving `TODO` comments in source. Small, specific, independently actionable. Remove only when actually done. Design: [specs/001-webtoons-covers.md](specs/001-webtoons-covers.md). ## Now - [ ] **User smoke test** in a real browser: the page (local server) and the userscript in Tampermonkey or Violentmonkey on a MangaBaka series page — Tower of God (9999 / title_no 95). The agent ran both in headless Chrome (the userscript with a GM shim); a real GM install is still untested. - [ ] **Gitea secret `REGISTRY_TOKEN`** (needs the user): an access token with package write permission, as a repository or user secret, so CI can push the image. Then check the first run of `.gitea/workflows/ci.yml`. - [ ] **Deploy** (needs the user): which server and domain (`MBSEED_PUBLIC_URL`), where the covers folder lives, whether the 1 GiB cap suits the disk, reverse proxy with TLS that appends `X-Forwarded-For`. ## Next - [ ] Capture MangaBaka snapshot / preview / save responses once someone with API access runs the token flow; replace the inline OpenAPI-shaped bodies in `test/mangabaka-client.test.ts` and `test/session.test.ts`. - [ ] Check whether MangaBaka's `hashes.sha256` matches the original bytes (spec §7.7): compare a cover we submitted with its hash on MangaBaka. If it doesn't, "already on MangaBaka" never matches. - [ ] Userscript: fill MangaBaka's cover form for users without a token (spec §4.9) — needs the logged-in form's markup and a check that it accepts programmatic input (spec §7.5). The panel offers copy-and-paste instead. - [ ] Small fixes from the final review (deferred as minor): a malformed `Location` on a proxied redirect gives 500 instead of 502; cap the `/api/upload` JSON body size (`maxRequestBodySize`); after Preview, re-run `draw()` so the button respects an unconfirmed link mismatch and the counts refresh after a partial upload; label the "direct" host's URL as "Source URL", not "Rehosted". - [ ] Mobile layout (the user deferred it, 2026-10-15): the page stacks under 1000px but was only checked at 760px. ## Verify with real services (once possible) - [ ] Download from the userscript panel in **Firefox** with Tampermonkey/Violentmonkey (checked in Chrome only); if the Blob link is blocked there, add `GM_download` (spec 002 §6). - [ ] Which of our servers and domain hosts it (`MBSEED_PUBLIC_URL`); where the covers folder lives. - [ ] Does catbox accept uploads from our server? - [ ] Does MangaBaka accept our storage URLs, litterbox/catbox URLs, and `swebtoon-phinf.pstatic.net` (`direct`)? - [ ] Does MangaBaka copy images on submission or on approval? - [ ] Is "main cover" really `is_default: true`? Ask on the MangaBaka Discord if unclear. - [ ] Where are personal access tokens created in the MangaBaka UI? Add it to the README. - [ ] Does the MangaBaka cover form accept fields filled by a userscript? - [ ] Small fixes from the spec 002 review (deferred as minor): Search again should use the stored inputs, not the fields; a prune failure after a good save reports "couldn't be saved"; ZIP times are UTC, not local; accented titles lose letters in the ZIP name (Pokémon → pok-mon); covers.txt shows the date, not the time; the "rehosted" mark says "rehosted on direct" for no rehosting and outlives expired links; `openHistory` reads `globalThis.indexedDB` outside its `try`. - [ ] Small Tapas fixes from the spec 003 review (deferred as minor): a non-series tapas.io link gets the generic "No supported source" error instead of "isn't a series"; an episode link to a mature series says it can't find the series (check `ageGateTarget` there); a mature series pasted by slug keeps the slug as its id, so a MangaBaka link by number warns; an all-digit slug is read as an id; accept a quoted `pageMeta` id; archived history covers fall back to the 400×600 `_z` copy when the original is gone. - [ ] Verify with a signed-in, age-verified Tapas account (userscript): the mature info page parses. - [ ] Possible race (unconfirmed): pressing **Find covers** before the page has mounted (it awaits `/api/config` and IndexedDB first) may submit the form natively and reload. Seen once in a scripted run; not reproduced. ## Someday - [ ] S3-compatible bucket as a `Storage` option, if a single server's disk stops being enough. - [ ] Password gate (spec §4.11) — only if the open site gets abused or traffic grows too large. - [ ] Cloudflare Workers entry (`server/worker.ts`, R2 binding). If added: Workers serve static assets before the Worker unless `run_worker_first` is set — needed for the gate to cover them. - [ ] Bun CLI on the same core. - [ ] More sources: Tapas, Tappytoon, Lezhin, Manta. - [ ] Following Webtoons language editions of the same series. - [ ] Edits beyond covers (series fields, links), via other submission resources. - [ ] CI: check `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` and the `docs/` paths exist; fail if `AGENTS.md` exceeds 150 lines. ## Recurring - [ ] Maintain `AGENTS.md`: - **Add a rule only in response to a real failure.** When an agent repeatedly gets something wrong, that is a gap; add one line, ideally with a code example. Do not pre-empt hypothetical mistakes. - **Update in the same PR as the convention change.** A stale rules file is worse than none — it actively misleads. - **Prune quarterly.** Delete rules whose convention has changed or whose mistake no longer occurs. - **Optional, cheap validation:** run the same task twice in clean sessions, with and without the file, and compare steps and token use. ## Known issues - Wayback answers vary run to run: the same Tower of God run found 17 or 18 covers (a capture month can be missing from one index response). Rerunning is the remedy; nothing is lost.