feat: the assistant knows chapters #158
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/the-assistant-knows-chapters"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What's in
get_doujinnamed chapters only when the model passedvariant_id, and even then it dumped every page in the server's rawsortOrderwith no chapter membership; withoutvariant_ida variant carried no chapter information at all; and the system prompt never used the word. So the assistant could not say which pages belong to a chapter, and the page numbers it quoted disagreed with the reader whenever chapter order differed from raw page order.get_doujinwithoutvariant_idnow shows each variant as(24 pages, 3 chapters, id …), orno chapters. The count comes from thechapterCountthe summary already carried; nothing on the wire changed.get_doujinwithvariant_idrenders the variant throughcore/reading_order.dart'sReadingOrder.of— the same rule the reader, the editor grid, the detail grid and the offline download use. Chapters come insortOrderaschapter "Title" (id …): pages 5-28(orpage 7, orno pages) with theirpageNumber:imageIdpairs beneath, and the ungrouped tail last. Page numbers are therefore reading-order numbers, so/read/<doujinId>/<variantId>?page=Nthroughnavigateopens the page the tool numbered.chapterIdnames a chapter the variant does not carry is listed last underorphaned, image ids only (their chapter is missing, so they are outside the reading order and have no page number). It is outsideReadingOrder, so no?page=Nreaches it, but the model can still pass its image id toview_images. Before this branch such a page was simply absent from the output, which contradicted the tool's own promise to list ALL pages.## Chapterssection: what chapters are, thatget_doujinwithvariant_idlists them with page ranges, that the numbers are the reader's, and thatrename_chapteris the only chapter write the assistant has. The per-turn context's viewed-doujin block carries the chapter count too, since it sharesrenderDoujin.Verification
Executed:
scripts/verify.sh appfrom the worktree atca47bc8, after rebasing ontomain(4710662): submodule, pub get, codegen with no generated diff,flutter analyze"No issues found!",flutter test1119 passed,== verify OK (app) ==.Layers exercised: the tool's rendering and the prompt text, at the unit level (
app/test/agent_tools_test.dart,app/test/assistant_agent_test.dart). No Redux, REST, use-case or persistence code changed.Mutation probes, each applied to the committed tree, the relevant file run, then restored:
ReadingOrder.ofreplaced by a rawsortOrdersortorder.length→variant.pages.lengthp.chapterId != null && !chapterIds.contains(...)→p.chapterId != null- orphaned:## Chaptersremoved from the system promptassistant_contextvariant line reverted to the pre-branch formTwo review rounds ran over this branch. The first found five minors, including the dropped-page defect above; the second found that the new orphan filter's chapter-membership half and its explanatory label were themselves unpinned, which the last two commits close. 17 of 19 further mutations in the second round were already red, covering every arm of the chapter-count wording, the range rendering, both sorts and the ungrouped guard.
Unverified / confirmed by reading only:
?page=Nlands on the page the tool numbered was established by readingreader_sequence.dartandreader_page.dart(the sequence wrapsReadingOrder.of;initialPageNumber - 1indexes it), not by a UI test on this branch.chapter_id(ChapterConfiguration.cs). The handling exists so the tool's "all pages" promise holds regardless.Follow-ups
docs/BACKLOG.md, Assistant "Tool gaps", extended in place: the assistant reads chapters and their page ranges but still has no tool to create or delete a chapter, to reorder chapters (PUT /api/variants/{id}/chapters/reorderexists since #155 and only the editor calls it), or to move pages between chapters.Closes #142
🤖 Generated with Claude Code
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! The assistant finally understands chapters~ You took the one canonical flatten rule (
core/reading_order.dart), reused it verbatim instead of copying it a fifth time, and made every page number the tool prints be a number the reader actually opens. That is exactly the kind of boring, load-bearing correctness that makes my wings flutter ♡Verdict: ✅ Looks good to me~
I chased every claim in the PR body and they all held:
renderVariantconsumesReadingOrder.of, the same objectReaderSequencewraps, andreader_page.dart:291indexesinitialPageNumber - 1into it (clamped). So?page=Nthroughnavigatelands on the exact page the tool numbered, even when chapter order disagrees with rawsortOrder. Verified by reading the reader + navigate code, then pinned by your disagreeing-orders fixture._rangefirst..last contiguity — not an assumption, a construction guarantee:ReadingOrder.ofappends each chapter's pages consecutively, sopages.first.number..pages.last.numberis provably the chapter's range. The comment saying so is true ♪chapterId != null && !chapterIds.contains), not just non-null; orphans get no number (no number would open them — honest!), are sorted bysortOrder, listed as bare image ids, and the label explains why they carry no number so the model isn't invited to invent one. The old code silently dropped them, contradicting the tool's "ALL pages" promise. Good catch on your own round one.rename_chapteris the only chapter write — traced the fulldoujin_writeswitch (update_fields/add_title/update_title/remove_title/assign/remove/rename_chapter/set_cover);reorderChaptersexists on the repo since #155 and onlychapter_panel.dartcalls it. The system prompt's claim and the BACKLOG entry are both accurate.describeChapterCountis shared by both render sites (renderDoujinvariant lines + tool header); the otherpageCountsurfaces (editor tab, offline page, search tool) render no chapter data, so nothing drifted.no pages, renamable, no pair line) — pinned; ungrouped tail omitted when empty — pinned; chapterless variant saysno chapters, never "orphaned" — pinned.Mutation probes (my own, on the committed tree): 5/5 RED and directional —
ReadingOrder.of→ flat rawsortOrderorderorder.length→variant.pages.length_rangefirst/last swappedchapterId != nullonly## Chapterssection deleted from promptThe header counting the reading order (not raw rows) is the right call: in the orphan world the alternative would promise page numbers that don't exist, and the orphan test pins
2 pagesover 4 raw rows with all 4 image ids still visible.✅ What I liked~
ReadingOrderinstead of duplicating the rule — the fifth divergent copy is a bug that never got to be born~describeChapterCountextracted once for both call sites, with the wording (1 chapter/no chapters) pinned by test._doujinhelper's opt-invariantsparameter — minimal ripple, 1119 tests unaffected.Automated review by Jibril · 2026-09-19
CI/CD: pending for head
ca47bc8(run 695) · Local checks: flutter analyze 0 issues · full suite 1119/1119 passed (matches PR body) · 5/5 mutation probes redFlutter Coverage
Total: 84.1% (9492 of 11292)