Skip to content

fix(cloud-agent): report partial Bitbucket branch listings - #8537

Merged
iscekic merged 1 commit into
mainfrom
drain/branch-listing-truncation-flag
Oct 22, 2026
Merged

iscekic merged 1 commit into
mainfrom
drain/branch-listing-truncation-flag

Conversation

@iscekic

@iscekic iscekic commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

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/branches with 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.ts
    • ProviderBranchListing / ProviderBranchListingSchema gain a required truncated: boolean; GitHub and GitLab return false because both walks page to completion.
    • The Bitbucket walk sets truncated only when the page budget ends it while a fresh cursor remains. A repeated cursor (paging cannot advance) still ends the walk without claiming truncation.
    • The repository default branch is put first in branches when the collected pages do not contain it, so a partial walk still offers the branch the session checks out.
  • Mobile (apps/mobile): RepositoryBranchesState and BranchPickerBridge carry 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/web Jest: 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).
  • Mobile Vitest: 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 --noEmit and pnpm --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/branches always answers another page, and whose repository object reports a default branch that sorts after every stubbed branch.

  • organizations.cloudAgentNext.listRepositoryBranches for that repository answered truncated: true, 1001 branches, the default branch first, defaultBranch named.
  • The stub request log shows 20 refs/branches page 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:

  • New-session branch row: zzz-default selected and marked Default, with the partial-list note below it.
  • Branch picker sheet: the note sits above the rows; the default branch is the first row.

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.

  1. 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: boolean on all providers
    Confidence: 0.75 · Precedent: Engineering conventions: pass data as typed JSON ("refactor from text to typed JSON"); a required field keeps the typed contract explicit.

  2. 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").

  3. Question: Default branch: The truncated walk can omit the provider's default branch. Where should the default branch be inserted into the returned branches when 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.

  4. Question: English copy: Which English copy for the new agentChat.newSession.branchListIncomplete key?
    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).

  5. 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.

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.
@iscekic iscekic added drain Work item from the findings drain janitor:features-workflows Janitor finding family: features-workflows labels Oct 22, 2026
@iscekic

iscekic commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

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.

New-session branch row with the partial-list note

Branch picker sheet with the note above the rows

@kilo-code-bot

kilo-code-bot Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The 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: [INFERENCE] The GitLab branch walk relies on GitLab's x-total-pages header (defaulting to 1 when absent), so truncated: false for GitLab assumes that header is present; this is unchanged adapter behavior and was not treated as a defect in this PR.

Files Reviewed (98 files)
  • apps/web/src/lib/cloud-agent/provider-branch-listing.ts
  • apps/web/src/lib/cloud-agent/provider-branch-listing.test.ts
  • apps/web/src/routers/cloud-agent-next-router.branches.test.ts
  • apps/web/src/routers/organizations/organization-cloud-agent-next-router.branches.test.ts
  • apps/mobile/src/lib/use-new-session-repos.ts
  • apps/mobile/src/lib/use-new-session-repos.test.ts
  • apps/mobile/src/lib/picker-bridge.ts
  • apps/mobile/src/components/agents/repository-branch-selector.tsx
  • apps/mobile/src/components/agents/repository-branch-selector.mounted.test.tsx
  • apps/mobile/src/app/(app)/agent-chat/branch-picker.tsx
  • apps/mobile/src/app/(app)/agent-chat/branch-picker.mounted.test.tsx
  • apps/mobile/src/i18n/locales/*.json (87 catalogs, one added key each)

Reviewed by deepseek-flash-latest · Input: 88.5K · Output: 18K · Cached: 1.7M

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added the merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. label Oct 22, 2026
@iscekic

iscekic commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

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.

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

Labels

drain Work item from the findings drain janitor:features-workflows Janitor finding family: features-workflows merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants