Skip to content

[feat] Skip the per-load members.yaml git reads for teams that do not use it #1393

Closed as not planned

Description

@SaulMoro

Problem

Follow-up to #1191. Every config load now probes the team repo for manifest/members.yaml from origin/<default>, including for teams that never add the file. applyRoleAssignment runs on each loadLocalConfig, loadLocalConfigForScope and readConfigFrom, and pull/init call refreshRoleAssignment on top. Each probe costs two git subprocesses (rev-parse --verify origin/<default>^{commit} and git show origin/<default>:./manifest/members.yaml). getDefaultBranch and parseManifestOnce already cache their part; the git reads are not cached.

The feature is opt-in, so a team that does not use it should not pay for it. The cost has not been measured yet: it is two short-lived processes per load, multiplied by however many loads a command does (workspace children, multiple scopes).

Proposed Solution

  1. Measure first: count loads and the added wall time for teamai pull and teamai status in a workspace with children, with and without members.yaml. If the cost is negligible, close this.
  2. If it is not, memoize the result of loadRoleAssignmentsIfPresent per process, keyed by repo path and source kind, following the existing defaultBranchCache in src/utils/git.ts. Invalidate it where the team repo moves: after the fetch in pull (before refreshRoleAssignment) and after the clone/update in init.

The fail-closed contract must hold: absent file is the only result that hands role selection back. A cached "absent" must not outlive a fetch that brings the file in, and a cached read error must not become "absent".

Alternatives Considered

  • Keying the cache on the resolved origin/<default> sha: no explicit invalidation, but still one rev-parse per load.

Activity

  1. added
    enhancementNew feature or request
    help wantedExtra attention is needed
    and removed
    help wantedExtra attention is needed
    on Oct 25, 2026
  2. self-assigned this
    on Oct 25, 2026
  3. SaulMoro commented on Oct 25, 2026

    @SaulMoro
    CollaboratorAuthor

    Measured on current main with a workspace whose team repo has no members.yaml: the same build, with and without loadRoleAssignmentsIfPresent stubbed to null, 15 interleaved runs per side.

    Command With probe Stubbed Extra git calls
    pull (fast path, "Already synced") 289 ms 258 ms 7
    status 138 ms 124 ms 3

    Medians. Every probe is a pair, rev-parse --verify origin/<default>^{commit} plus show origin/<default>:./manifest/members.yaml, about 4.5 ms per call here. pull probes three times: at load, in refreshRoleAssignment after the fetch, and at a later load. Add one rev-parse --abbrev-ref origin/HEAD the first time getDefaultBranch runs.

    What the remedies would save:

    • A per-process memo invalidated in refreshRoleAssignment removes only the third pair on pull (about 9 ms) and nothing on status or roles list, which probe once. It also adds the invalidation risk described above.
    • A single ls-tree origin/<default> -- ./manifest/members.yaml per probe (an error means no fetched branch, empty output means absent, then show only when present) removes the rev-parse: about 13 ms on pull and 4.5 ms on status, with no state.

    So the absent-file cost is about 30 ms per pull, and the cheapest safe fix recovers less than half of it. I'm not opening a PR for that now. A real saving would mean resolving the assignment once per pull instead of once per config load, which is a larger change. Leaving this open in case that becomes worth it.

  4. SaulMoro commented on Oct 25, 2026

    @SaulMoro
    CollaboratorAuthor

    Closing per the measurement above: the safe fix recovers about 13 ms per pull, which does not justify the change. Reopen if config loads multiply (for example many workspace children) and the probe cost becomes visible.

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions