Repository navigation
fix(cloud-agent): report partial Bitbucket branch listings - #8537
Conversation
The Bitbucket branch listing walks at most 20 pages of refs. When the provider still returns a next cursor after that, the listing returned the pages it had collected as if they were the repository's whole branch set. Return a `truncated` flag on the listing contract (false for GitHub and GitLab, whose walks page to completion), set it when the page budget ends the walk with a cursor remaining, and keep the repository default branch in the returned list so a partial walk still offers the branch the session checks out. The mobile new-session branch row and picker sheet show a note when the listing is partial, translated in every locale.
|
bot: Android emulator against the local dev stack, owned fake account in a test organization whose Bitbucket fixture keeps serving another page past the listing bound. Observed on the new-session form: the branch row preselects and marks the fixture default branch, and the partial-list note renders under it. Observed in the branch picker sheet: the same note renders above the rows rather than after them, and the fixture default branch is the first row even though the paged result never listed it. |
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe Bitbucket page-budget truncation flag, default-branch prepend, contract change, and mobile partial-list notice are correct and consistently propagated; no defects found in the 98 changed files. Assumptions: Files Reviewed (98 files)
Reviewed by deepseek-flash-latest · Input: 88.5K · Output: 18K · Cached: 1.7M Review guidance: REVIEW.md from base branch |
|
bot: Follow-up review found no actionable remarks. The head has passing CI and human approval; the required evidence header is now published. Shared judge requests temporarily received HTTP 429 responses. Gateway logs show WAF throttling on the SystemOne path, and a later response matches the gateway account-rate limiter; these responses do not indicate a spend cap. After cooldown, a neutral diagnostic classification and the gated evidence update succeeded. Durable infrastructure recovery remains external: this VM has no exposed Vercel admin credential, Secret Manager listing is denied, and the installed judge client is outside the authorized repository. No gate, quota, or production configuration was changed. The remaining infrastructure work is to tune the authorized limiter or add bounded retry and backoff in the shared judge client while preserving fail-closed review. |


Evidence
Evidence: partially demonstrated — Code inspection established the capped Bitbucket branch walk; the initial session's local server and Android runs observed the truncation flag, retained default branch, and partial-list notices. Live Bitbucket paging remains unproven.
Change
Bitbucket's branch listing walks
/refs/brancheswith a bound of 20 pages. When the provider still returned a next cursor after the last allowed page, the listing returned the pages it had collected as if they were the repository's whole branch set, and a default branch that sorted past the bound could be absent from it.apps/web/src/lib/cloud-agent/provider-branch-listing.tsProviderBranchListing/ProviderBranchListingSchemagain a requiredtruncated: boolean; GitHub and GitLab returnfalsebecause both walks page to completion.truncatedonly when the page budget ends it while a fresh cursor remains. A repeated cursor (paging cannot advance) still ends the walk without claiming truncation.brancheswhen the collected pages do not contain it, so a partial walk still offers the branch the session checks out.apps/mobile):RepositoryBranchesStateandBranchPickerBridgecarry the flag. The new-session branch row shows a note under the trigger, and the branch picker sheet shows the note above its rows, in every locale (agentChat.newSession.branchListIncomplete).Verification
Unit and contract tests
apps/webJest:provider-branch-listing.test.ts,cloud-agent-next-router.branches.test.ts,organization-cloud-agent-next-router.branches.test.ts— 38 passed. The Bitbucket cases cover: a provider that always returns a fresh cursor (walk stops at 20 pages,truncated: true), a default branch the pages never contain (returned first, still truncated), a default the pages do contain (no duplicate), and a repeated cursor (list kept,truncated: false).use-new-session-repos.test.ts,repository-branch-selector.mounted.test.tsx,branch-picker.mounted.test.tsx— 45 passed, including the partial note in both surfaces and no note for a complete list.node tools/i18n/check-catalogs.mjs(87 catalogs),pnpm --filter kilo-app check:i18n,check:plurals— pass.pnpm --filter web exec tsgo --noEmitandpnpm --filter kilo-app typecheck— clean.End-to-end through the real server
Local dev stack (Next.js, Postgres, real tRPC routers, real provider read layer) with a Bitbucket stub at the network boundary whose
/2.0/repositories/{workspace}/{repo}/refs/branchesalways answers another page, and whose repository object reports a default branch that sorts after every stubbed branch.organizations.cloudAgentNext.listRepositoryBranchesfor that repository answeredtruncated: true, 1001 branches, the default branch first,defaultBranchnamed.refs/branchespage requests and no 21st: the bound stayed, the answer now says so.Mobile surface
Android emulator, local dev stack, owned fake account in a local organization with a Bitbucket integration fixture:
zzz-defaultselected and marked Default, with the partial-list note below it.Screenshots are published as a comment on this pull request.
Boundary
The provider is stubbed at the network boundary; this proves the app's own listing code, contract, and UI against provider-shaped pages. It does not prove a live Bitbucket workspace's paging behavior.
Proxy answers
The owner's proxy gave these answers in the owner's place.
Question: Listing contract: The listing contract is
{ defaultBranch, branches }with a strict zod schema shared by both routers and the mobile app. How should the truncation signal enter it?Answer: Required
truncated: booleanon all providersConfidence: 0.75 · Precedent: Engineering conventions: pass data as typed JSON ("refactor from text to typed JSON"); a required field keeps the typed contract explicit.
Question: UI placement: Where should the 'this list is partial' note appear in the mobile new-session flow?
Answer: Branch picker sheet + a note row under the selector trigger
Confidence: 0.70 · Precedent: Fix the class on every affected surface ("fix this for all shared services model pickers on all surfaces").
Question: Default branch: The truncated walk can omit the provider's default branch. Where should the default branch be inserted into the returned
brancheswhen it is absent?Answer: First in the list
Confidence: 0.80 · Precedent: UX and design quality: keep similar elements consistent; the preselected default matches the trigger.
Question: English copy: Which English copy for the new
agentChat.newSession.branchListIncompletekey?Answer: Only some branches are shown. The repository has more branches than this list can include.
Confidence: 0.50 · Precedent: Remove redundant copy (owner asked to remove the redundant "context" copy).
Question: How should shared judge throttling be handled?
Answer: Treat it as a workflow bug: identify quota, spend-cap, or rate-limit causes; raise an authorized cap or add fallback, retry, and backoff; keep the session and prepared evidence update; do not bypass the gate; record any external gap on this PR.
Confidence: 0.55 · Precedent: Keep work converging and fix the class of issue preventing progress.