Repository navigation
Conversation
…tion cursor Each inbox load reads one provider page per enumerated repository and continues from the `updated_on` boundary of the last row served. The continuation cursor is an HMAC-signed token bound to the workspace, and a load without usable continuation state starts from the first page. The merge keeps a bounded newest-first window, and the repository fan-out is capped by the same per-load request budget.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe incremental commit always issues a continuation when Assumptions: Files Reviewed (2 files)
Previous Review Summaries (9 snapshots, latest commit 15e6cde)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 15e6cde)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe empty-window hand-off is fixed and covered by a test, but the same cursor suppression still silently truncates the walk when a repository page advertises Assumptions: Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (2 files)
Fix these issues in Kilo Cloud Previous review (commit a74138a)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe incremental fix correctly gives each repository window its own ceiling, but the window transition is still gated on a non-null ceiling, so a workspace whose first window yields no orderable rows never reaches the remaining windows. Assumptions: Overview
Issue Details (click to expand)WARNING
Files Reviewed (2 files)
Fix these issues in Kilo Cloud Previous review (commit 82a35e8)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe new repository-window walk reuses the first window's Assumptions: Overview
Issue Details (click to expand)WARNING
Files Reviewed (2 files)
Fix these issues in Kilo Cloud Previous review (commit 55ac218)Status: 3 Issues Found | Recommendation: Address before merge Executive SummaryThe per-repository page-position redesign is logically sound, but the new 300-repository cap silently hides PRs from larger cached workspaces, and two smaller gaps remain around missing Assumptions: Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (3 files)
Fix these issues in Kilo Cloud Previous review (commit 7ff7b43)Status: No Issues Found | Recommendation: Merge Executive SummaryThe one-line Assumptions: Files Reviewed (2 files)
Previous WARNING (dangling page after an omitted Previous review (commit 26679ed)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe page-local continuation fixes the tied-row loss, but an omitted final-page Assumptions: Overview
Issue Details (click to expand)WARNING
Files Reviewed (2 files)
Previous review (commit f46f4de)Status: 2 Issues Found | Recommendation: Address before merge Executive SummaryThe signed cursor is correctly bound, bounded and wire-sized, but a boundary timestamp that fills more than one provider page can still permanently drop rows once another repository advances the global tie cursor. Assumptions: Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (3 files)
Previous review (commit 5619475)Status: No Issues Found | Recommendation: Merge Executive SummaryThe follow-up commit resolves the prior boundary-precision finding: the continuation cursor now carries the provider's own Files Reviewed (2 files)
Previous review (commit a8b1131)Status: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe signed-cursor rewrite of the Bitbucket inbox is sound in its top-K fan-out and token handling, but reformatting the Overview
Issue Details (click to expand)WARNING
Files Reviewed (2 files)
Reviewed by deepseek-flash-latest · Input: 58.1K · Output: 9.9K · Cached: 576.6K Review guidance: REVIEW.md from base branch |
The continuation cursor carries the provider's own `updated_on` string, so a later inbox page asks for rows at or below that exact value. The merge orders rows by the same sub-millisecond value, and the boundary comes from the last row in the window that has a parseable timestamp.
|
bot: Fixed in 5619475. The cursor now carries the provider's own Added |
|
Changes required before merge: the new signed inbox continuation has progress and wire-size gaps. At apps/web/src/lib/provider-review/bitbucket-read.ts:997, every continuation reads provider page one. Rows already served at the boundary are removed locally at line 1075. If a tied timestamp fills that provider page, the next request sees only already-served rows, produces no boundary, and returns no continuation despite unserved provider pages. Carrying only the previous window of served refs can also repeat tied rows across later inbox pages. The cursor also embeds a page of JSON-encoded reference keys at line 1110, while provider-review-router.ts:91 caps the received cursor at 2048 characters. A synthetic ordinary-reference payload already exceeds that bound before the signer adds its timestamp and nonce, so a server-issued cursor can fail the next tRPC request. Use a stable tie-breaking continuation that advances across provider pages and remains within an explicit receiving wire limit. Add equal-timestamp cases spanning provider and inbox pages, plus a maximum-size cursor round trip through the real router. |
…-inbox-paging # Conflicts: # apps/web/src/lib/provider-review/bitbucket-read.test.ts # apps/web/src/lib/provider-review/bitbucket-read.ts
…pages Every inbox load reads one provider page per integration repository. A continuation now advances a repository's provider page when the page holds only rows already served at the continuation boundary, so rows that share a timestamp across provider pages stay reachable. The merged order breaks timestamp ties by repository then pull-request id, so the continuation carries only the last served ref at its boundary instead of every ref at that boundary, and the per-repository page positions are packed two bytes each. A three-hundred-repository continuation is checked against the provider-review router's page-cursor limit.
|
bot: Addressed in
Evidence at head |
The continuation records, per repository, the provider page it is on and how many of that page's rows are served, instead of one cross-repository tie key. A repository whose page rows are all served moves to the next provider page in the same load, and a repository with nothing left at the boundary stops being read until the boundary changes, so rows that share a timestamp across pages stay reachable no matter which repository the merged order reaches last. The cursor carries two packed bytes per repository, and a 300-repository continuation stays within the provider-review router's page-cursor limit.
Bitbucket omits the next link entirely on the last page, so a repository is now paginated only while the link is present. Added a case where one repository's single-row last page carries no next link while another repository keeps paginating: the finished repository is not requested again, and the provider's page-not-found answer never reaches the inbox.
|
bot: Addressed in
Unit: 7 suites / 279 tests. |
…gone A cached repository the provider no longer serves, and a provider page an earlier load was promised for a collection that has since shrunk, now end that repository's walk instead of the whole inbox load. The load still serves every repository the provider answers for, and the repository stops appearing in later continuations.
A workspace whose cached repository set is larger than one cursor carries is now walked one window at a time, so every cached repository is served instead of the walk stopping at the first window. A provider row without a comparable timestamp is left out of the merged order instead of ending the walk before the rows behind it, and the omitted-next regression test now records provider requests so a page past a repository's last page fails it.
…tarts A repository window's rows are read for the first time when the walk reaches that window, so the previous window's newest timestamp cannot bound them: a pull request newer than it stayed outside the collection for the whole walk. Each window now starts without a ceiling, records the newest timestamp of its own first load, and filters later loads of that window with it.
…d nothing A window whose repositories the provider no longer serves, or whose pages are empty, produces no timestamp and therefore no ceiling. The walk now moves to the next repository window in that case, so the windows behind it are still read instead of the inbox ending at an empty slice.
The continuation carries the window's provider timestamp bound whenever the window has produced one. Where it has not, the next load reads the window without that bound, so the walk reaches every remaining provider page and every repository window behind it.
Evidence
Evidence: demonstrated — on this work VM,
providerReview.listInboxran end to end through the real Next.js server, real Postgres and the real tRPC router against one local stub answeringapi.bitbucket.org, with three cached repositories:acme/apispanning two provider pages,acme/widgetsholding one older row, andacme/gonethat the provider answers with404. The first load served 50 rows and issued a continuation; the continuation served the remaining 12 and ended; all 62 refs were distinct; and the stub observed one provider request per repository per load —page=1for all three repositories on the first load, thenpage=2foracme/apiandpage=1foracme/widgetsunder the continuation'supdated_onceiling.acme/gonewas read once, was not requested again, and did not stop the load: the other repositories' rows were served in both loads.Change
The Bitbucket review inbox pages with a signed continuation cursor and reads a bounded amount of provider work per load.
listInboxenumerates the integration's cached repositories (sorted) and reads at most one provider page per repository that still has rows.updated_onthe first load saw. Later loads ask forstate="OPEN" AND updated_on <= <ceiling>, so every pull request that existed when the walk started stays inside the collection, and one updated afterwards appears on a fresh inbox load.updated_on; a workspace larger than one window is served window by window rather than in one global merge.updated_onis left out of the merged order: it has no comparable position in the newest-first order or in a continuation, and leaving it out keeps the ceiling defined for every load that serves rows.nextCursoris issued only while some repository still has rows, and the response shape (items,nextCursor) is unchanged, so the web and mobile inboxes need no change.pageCursorlimit (2048 characters) even for a full window positioned past its first page;INBOX_CURSOR_MAX_CHARSnames that bound and a test pins it.Verification
All of the following ran on this VM at head
4e051d9df.pnpm --filter web exec jest --runInBand src/lib/provider-review src/routers/provider-review-router.test.ts— 7 suites, 285 tests passed.updated_on <= <ceiling>onpage=2and serves the remaining 10, then ends.updated_onfilter.404for every repository and the one behind it holds a row: the first load serves nothing and issues a continuation, the next load serves that row, and the walk ends.page=2and a returned cursor within the receiving limit.404: the load serves the other repositories' rows in full.nextlink: the walk ends there, and the recorded provider requests show no request past either repository's last page.pnpm --filter web typecheck(tsgo) passed on the same tree.forge-integration-e2eharness, run on this VM at head4e051d9df): 31/31 checks passed, against the real cloud dev stack (nextjson :3000, Postgres, tRPC), one stub serving the git-token-service broker,gitlab.com,api.bitbucket.organdapi.github.com. Provider paths observed:providerReview.listInbox(bitbucket) first load: 50 rows, each with its full ref; the stub sawGET /2.0/repositories/acme/api/pullrequests,GET /2.0/repositories/acme/gone/pullrequestsandGET /2.0/repositories/acme/widgets/pullrequests, all withpagelen=50,page=1,q=state="OPEN",sort=-updated_on.acme/goneanswered404and the load still returned rows.nextCursorwasnull; the stub sawGET /2.0/repositories/acme/api/pullrequestswithpage=2andq=state="OPEN" AND updated_on <= 2026-01-02T01:00:00Z, andGET /2.0/repositories/acme/widgets/pullrequestswithpage=1and the same ceiling.acme/gonewas not requested again.POST /api/webhooks/{gitlab,bitbucket/<integrationId>,github}all answered202; Postgres shows onecloud_agent_code_reviewsrow per provider (acme/apiSecurity - Fix npm audit vulnerabilities #12,acme/widgetsApp Builder - Unit and Integration tests #7,group/sub/repoApp Builder - Unit and Integration tests #7).Boundary. The E2E proves this repository's own code and contracts against provider-shaped responses; it does not prove a real Bitbucket workspace accepts these requests, because no owned workspace credentials exist on this work VM. Review-job dispatch and model calls stay best-effort (
CODE_REVIEW_WORKER_URLpoints at the stub), so no review is claimed to have run. Bitbucket write paths other than the top-level comment (merge, thread resolution, inline comments) were not exercised by this run. The change is server-side and has no visual surface, so there are no screenshots.Production prerequisites
None.
Proxy answers
The owner's proxy gave these answers in the owner's place.
Answer: Keyset + signed cursor (Recommended)
Confidence: 0.70 · Precedent: Fix the root cause and the class of the issue: session 7f3470e0ba6f, "fix class of issue preventing progress". Keyset paging makes the work per call flat at any depth, keeps the global ordering correct, and causes no product regression.
Answer: Keep 300 (Recommended)
Confidence: 0.60 · Precedent: Do the least work possible with no drop in quality: session 7f3470e0ba6f, "with no drop in quality". The cost per call becomes fixed and bounded at today's page-1 cost, and no workspace loses coverage.
Answer: Serve the first page (Recommended)
Confidence: 0.70 · Precedent: none
Answer: 1 hour (Recommended)
Confidence: 0.60 · Precedent: none
Answer: Remove it (Recommended)
Confidence: 0.75 · Precedent: Rip out obsolete limits instead of keeping them: session ad6a3f589364, "alongside? why not instead?". The depth cap no longer bounds any work under keyset paging.
Answer: Ship with the documented bound
Confidence: 0.72 · Precedent: Speed and least work: choose the simplest design that reaches the goal — session a30dc8dc131a, owner typed "Simplest please" instead of the recommended durable managed delivery
Answer: Rotate repository windows across pages
Confidence: 0.70 · Precedent: Choose the simplest design that reaches the goal (session 1f0202ee8c71: "What's the simplest solution that gets us to our goal?"). The goal is bounded work per call with no loss of coverage.