@vzn/vx 0.0.644 → 0.0.645

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.
@@ -553,6 +553,44 @@ export function localBranchScope(
553
553
  return branchCacheScope(repo, name)
554
554
  }
555
555
 
556
+ /**
557
+ * The refs a remote reads, in order (2026-10-20): the run's own branch,
558
+ * then the branch it merges into, then the default branch, each once. On
559
+ * CI from its env (a GitHub pull request's head branch, a merge queue's
560
+ * queue ref, a GitLab pipeline's ref), else from git: the checked-out
561
+ * branch, then the default (`origin/HEAD`). A remote plugin keys or scopes
562
+ * its entries by them (`scope` on turboCache/nxCache); core keys nothing
563
+ * by them.
564
+ */
565
+ export function cacheRefs(
566
+ workspaceRoot: string,
567
+ baseBranch: string | undefined,
568
+ env: NodeJS.ProcessEnv = process.env,
569
+ ): string[] {
570
+ const set = (v: string | undefined): string | undefined =>
571
+ v !== undefined && v.trim() !== '' ? v.trim() : undefined
572
+ const head = (b: string | undefined) => (b === undefined ? undefined : `refs/heads/${b}`)
573
+ let own: string | undefined
574
+ let base: string | undefined
575
+ if (env['GITHUB_ACTIONS'] === 'true') {
576
+ own = head(set(env['GITHUB_HEAD_REF'])) ?? set(env['GITHUB_REF'])
577
+ base = head(set(env['GITHUB_BASE_REF']))
578
+ const queue = /^refs\/heads\/gh-readonly-queue\/(.+)\/pr-\d+-[0-9a-f]+$/.exec(own ?? '')
579
+ if (queue !== null) base = head(queue[1])
580
+ } else if (env['GITLAB_CI'] === 'true') {
581
+ const tag = set(env['CI_COMMIT_TAG'])
582
+ own = tag !== undefined ? `refs/tags/${tag}` : head(set(env['CI_COMMIT_REF_NAME']))
583
+ base = head(set(env['CI_MERGE_REQUEST_TARGET_BRANCH_NAME']))
584
+ } else {
585
+ own = head(
586
+ (readHeadDirect(workspaceRoot) ?? captureGitContext(workspaceRoot, null, env)).branch ??
587
+ undefined,
588
+ )
589
+ }
590
+ const trunk = head(baseBranch ?? captureDefaultBranch(env, workspaceRoot) ?? undefined)
591
+ return [...new Set([own, base, trunk].filter((r): r is string => r !== undefined))]
592
+ }
593
+
556
594
  /**
557
595
  * The repository's path on its host (`owner/repo`; a GitLab subgroup's
558
596
  * `group/sub/repo` whole, as `gitlab()` names it); undefined for a local path.
@@ -591,7 +629,7 @@ function gitConfigSections(workspaceRoot: string): Map<string, Map<string, strin
591
629
  * The run's cache scope (owner, 2026-10-17): `VX_CACHE_SCOPE` (empty: none),
592
630
  * else a plugin's (`setBranch`, `github()` on Actions; null: the plugin
593
631
  * named the run trusted), else, with a cache plugin to share it, the
594
- * branch's from git. Undefined: the default keys.
632
+ * branch's from git. Undefined: no scope. It keys plugin entries only.
595
633
  */
596
634
  export function resolveCacheScope(
597
635
  workspaceRoot: string,
@@ -810,6 +810,8 @@ async function runOnBus(
810
810
  localWrite: policy.localWrite,
811
811
  remote: remoteCacheEnabled && (policy.remoteRead || policy.remoteWrite),
812
812
  traffic: prepared.localCache.traffic,
813
+ downloads: prepared.localCache.downloads,
814
+ uploads: prepared.localCache.uploads,
813
815
  notDownloaded: () => deferredOutputs.pending().length,
814
816
  },
815
817
  concurrency,
@@ -97,9 +97,7 @@ export interface ComputeHashArgs {
97
97
  */
98
98
  export async function computeTaskHash(args: ComputeHashArgs): Promise<string> {
99
99
  if (isKeyless(args.node.config)) return keylessHash(args.node.id)
100
- const key = await taskHash(args)
101
- args.cache.noteKey?.(args.node.id, key)
102
- return key
100
+ return taskHash(args)
103
101
  }
104
102
 
105
103
  async function taskHash(args: ComputeHashArgs): Promise<string> {
@@ -10,6 +10,7 @@ import { isGroupTask } from '../graph/index.js'
10
10
  import {
11
11
  barWidth,
12
12
  ERROR,
13
+ formatBytes,
13
14
  formatElapsed,
14
15
  gradientRule,
15
16
  paint,
@@ -203,6 +204,9 @@ export interface RunContext {
203
204
  readonly inFlight: number
204
205
  readonly keys: ReadonlyMap<string, { uploading: number; failures: readonly string[] }>
205
206
  }
207
+ /** Bytes the run's remote hits pulled, and its landed uploads pushed (live refs). */
208
+ downloads?: { readonly bytes: number }
209
+ uploads?: { readonly bytes: number }
206
210
  /** Tasks whose outputs are still in the remote store. */
207
211
  notDownloaded: () => number
208
212
  }
@@ -335,9 +339,17 @@ export function formatSummarySection(
335
339
  ]
336
340
  // The layer words are dim; only the counts carry colour (M, 2026-10-15).
337
341
  if (local.length > 0) cacheParts.push(`${dim('local')} ${local.join(' ')}`)
342
+ // Each transfer count is followed by its bytes, dim: what the
343
+ // remote moved is the cost a hit or an upload paid.
344
+ const sized = (count: number, glyph: string, bytes: number | undefined): string[] =>
345
+ count === 0
346
+ ? []
347
+ : bytes === undefined || bytes === 0
348
+ ? n(count, glyph, REMOTE)
349
+ : [...n(count, glyph, REMOTE), dim(formatBytes(bytes))]
338
350
  const remote = [
339
- ...n(b.restoredRemote, '\u2193', REMOTE),
340
- ...n(b.uploaded, '\u2191', REMOTE),
351
+ ...sized(b.restoredRemote, '\u2193', layers.downloads?.bytes),
352
+ ...sized(b.uploaded, '\u2191', layers.uploads?.bytes),
341
353
  ...n(b.remoteFailed, '\u2717', ERROR),
342
354
  ...n(b.uploading, '\u21e1', ACCENT),
343
355
  ]
package/src/settings.ts CHANGED
@@ -127,7 +127,7 @@ export const SETTINGS: readonly Setting[] = [
127
127
  path: 'cache.scope',
128
128
  kind: { type: 'string' },
129
129
  default: "the branch's, `<owner>/<repo>:<branch>`, with a remote cache off `baseBranch`",
130
- doc: "A branch's remote entries (`'vznjs/vx:feat-x'`): tasks the branch changed read the scope's key, the rest the default key; the local cache never uses it. Empty: no scope.",
130
+ doc: "The branch scope plugin entries are keyed under (`'vznjs/vx:feat-x'`); task keys never carry it. Empty: no scope.",
131
131
  config: false,
132
132
  },
133
133
  {
@@ -192,12 +192,6 @@ export const SETTINGS: readonly Setting[] = [
192
192
  default: 'true',
193
193
  doc: 'Keep a larger entry as its plain files, which a hit copies or clones out; off, as one `.tar.zst`.',
194
194
  },
195
- {
196
- path: 'cache.store.verify',
197
- kind: { type: 'enum', values: ['stat', 'hash', 'none'] },
198
- default: 'stat',
199
- doc: "What a hit on plain files checks first: each file's size and mtime, every byte, or nothing.",
200
- },
201
195
  {
202
196
  path: 'cache.upload.failures',
203
197
  kind: { type: 'enum', values: ['ci', 'local', 'always'] },
@@ -14,7 +14,6 @@ import {
14
14
  gitSpawnRefusal,
15
15
  isExecutableMissing,
16
16
  isInstalledPath,
17
- isUserError,
18
17
  notAWorkTree,
19
18
  relPosix,
20
19
  UserError,
@@ -741,44 +740,6 @@ function noHistoryRefusal(workspaceRoot: string): UserError | undefined {
741
740
  return undefined
742
741
  }
743
742
 
744
- /**
745
- * What a branch changed, for which of its tasks read its cache scope
746
- * (owner, 2026-10-17): from `base` (a plugin's: a pull request's base
747
- * commit), else from the merge base with the base branch. No base, or
748
- * one git cannot resolve (a CI checkout at `fetch-depth: 1`), is no
749
- * change: every task reads the default key, which costs hits, never
750
- * correctness, since a key must still match.
751
- */
752
- export async function branchChanges(
753
- workspaceRoot: string,
754
- base: string | undefined,
755
- baseBranch: string | undefined,
756
- projects: Promise<readonly ProjectMeta[]>,
757
- /** The run's own enumeration, so the diff walks nothing a second time. */
758
- walked: Pick<AffectedArgs, 'untracked' | 'links'> = {},
759
- ): Promise<AffectedChanges> {
760
- const none: AffectedChanges = {
761
- projects: new Set(),
762
- changed: [],
763
- paths: new Map(),
764
- whole: new Set(),
765
- }
766
- const since = base ?? (await baseBranchRef(workspaceRoot, baseBranch))?.ref
767
- if (since === undefined) return none
768
- try {
769
- return await affectedChanges({
770
- workspaceRoot,
771
- since,
772
- projects,
773
- configImports: false,
774
- ...walked,
775
- })
776
- } catch (err) {
777
- if (!isUserError(err)) throw err
778
- return none
779
- }
780
- }
781
-
782
743
  /**
783
744
  * The base branch as a ref: `origin/<name>`, else the local branch (a
784
745
  * clone with no remote), and whether HEAD is on it. The name is the
@@ -6,7 +6,6 @@ export {
6
6
  type AffectedChanges,
7
7
  affectedProjects,
8
8
  defaultAffectedBase,
9
- branchChanges,
10
9
  type FingerprintClaims,
11
10
  refIsHead,
12
11
  } from './affected.js'