Files
open-design/apps/daemon
lefarcenandGitHub 2856f87e8c feat(collab): add an opt-in cumulative ceiling for background content pulls (#7403)
* feat(collab): add an opt-in cumulative ceiling for background content pulls

`background-pull-size-guard` (incident #6512) asks one question per project:
is THIS version too big to push onto every member's disk. It cannot see
accumulation, and nothing else in the path can either.

Measured on a live Team workspace — 12 shared projects of ~2.9 MB each, 12
files apiece, every one an order of magnitude below the 2000-entry threshold.
A member who did nothing but open the client pulled 23 MB across 8 projects
within 50s, and the sweep log shows why:

  catch-up completed ... scanned=25 candidates=25 headChecks=4 suppressed=0

Every project cleared the gate individually. `headChecks=4` is a per-round
batch size, not a ceiling — later rounds keep going. So member onboarding cost
grows linearly with team size, with no bound.

This adds the missing second dimension: a per-process budget of entries the
BACKGROUND lanes may materialize before deferring the rest. Deferring is not
denying — the foreground open-project lane never consults this guard, so
anything skipped still materializes the moment the user opens it.

Deliberately inert by default. `OD_COLLAB_BACKGROUND_PULL_MAX_CUMULATIVE_ENTRIES`
defaults to 0 (disabled) and a malformed value disables rather than guesses,
mirroring how `maxEntries` refuses to be silently misconfigured. Picking a real
ceiling is a capacity decision that needs production data on team sizes and
pre-pull hit rate; shipping a guessed default would silently change what every
existing client downloads.

Budget is only consumed by decisions this guard actually allowed, and an
exhausted budget is NOT recorded in `deferredVersions`: that map means "this
version is permanently too big", whereas the budget is a transient per-process
limit that a restart resets.

Verified by unit spec, NOT end to end. The local vela (0.0.27-test.3) has no
`team-projects pull --authorize-only` flag, so `probeUnavailable` latches on
first use and every size decision short-circuits to 'pull' — see the follow-up
note on the PR, since that also disables the pre-existing #6512 protection on
any client shipping a CLI that old.

* fix(collab): say which ceiling deferred a background pull

Verifying the cumulative budget end to end (vela-cli 0.0.33, live Team
workspace) produced this line:

  background shared-project pull deferred (oversized):
    projectId=many204328n11 version=2 entries=12 maxEntries=2000

Which reads as a contradiction — 12 entries against a 2000 threshold is not
oversized. The project was deferred because the session budget was spent, but
both ceilings logged the same word.

The two need different responses: one says raise the per-project threshold,
the other says raise the session budget. Carry the reason on the observation
so the log points at the knob that actually applied.

* fix(collab): decide the per-project ceiling first and remember budget deferrals

Two review findings on #7403, both correct.

**Order.** The cumulative ceiling was evaluated before the per-project one, so
a project that independently exceeds `maxEntries` was labelled
`budget-exhausted` whenever the remaining budget happened to be smaller than
it. That points a reader at the wrong knob, and worse, it never reached
`deferredVersions` — so an oversized project was re-probed on every later
round. Exceeding `maxEntries` is a permanent property of the version and is
now decided, and cached, first.

**Memoization.** A deferral is terminal only for the current work item; later
catch-up rounds revisit a head that is still unmaterialized. The budget branch
recorded nothing, so every round repeated the remote authorize-only probe and
emitted another deferral log for every project past the budget — unbounded
remote calls for a decision that cannot change until the process restarts.

My comment justified leaving it uncached by worrying about a restart still
suppressing the project. That reasoning does not hold: every map in this guard
is already process-local, so a restart clears the budget and these entries
together. Budget deferrals are now remembered in their own map, kept separate
from `deferredVersions` so "too big" and "arrived after the budget was spent"
stay distinguishable.

Verified live (vela-cli 0.0.33, budget=30): unchanged capping behaviour —
2 projects / 5.8 MB versus 8 / 24 MB unbudgeted — and the deferral log now
stays at 5 lines across 100s instead of growing every sweep round, one per
project.
2026-08-26 02:13:51 +00:00
..