Idea
jira issue list --json returns a bare array, so a machine consumer cannot tell a complete result from a truncated one. Fifty objects come back whether there were fifty or nine hundred. Emit a truncation signal out of band — a stderr line and a distinct exit code — without changing any JSON shape.
Why
A caller capped this query, got a full page back, and had no way to know rows were missing. Downstream that turned into a silent layout bug rather than a visible error: the consumer rendered a perfectly ordinary-looking result that was quietly incomplete.
The default of 50 is not the defect — it is a sensible default for a human at a terminal. The defect is that the JSON gives a program no way to ask "was that all of it?".
Context
src/commands/issue.ts:87 — .option("-n, --limit <n>", "maximum issues to return", "50"). Same default on search in src/commands/misc.ts:13. Both end in printJson(issues) on a bare array.
@kud/jira src/client.ts:156 — searchIssues is honest: const limit = opts.limit ?? 50, pages at Math.min(100, limit - issues.length), three stop conditions, slice(0, limit). So --limit N genuinely fetches N. The library is not the problem.
src/types.ts:84 — JiraSearchPage is { issues, nextPageToken?, isLast? } with no total. That matches Jira's newer /search/jql, which dropped total counts. So "50 of 900" is not buildable — only "there is more" is. Any design promising a count cannot ship.
searchIssues has three call sites, all inside this CLI (issue.ts:92, misc.ts:17, tui/data.ts:61 — that last one passes limit: 200), plus the library's own tests. No external consumers found.
Direction
Minimum honest fix — a stderr warning plus a distinct exit code when issues.length === limit, in issue.ts and misc.ts. No library change, no shape change, byte-identical JSON. Callers that already read exit code and stdout as separate channels consume it with a two-line change. False-positive only on an exact boundary, which is the right side to err on.
Fuller fix, if it earns it — the knowledge exists at the exact moment it is discarded: when searchIssues' while loop exits on its own condition, page.nextPageToken was live and page.isLast was false. Capture it additively — a second export searchIssuesPage(jql, opts): Promise<{ issues, truncated }>, with searchIssues reimplemented as a one-line wrapper returning .issues. Existing contract and tests untouched, minor version.
Explicitly rejected, with reasons — do not reach for these:
--all / --limit 0. Looks the most helpful and is the worst. It hands an unbounded pagination loop to a corporate Atlassian behind a VPN, inside callers that wrap this in a timeout — turning a fast degradation into a hang. And it does not fix the defect anyway: an exhausted result is still a bare array with no signal. It moves the failure from silently wrong to silently slow.
- Changing
searchIssues' return type to { issues, truncated }. A breaking change to a published library, breaking three call sites and every test in client.test.ts, to carry one boolean.
- Changing
printJson's shape. Breaks every existing --json consumer.
Check
jira issue list -q "<a query with more results than the limit>" -n 5 --json prints five objects on stdout, a warning on stderr, and exits non-zero-but-distinct.
- The same command under the limit exits 0 with nothing on stderr.
- Existing
--json consumers parse identically in both cases.
Idea
jira issue list --jsonreturns a bare array, so a machine consumer cannot tell a complete result from a truncated one. Fifty objects come back whether there were fifty or nine hundred. Emit a truncation signal out of band — a stderr line and a distinct exit code — without changing any JSON shape.Why
A caller capped this query, got a full page back, and had no way to know rows were missing. Downstream that turned into a silent layout bug rather than a visible error: the consumer rendered a perfectly ordinary-looking result that was quietly incomplete.
The default of
50is not the defect — it is a sensible default for a human at a terminal. The defect is that the JSON gives a program no way to ask "was that all of it?".Context
src/commands/issue.ts:87—.option("-n, --limit <n>", "maximum issues to return", "50"). Same default onsearchinsrc/commands/misc.ts:13. Both end inprintJson(issues)on a bare array.@kud/jirasrc/client.ts:156—searchIssuesis honest:const limit = opts.limit ?? 50, pages atMath.min(100, limit - issues.length), three stop conditions,slice(0, limit). So--limit Ngenuinely fetches N. The library is not the problem.src/types.ts:84—JiraSearchPageis{ issues, nextPageToken?, isLast? }with nototal. That matches Jira's newer/search/jql, which dropped total counts. So "50 of 900" is not buildable — only "there is more" is. Any design promising a count cannot ship.searchIssueshas three call sites, all inside this CLI (issue.ts:92,misc.ts:17,tui/data.ts:61— that last one passeslimit: 200), plus the library's own tests. No external consumers found.Direction
Minimum honest fix — a stderr warning plus a distinct exit code when
issues.length === limit, inissue.tsandmisc.ts. No library change, no shape change, byte-identical JSON. Callers that already read exit code and stdout as separate channels consume it with a two-line change. False-positive only on an exact boundary, which is the right side to err on.Fuller fix, if it earns it — the knowledge exists at the exact moment it is discarded: when
searchIssues'whileloop exits on its own condition,page.nextPageTokenwas live andpage.isLastwas false. Capture it additively — a second exportsearchIssuesPage(jql, opts): Promise<{ issues, truncated }>, withsearchIssuesreimplemented as a one-line wrapper returning.issues. Existing contract and tests untouched, minor version.Explicitly rejected, with reasons — do not reach for these:
--all/--limit 0. Looks the most helpful and is the worst. It hands an unbounded pagination loop to a corporate Atlassian behind a VPN, inside callers that wrap this in a timeout — turning a fast degradation into a hang. And it does not fix the defect anyway: an exhausted result is still a bare array with no signal. It moves the failure from silently wrong to silently slow.searchIssues' return type to{ issues, truncated }. A breaking change to a published library, breaking three call sites and every test inclient.test.ts, to carry one boolean.printJson's shape. Breaks every existing--jsonconsumer.Check
jira issue list -q "<a query with more results than the limit>" -n 5 --jsonprints five objects on stdout, a warning on stderr, and exits non-zero-but-distinct.--jsonconsumers parse identically in both cases.