Skip to content

pm list: --output-limit trims a --limit page but next_cursor still points after the producer page, so following it silently skips rows #1420

Description

@unbraind

Problem

When --output-limit trims a page that a producer --limit already cut, next_cursor still points after the last row of the producer page, not after the last row actually delivered. An agent that follows the advertised cursor silently loses every row between the two limits. No error, no has_more signal for the gap.

Reproduced on @unbrained/pm-cli 2026.10.6 (and 2026.10.5) with 70 open items:

pm list --json --limit 50 --output-limit 30 --output-budget unbounded > p1.json
jq '.items|length, .items[-1].id' p1.json                         # 30, "demo-0007"  (row index 29)
jq -r .next_cursor p1.json | base64 -d                            # {"after_id":"demo-0038","after_index":49}
pm list --json --limit 50 --after "$(jq -r .next_cursor p1.json)" --output-budget unbounded \
  | jq '.items[0].id'                                             # "demo-0043" (row index 50)

Rows 30–49 (demo-0012 … demo-0038) are never returned by any page. #1411 fixed the stale-replay case where --output-limit and --output-budget both cut rows. This simpler combination, a producer --limit plus an --output-limit trim, still advertises the producer cursor.

Why it matters

--output-limit is the token-saving control agents are told to use, and following next_cursor is the documented way to page. The combination drops data silently. That is worse than a refusal: an agent doing triage or a sweep ("close every stale item") believes it saw everything.

Expected

  • When an output ceiling (--output-limit or --output-budget) removes rows from a producer page, rebase next_cursor to the last delivered row (after_id = that row, after_index = the producer page's start index + delivered count − 1), exactly as the read-output budget path already does for its own truncation.
  • Or, if the producer cursor is intentionally kept, refuse the trim with an explicit receipt that names the undelivered range and how to fetch it.
  • A regression test that walks every page under --limit N --output-limit M (M < N) and asserts the union of delivered ids equals the full result set, in order, without duplicates.

(Found while keeping the native Rust port, pm-rust, byte-identical to the published CLI: the port reproduces this exactly, so it is fixed upstream first and mirrored after.)

No activity

Activity on this issue will appear here.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions