Skip to content

fix: add pagination support for recap trace list#596

Merged
anandgupta42 merged 5 commits intoAltimateAI:mainfrom
VJ-yadav:fix/recap-pagination
Apr 5, 2026
Merged

fix: add pagination support for recap trace list#596
anandgupta42 merged 5 commits intoAltimateAI:mainfrom
VJ-yadav:fix/recap-pagination

Conversation

@VJ-yadav
Copy link
Copy Markdown
Contributor

@VJ-yadav VJ-yadav commented Mar 30, 2026

Summary

Fixes #418 — recap pagination broken for large lists.

  • TUI dialog: removed hardcoded .slice(0, 50) cap so all traces are accessible via the dialog's built-in scrolling
  • CLI --offset option: added --offset flag to trace list command, enabling navigation past the first page
  • listTracesPaginated(): added paginated variant of listTraces() that returns { traces, total, offset, limit } metadata, used by the CLI handler
  • Pagination footer: CLI output now shows "Showing X-Y of N" with a next-page hint when more results exist
  • Empty page clarity: offset-past-end now says "No traces on this page (offset N past end of M traces)" instead of the misleading "No traces found"

Test Plan

  • altimate-code trace list — shows first 20 traces with "Showing 1-20 of N" footer
  • altimate-code trace list --limit 5 — shows 5 traces with next-page hint
  • altimate-code trace list --offset 5 --limit 5 — shows traces 6-10
  • altimate-code trace list --offset 9999 — shows "offset past end" message, not "No traces found"
  • altimate-code trace list with 0 traces — shows "No traces found" with setup hint
  • TUI trace dialog — can scroll through all traces (no 50-item cap)
  • altimate-code trace view <bad-id> — fallback list shows pagination metadata

Checklist

Summary by CodeRabbit

  • New Features
    • Added pagination for trace listing with configurable offset and limit.
    • Listing output shows pagination summary ("Showing X–Y of total") and prints a suggested next-page command when more results exist.
    • Added a CLI option to set offset for paginated trace navigation.
    • Trace selection dialog now shows all available traces instead of truncating the list.

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@github-actions
Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

Warning

Rate limit exceeded

@anandgupta42 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 24 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 7 minutes and 24 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c93c201e-c9b8-45ab-b665-b7cc85e9c5b7

📥 Commits

Reviewing files that changed from the base of the PR and between dbfa95f and 87562bf.

📒 Files selected for processing (4)
  • packages/opencode/src/altimate/observability/tracing.ts
  • packages/opencode/src/cli/cmd/trace.ts
  • packages/opencode/src/cli/cmd/tui/component/dialog-trace-list.tsx
  • packages/opencode/test/altimate/tracing.test.ts
📝 Walkthrough

Walkthrough

Added paginated trace listing: new Trace.listTracesPaginated(dir?, options?) returns a slice plus total/offset/limit; CLI trace list gained --offset and prints pagination ranges/next-page hint; TUI trace dialog no longer truncates results to 50 items.

Changes

Cohort / File(s) Summary
Core Pagination Support
packages/opencode/src/altimate/observability/tracing.ts
Added Trace.listTracesPaginated() returning { traces, total, offset, limit }. Normalizes/clamps offset and limit, delegates data retrieval to existing Trace.listTraces().
CLI Pagination Integration
packages/opencode/src/cli/cmd/trace.ts
trace list now accepts --offset and --limit, calls listTracesPaginated(), distinguishes empty total vs. empty page, prints "Showing X–Y of N" and a Next page hint. listTraces() signature updated to accept pagination metadata.
TUI Display Limit Removal
packages/opencode/src/cli/cmd/tui/component/dialog-trace-list.tsx
Removed hardcoded items.slice(0, 50) so dialog builds options from all returned items instead of truncating to first 50.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant CLI as "CLI: trace list"
  participant Trace as "Trace.listTracesPaginated"
  participant Store as "Filesystem / Trace.listTraces"

  User->>CLI: run `trace list --offset N --limit M`
  CLI->>Trace: listTracesPaginated(dir, {offset:N, limit:M})
  Trace->>Store: listTraces(dir) (reads files / parses JSON)
  Store-->>Trace: full trace array (or [] on failure)
  Trace-->>CLI: { traces: slice(offset, limit), total, offset, limit }
  CLI->>CLI: render header, items, footer ("Showing X–Y of total"), next-page hint
  CLI-->>User: paginated listing output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

contributor

Poem

🐰
Hopping through traces wide and neat,
Pages and offsets set the beat.
No fifty-limit in my trail,
Next-page carrots mark the trail.
I celebrate each paged repeat. 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is comprehensive but does not include the required 'PINEAPPLE' word at the top as mandated by the template for AI-generated contributions. Add 'PINEAPPLE' at the very top of the PR description before any other content, as required by the repository template for AI-generated contributions.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix: add pagination support for recap trace list' clearly and concisely summarizes the main change—adding pagination support to the trace list functionality.
Linked Issues check ✅ Passed All four coding objectives from issue #418 are addressed: TUI dialog cap removed, CLI --offset option added, listTracesPaginated() API implemented with metadata, and empty-page messaging improved.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the pagination objectives in #418. The modifications to tracing.ts, trace.ts, and dialog-trace-list.tsx focus exclusively on pagination support without introducing unrelated functionality.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/altimate/observability/tracing.ts`:
- Around line 999-1005: The returned pagination metadata may include NaN,
fractional or infinite values for offset/limit; update the logic that computes
offset and limit in tracing.ts to first coerce inputs to finite integers (use
Number.isFinite and Math.trunc), fall back to the existing defaults (0 for
offset, 20 for limit), then clamp with Math.max(0, offset) and Math.max(1,
limit) before using them for slice and returning them in the response (refer to
the offset and limit variables used in this block).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b341b9b3-16f3-4876-977b-f1b4c8a4f3fd

📥 Commits

Reviewing files that changed from the base of the PR and between 99270e5 and 28bd42b.

📒 Files selected for processing (3)
  • packages/opencode/src/altimate/observability/tracing.ts
  • packages/opencode/src/cli/cmd/trace.ts
  • packages/opencode/src/cli/cmd/tui/component/dialog-trace-list.tsx

@VJ-yadav VJ-yadav force-pushed the fix/recap-pagination branch from a7968fc to b018d62 Compare April 3, 2026 06:11
@dev-punia-altimate
Copy link
Copy Markdown

❌ Tests — Failures Detected

TypeScript — 15 failure(s)

  • connection_refused [2.48ms]
  • timeout [2.37ms]
  • permission_denied [2.51ms]
  • parse_error [2.22ms]
  • oom [2.52ms]
  • network_error [2.33ms]
  • auth_failure [2.50ms]
  • rate_limit [2.65ms]
  • internal_error [2.71ms]
  • empty_error [0.24ms]
  • connection_refused [0.14ms]
  • timeout [0.07ms]
  • permission_denied [0.07ms]
  • parse_error [0.06ms]
  • oom [0.07ms]

cc @VJ-yadav
Tested at b018d629 | Run log | Powered by QA Autopilot

@anandgupta42
Copy link
Copy Markdown
Contributor

Review — Ready after rebase

Scope: Fixes #418 — recap pagination broken for large lists. All 4 subtasks in the issue are addressed.

Analysis

  • dialog-trace-list.tsx — removes hardcoded .slice(0, 50) (legit bug, TUI dialog has its own scrolling)
  • trace.ts — adds --offset CLI flag + "Showing X-Y of N" footer + next-page hint
  • tracing.ts — new listTracesPaginated() returns { traces, total, offset, limit } metadata. Clamps offset/limit to safe values
  • "No traces on this page (offset N past end of M traces)" message is a real UX improvement over the misleading "No traces found"
  • Defaults unchanged → no behavior break for existing scripts/users

Files changed (3): observability/tracing.ts, cli/cmd/trace.ts, dialog-trace-list.tsx (+57, -8)

CI status (commit b018d629)

  • ⚠️ Only 3 checks rancheck-standards, check-compliance, GitGuardian. Missing: TypeScript, Marker Guard, anti-slop, Driver E2E
  • This PR is ~1 week behind main — TypeScript/Marker Guard workflows were likely added/tightened after branch creation. A rebase will retrigger the full CI suite
  • centralized-test-results shows the same flaky 15-failure set as every other open PR in this batch — pre-existing infra noise

Recommendation
Ready for merge pending rebase + full CI pass. After rebase, confirm Marker Guard is clean — tracing.ts is in altimate/observability/ so it should be ours, but verify. No code changes requested.

cc @anandgupta42 — rebase and re-run CI; if green, ready for /release.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/cli/cmd/trace.ts`:
- Around line 171-174: Replace the logical-OR fallbacks for pagination with
nullish coalescing so explicit zeros are preserved: in the call to
Trace.listTracesPaginated (the invocation using tracesDir and the args object),
change args.offset || 0 and args.limit || 20 to args.offset ?? 0 and args.limit
?? 20 so that a provided 0 is passed through to listTracesPaginated (which
performs validation/clamping).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a9e48842-6741-4a1e-9e40-fe5417610e8f

📥 Commits

Reviewing files that changed from the base of the PR and between 28bd42b and dbfa95f.

📒 Files selected for processing (3)
  • packages/opencode/src/altimate/observability/tracing.ts
  • packages/opencode/src/cli/cmd/trace.ts
  • packages/opencode/src/cli/cmd/tui/component/dialog-trace-list.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/opencode/src/cli/cmd/tui/component/dialog-trace-list.tsx
  • packages/opencode/src/altimate/observability/tracing.ts

VJ-yadav and others added 2 commits April 4, 2026 23:40
- Add `listTracesPaginated()` method to Trace class returning page of
  traces with total count, offset, and limit metadata
- Add `--offset` CLI option to `trace list` command for navigating
  past the first page of results
- Wire CLI handler to use `listTracesPaginated()` instead of manual
  array slicing
- Remove hardcoded `.slice(0, 50)` cap in TUI dialog so all traces
  are accessible via built-in scrolling
- Show "Showing X-Y of N" pagination footer with next-page hint
- Distinguish empty results (no traces exist) from offset-past-end
  (offset exceeds total count) with clear messaging

Closes AltimateAI#418

Co-Authored-By: Vijay Yadav <vijay@studentsucceed.com>
Coerce offset/limit to finite integers via Number.isFinite and
Math.trunc before using them for slice and returning in metadata.
Prevents NaN, fractional, or infinite values from producing invalid
display ranges.

Co-Authored-By: Vijay Yadav <vijay@studentsucceed.com>
@anandgupta42 anandgupta42 force-pushed the fix/recap-pagination branch from dbfa95f to b30e7d4 Compare April 5, 2026 06:41
Code review (GPT + Gemini) flagged two follow-ups:

1. TUI freeze risk after removing .slice(0, 50) — DialogSelect creates
   reactive nodes per item via Solid's <For>, so unbounded rendering
   can lag noticeably on trace directories with thousands of entries.
2. listTracesPaginated had no unit tests for boundary math.

Fixes:
- Cap dialog-trace-list at MAX_TUI_ITEMS=500 with an explicit '... N
  more not shown' footer row pointing users to 'altimate-code trace
  list --offset N' for the full set. 500 is 10× the old cap and
  covers the vast majority of real usage, while leaving TUI rendering
  bounded. The onSelect handler ignores the truncation marker row.
- Add 10 listTracesPaginated regression tests covering: empty dir,
  bounded page size, multi-page traversal, offset === total, offset
  > total, negative offset clamping, non-positive limit clamping,
  fractional truncation, NaN → default fallback, and default options.

The I/O-layer optimization (slice filenames before JSON.parse) called
out by Gemini is a separate perf concern that requires embedding
timestamps in trace filenames; tracked as a follow-up.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/opencode/test/altimate/tracing.test.ts">

<violation number="1" location="packages/opencode/test/altimate/tracing.test.ts:746">
P2: Reusing a single `Trace` instance across multiple `startTrace`/`endTrace` cycles causes spans to accumulate — each successive trace file will contain all spans from earlier iterations. Create a new tracer per iteration, matching the pattern used elsewhere in this file (line ~706).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

@anandgupta42
Copy link
Copy Markdown
Contributor

Consensus code-review applied — fixes pushed

Ran a 4-participant consensus review (Claude + GPT 5.4 + Gemini 3.1 Pro + self-review).

Findings and actions

Finding 1 — TUI freeze risk from uncapped list (both models, MAJOR)
Fixed: Cap dialog-trace-list.tsx at MAX_TUI_ITEMS=500 with an explicit "... N more not shown" footer row. The onSelect handler ignores the truncation marker. 500 is 10× the old cap — covers the vast majority of real usage while keeping Solid's <For> reactive-node count bounded. Users with >500 traces can use altimate-code trace list --offset N from the CLI to navigate the full set.

Finding 2 — No unit tests for listTracesPaginated boundary math (both models, MAJOR)
Fixed: Added 10 regression tests covering empty dir, bounded page size, multi-page traversal, offset === total, offset > total, negative-offset clamping, non-positive limit clamping, fractional truncation, NaN → default fallback, and default options. All pass.

Finding 3 — "Fake pagination" at I/O layer (both models, CRITICAL/MAJOR)
🔧 Deferred as follow-up: listTracesPaginated currently slices in memory after reading all trace files. True I/O-layer pagination would require either embedding timestamps in filenames (trace file-naming convention change) or fs.stat-ing every file for mtime (which just moves the I/O cost). Both options are a scope expansion beyond issue #418's stated CLI/TUI UX fix. Tracked as a follow-up — current behavior is no worse than pre-PR (which also hydrated the full list for the TUI).

Finding 4 — CLI input validation (both models, MINOR)
Already handled by normalize pagination inputs to finite integers commit b30e7d4823 in this PR (negative/fractional/NaN inputs clamp to safe defaults).

Test coverage

All 75 tracing tests pass (65 pre-existing + 10 new). TypeScript clean. All CI green.

Pushed as 9cf3d54715. Ready for merge.

anandgupta42 and others added 2 commits April 5, 2026 07:27
- trace.ts:172-173 (coderabbit): switch pagination fallbacks from || to ??
  so an explicit --offset 0 / --limit 0 reaches listTracesPaginated() for
  clamping, rather than being swallowed as falsy and replaced with
  defaults. The API already clamps limit<1 to 1, so --limit 0 now
  routes through that clamp path correctly.

- tracing.test.ts:746 (cubic): create a fresh Trace instance per
  iteration inside seedTraces() rather than reusing a single tracer.
  Reusing a tracer across startTrace/endTrace cycles accumulates
  spans in memory across iterations. Matches the pattern used by
  the maxFiles test.
@anandgupta42 anandgupta42 merged commit b66d9f5 into AltimateAI:main Apr 5, 2026
13 checks passed
@anandgupta42
Copy link
Copy Markdown
Contributor

E2E verification complete

Ran end-to-end CLI scenarios against a real seeded traces directory (15 traces) and visually inspected the TUI dialog options at multiple scales. All verified.

CLI e2e — seeded 15 traces in /tmp/e2e-traces

Scenario Command Output
Default trace list Shows 1-15 of 15, no next-page hint ✓
Limit=5 trace list --limit 5 Shows 1-5 of 15 + Next page: --offset 5 --limit 5
Middle page trace list --offset 5 --limit 5 Shows 6-10 of 15 + next-page hint ✓
Last page trace list --offset 10 --limit 5 Shows 11-15 of 15, no next-page hint ✓
Past end trace list --offset 9999 No traces on this page (offset 9999 past end of 15 traces) + Try: --offset 0 --limit 5
Negative offset --offset -5 --limit 3 Clamped to offset=0, shows 1-3 ✓
Zero limit --limit 0 Clamped to limit=1, shows 1-1 ✓
Fractional --offset 2.9 --limit 3.7 Truncated to offset=2 limit=3, shows 3-5 ✓

The ?? fix (nullish coalescing) preserves explicit 0 values correctly: --limit 0 reaches the API's clamp-to-1 path rather than being promoted to the 20 default.

TUI visual inspection — dialog options at multiple scales

Replicated the options() memo from dialog-trace-list.tsx with fake trace data and rendered what the dialog would show:

Trace count Rows rendered Truncation marker Rationale
0 0 Empty state ✓
10 10 Under cap, all visible ✓
500 (exactly at cap) 500 no Edge-case: cap unreached ✓
501 501 (500 + marker) ... 1 more not shown Just-over-cap triggers marker ✓
600 501 (500 + marker) ... 100 more not shown + Showing 500 of 600 — use CLI --offset to navigate Gemini's freeze-risk scenario ✓
5000 501 (500 + marker) ... 4500 more not shown Extreme case — saves 4500 reactive nodes ✓

Marker row specifics:

  • title: "... N more not shown"
  • category: "Older" (groups below date categories)
  • footer: "Showing 500 of <total> — use CLI --offset to navigate"
  • value: "__truncated__" — onSelect handler explicitly no-ops on this value
  • Error/crashed trace statuses render with [error] / [crashed] prefixes ✓

What's covered now

  1. 10 unit testslistTracesPaginated boundary math
  2. 8 CLI e2e scenarios — verified against real seeded traces
  3. 6 TUI scale scenarios — verified against fake data at 0/10/500/501/600/5000 items
  4. Status badge rendering — verified [error] prefix
  5. TypeScript + all existing tracing tests — green

All CI checks CLEAN. Ready for merge.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: recap pagination broken for large lists

3 participants