@gitkraken/core-gitlens 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.md +57 -1
  2. package/dist/git/cache.d.ts +84 -29
  3. package/dist/git/cache.js +188 -54
  4. package/dist/git/cache.js.map +1 -1
  5. package/dist/git/features.d.ts +1 -1
  6. package/dist/git/features.js +4 -0
  7. package/dist/git/features.js.map +1 -1
  8. package/dist/git/models/branch.d.ts +15 -2
  9. package/dist/git/models/branch.js +27 -5
  10. package/dist/git/models/branch.js.map +1 -1
  11. package/dist/git/models/status.js +1 -1
  12. package/dist/git/models/worktree.d.ts +4 -1
  13. package/dist/git/models/worktree.js +4 -2
  14. package/dist/git/models/worktree.js.map +1 -1
  15. package/dist/git/providers/branches.d.ts +73 -8
  16. package/dist/git/providers/pausedOperations.d.ts +6 -0
  17. package/dist/git/providers/provider.d.ts +34 -2
  18. package/dist/git/providers/status.d.ts +8 -2
  19. package/dist/git/remotes/azure-devops.js +61 -53
  20. package/dist/git/remotes/azure-devops.js.map +1 -1
  21. package/dist/git/service.d.ts +8 -5
  22. package/dist/git/service.js +16 -8
  23. package/dist/git/service.js.map +1 -1
  24. package/dist/git/utils/branch.utils.d.ts +8 -1
  25. package/dist/git/utils/branch.utils.js +30 -1
  26. package/dist/git/utils/branch.utils.js.map +1 -1
  27. package/dist/git/watching/changeEvent.d.ts +13 -2
  28. package/dist/git/watching/changeEvent.js +17 -3
  29. package/dist/git/watching/changeEvent.js.map +1 -1
  30. package/dist/git/watching/gitDirPoller.d.ts +111 -0
  31. package/dist/git/watching/gitDirPoller.js +266 -0
  32. package/dist/git/watching/gitDirPoller.js.map +1 -0
  33. package/dist/git/watching/provider.d.ts +16 -0
  34. package/dist/git/watching/watchGroup.d.ts +40 -4
  35. package/dist/git/watching/watchGroup.js +143 -17
  36. package/dist/git/watching/watchGroup.js.map +1 -1
  37. package/dist/git/watching/watchService.d.ts +70 -1
  38. package/dist/git/watching/watchService.js +158 -13
  39. package/dist/git/watching/watchService.js.map +1 -1
  40. package/dist/git/watching/watchSession.d.ts +44 -0
  41. package/dist/git/watching/watchSession.js +91 -6
  42. package/dist/git/watching/watchSession.js.map +1 -1
  43. package/dist/git/watching/watcherPatterns.d.ts +21 -0
  44. package/dist/git/watching/watcherPatterns.js +67 -1
  45. package/dist/git/watching/watcherPatterns.js.map +1 -1
  46. package/dist/git/watching/worktreeSummary.d.ts +34 -7
  47. package/dist/git/watching/worktreeSummary.js +39 -12
  48. package/dist/git/watching/worktreeSummary.js.map +1 -1
  49. package/dist/git-cli/cliGitProvider.d.ts +34 -2
  50. package/dist/git-cli/cliGitProvider.js +119 -17
  51. package/dist/git-cli/cliGitProvider.js.map +1 -1
  52. package/dist/git-cli/exec/commandClassifier.d.ts +15 -0
  53. package/dist/git-cli/exec/commandClassifier.js +48 -2
  54. package/dist/git-cli/exec/commandClassifier.js.map +1 -1
  55. package/dist/git-cli/exec/git.d.ts +15 -3
  56. package/dist/git-cli/exec/git.js +38 -17
  57. package/dist/git-cli/exec/git.js.map +1 -1
  58. package/dist/git-cli/exec/gitQueue.d.ts +2 -0
  59. package/dist/git-cli/exec/gitQueue.js +2 -1
  60. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  61. package/dist/git-cli/exec/indexLock.d.ts +38 -0
  62. package/dist/git-cli/exec/indexLock.js +150 -0
  63. package/dist/git-cli/exec/indexLock.js.map +1 -0
  64. package/dist/git-cli/parsers/worktreeParser.js +42 -2
  65. package/dist/git-cli/parsers/worktreeParser.js.map +1 -1
  66. package/dist/git-cli/providers/branches.d.ts +109 -10
  67. package/dist/git-cli/providers/branches.js +624 -131
  68. package/dist/git-cli/providers/branches.js.map +1 -1
  69. package/dist/git-cli/providers/config.d.ts +9 -5
  70. package/dist/git-cli/providers/config.js +60 -27
  71. package/dist/git-cli/providers/config.js.map +1 -1
  72. package/dist/git-cli/providers/operations.d.ts +17 -0
  73. package/dist/git-cli/providers/operations.js +153 -96
  74. package/dist/git-cli/providers/operations.js.map +1 -1
  75. package/dist/git-cli/providers/pausedOperations.d.ts +8 -0
  76. package/dist/git-cli/providers/pausedOperations.js +60 -40
  77. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  78. package/dist/git-cli/providers/refs.js +11 -8
  79. package/dist/git-cli/providers/refs.js.map +1 -1
  80. package/dist/git-cli/providers/remotes.js +19 -10
  81. package/dist/git-cli/providers/remotes.js.map +1 -1
  82. package/dist/git-cli/providers/staging.js +40 -15
  83. package/dist/git-cli/providers/staging.js.map +1 -1
  84. package/dist/git-cli/providers/stash.d.ts +2 -0
  85. package/dist/git-cli/providers/stash.js +33 -18
  86. package/dist/git-cli/providers/stash.js.map +1 -1
  87. package/dist/git-cli/providers/status.d.ts +3 -1
  88. package/dist/git-cli/providers/status.js +38 -20
  89. package/dist/git-cli/providers/status.js.map +1 -1
  90. package/dist/git-cli/providers/tags.js +6 -4
  91. package/dist/git-cli/providers/tags.js.map +1 -1
  92. package/dist/git-cli/providers/worktrees.d.ts +1 -0
  93. package/dist/git-cli/providers/worktrees.js +60 -31
  94. package/dist/git-cli/providers/worktrees.js.map +1 -1
  95. package/dist/git-cli/service.d.ts +6 -0
  96. package/dist/git-cli/service.js +5 -2
  97. package/dist/git-cli/service.js.map +1 -1
  98. package/dist/ipc/discovery.js +1 -1
  99. package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
  100. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  101. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
  102. package/dist/plus/git-github/providers/github/status.d.ts +3 -1
  103. package/dist/plus/git-github/providers/github/status.js +1 -1
  104. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  105. package/dist/plus/integrations/collectionMetadata.d.ts +13 -2
  106. package/dist/plus/integrations/collectionMetadata.js +14 -2
  107. package/dist/plus/integrations/collectionMetadata.js.map +1 -1
  108. package/dist/plus/integrations/index.d.ts +2 -2
  109. package/dist/plus/integrations/index.js.map +1 -1
  110. package/dist/plus/integrations/integrationService.d.ts +1 -0
  111. package/dist/plus/integrations/integrationService.js +1 -1
  112. package/dist/plus/integrations/integrationService.js.map +1 -1
  113. package/dist/plus/integrations/manager.d.ts +1 -0
  114. package/dist/plus/integrations/models/gitHostIntegration.d.ts +41 -5
  115. package/dist/plus/integrations/models/gitHostIntegration.js +106 -29
  116. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  117. package/dist/plus/integrations/models/issueReads.d.ts +17 -4
  118. package/dist/plus/integrations/providers/apiClients.d.ts +2 -0
  119. package/dist/plus/integrations/providers/apiClients.js +7 -1
  120. package/dist/plus/integrations/providers/apiClients.js.map +1 -1
  121. package/dist/plus/integrations/providers/azure/azure.d.ts +5 -4
  122. package/dist/plus/integrations/providers/azure/azure.js +37 -77
  123. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  124. package/dist/plus/integrations/providers/azure/azure.utils.js +20 -17
  125. package/dist/plus/integrations/providers/azure/azure.utils.js.map +1 -1
  126. package/dist/plus/integrations/providers/azure/models.d.ts +2 -2
  127. package/dist/plus/integrations/providers/azure/models.js +4 -4
  128. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  129. package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +18 -14
  130. package/dist/plus/integrations/providers/azure/workItemStateCategories.js +69 -17
  131. package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
  132. package/dist/plus/integrations/providers/azureDevOps.d.ts +44 -0
  133. package/dist/plus/integrations/providers/azureDevOps.js +108 -17
  134. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  135. package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +45 -1
  136. package/dist/plus/integrations/providers/azureDevOpsServer.js +121 -6
  137. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
  138. package/dist/plus/integrations/providers/jira-server.js +18 -14
  139. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  140. package/dist/plus/integrations/providers/jira.js +18 -14
  141. package/dist/plus/integrations/providers/jira.js.map +1 -1
  142. package/dist/plus/integrations/providers/models.d.ts +1 -2
  143. package/dist/plus/integrations/providers/models.js +9 -2
  144. package/dist/plus/integrations/providers/models.js.map +1 -1
  145. package/dist/plus/integrations/providers/providersApi.d.ts +7 -17
  146. package/dist/plus/integrations/providers/providersApi.js +85 -78
  147. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  148. package/dist/plus/integrations/providers/utils/jiraIssueDrains.d.ts +22 -0
  149. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js +69 -9
  150. package/dist/plus/integrations/providers/utils/jiraIssueDrains.js.map +1 -1
  151. package/dist/plus/integrations/providers/utils/providerPaging.js +8 -2
  152. package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
  153. package/dist/plus/integrations/reads/filters.d.ts +3 -3
  154. package/dist/plus/integrations/reads/filters.js.map +1 -1
  155. package/dist/plus/integrations/reads/issueBatch.d.ts +2 -1
  156. package/dist/plus/integrations/reads/issueBatch.js +1 -1
  157. package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
  158. package/dist/plus/integrations/reads/issueTracker.js +23 -14
  159. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  160. package/dist/plus/integrations/reads/issues.d.ts +2 -1
  161. package/dist/plus/integrations/reads/issues.js +18 -3
  162. package/dist/plus/integrations/reads/issues.js.map +1 -1
  163. package/dist/plus/integrations/reads/pullRequestBatch.js +1 -1
  164. package/dist/plus/integrations/reads/resolveRepository.js +12 -3
  165. package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
  166. package/dist/plus/integrations/reads/warnings.d.ts +11 -4
  167. package/dist/plus/integrations/reads/warnings.js +15 -5
  168. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  169. package/dist/plus/integrations/results.d.ts +36 -2
  170. package/dist/plus/integrations/results.js +33 -13
  171. package/dist/plus/integrations/results.js.map +1 -1
  172. package/dist/utils/env/node/exec.js +2 -2
  173. package/dist/utils/promiseCache.d.ts +10 -0
  174. package/dist/utils/promiseCache.js +17 -2
  175. package/dist/utils/promiseCache.js.map +1 -1
  176. package/docs/integrations.md +52 -20
  177. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -6,6 +6,61 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.13.0] - 2026-10-18
10
+
11
+ ### Added
12
+
13
+ - Adds `GitPausedOperationsSubProvider.hasPausedOperation(repoPath, cancellation?)`, which answers whether git's dir holds a sentinel of any in-progress operation (merge, cherry-pick, revert, rebase, `git am`, or a sequencer run with a `todo`) from presence alone. Unlike `getPausedOperationStatus`, it is also `true` for states that can't be described, such as a stopped `git am`, a rebase between steps, or a sequencer it can't parse, and it rejects when git's dir can't be read rather than answering `false` (git, git-cli)
14
+ - Adds a `paths` option to `getUntrackedFiles` to limit the read to repo-relative files or folders. Paths match literally, so a folder named like a glob (`[id]/`) doesn't pull in its siblings; long lists are split to fit the command line; and an empty array answers empty without running git (git, git-cli)
15
+ - Adds `getAheadBehindCounts(repoPath, base, options?: { remotes?: boolean; refs?: readonly string[] }, cancellation?)` to `GitBranchesSubProvider`, returning how far every branch has diverged from `base` as a `Map<string, { ahead: number; behind: number }>` keyed by full ref name (`refs/heads/x`, plus `refs/remotes/<remote>/x` with `remotes`); symbolic refs such as `refs/remotes/origin/HEAD` are left out. `refs` limits it to those full ref names, so a host counts only the branches it shows. It uses one `for-each-ref` on Git 2.41+; before that, one `for-each-ref` and one `rev-parse` plus a background-priority count for each distinct branch tip not at `base`, remembering each count by its pair of commits (outside shallow clones) so a repeat call recounts only the tips that moved. It rejects when `base` can't be resolved or the counts can't be read (git, git-cli)
16
+ - Adds the `git:for-each-ref:ahead-behind` git feature (Git 2.41), for `%(ahead-behind:<commit>)` in `for-each-ref` formats (git, git-cli)
17
+ - Adds the `git:worktree:list:lock-reason` git feature (Git 2.31), for `worktree list --porcelain` printing a lock's reason (git, git-cli)
18
+ - Adds `getIgnoredEntries(repoPath, cancellation?)` to `GitProvider`, which lists the working tree's ignored entries as `git status --ignored` does: repo-relative `/`-separated paths, with a directory whose contents are all ignored as one entry with a trailing `/`, sorted and not capped (git, git-cli)
19
+ - Adds `getIgnoredPaths(repoPath, paths, cancellation?)` to `GitProvider`, an exact `git check-ignore` of which of the given repo-relative paths are ignored, returned as a `Set<string>`. A tracked file isn't reported, and it answers where the in-memory `GitIgnoreFilter` errs toward not-ignored (git, git-cli)
20
+ - Adds `getMergedBranches(repoPath, into, options?: { remotes?: boolean }, cancellation?)` to `GitBranchesSubProvider`, returning the full ref names (`refs/heads/x`, plus `refs/remotes/<remote>/x` with `remotes`) of the branches whose tips are reachable from `into`, in one `for-each-ref --merged`. It is ancestry only, so a squash-merged or cherry-picked branch isn't included (use `getBranchMergedStatus` for that heuristic), and a branch whose tip equals `into`'s is. Symbolic refs are left out, and it rejects when `into` can't be resolved (git, git-cli)
21
+ - Adds `GitProvider.onDidAnnounceChanges`, which fires `AnnouncedRepositoryChanges` (`{ repoPath, changes }`) as the provider announces one of its own writes, once per path (sibling worktrees included), after the write finished and its caches were evicted. `GitService` forwards it to its watch service (git, git-cli)
22
+ - Adds an opt-in polling fallback for paths a watcher can't watch (WSL `/mnt` drives, network shares, FUSE mounts, UNC paths). A host passes `watchPolling: WatchPollingOptions` to `createCliGitService` or `GitService.createSingleton(watchingProvider, { watchPolling })`; it requires `stat(path)` and takes optional `isActive`, `intervalMs` (60000), `activeCheckMs` (5000, used only with `isActive`), `getRefs` and `getWorkingTreeFingerprint`. With no option nothing changes (git, git-cli)
23
+ - Adds `FileWatcherOptions.onDidChangeReliability` and the `FileWatcherReliability` type (`'reliable' | 'unreliable' | 'unwatchable'`), through which a `FileWatchingProvider` reports that a watcher is only partly trusted (polled beside) or can't watch (polled instead); core polls the git dir of such a watcher and feeds the changes through the same classification as native events, and rescans when a watcher recovers from `unwatchable`. It is passed only when the host opted into polling (git)
24
+ - Adds `RepositoryWatchService.getWatchMode(repoPath)`, returning `'poll'` while a watcher is polled in place of a native one, `'events'` while watched natively, and `undefined` when nothing watches the repository, and `onDidChangeWatchMode`, which fires `{ repoPath, mode }` as it changes between `'events'` and `'poll'` while the repository is watched (git)
25
+ - Adds `forkPoint`, `tier` (`AheadOfBaseTier`: `'user'`, `'detected'`, `'recorded'`, `'created'` or `'default'`) and `reason` to `getAheadOfBase`'s result, and `forkPoint` and `tier` to `WorktreeSummaryBase`. `forkPoint` is where HEAD forked from the base, so a host can cut a diff or log at the fork rather than at the base's tip; `tier` says which source decided the base; and `reason` (`'none'`, `'self'` or `'unborn'`), set when there is no base, tells nothing being found from the branch being its own base at HEAD's commit and from an unborn HEAD. All three come from work the read already does, so no git run is added (git, git-cli)
26
+ - Adds a one-time `git remote set-head -a` after a fetch or pull core runs, on Git before 2.48, for each remote that fetch read with its configured refspecs and whose `refs/remotes/<remote>/HEAD` symref (the default branch the base reads) is missing — Git 2.48 and later create it on such a fetch themselves. It runs at most once per repository and remote, isn't awaited by the fetch, can't prompt (credential, askpass and SSH prompts off) and gives up after 10 seconds; core otherwise never contacts a remote for the default branch (git-cli)
27
+ - Adds the `skipUserTarget` and `preferredTarget` options to `getAheadOfBase`, and the `'preferred'` tier (`AheadOfBaseTier`). `skipUserTarget` leaves the user's merge target out, giving the automatic order a merge-target picker shows and letting a host tell whether the user's pick matches it. `preferredTarget` is tried before every other source, also on a detached HEAD, so a diff or log can run against a target picked for the moment; it is measured like a recorded one (as itself or its tracking ref, whichever forked nearer), and tier `'preferred'` tells the host it was used; any other tier, or no base, means it fell through to the usual order as unusable (git, git-cli)
28
+
29
+ ### Changed
30
+
31
+ - Changes the warning for a Jira or Jira Data Center issue that `@gitkraken/provider-apis` can't read to `kind: 'unreadable-items'`, a new `ProviderWarningKind` member, where it was `'other'`, so it is recognized by its kind rather than its message. It carries `unreadableItems: { keys, complete }` (the new `ProviderWarningUnreadableItems`): the keys of the issues left out, read from provider-apis' message, and whether they are all of them. The read still sets `fetchFailed`, but no longer retracts the omissions of the read, since no request failed. The `ProviderWarningKind` union widened, so an exhaustive `switch` on it needs a new case ([#6011](https://github.com/gitkraken/vscode-gitlens/issues/6011)) (plus/integrations)
32
+ - Changes `listIssueTrackerIssuesPage` to report a Jira project cut short by its page backstop with one warning per project, naming it in the message and in `omission.scope`, where it reported one warning for the whole page. A relationship of a user-scoped Jira read stopped by the backstop is now a `pagination-incomplete` omission scoped to its project rather than an unscoped one, with the omission's message. So is a Jira project read stopped by the backstop after a page that dropped an issue, where it was a failure. Linear and Trello keep the warning for the whole page ([#6011](https://github.com/gitkraken/vscode-gitlens/issues/6011)) (plus/integrations)
33
+ - Changes setting an upstream, renaming or deleting a branch, creating one from a remote-tracking start point without `noTracking` (including `checkout` and `createWorktree` with `createBranch`), where git's default `branch.autoSetupMerge` writes its tracking, adding or removing a remote, and `setConfig` (for the repository's own config, not `global` or a custom `file`) to announce `config` through `hooks.repository.onChanged` along with `heads` or `remotes`, where they announced only those (or nothing), since each rewrites `.git/config`. A host that emitted the config change itself after these writes should stop, or it announces it twice. A raw `git branch` run with `notify: 'infer'` announces `config` only for a rename, copy, delete, upstream, `--track` or `--edit-description` form (git, git-cli)
34
+ - Changes `getUntrackedFiles` to take an `options` parameter (`{ paths?: readonly string[] }`) before `cancellation`: `getUntrackedFiles(repoPath, options?, cancellation?)`. A caller passing a cancellation signal as the second argument must pass `undefined` for `options` first (git, git-cli)
35
+ - Changes typed writes to announce through `hooks.repository.onChanged` (and reset their caches) once git has run, whether it succeeded or failed, where they announced only on success. A commit refused by a hook, a half-finished `reset`, `restore` or `checkout`, a merge or rebase that failed for a reason other than conflicts, a rejected branch push or delete, and a failed stash, tag, remote or worktree write can still change HEAD, the index or refs, so a host that emitted the change itself in a `finally` block should stop. A write that rejects its arguments before calling git still announces nothing (git-cli)
36
+ - Changes `Git.rev_parse__git_dir` to reject with git's error on any failure other than "not a git repository", where it resolved `undefined` for every failure. It still resolves `undefined` when git reports the path isn't in a repository, and now also when the path doesn't exist, so a caller that treated `undefined` as "not a repository" must now also handle a rejection for dubious ownership, a timeout or cancellation, or a missing git binary (git-cli)
37
+ - Changes `push` to pass `-u` (`--set-upstream` when publishing) only when the push establishes tracking (publishing, or a branch whose upstream is missing), where it passed `-u` for any branch with an upstream and so rewrote the same tracking into `.git/config` on every push. The push now announces `config` only when it sets tracking, so a host that ran its own push to avoid the config write and its watcher events no longer needs to (git-cli)
38
+ - Changes index-writing git runs (`add`, `checkout`, `commit`, `mv`, `read-tree`, `reset`, `restore`, `rm`, `switch`, `update-index`, and `apply` with `--index`, `--cached` or `--3way` but not `--check`) to run one at a time per checkout, in arrival order, and to retry up to three times (after 100, 200 and 400ms) when `index.lock` is held by another process, where a second write, or another process's, made git fail at once. Multi-step and long-running verbs (`stash`, `merge`, `rebase`, `cherry-pick`, `revert`, `am`, `pull`) and runs with their own `GIT_INDEX_FILE` are left out. A host that queued and retried its own index writes can drop that (git-cli)
39
+ - Changes announcements to reach every registered worktree of the repository: a write in one worktree now also announces, through `hooks.repository.onChanged` and with each sibling's own caches and status clock reset (the shared caches are reset once, for the write's checkout, before any path is announced), the part of its changes that worktrees share (`heads`, `tags`, `stash`, `remotes`, `worktrees`, `config`) to each sibling. An empty or `unknown` change reaches them as every shared kind, and `closed` reaches none. Each path hears a write once, so a host that re-announced shared changes for the main checkout itself should stop (git-cli)
40
+ - Changes the watcher to report core's own writes once: a write's announcement now replaces the watcher's pending changes of the kinds it announced and fires the announced kinds as the watch session's one event for the write (every kind a watcher reports for an empty or `unknown` announcement), merging the write's late `.git` echo into it, so subscribers no longer re-read status, log and refs for that echo. Watcher changes are never dropped: one of an announced kind arriving after the announced event fired, or later than the debounce delay after the announcement, is reported as usual, so an outside change right after a write (a `git push` just after a fetch) still refreshes. Other kinds, injected changes, overflow rescans and working-tree changes pass untouched. The event's new `WatcherRepoChangeEvent.announced` names the kinds that come only from such announcements, which `hooks.repository.onChanged` already delivered with their caches evicted, so a host that handled the hook can skip them; a kind the watcher or an injected change also reported in the same window isn't among them, save the write's own echo, and `WatcherRepoChangeEvent.getUnannouncedChanges()` returns the rest. `createCliGitService` skips those kinds when it applies the event to the provider's cache, so what a host re-read after the hook is kept (git, git-cli)
41
+ - Changes the announcement of a write to evict everything the watcher's echo used to for the write's own checkout, so a host without a model that reinjects changes doesn't keep stale caches (git-cli)
42
+ - Changes `getAheadOfBase`'s default branch to prefer the `upstream` remote over `origin`, then the first remote, reading the local `HEAD` symref of the first of them that has one (so an `upstream` added after cloning, which has none, doesn't hide `origin`'s), else guessing `<remote>/main` then `<remote>/master` in the same remote order, and using the remote ref (`<remote>/<name>`) when no local branch of that name exists, where it read only `origin/HEAD` and only as a local branch; and on the default branch itself it now measures against the branch's upstream — `upstream/<branch>` when an `upstream` remote has it, else `<branch>@{u}` — as `tier: 'upstream'` (a new `AheadOfBaseTier` member), so unpushed commits on `main` count, where it reported no base. It answers no base with `reason: 'self'` when there is no upstream or it sits at HEAD's commit, and never contacts the network (git, git-cli)
43
+ - Changes `getAheadOfBase` to take `branch: string | undefined` and, for a detached HEAD (`undefined`, or a detached-HEAD name as before), to measure against the default branch, tier `'default'`, with no self check, where it answered no base. The worktree summary now reports that base for a detached HEAD too (git, git-cli)
44
+ - Changes `getAheadOfBase` to take an `options` parameter before `cancellation`: `getAheadOfBase(repoPath, branch, options?, cancellation?)`. A caller passing a cancellation signal as the third argument must pass `undefined` for `options` first (git, git-cli)
45
+ - Changes `getAheadOfBase` to measure a branch with no stored merge target or recorded base against the branch git's reflog says it was created from (`git switch -c feat upstream/main`), as `tier: 'created'` (a new `AheadOfBaseTier` member), so a fork's branch cut from `upstream/main` no longer counts the commits `origin` hasn't caught up on. Only a local or remote-tracking branch counts — not `HEAD`, a sha, a tag, or the branch's own remote copy (`git switch feat` from `origin/feat`) — and the default branch itself still measures against its own upstream. The default branch wins, as `tier: 'default'`, when HEAD forked strictly nearer to it (a branch cut from one since merged and rebased onto the default), so a stacked branch keeps its unmerged parent. Both are also compared with the `upstream` remote's copy (`upstream/main`), which wins when HEAD forked strictly nearer to it, keeping the tier; a synced fork keeps `main` or `origin/main`. Nothing is written back. The reflog is read once per branch per session, only when no stored target resolves; a branch with a usable created-from also reads the default's fork points alongside, and the `upstream` comparison costs one fork-point read (none when that copy sits at the compared branch's or its tracking ref's tip), with `dependsOn` then naming `refs/remotes/upstream/<name>` (git, git-cli)
46
+ - Changes `onDidChangeMergeTargets` to also fire for core's own writes of a branch's merge target, detected target or recorded base, once per write, naming the branch, and only when the value changed — not for the saves core makes itself while answering a read; the watcher's later report of the same write doesn't fire it again. A host that raised its own merge-target change after calling `storeUserMergeTargetBranchName`, `storeMergeTargetBranchName` or `storeBaseBranchName` can stop, and a listener must not write merge keys back in response, or it loops (git, git-cli)
47
+ - Changes the worktree summary to re-read its base as soon as core writes the branch's merge target or base, so `getSummary` right after an awaited store returns the new base; the watcher's later report of the same write doesn't recompute it again. Only the writing repository's summaries re-read, through the new optional `GitProvider.getCommonPath` (git, git-cli)
48
+
49
+ ### Fixed
50
+
51
+ - Fixes Azure DevOps Services and Server issue lists omitting Removed or Completed work items without closure dates. State filters now reach project and account-wide reads, and workflow metadata is shared with identity and presentation reads ([#6013](https://github.com/gitkraken/vscode-gitlens/issues/6013)) (plus/integrations)
52
+ - Fixes `listIssueTrackerIssuesPage` publishing no warning for a Jira project, or a relationship of a user-scoped Jira read, cut short by the page backstop when the read also failed, which an issue another project or relationship couldn't read is enough for: the skipped issue then stood for the whole gap. The cut is now reported for its project whatever else failed. A Jira issue that can't be read is no longer published as an authentication, rate-limit or not-found failure, nor as an unreachable server, when its own error names an HTTP status ([#6011](https://github.com/gitkraken/vscode-gitlens/issues/6011)) (plus/integrations)
53
+ - Fixes Azure DevOps remotes in the legacy `{org}.visualstudio.com/DefaultCollection/{project}/_git/{repo}` form (any casing of `DefaultCollection`) having no `providerDesc` and a `repoDesc.name` that kept the collection segment, so every pull request, work item and commit author read threw `Invalid Azure repository descriptor`. The provider now maps them to `owner: '{org}'` and `name: '{project}/_git/{repo}'`. Remotes with no project segment (`{org}.visualstudio.com/DefaultCollection/_git/{repo}`, `{org}.visualstudio.com/_git/{repo}` and `dev.azure.com/{org}/_git/{repo}`) resolve with the project named after the repository, and their `#` work item autolink points at the organization rather than a malformed URL. `parseAzureHttpsUrl` follows the same rules and returns percent-decoded names; it now also throws for a URL with segments after the repository name (a pull request page, for one), which its unanchored match used to accept; `getAzurePullRequestIdentityFromMaybeUrl` now reads a pasted dev.azure.com or visualstudio.com pull request URL with that same parser (so the legacy and project-less forms resolve, `_git` matches in any casing, and a dev.azure.com URL with more than an organization and a project before `_git` no longer resolves); Server URLs keep their own rules ([#5999](https://github.com/gitkraken/vscode-gitlens/issues/5999)) (git, plus/integrations)
54
+ - Fixes Azure DevOps Server repository scopes a consumer parsed from a remote cloned without the project segment behind a virtual directory (`{vdir}/{collection}/_git/{repo}`), named as collection `{vdir}` and project `{collection}`, reading nothing: the repo-scoped pull request and issue reads (`listPullRequestsPage`, `listIssuesPage`), `searchPullRequestsPage` / `searchIssuesPage` and their counts, `getPullRequestsForBranches` and the pull request and issue batch and etag reads were refused or answered 400 "A project name is required in order to reference a Git repository by name". The integration now settles such a scope against the collections it discovers, as it settles a remote's own descriptor since #6000 ([#6009](https://github.com/gitkraken/vscode-gitlens/issues/6009)) (plus/integrations)
55
+ - Fixes Azure DevOps remotes of a repository named after its project and cloned without the project segment (`{collection}/_git/{repo}`, the clone URL TFS 2018 reports) never reading pull requests, linked pull requests or commit authors. On a server at the host root the remote now has a project, so `repoName` reads `{repo}/_git/{repo}` and `providerDesc` is set where both were missing; behind a virtual directory, over HTTPS or SSH, the Azure DevOps Server integration tells the collection from a virtual directory by the collections it discovers, and `resolveRepository` reports the repository's own collection and project. A failed or canceled `getDefaultBranch` or `getRepositoryMetadata` lookup is no longer cached as an answer (a missing repository still is), as a failed pull request lookup already wasn't ([#6000](https://github.com/gitkraken/vscode-gitlens/issues/6000)) (git, plus/integrations)
56
+ - Fixes a worktree's lock reason reading as a bare `locked: true` on Git before 2.31, which prints `locked` without the reason: `getWorktrees` now reads the reason from the worktree's admin `locked` file, only on Git before 2.31 (git-cli)
57
+ - Fixes lock and prunable reasons with unusual characters (e.g. a newline or a tab) arriving C-quoted: `parseGitWorktrees` now unquotes them (git-cli)
58
+ - Fixes `onCurrentBranchAccessed`, `onCurrentBranchModified` and `onCurrentBranchAgentActivity` dropping calls: each kept only its last call across every repository for 2.5 minutes, so of two checkouts stamped close together only one was recorded, minutes later. They now record each repository's branch, at most once per key per 5 minutes per branch, write one at a time per repository, and return a promise that settles once the write is done (it never rejects), so a host that wrote the `gk-last-*` keys itself can call them instead. The interface now also documents what each stamp means (`gk-last-modified`: the working tree or index changed while on the branch, not only commits) (git, git-cli)
59
+ - Fixes `getBranches`, `getBranch` and `getWorktrees` returning a branch's old `lastAccessedDate`, `lastModifiedDate`, `agentLastActivityAt` and disposition after `onCurrentBranchAccessed`, `onCurrentBranchModified`, `onCurrentBranchAgentActivity` or a `setGkConfig` of one of those keys wrote a new value, until the next ref or config change: core's write now updates the cached branch lists, current branches and worktrees of the repository and its worktrees in place, with no re-read, and clears them only for a branch's first stamp or while one of them is still being read. `GitWorktree.effectiveDate` is no longer memoized, so it follows (git, git-cli)
60
+ - Fixes a write to `.git/gk/config` failing on the file's lock when another write landed at the same moment (a merge-target pick beside an activity stamp or a disposition, say), so the user's pick was rejected: `setGkConfig`, `removeGkConfigBranchSection`, `renameGkConfigBranchSection` and the legacy-key migration now write each repository's file one at a time (a key's writes in call order), and every `git config` run (`.git/config` and `.git/gk/config` alike, from any caller) retries up to three times (after 100, 200 and 400ms) when another process holds the file's lock, where git failed at once. Other verbs that write config, such as `branch -m`, aren't retried, since they can fail after a partial change (git-cli)
61
+ - Fixes `getBranches` and `getBranch` keeping a branch's old `lastAccessedDate`, `lastModifiedDate`, `agentLastActivityAt` and disposition after another process (another host sharing the repository) changed them in `.git/gk/config`, until the next ref change: the watcher's reconcile of that file now also tracks these keys and updates the cached branches in place when one changed (clearing them only where it can't), never for core's own write, and never firing `onDidChangeMergeTargets` (git, git-cli)
62
+ - Fixes a git run's own `timeout` being ignored when the host disabled the default timeout (`gitTimeout: 0`), so a run with its own cap, such as `getContributorsStats` given a `timeout`, or the background `remote set-head` after a fetch, could run unbounded (git-cli)
63
+
9
64
  ## [0.12.0] - 2026-10-16
10
65
 
11
66
  ### Added
@@ -675,7 +730,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
675
730
 
676
731
  - Initial release. Bundles `@gitlens/utils`, `@gitlens/git`, `@gitlens/git-cli`, `@gitlens/ai`, and `@gitlens/git-github` into a single core npm package with subpath exports.
677
732
 
678
- [unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.12.0...HEAD
733
+ [unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.13.0...HEAD
734
+ [0.13.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.12.0...gitkraken:releases/core/v0.13.0
679
735
  [0.12.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.11.1...gitkraken:releases/core/v0.12.0
680
736
  [0.11.1]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.11.0...gitkraken:releases/core/v0.11.1
681
737
  [0.11.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.10.7...gitkraken:releases/core/v0.11.0
@@ -8,7 +8,7 @@ import { ParsedGitDiffHunks } from "./models/diff.js";
8
8
  import { GitBranchReference, GitRefTip, RefRecord } from "./models/reference.js";
9
9
  import { GitCommit } from "./models/commit.js";
10
10
  import { ProgressiveGitBlame } from "./models/blame.js";
11
- import { BranchMetadata, GitBranch } from "./models/branch.js";
11
+ import { BranchMetadata, BranchMetadataGkConfigKey, GitBranch } from "./models/branch.js";
12
12
  import { GitContributor, GitContributorsStats } from "./models/contributor.js";
13
13
  import { GitLog } from "./models/log.js";
14
14
  import { ConflictDetectionResult } from "./models/mergeConflicts.js";
@@ -50,7 +50,8 @@ export interface MergeTargetsChangeEvent {
50
50
  /**
51
51
  * Branches whose merge-relevant keys (`gk-merge-base`, `gk-merge-target`, `gk-merge-target-user`,
52
52
  * `gk-target-base`) changed. `undefined` when it can't be told, so any branch's may have: the coarse fallback
53
- * (no reconciler, or a failed reconcile), or a change with no earlier snapshot to diff against.
53
+ * (no reconciler, or a failed reconcile), or an external change with no earlier snapshot to diff against. Core's
54
+ * own write names its one branch.
54
55
  */
55
56
  readonly refs: ReadonlySet<string> | undefined;
56
57
  }
@@ -63,6 +64,12 @@ export declare function shouldEvictBlameCacheEntry(progressive: ProgressiveGitBl
63
64
  * naming the targets to skip via `skipInvalidation`.
64
65
  */
65
66
  export type GkConfigInvalidationTarget = 'branchOverviews' | 'baseBranchName';
67
+ /** A changed `branch.<branch>.<key>` gk config value for {@link Cache.patchBranchMetadata}; `undefined` is a removal */
68
+ export interface BranchMetadataChange {
69
+ readonly branch: string;
70
+ readonly key: BranchMetadataGkConfigKey;
71
+ readonly value: string | undefined;
72
+ }
66
73
  export declare class Cache implements Disposable {
67
74
  private _caches;
68
75
  private _commonPathRegistry;
@@ -73,18 +80,22 @@ export declare class Cache implements Disposable {
73
80
  /** Monotonic per-path "close clock" — see {@link getCloseGeneration}. */
74
81
  private _closeGenerations;
75
82
  /**
76
- * Per-commonPath snapshot of the merge-relevant subset of `.git/gk/config` (keys matching
77
- * {@link branchOverviewGkConfigKeysRegex}), used by {@link reconcileGkConfigMap} to diff a watcher
78
- * `'gkConfig'` event down to only the keys that actually changed, instead of coarsely re-deriving
79
- * `baseBranchName`/`branchOverviews` on every gk write. Absent means "never observed".
83
+ * Per-commonPath snapshot of the subset of `.git/gk/config` that derived caches depend on — merge-relevant keys
84
+ * ({@link branchOverviewGkConfigKeysRegex}) and branch metadata keys ({@link parseBranchMetadataGkConfigKey}) —
85
+ * used by {@link reconcileGkConfigMap} to diff a watcher `'gkConfig'` event down to only the keys that actually
86
+ * changed, instead of coarsely re-deriving `baseBranchName`/`branchOverviews` and the branches on every gk write.
87
+ * Absent means "never observed".
80
88
  */
81
- private _gkConfigMergeSnapshots;
89
+ private _gkConfigSnapshots;
82
90
  private readonly _onDidChangeMergeTargets;
83
91
  /**
84
- * Fires when an external `.git/gk/config` write changed a branch's merge-relevant keys — never for a write that
85
- * only touched other keys (activity timestamps), and never for core's own writes, which
86
- * {@link recordGkConfigWrite} folds into the snapshot before the watcher reports them. Fires after the derived
87
- * caches were cleared, so a listener's re-read sees the new values.
92
+ * Fires when a `.git/gk/config` write changed a branch's merge-relevant keys — never for a write that only touched
93
+ * other keys (activity timestamps). Core's own key store fires it once, as the write completes (see
94
+ * {@link recordGkConfigWrite}), and the watcher's later report of that write doesn't fire it again; core's own
95
+ * section remove and rename (a branch delete or rename) never fire it, nor do its internal saves while answering
96
+ * a read (nobody awaits those, and only another process's watcher reports them). Fires after the derived caches were
97
+ * cleared, so a listener's re-read sees the new values. A listener must not write merge keys back in response,
98
+ * or it loops.
88
99
  */
89
100
  get onDidChangeMergeTargets(): Event<MergeTargetsChangeEvent>;
90
101
  /**
@@ -164,6 +175,7 @@ export declare class Cache implements Disposable {
164
175
  * letting an in-flight read complete and share its answer with new callers is fine.
165
176
  */
166
177
  evictCaches(repoPath: string, ...types: CachedGitTypes[]): void;
178
+ /** `worktreeOnly` leaves the shared (commonPath-keyed) entries alone (see {@link applyRepositoryChanges}) */
167
179
  private clearCachesCore;
168
180
  /**
169
181
  * Evicts a single shared (commonPath-keyed) cache entry for `repoPath` and its sibling worktrees.
@@ -246,8 +258,14 @@ export declare class Cache implements Disposable {
246
258
  * `'gkConfig'` change, returning the cache types it cleared. `inFlight` is as {@link clearCaches}
247
259
  * (`'share'`) vs {@link evictCaches} (`'evict'`). `'unknown'` and `'closed'` map to nothing here: the
248
260
  * watcher unregisters the path on them, and an announced write resets everything instead.
261
+ *
262
+ * `options.worktreeOnly` clears only `repoPath`'s own entries and status clock, leaving the shared
263
+ * (commonPath-keyed) ones alone — for a sibling worktree once the change was applied to the worktree it ran in,
264
+ * which already cleared them for every worktree of the repository.
249
265
  */
250
- applyRepositoryChanges(repoPath: string, changes: Iterable<RepositoryChange>, inFlight: 'share' | 'evict'): CachedGitTypes[];
266
+ applyRepositoryChanges(repoPath: string, changes: Iterable<RepositoryChange>, inFlight: 'share' | 'evict', options?: {
267
+ worktreeOnly?: boolean;
268
+ }): CachedGitTypes[];
251
269
  /**
252
270
  * Handles a watcher-observed `'gkConfig'` change. Always evicts the cached bulk map (forcing the
253
271
  * next read to hit disk). If a reconciler is registered (see {@link setGkConfigReconciler}),
@@ -257,12 +275,21 @@ export declare class Cache implements Disposable {
257
275
  * clear when no reconciler is registered (e.g. the GitHub provider) so nothing can go stale.
258
276
  */
259
277
  private handleGkConfigChanged;
260
- /** The coarse fallback: every derived merge cache is cleared, so any branch's merge targets may have changed */
278
+ /**
279
+ * The coarse fallback: every derived merge cache and the branches are cleared, so any branch's merge targets or
280
+ * metadata may have changed. Evicting the branches even when only merge keys changed is the price of not knowing.
281
+ */
261
282
  private clearGkConfigCoarsely;
262
283
  /** Hard-evicts the cached bulk `.git/gk/config` map so the next read hits disk. */
263
284
  deleteGkConfigMap(repoPath: string): void;
264
- /** The merge-relevant gk config snapshot currently serving as the reconcile baseline. */
265
- getGkConfigMergeSnapshot(repoPath: string): ReadonlyMap<string, string> | undefined;
285
+ /**
286
+ * Whether a write of `key` must first read the gk config to seed the reconcile snapshot: without one,
287
+ * {@link recordGkConfigWrite} can't tell whether the write changed anything, and the watcher's reconcile of it
288
+ * would report every branch as changed.
289
+ */
290
+ needsGkConfigSnapshot(repoPath: string, key: string): boolean;
291
+ /** The gk config snapshot currently serving as the reconcile baseline. */
292
+ getGkConfigSnapshot(repoPath: string): ReadonlyMap<string, string> | undefined;
266
293
  getBranches(repoPath: string, factory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<PagedResult<GitBranch>>, mapper: (branches: PagedResult<GitBranch>, targetRepoPath: string, commonPath: string, cancellation?: AbortSignal) => PromiseOrValue<PagedResult<GitBranch>>, cancellation?: AbortSignal): Promise<PagedResult<GitBranch>>;
267
294
  private static readonly globalConfigKey;
268
295
  getConfig(repoPath: string | undefined, key: string, factory: () => PromiseOrValue<string | undefined>): Promise<string | undefined>;
@@ -273,12 +300,12 @@ export declare class Cache implements Disposable {
273
300
  * per-namespace gk lookups are served from it in-memory (see `getGkConfigMap` in the CLI config
274
301
  * sub-provider). Invalidated by `deleteGkConfig` (write) and, on a watcher `'gkConfig'` event, by
275
302
  * `handleGkConfigChanged` (reconciled precisely when a reconciler is registered, or the coarse
276
- * clear otherwise). The first fresh read seeds the merge-relevant snapshot used by
303
+ * clear otherwise). The first fresh read seeds the snapshot used by
277
304
  * `reconcileGkConfigMap`; later refreshes of that snapshot are owned by the reconcile itself.
278
305
  */
279
306
  getGkConfigMap(repoPath: string, factory: (cacheable: CacheController) => PromiseOrValue<Map<string, string>>): Promise<Map<string, string>>;
280
- /** Extracts the subset of a gk config map whose keys participate in the `branchOverviews`/`baseBranchName` lineage. */
281
- private extractMergeRelevantGkConfig;
307
+ /** Extracts the subset of a gk config map that the reconcile baseline tracks (see {@link _gkConfigSnapshots}). */
308
+ private extractReconciledGkConfig;
282
309
  /**
283
310
  * Clears the cached `.git/gk/config` map and invalidates the derived caches
284
311
  * (`baseBranchName`/`branchOverviews`) for the written key's ref.
@@ -294,17 +321,21 @@ export declare class Cache implements Disposable {
294
321
  skipInvalidation?: readonly GkConfigInvalidationTarget[];
295
322
  }): void;
296
323
  /**
297
- * Keeps the merge-relevant gk config snapshot in sync with OUR OWN writes, so the next
298
- * watcher-triggered `reconcileGkConfigMap` diffs a self-write as unchanged rather than as an
299
- * external change (which would otherwise defeat `skipInvalidation`). No-ops for keys outside the
300
- * merge-relevant subset, and if no snapshot exists yet for this repo — nothing to keep in sync;
301
- * the next real read (`getGkConfigMap`) populates one from scratch.
324
+ * Keeps the gk config snapshot in sync with OUR OWN writes, so the next watcher-triggered
325
+ * `reconcileGkConfigMap` diffs a self-write as unchanged rather than as an external change (which would
326
+ * otherwise defeat `skipInvalidation`, or evict the branches a second time after a branch-activity stamp),
327
+ * and fires {@link onDidChangeMergeTargets} naming the key's branch when a merge-relevant value differs from
328
+ * the snapshot's, unless `announce` is `false` (an internal save while answering a read, which nobody awaits;
329
+ * only another process's watcher reports it). No-ops for keys the snapshot doesn't track, and if no snapshot exists yet for this repo
330
+ * (the writer seeds one first; see {@link needsGkConfigSnapshot}).
302
331
  */
303
- recordGkConfigWrite(repoPath: string, key: string, value: string | undefined): void;
332
+ recordGkConfigWrite(repoPath: string, key: string, value: string | undefined, options?: {
333
+ announce?: boolean;
334
+ }): void;
304
335
  /**
305
336
  * {@link recordGkConfigWrite} for a whole `branch.<ref>` section: our own `--remove-section` (a branch delete) or
306
337
  * `--rename-section` (a branch rename, to `renamedTo`), so the reconcile that follows doesn't report it as an
307
- * external merge-target change.
338
+ * external merge-target or metadata change — the branch op's own ref change already evicts the branches.
308
339
  */
309
340
  recordGkConfigSectionWrite(repoPath: string, ref: string, renamedTo?: string): void;
310
341
  /**
@@ -315,11 +346,13 @@ export declare class Cache implements Disposable {
315
346
  */
316
347
  setGkConfigReconciler(reconciler: (repoPath: string, priorSnapshot: ReadonlyMap<string, string> | undefined) => PromiseOrValue<GkReconcileOutcome>): void;
317
348
  /**
318
- * Diffs a freshly-read gk config map's merge-relevant subset against `priorSnapshot` (captured by
319
- * `handleGkConfigChanged` before the reconcile started, so it reflects the pre-change state even
320
- * though this call's own re-read already raced ahead and refreshed the live snapshot), cascading
349
+ * Diffs a freshly-read gk config map's tracked subset against `priorSnapshot` (captured by
350
+ * `handleGkConfigChanged` before the reconcile started, so it reflects the pre-change state), cascading
321
351
  * `baseBranchName`/`branchOverviews` for every ref whose merge-relevant key actually changed, then firing
322
- * {@link onDidChangeMergeTargets} naming those refs.
352
+ * {@link onDidChangeMergeTargets} naming those refs. Changed branch metadata keys (another process's
353
+ * activity stamps or disposition) are patched into the cached branches in one call, and never fire the event.
354
+ * A key core itself wrote since `priorSnapshot` was captured (recorded in the live snapshot) is neither diffed nor
355
+ * overwritten by this read, which may predate the write: its writer already cascaded and announced it.
323
356
  * `priorSnapshot` of `undefined` (never observed before this reconcile) is treated as "everything
324
357
  * may have changed" — a full coarse clear, same as the pre-existing watcher behavior. Returns
325
358
  * whether anything changed (i.e. whether a follow-up repository-changed event is warranted).
@@ -359,6 +392,28 @@ export declare class Cache implements Disposable {
359
392
  * re-derivation this triggers just reads the stale value straight back.
360
393
  */
361
394
  deleteBaseBranchName(repoPath: string, ref: string): void;
395
+ /**
396
+ * Applies changed branch metadata keys (written here or reconciled from another process) to the cached branches
397
+ * without re-reading them, by updating {@link BranchMetadata} objects in place — the one exception to cached values
398
+ * never changing, since rebuilding every branch list, current branch and worktree list on every activity stamp
399
+ * costs far more. Patches every object a cached branch of the repository's worktrees holds for a changed branch:
400
+ * the cached map's, and any older map's that a cached branch list, current branch or worktree list still holds.
401
+ *
402
+ * Falls back to {@link deleteBranchMetadata} when one of them is still being read (it may have read the file
403
+ * before the change), or the cached map or a cached branch of a changed name has no object to patch.
404
+ */
405
+ patchBranchMetadata(repoPath: string, changes: readonly BranchMetadataChange[]): void;
406
+ /**
407
+ * Adds to `targets` every metadata object a cached holder has for each named branch (see
408
+ * {@link patchBranchMetadata}); `false` when the holders must be evicted instead.
409
+ */
410
+ private collectBranchMetadata;
411
+ /**
412
+ * Drops the cached branches and worktrees for `repoPath` and its sibling worktrees when their metadata changed in
413
+ * a way {@link patchBranchMetadata} can't apply in place. Hard-evicts, so a read that started before the change
414
+ * isn't joined.
415
+ */
416
+ deleteBranchMetadata(repoPath: string): void;
362
417
  getBranchMergedStatus(repoPath: string, cacheKey: string, factory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<GitBranchMergedStatus>, cancellation?: AbortSignal): Promise<GitBranchMergedStatus>;
363
418
  getBranchMetadataMap(repoPath: string, factory: (commonPath: string) => PromiseOrValue<Map<string, BranchMetadata>>): Promise<Map<string, BranchMetadata>>;
364
419
  getDefaultBranchName(repoPath: string, remote: string, factory: (commonPath: string, cacheable: CacheController, cancellation?: AbortSignal) => PromiseOrValue<string | undefined>, cancellation?: AbortSignal): Promise<string | undefined>;