Skip to content

fix(jtk): auto-paginate search/list past Jira's 100-result page cap#182

Merged
rianjs merged 2 commits intomainfrom
fix/jtk-search-auto-paginate
Mar 15, 2026
Merged

fix(jtk): auto-paginate search/list past Jira's 100-result page cap#182
rianjs merged 2 commits intomainfrom
fix/jtk-search-auto-paginate

Conversation

@rianjs
Copy link
Copy Markdown
Contributor

@rianjs rianjs commented Mar 15, 2026

Closes #181

Summary

  • SearchPage now auto-paginates when MaxResults exceeds the per-request page size, looping internally with cursor-based tokens
  • --max flag semantics change from "page size" to "max total results" (non-breaking: values ≤ 100 behave identically)
  • Internal page size capped at min(maxResults, 100) for efficient fetching
  • --next-page-token still works as a starting point for the pagination loop
  • New Total field in PaginationInfo reports actual result count in JSON output
  • Removes unused SearchAll method (superseded by SearchPage with MaxResults)

Test plan

  • API-layer: multi-page pagination collects all results
  • API-layer: stops at MaxResults when more pages exist
  • API-layer: trims overshoot when last page exceeds limit
  • API-layer: passes fields on every page request
  • API-layer: respects --next-page-token as starting point
  • API-layer: cancelled context returns error
  • API-layer: error mid-pagination propagates
  • API-layer: page size capped at 100
  • API-layer: single-page mode unchanged
  • Command-layer: runSearch auto-pagination JSON output
  • Command-layer: runList auto-pagination JSON output
  • All existing tests pass
  • Manual: jtk issues search --jql '...' -o json --max 200 | jq '.issues | length'

…181)

SearchPage now loops internally when MaxResults exceeds the per-request
page size, accumulating results across pages. The --max flag means
"max total results" instead of "page size." Removes unused SearchAll
method (superseded by SearchPage with MaxResults).
Copy link
Copy Markdown

@monit-reviewer monit-reviewer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: f16d18a

Summary

No issues found.


Completed in 47s | $0.19 | sonnet
Field Value
Model sonnet
Reviewers hybrid-synthesis, security:code-auditor
Reviewed by pr-review-daemon · monit-pr-reviewer
Duration 47s (Reviewers: 45s · Synthesis: 4s)
Cost $0.19
Tokens 93.0k in / 2.5k out
Turns 6

@rianjs
Copy link
Copy Markdown
Contributor Author

rianjs commented Mar 15, 2026

TDD Coverage Assessment

All 19 new tests pass and the full suite is green. The coverage is genuinely good for the core pagination loop, but there are a handful of gaps worth noting before merge.

What is well covered

  • Multi-page happy path with token chaining verified (correct token forwarded on page 2)
  • Stops at MaxResults when the API has more (2 requests, no 3rd)
  • Overshoot trimming (75-issue pages, MaxResults=100, final slice is exactly 100)
  • Fields propagated on every page request
  • Page size capped at 100 wire-level (PageSize: 200 → request sees ≤ 100)
  • Context cancellation before first request
  • Error propagation mid-pagination
  • Single-page default mode (MaxResults=0)
  • Command-layer integration for both search and list (JSON output, multi-page)

Gaps

1. Page-size cap in single-page mode is untested

TestSearchPage_PageSizeCappedAt100 passes MaxResults=500, PageSize=200. After capping pageSize to 100, maxResults > pageSize, so the test falls into the multi-page path. The single-page branch (maxResults <= pageSize) with an oversized PageSize is never exercised. Example: MaxResults=50, PageSize=200 — the cap applies but no test verifies the wire request uses 50, not 200.

2. isLast=false / NextPageToken semantics after a trim are ambiguous and untested

When the last page overshoots and we trim, the code sets isLast = false and leaves nextToken pointing to whatever the API returned for the page after the one that overshot. A consumer cannot use that token to resume from the trim point — it resumes from the wrong offset. The test for overshoot (TrimsOvershoot) only checks len(result.Issues) == 100 and IsLast == false; it does not assert what NextPageToken contains or whether it is usable. This is worth either documenting clearly or testing the consumer-visible contract.

3. Starting token with multi-page continuation

TestSearchPage_AutoPagination_WithNextPageToken passes NextPageToken: "starthere" and MaxResults: 200, but the server returns IsLast: true on the first page (only 50 issues). So the loop exits after one request. There is no test where a non-empty starting token is used and then the loop makes a second request with the API-returned continuation token.

4. Empty result set in multi-page mode

No test covers MaxResults=200 when the API returns zero issues on the first request. The len(result.Issues) == 0 branch in the loop sets isLast=true and breaks — this should work, but it is untested.

5. Table output with auto-pagination (minor)

The two command-layer tests only use output: "json". The "More results available (use --next-page-token...)" footer rendered in table mode when !IsLast is not tested. Not a correctness gap (the logic is trivial), but the happy-path table render with paginated results has no coverage.

Verdict

The core pagination algorithm is well-tested — the loop, stopping condition, trim, and error paths are all covered. The gaps above are real but they are on edge cases and post-trim semantics rather than the main contract. The change is safe to merge as-is. If you want to close the gaps, priority order would be: (2) → (3) → (1) → (4) → (5).

@rianjs rianjs merged commit d245273 into main Mar 15, 2026
7 checks passed
@rianjs rianjs deleted the fix/jtk-search-auto-paginate branch March 15, 2026 09:55
rianjs added a commit that referenced this pull request Mar 28, 2026
Catches up documentation for recent features and fixes:
- README: document --fields flag, auto-pagination, fields command group,
  users get subcommand, --assignee none, multi-value --field, and
  escape sequences in comment --body
- CHANGELOG: add entries for PRs #178, #180, #182, #186-189
- integration-tests: add test cases for auto-pagination, --fields,
  users get, --assignee none, multi-value --field, and escape sequences

Closes #183
rianjs added a commit that referenced this pull request Mar 28, 2026
#190)

Catches up documentation for recent features and fixes:
- README: document --fields flag, auto-pagination, fields command group,
  users get subcommand, --assignee none, multi-value --field, and
  escape sequences in comment --body
- CHANGELOG: add entries for PRs #178, #180, #182, #186-189
- integration-tests: add test cases for auto-pagination, --fields,
  users get, --assignee none, multi-value --field, and escape sequences

Closes #183
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(jtk): issues search does not auto-paginate past first page

2 participants