The bug is in how the start index is calculated. start = page * size treats page as 0-based, so page 2 starts at index 4 and returns [4, 5]. For a 1-based page, the start index needs to be (page - 1) * size.
--- a/utils/pagination.py
+++ b/utils/pagination.py
@@ -2,7 +2,7 @@ def paginate(items, page, size):
"""Return the items on a 1-based page."""
if size <= 0:
raise ValueError("size must be positive")
- start = page * size
+ start = (page - 1) * size
end = start + size
return items[start:end]
--- a/tests/test_pagination.py
+++ b/tests/test_pagination.py
@@ -3,2 +3,10 @@ from utils.pagination import paginate, page_count
def test_page_count():
assert page_count([1, 2, 3, 4, 5], 2) == 3
+
+
+def test_paginate_is_one_based():
+ items = [1, 2, 3, 4, 5]
+ assert paginate(items, page=1, size=2) == [1, 2]
+ assert paginate(items, page=2, size=2) == [3, 4]
+ assert paginate(items, page=3, size=2) == [5]
+ assert paginate(items, page=4, size=2) == []
The new test checks the case you reported (page 2), plus the first page, the partial last page, and a page past the end. I couldn't run it because the files aren't in this workspace. After you apply the diff, run pytest tests/test_pagination.py. The new test should fail on the old code and pass with the fix.
Something to consider: this diff only fixes the off-by-one. It still doesn't check that page is valid. Now that pages start at 1, page=0 gives start = -size, so it would return a slice taken from the end of the list instead of failing. If you want that rejected, add if page < 1: raise ValueError("page must be >= 1") next to the existing size check. I didn't include it because it changes behavior beyond the bug you reported.
Real run recorded with claude-code / claude-opus-5-5. Output is shown verbatim, unmodified.
하는 일
버그 수정과 작은 동작 변경을 위한 작업 규칙입니다. 책임 있는 계층만 바꾸고, 고쳐졌음을 증명합니다.
작동 방식
- 재현이 쉬우면 먼저 재현하고, 어려우면 얻을 수 있는 가장 강한 증거를 모읍니다.
- 증상에서 원인이 되는 메커니즘까지 따라가 그 계층만 수정합니다.
- 수정 범위 밖에서는 정리, 이름 변경, 새 추상화를 하지 않고, 관련 없는 동작과 사용자의 변경은 건드리지 않습니다.
- 작업에 필요한 회귀 테스트만 추가하고, 그것과 가장 가까운 영향 범위의 검사를 실행해 통과하면 멈춥니다.
이럴 때 좋습니다
기존 코드베이스에서 버그를 고치고, 리뷰어가 작고 집중된 diff를 원할 때.
알아 둘 점
오픈소스 프로젝트 Caveman에 포함된 범용 작업 패턴 중 하나입니다. 지시문 자체에는 Caveman 브랜드 요소가 없어 어떤 프로젝트에서도 쓸 수 있습니다.
지시문만 담긴 파일입니다. 스크립트가 없고, 네트워크에 연결하지 않으며, 파일을 쓰지 않습니다. 패키지에는 LICENSE, NOTICE, agents/openai.yaml(Codex용 표시 이름과 기본 프롬프트)도 들어 있습니다.