Repository navigation
Closed
Labels
app/corePackage: core (pkgs/ or apps/ in this repo)Package: core (pkgs/ or apps/ in this repo)app/pluginPackage: plugin (pkgs/ or apps/ in this repo)Package: plugin (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)Something isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobFiled by the new-issue-creator jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted testsQueue packet kind: bounded fix with reproduction and targeted tests
Description
Problem
The plugin host's vcs.branch.list passes a plugin-supplied limit through to git for-each-ref --count= untouched — no default, no cap, and no integer validation. The HTTP endpoint it mirrors applies all three. The sibling divergence for session.list was filed as #935; this is the same class on the VCS surface, with an extra failure mode: non-integer limits make the git call itself fail.
Verified on main 3a1c3a0c78:
Plugin limit |
Plugin host result | HTTP vcs.branch.list result |
|---|---|---|
| omitted | every local + remote branch (no --count argument at all) |
newest 50 |
10000 |
--count=10000 honoured verbatim |
capped at 100 |
0 |
falsy in the adapter, so --count is omitted → every branch (asking for none returns all) |
rejected: query schema requires a positive integer |
-5 |
--count=-5 → git for-each-ref usage error, exit 129 (verified on laptop) |
rejected: positive integer only |
1.5 |
--count=1.5 → error: option 'count' expects an integer value (verified on laptop) |
rejected: positive integer only |
Evidence (file:line, main 3a1c3a0)
packages/core/src/plugin/host.ts:547-549—branch.list: (input) => response(vcs.branches({ search: input?.search, limit: input?.limit })): the caller's limit passes through untouched.packages/core/src/plugin/vcs/git.ts:261-276—branches()builds--count=${options.limit}wheneveroptions?.limitis truthy (line 270); an undefined or0limit omits--countentirely, sofor-each-refreturns every ref.packages/server/src/handlers/vcs.ts:87— the HTTP handler the plugin surface mirrors appliesMath.min(ctx.query.limit ?? 50, 100): default 50, ceiling 100.packages/protocol/src/groups/vcs.ts:21-25— the HTTP query schema restrictslimittoPositiveInt; the plugin input (packages/plugin/src/effect/vcs.ts:14-17,packages/plugin/src/promise/vcs.ts:13) is a bare optionalnumberwith no such restriction.- Laptop verification of the git failure modes:
git for-each-ref --count=-5→ usage error, exit 129;--count=1.5→error: option 'count' expects an integer value with an optional k/m/g suffix;--count=0→ all refs (0 means no limit to git, matching the adapter's falsy-omission behaviour).
Dedup: gh issue list --search "vcs branch limit plugin" and --search "branch.list" return nothing covering this; #935 covers session.list only, a different surface and code path.
Why it matters
- The two surfaces of the same endpoint disagree silently: a plugin paging branches with the documented HTTP behaviour in mind gets the whole ref set on page one, and on a long-lived repo with thousands of remote branches that is an unbounded list materialised through the plugin host.
limit: 0inverting to "return everything" is the worst case of the divergence — the smallest request produces the largest response.- A fractional or negative limit (easy for a plugin computing a page size dynamically) doesn't degrade to a default; it fails the whole
for-each-refcall with a git usage error surfaced to the plugin.
Acceptance criteria
- Plugin
vcs.branch.listwith nolimitreturns at most the HTTP default (50), and an explicit limit is capped at the HTTP ceiling (100) — or the divergence is explicitly documented in the plugin API docs with the unbounded behaviour called out. - A limit of
0, a negative number, or a non-integer no longer reachesgit for-each-ref --count=: it is rejected, defaulted, or normalised to a positive integer before the adapter builds the command. - Tests (e.g. in
packages/core/test/vcs.test.tsor the plugin host tests) pin: no-limit returns the default page on a repo with more branches than the default,limit: 0does not return every branch, and a fractional limit does not surface a git usage error. - HTTP
vcs.branch.listbehaviour is unchanged.
Metadata
Metadata
Assignees
Labels
app/corePackage: core (pkgs/ or apps/ in this repo)Package: core (pkgs/ or apps/ in this repo)app/pluginPackage: plugin (pkgs/ or apps/ in this repo)Package: plugin (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)Something isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobFiled by the new-issue-creator jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted testsQueue packet kind: bounded fix with reproduction and targeted tests
Activity
dezren39 commentedon Oct 30, 2026
🤖 Agent note · filed
vcs.branch.listlimit divergence: the plugin host passeslimituntouched togit for-each-ref --count=while the HTTP endpoint it mirrors defaults 50 / caps 100 / requires a positive integer — no-limit andlimit: 0return every branch, and-5/1.5fail the git call outright (laptop-verified). Sibling of fix(core): plugin session.list has no default page size — a no-limit call returns every session, not the documented newest 50 (PR #766) #935 (pluginsession.list), different surface and code path.--count=, and tests pin the no-limit,limit: 0, and fractional cases.1 remaining item
dezren39 commentedon Oct 30, 2026
🤖 Agent note · parked — CI pending on PR #946
5351961550, branchqueue/3782-945-plugin-vcs-branch-limit(worktree~/git/fleet/3782-945-plugin-vcs-branch-limit).bun test test/vcs.test.ts37 pass on a real 61-branch repo,bun run typecheckclean inpackages/coreandpackages/server,oxlintclean on the four changed files.fix(core): bound and normalise the plugin vcs.branch.list limit (#945) (
dezren39 commentedon Oct 30, 2026
Completed (task 3782): PR #946 merged (squash,
01cf577ecf) and this issue closed by it. Final CI state at merge: basic typecheck, basic unit (linux), basic unit (windows), basic affected packages, check-standards and check-compliance all SUCCESS. The e2e (linux/windows) jobs never left the queue — stuck QUEUED for ~45 minutes in the fleet runner backlog that also held up main-branch runs — so the merge went ahead per the standing directive after the change itself was verified sound: diff reviewed (limit normalised to default 50 / ceiling 100, non-positive and fractional limits clamped before reachinggit for-each-ref), localvcs.test.ts37 pass with typecheck clean, and the Codex gate clean (0 review threads / 0 reviews on PR #946). If e2e later surfaces a regression from this change, it will arrive as a normal CI failure on main.