@brainervirus/workit-cursor 7.0.0 → 7.2.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.
@@ -16576,7 +16576,7 @@ class StdioServerTransport {
16576
16576
  import { fileURLToPath as fileURLToPath2 } from "node:url";
16577
16577
 
16578
16578
  // packages/workit-core/src/core.ts
16579
- import { spawnSync as spawnSync11 } from "node:child_process";
16579
+ import { spawnSync as spawnSync12 } from "node:child_process";
16580
16580
  import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
16581
16581
  import path19 from "node:path";
16582
16582
 
@@ -21262,6 +21262,11 @@ function worktreeSignal(cwd, options = {}) {
21262
21262
  }
21263
21263
  return `sig:${hash.digest("hex")}`;
21264
21264
  }
21265
+ function mergeBase(cwd, a, b) {
21266
+ if (!safeArg(a) || !safeArg(b))
21267
+ return null;
21268
+ return line(git2(cwd, ["merge-base", a, b]));
21269
+ }
21265
21270
  function patchId(cwd, base, head) {
21266
21271
  if (!safeArg(base) || !safeArg(head))
21267
21272
  return null;
@@ -21285,9 +21290,33 @@ function patchId(cwd, base, head) {
21285
21290
  const id = git2(cwd, ["patch-id", "--stable"], { input: diff.stdout });
21286
21291
  return line(id)?.split(/\s+/u)[0] ?? null;
21287
21292
  }
21293
+ function remoteNames(cwd) {
21294
+ return (git2(cwd, ["remote"]).stdout ?? "").split(/\r?\n/u).map((value) => value.trim()).filter(Boolean);
21295
+ }
21296
+ function resolveRef(cwd, ref) {
21297
+ if (!safeArg(ref))
21298
+ return null;
21299
+ return line(git2(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
21300
+ }
21301
+ var config2 = (cwd, key) => line(git2(cwd, ["config", "--get", key]));
21288
21302
  function currentBranch(cwd) {
21289
21303
  return line(git2(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
21290
21304
  }
21305
+ function pushRemoteName(cwd, branch) {
21306
+ const name = branch ?? currentBranch(cwd);
21307
+ const remotes = remoteNames(cwd);
21308
+ const candidates = [
21309
+ name ? config2(cwd, `branch.${name}.pushRemote`) : null,
21310
+ config2(cwd, "remote.pushDefault"),
21311
+ name ? config2(cwd, `branch.${name}.remote`) : null
21312
+ ];
21313
+ for (const candidate of candidates)
21314
+ if (candidate && candidate !== "." && remotes.includes(candidate))
21315
+ return candidate;
21316
+ if (remotes.includes("origin"))
21317
+ return "origin";
21318
+ return remotes.length === 1 ? remotes[0] : null;
21319
+ }
21291
21320
 
21292
21321
  // packages/workit-core/src/core/policy/derive.ts
21293
21322
  import { existsSync as existsSync3 } from "node:fs";
@@ -22901,6 +22930,8 @@ var readConfig = () => {
22901
22930
  throw new Error(result.error);
22902
22931
  return result.config ?? DEFAULTS;
22903
22932
  };
22933
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path12.join(configDir(), "vcs.json");
22934
+ var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
22904
22935
  var resolveBranchPolicy = (config, workspace) => {
22905
22936
  const wp = workspace?.branchPolicy ?? {};
22906
22937
  const preset = Object.hasOwn(PRESETS, wp.preset) ? wp.preset : config.branchPolicy?.preset ?? "gitflow";
@@ -22908,7 +22939,7 @@ var resolveBranchPolicy = (config, workspace) => {
22908
22939
  allowed: wp.allowed,
22909
22940
  protectedNames: wp.protected
22910
22941
  }, config);
22911
- const allowed = merged.allowed.map((p) => new RegExp(`^${p.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i"));
22942
+ const allowed = merged.allowed.map(branchGlobPattern);
22912
22943
  return {
22913
22944
  preset,
22914
22945
  allowed,
@@ -22925,16 +22956,6 @@ var COMMIT_PRESETS = [
22925
22956
  "custom",
22926
22957
  "auto"
22927
22958
  ];
22928
- var resolveCommitPolicy = (config, workspace) => {
22929
- const wp = workspace?.commitPolicy ?? {};
22930
- if (COMMIT_PRESETS.includes(String(wp.preset ?? ""))) {
22931
- return {
22932
- preset: wp.preset,
22933
- ...typeof wp.pattern === "string" ? { pattern: wp.pattern } : {}
22934
- };
22935
- }
22936
- return config.commitPolicy ?? { preset: "conventional" };
22937
- };
22938
22959
 
22939
22960
  // packages/workit-core/src/core/workspaces.ts
22940
22961
  import { createHash as createHash8 } from "node:crypto";
@@ -22973,26 +22994,31 @@ var versionSourceSchema = discriminatedUnion("kind", [
22973
22994
  object2({ kind: literal("manual") }).strict()
22974
22995
  ]);
22975
22996
  var releaseTrackSchema = object2({
22976
- strategy: branchPreset,
22997
+ strategy: branchPreset.optional(),
22977
22998
  productionBranch: nonBlank,
22978
22999
  integrationBranch: nonBlank,
22979
- naming: object2({ feature: nonBlank, release: nonBlank, hotfix: nonBlank }).strict(),
22980
- baseBranch: nonBlank,
22981
- mergeBackBranches: array(nonBlank),
22982
- pullRequestTarget: nonBlank,
22983
- tagNamespace: string2(),
22984
- versionSource: versionSourceSchema,
22985
- requiredChecks: array(nonBlank)
22986
- }).strict().superRefine((track, context) => {
23000
+ naming: object2({
23001
+ feature: nonBlank.optional(),
23002
+ release: nonBlank.optional(),
23003
+ hotfix: nonBlank.optional()
23004
+ }).passthrough().optional(),
23005
+ baseBranch: nonBlank.optional(),
23006
+ mergeBackBranches: array(nonBlank).optional(),
23007
+ pullRequestTarget: nonBlank.optional(),
23008
+ tagNamespace: string2().optional(),
23009
+ versionSource: versionSourceSchema.optional(),
23010
+ requiredChecks: array(nonBlank).optional(),
23011
+ critical: array(nonBlank).optional()
23012
+ }).passthrough().superRefine((track, context) => {
22987
23013
  for (const [field, values] of [
22988
- ["mergeBackBranches", track.mergeBackBranches],
22989
- ["requiredChecks", track.requiredChecks]
23014
+ ["mergeBackBranches", track.mergeBackBranches ?? []],
23015
+ ["requiredChecks", track.requiredChecks ?? []]
22990
23016
  ]) {
22991
23017
  if (new Set(values).size !== values.length) {
22992
23018
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
22993
23019
  }
22994
23020
  }
22995
- if (track.versionSource.kind === "package-json" && (path13.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
23021
+ if (track.versionSource?.kind === "package-json" && (path13.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
22996
23022
  context.addIssue({
22997
23023
  code: "custom",
22998
23024
  path: ["versionSource", "path"],
@@ -23010,7 +23036,7 @@ var workspaceConfigSchema = object2({
23010
23036
  account: nonBlank.optional()
23011
23037
  }).passthrough().optional(),
23012
23038
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
23013
- defaultEndpoint: _enum(["commit", "pr"]).optional(),
23039
+ defaultEndpoint: unknown().optional(),
23014
23040
  verification: _enum(["self", "independent"]).optional(),
23015
23041
  autonomy: object2(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
23016
23042
  kind,
@@ -23260,7 +23286,7 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
23260
23286
  var runtimeWorkspaceIndexSchema = object2({
23261
23287
  workspaces: array(object2({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
23262
23288
  }).passthrough();
23263
- var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
23289
+ var matchRuntimeWorkspace = (cwd) => {
23264
23290
  const file = path13.join(configDir(), "workspaces.json");
23265
23291
  let raw;
23266
23292
  try {
@@ -23295,8 +23321,17 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
23295
23321
  });
23296
23322
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
23297
23323
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
23298
- if (!selected)
23324
+ return selected ? { file, selected } : null;
23325
+ };
23326
+ var resolveRuntimeReleaseTracks = (cwd) => {
23327
+ const matched = matchRuntimeWorkspace(cwd);
23328
+ return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
23329
+ };
23330
+ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
23331
+ const matched = matchRuntimeWorkspace(cwd);
23332
+ if (!matched)
23299
23333
  return null;
23334
+ const { file, selected } = matched;
23300
23335
  const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
23301
23336
  if (!policy.success) {
23302
23337
  const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
@@ -23322,15 +23357,410 @@ var resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
23322
23357
  source: profilePolicy ? `profile:${profileName}` : workspacePolicy ? `workspace:${candidate.name}` : "user-default"
23323
23358
  };
23324
23359
  };
23360
+ function workspaceDefaultTarget(cwd, globalDefault) {
23361
+ const ws = resolveRuntimeWorkspaceVcs(cwd);
23362
+ const wp = ws?.branchPolicy ?? {};
23363
+ const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
23364
+ const selected = resolveRuntimeWorkspacePolicy(cwd, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined);
23365
+ const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null).defaultTargetBranch;
23366
+ return String(ws?.vcs?.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : globalDefault ?? policyDefault) ?? "develop");
23367
+ }
23325
23368
 
23326
23369
  // packages/workit-core/src/core/vcs-config.ts
23327
23370
  import fs12 from "node:fs";
23328
23371
  import path14 from "node:path";
23372
+ import { spawnSync as spawnSync8 } from "node:child_process";
23373
+
23374
+ // packages/workit-core/src/core/release-tracks.ts
23375
+ import { createHash as createHash9 } from "node:crypto";
23329
23376
  import { spawnSync as spawnSync7 } from "node:child_process";
23330
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path14.join(configDir(), "vcs.json");
23377
+ var KNOWN_FIELDS = new Set([
23378
+ "strategy",
23379
+ "productionBranch",
23380
+ "integrationBranch",
23381
+ "naming",
23382
+ "baseBranch",
23383
+ "mergeBackBranches",
23384
+ "pullRequestTarget",
23385
+ "tagNamespace",
23386
+ "versionSource",
23387
+ "requiredChecks",
23388
+ "critical"
23389
+ ]);
23390
+ var BRANCH_FIELDS = ["productionBranch", "integrationBranch", "baseBranch", "pullRequestTarget"];
23391
+ var PLACEHOLDER = /\{[^}]*\}/gu;
23392
+ var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
23393
+ var branchName = (value) => typeof value === "string" && value.trim() && !value.trim().startsWith("-") ? value.trim() : null;
23394
+ var namedBranches = (entry) => [
23395
+ ...BRANCH_FIELDS.map((field) => branchName(entry[field])),
23396
+ ...Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : []
23397
+ ].filter((name) => name !== null);
23398
+ var literalOf = (template) => template.replace(PLACEHOLDER, "").replace(/[*/]/gu, "").trim();
23399
+ function readReleaseTracks(raw) {
23400
+ const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
23401
+ if (raw === undefined || raw === null)
23402
+ return out;
23403
+ if (!isRecord3(raw)) {
23404
+ out.issues.push("releaseTracks is not an object; ignored");
23405
+ return out;
23406
+ }
23407
+ const fatal = [];
23408
+ const protectedNames = new Set;
23409
+ for (const [name, entry] of Object.entries(raw).toSorted(([a], [b]) => a < b ? -1 : 1)) {
23410
+ const label = `release track ${JSON.stringify(name)}`;
23411
+ if (!isRecord3(entry)) {
23412
+ out.issues.push(`${label} is not an object; ignored`);
23413
+ continue;
23414
+ }
23415
+ for (const branch of namedBranches(entry))
23416
+ protectedNames.add(branch);
23417
+ if (!name.trim()) {
23418
+ out.issues.push("a release track with a blank name was ignored");
23419
+ continue;
23420
+ }
23421
+ let critical = [];
23422
+ if (Array.isArray(entry.critical))
23423
+ critical = entry.critical.filter((item) => typeof item === "string");
23424
+ else if (entry.critical !== undefined)
23425
+ out.issues.push(`${label} critical: must be a list of field names; ignored`);
23426
+ const isCritical = (field) => critical.some((item) => field === item || field.startsWith(`${item}.`));
23427
+ const problem = (field, message) => {
23428
+ if (isCritical(field))
23429
+ fatal.push(`${label} ${field}: ${message}`);
23430
+ else
23431
+ out.issues.push(`${label} ${field}: ${message}`);
23432
+ };
23433
+ for (const key of Object.keys(entry))
23434
+ if (!KNOWN_FIELDS.has(key))
23435
+ problem(key, "unknown field, ignored");
23436
+ const productionBranch = branchName(entry.productionBranch);
23437
+ const integrationBranch = branchName(entry.integrationBranch);
23438
+ if (!productionBranch)
23439
+ problem("productionBranch", "missing or not a branch name");
23440
+ if (!integrationBranch)
23441
+ problem("integrationBranch", "missing or not a branch name");
23442
+ const optionalBranch = (field) => {
23443
+ if (entry[field] === undefined)
23444
+ return null;
23445
+ const value = branchName(entry[field]);
23446
+ if (!value)
23447
+ problem(field, "not a branch name; using the integration branch");
23448
+ return value;
23449
+ };
23450
+ const baseBranch = optionalBranch("baseBranch");
23451
+ const pullRequestTarget = optionalBranch("pullRequestTarget");
23452
+ let mergeBackBranches = [];
23453
+ if (entry.mergeBackBranches !== undefined) {
23454
+ const list = Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : [null];
23455
+ if (list.some((item) => item === null))
23456
+ problem("mergeBackBranches", "must be a list of branch names; ignored");
23457
+ else
23458
+ mergeBackBranches = [...new Set(list)];
23459
+ }
23460
+ const naming = {};
23461
+ if (entry.naming !== undefined) {
23462
+ if (!isRecord3(entry.naming))
23463
+ problem("naming", "not an object; ignored");
23464
+ else
23465
+ for (const kind of ["feature", "release", "hotfix"]) {
23466
+ const template = entry.naming[kind];
23467
+ if (template === undefined)
23468
+ continue;
23469
+ if (typeof template !== "string" || !template.trim())
23470
+ problem(`naming.${kind}`, "not a template string; ignored");
23471
+ else if (!literalOf(template))
23472
+ problem(`naming.${kind}`, "needs literal text besides placeholders; ignored");
23473
+ else
23474
+ naming[kind] = template.trim();
23475
+ }
23476
+ }
23477
+ if (!productionBranch || !integrationBranch) {
23478
+ out.issues.push(`${label} was skipped: it needs a productionBranch and integrationBranch`);
23479
+ continue;
23480
+ }
23481
+ out.tracks.push({
23482
+ name,
23483
+ productionBranch,
23484
+ integrationBranch,
23485
+ baseBranch: baseBranch ?? integrationBranch,
23486
+ pullRequestTarget: pullRequestTarget ?? integrationBranch,
23487
+ mergeBackBranches,
23488
+ naming
23489
+ });
23490
+ }
23491
+ out.protectedBranches = [...protectedNames];
23492
+ if (fatal.length)
23493
+ out.error = `workspace releaseTracks cannot be read by this Workit (${fatal.join("; ")}); upgrade Workit or fix the track`;
23494
+ return out;
23495
+ }
23496
+ var IMPLICIT = "";
23497
+ var ownedBy = (tracks, branch) => tracks.filter((track) => [track.integrationBranch, track.productionBranch, track.baseBranch].includes(branch));
23498
+ var shortRef = (ref, remotes) => {
23499
+ const bare = ref.replace(/^refs\/heads\//u, "").replace(/^refs\/remotes\/[^/]+\//u, "");
23500
+ const remote = remotes.find((name) => bare.startsWith(`${name}/`));
23501
+ return remote ? bare.slice(remote.length + 1) : bare;
23502
+ };
23503
+ var MAX_RECORDED_HOPS = 10;
23504
+ function resolveReleaseTrack(input) {
23505
+ const tracks = [...input.tracks];
23506
+ const issues = [...input.issues ?? []];
23507
+ const requested = input.requested?.trim();
23508
+ if (tracks.length === 0) {
23509
+ if (requested)
23510
+ return {
23511
+ status: "invalid",
23512
+ error: `no release tracks configured for this workspace; --track ${requested} cannot apply`,
23513
+ issues
23514
+ };
23515
+ return { status: "none", issues };
23516
+ }
23517
+ const names = tracks.map((track) => track.name).join(", ");
23518
+ let envProblem = null;
23519
+ const done = (track, source, detail, warnings = [], ambiguous = null) => ({
23520
+ status: "resolved",
23521
+ track: track && track.name !== IMPLICIT ? track : null,
23522
+ source,
23523
+ detail,
23524
+ warnings: [...issues, ...envProblem ? [envProblem] : [], ...warnings],
23525
+ tracks,
23526
+ blocking: envProblem ?? ambiguous
23527
+ });
23528
+ if (requested) {
23529
+ const named = tracks.find((track) => track.name === requested);
23530
+ if (!named)
23531
+ return {
23532
+ status: "invalid",
23533
+ error: `no release track ${JSON.stringify(requested)}; configured: ${names}`,
23534
+ issues
23535
+ };
23536
+ return done(named, "flag", `track ${named.name} was requested explicitly`);
23537
+ }
23538
+ const owned = (branch) => branch !== null && tracks.some((track) => [
23539
+ track.integrationBranch,
23540
+ track.productionBranch,
23541
+ track.baseBranch,
23542
+ track.pullRequestTarget
23543
+ ].includes(branch));
23544
+ const implicit = input.defaultBranch && !owned(input.defaultBranch) ? {
23545
+ name: IMPLICIT,
23546
+ productionBranch: input.defaultBranch,
23547
+ integrationBranch: input.defaultBranch,
23548
+ baseBranch: input.defaultBranch,
23549
+ pullRequestTarget: input.defaultBranch,
23550
+ mergeBackBranches: [],
23551
+ naming: {}
23552
+ } : null;
23553
+ const candidates = implicit ? [...tracks, implicit] : tracks;
23554
+ const label = (track) => track.name === IMPLICIT ? `the workspace default line (${track.integrationBranch})` : `track ${track.name}`;
23555
+ const fallback = (why) => {
23556
+ const byDefault = input.defaultBranch ? tracks.filter((track) => track.integrationBranch === input.defaultBranch || track.pullRequestTarget === input.defaultBranch) : [];
23557
+ const track = byDefault.length === 1 ? byDefault[0] : null;
23558
+ const target = track ? `track ${track.name}` : `default target ${input.defaultBranch ?? "(none)"}`;
23559
+ const ambiguous = candidates.length >= 2 ? `can't tell which release line ${input.branch ?? "HEAD"} is on (${why}); pass --track <name> (${names}) or --base <branch>` : null;
23560
+ return done(track, "default", `${why}; using the workspace ${target}`, [
23561
+ `release track not determined: ${why}; using the workspace ${target} (pass --track <name> to choose)`
23562
+ ], ambiguous);
23563
+ };
23564
+ const branch = input.branch;
23565
+ if (branch) {
23566
+ const owners = ownedBy(candidates, branch);
23567
+ if (owners.length === 1)
23568
+ return done(owners[0], "branch", `${branch} is a branch of ${label(owners[0])}`);
23569
+ if (owners.length > 1)
23570
+ return fallback(`${branch} belongs to more than one track (${owners.map((track) => track.name).join(", ")})`);
23571
+ }
23572
+ const env = input.envRequested?.trim();
23573
+ if (env) {
23574
+ const named = tracks.find((track) => track.name === env);
23575
+ if (named)
23576
+ return done(named, "env", `WORKFLOW_RELEASE_TRACK selects track ${named.name}`);
23577
+ envProblem = `WORKFLOW_RELEASE_TRACK=${env} names no release track of this workspace (${names}); ignored`;
23578
+ }
23579
+ if (!branch)
23580
+ return fallback("HEAD is detached");
23581
+ if (tracks.length === 1 && !implicit)
23582
+ return done(tracks[0], "only-track", `${tracks[0].name} is the only track`);
23583
+ let remotes = null;
23584
+ const short = (ref) => shortRef(ref, remotes ??= input.probe.remotes());
23585
+ const ownerOf = (ref) => {
23586
+ const owner = ownedBy(candidates, short(ref));
23587
+ return owner.length === 1 ? owner[0] : null;
23588
+ };
23589
+ const followRecorded = (start) => {
23590
+ let cursor = start;
23591
+ const seen = new Set([start]);
23592
+ for (let hop = 0;hop < MAX_RECORDED_HOPS; hop += 1) {
23593
+ const recorded = input.probe.recordedBase(cursor);
23594
+ if (!recorded)
23595
+ return null;
23596
+ const base = short(recorded);
23597
+ const owner = ownerOf(base);
23598
+ if (owner)
23599
+ return owner;
23600
+ if (ownedBy(candidates, base).length > 1 || seen.has(base))
23601
+ return null;
23602
+ seen.add(base);
23603
+ cursor = base;
23604
+ }
23605
+ return null;
23606
+ };
23607
+ const recordedOwner = followRecorded(branch);
23608
+ if (recordedOwner)
23609
+ return done(recordedOwner, "recorded-base", `${branch} was created on ${label(recordedOwner)}'s line (recorded base)`);
23610
+ for (const source of ["reflog", "checkout"]) {
23611
+ const ref = source === "reflog" ? input.probe.createdFrom(branch) : input.probe.checkedOutFrom(branch);
23612
+ if (!ref)
23613
+ continue;
23614
+ const owner = ownerOf(ref) ?? followRecorded(short(ref));
23615
+ if (owner)
23616
+ return done(owner, source, `${branch} was created from ${short(ref)} (${source === "reflog" ? "branch reflog" : "HEAD reflog"})`);
23617
+ }
23618
+ const forks = [];
23619
+ for (const track of candidates)
23620
+ for (const ref of new Set([track.integrationBranch, track.baseBranch])) {
23621
+ const sha = input.probe.mergeBase(branch, ref);
23622
+ if (sha)
23623
+ forks.push({ track, ref, sha });
23624
+ }
23625
+ if (forks.length === 0)
23626
+ return fallback(`no track branch could be compared with ${branch} (fetch the track branches)`);
23627
+ const ancestry = new Map;
23628
+ const descends = (older, newer) => {
23629
+ if (older === newer)
23630
+ return false;
23631
+ const key = `${older}>${newer}`;
23632
+ if (!ancestry.has(key))
23633
+ ancestry.set(key, input.probe.isAncestor(older, newer));
23634
+ return ancestry.get(key);
23635
+ };
23636
+ const winners = forks.filter((fork) => forks.every((other) => other.track === fork.track || descends(other.sha, fork.sha)));
23637
+ const winningTracks = [...new Set(winners.map((fork) => fork.track))];
23638
+ if (winningTracks.length === 1 && forks.some((fork) => fork.track !== winningTracks[0])) {
23639
+ const win = winners[0];
23640
+ return done(win.track, "ancestry", `${branch} forked from ${win.ref} at ${win.sha.slice(0, 12)}, after every other line's fork point`);
23641
+ }
23642
+ if (winningTracks.length === 1)
23643
+ return fallback(`only ${label(winningTracks[0])} could be compared with ${branch}`);
23644
+ const newest = forks.filter((fork) => !forks.some((other) => descends(fork.sha, other.sha)));
23645
+ return fallback(`${branch} has the same or unrelated fork points with ${[...new Set(newest.map((fork) => `${fork.ref} (${fork.track.name === IMPLICIT ? "workspace default" : fork.track.name})`))].join(" and ")}`);
23646
+ }
23647
+ var git4 = (cwd, args) => {
23648
+ const run = spawnSync7("git", args, {
23649
+ cwd,
23650
+ encoding: "utf8",
23651
+ timeout: 20000,
23652
+ windowsHide: true,
23653
+ stdio: ["ignore", "pipe", "ignore"]
23654
+ });
23655
+ return run.status === 0 ? (run.stdout ?? "").trim() : null;
23656
+ };
23657
+ var recordedBaseKey = (branch) => `branch.${branch}.workitBase`;
23658
+ var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
23659
+ var reflog = (cwd, ref) => (git4(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
23660
+ `).map((line) => {
23661
+ const [sha = "", selector = "", ...subject] = line.split("\t");
23662
+ return {
23663
+ sha,
23664
+ time: Number(/@\{(\d+)\}$/u.exec(selector)?.[1] ?? Number.NaN),
23665
+ subject: subject.join("\t")
23666
+ };
23667
+ }).filter((entry) => entry.sha && Number.isFinite(entry.time));
23668
+ function gitTrackProbe(cwd) {
23669
+ let remote;
23670
+ let remotes;
23671
+ const tip = (branch) => {
23672
+ remote ??= pushRemoteName(cwd) ?? "origin";
23673
+ return resolveRef(cwd, `refs/remotes/${remote}/${branch}`) ?? resolveRef(cwd, `refs/heads/${branch}`);
23674
+ };
23675
+ return {
23676
+ remotes: () => remotes ??= remoteNames(cwd),
23677
+ recordedBase: (branch) => git4(cwd, ["config", "--get", recordedBaseKey(branch)]) || null,
23678
+ createdFrom: (branch) => {
23679
+ const log = git4(cwd, ["reflog", "show", "--format=%gs", `refs/heads/${branch}`, "--"]);
23680
+ const oldest = log?.split(`
23681
+ `).findLast(Boolean) ?? "";
23682
+ const match = /^branch: Created from (\S+)$/u.exec(oldest);
23683
+ return match && match[1] !== "HEAD" ? match[1] : null;
23684
+ },
23685
+ checkedOutFrom: (branch) => {
23686
+ const own = reflog(cwd, `refs/heads/${branch}`);
23687
+ const created = own.at(-1);
23688
+ if (!created || created.subject !== "branch: Created from HEAD")
23689
+ return null;
23690
+ const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp(branch)}$`, "u");
23691
+ const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
23692
+ return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
23693
+ },
23694
+ mergeBase: (branch, trackBranch) => {
23695
+ const base = tip(trackBranch);
23696
+ return base && resolveRef(cwd, `refs/heads/${branch}`) ? mergeBase(cwd, base, `refs/heads/${branch}`) : null;
23697
+ },
23698
+ isAncestor: (ancestor, descendant) => git4(cwd, ["merge-base", "--is-ancestor", ancestor, descendant]) !== null
23699
+ };
23700
+ }
23701
+ function workspaceReleaseTracks(cwd) {
23702
+ const raw = resolveRuntimeReleaseTracks(cwd);
23703
+ return { workspace: raw?.workspace ?? null, ...readReleaseTracks(raw?.releaseTracks) };
23704
+ }
23705
+ var memo3 = new Map;
23706
+ var MEMO_LIMIT = 64;
23707
+ function resolveTrackFor(cwd, options) {
23708
+ const read = workspaceReleaseTracks(cwd);
23709
+ if (read.error)
23710
+ return { status: "invalid", error: read.error, issues: read.issues };
23711
+ if (read.tracks.length === 0 && !options.track?.trim())
23712
+ return { status: "none", issues: read.issues };
23713
+ const branch = options.branch === undefined ? currentBranch(cwd) : options.branch;
23714
+ const envRequested = process.env.WORKFLOW_RELEASE_TRACK?.trim() || null;
23715
+ const input = {
23716
+ tracks: read.tracks,
23717
+ requested: options.track ?? null,
23718
+ envRequested,
23719
+ branch,
23720
+ defaultBranch: options.defaultBranch,
23721
+ issues: read.issues
23722
+ };
23723
+ let key = null;
23724
+ if (!options.probe) {
23725
+ const refs = git4(cwd, [
23726
+ "for-each-ref",
23727
+ "--format=%(refname) %(objectname)",
23728
+ "refs/heads",
23729
+ "refs/remotes"
23730
+ ]) ?? "";
23731
+ const head = git4(cwd, ["reflog", "show", "-n", "1", "--format=%H %gs", "HEAD", "--"]) ?? "";
23732
+ const own = branch ? [
23733
+ git4(cwd, [
23734
+ "log",
23735
+ "-g",
23736
+ "-n",
23737
+ "1",
23738
+ "--date=unix",
23739
+ "--format=%H %gd %gs",
23740
+ `refs/heads/${branch}`,
23741
+ "--"
23742
+ ]) ?? "",
23743
+ git4(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
23744
+ ] : [];
23745
+ key = createHash9("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
23746
+ const hit = memo3.get(key);
23747
+ if (hit)
23748
+ return hit;
23749
+ }
23750
+ const resolution = resolveReleaseTrack({ ...input, probe: options.probe ?? gitTrackProbe(cwd) });
23751
+ if (key) {
23752
+ if (memo3.size >= MEMO_LIMIT)
23753
+ memo3.delete(memo3.keys().next().value);
23754
+ memo3.set(key, resolution);
23755
+ }
23756
+ return resolution;
23757
+ }
23758
+
23759
+ // packages/workit-core/src/core/vcs-config.ts
23760
+ var workspacesPath = () => path14.join(configDir(), "workspaces.json");
23331
23761
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
23332
23762
  var remoteProvider = (cwd) => {
23333
- const r = spawnSync7("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
23763
+ const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
23334
23764
  if (r.status !== 0)
23335
23765
  return null;
23336
23766
  const url = (r.stdout ?? "").trim();
@@ -23367,7 +23797,7 @@ var remoteEndpoint = (remote) => {
23367
23797
  var configuredSshEndpoint = (host) => {
23368
23798
  if (host.startsWith("-"))
23369
23799
  return null;
23370
- const resolved = spawnSync7("ssh", ["-G", host], {
23800
+ const resolved = spawnSync8("ssh", ["-G", host], {
23371
23801
  encoding: "utf8",
23372
23802
  timeout: 5000,
23373
23803
  maxBuffer: 1024 * 1024,
@@ -23432,7 +23862,16 @@ var readVcsConfig = () => {
23432
23862
  }
23433
23863
  return { status: "malformed", path: file, config: {}, error: `${file} is not a JSON object` };
23434
23864
  };
23435
- function vcsConfig(mode, cwd) {
23865
+ var trackSummary = (resolution) => resolution.status === "resolved" ? {
23866
+ name: resolution.track?.name ?? null,
23867
+ source: resolution.source,
23868
+ detail: resolution.detail,
23869
+ warnings: resolution.warnings,
23870
+ track: resolution.track,
23871
+ tracks: resolution.tracks,
23872
+ blocking: resolution.blocking
23873
+ } : null;
23874
+ function vcsConfig(mode, cwd, options = {}) {
23436
23875
  const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
23437
23876
  const wsVcs = ws?.vcs ?? {};
23438
23877
  const wsYt = ws?.youtrack ?? {};
@@ -23442,10 +23881,7 @@ function vcsConfig(mode, cwd) {
23442
23881
  const determinateRoot = cwd !== undefined || process.env.WORKFLOW_WORKSPACE_ROOT !== undefined;
23443
23882
  const rawProvider = wsVcs.provider ?? (determinateRoot ? remoteProvider(root) : null) ?? cfg.provider ?? null;
23444
23883
  const provider = rawProvider === null || rawProvider === undefined ? null : String(rawProvider).toLowerCase() || null;
23445
- const wp = ws?.branchPolicy ?? {};
23446
- const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
23447
- const policyDefault = resolveBranchPolicyFor(root).defaultTargetBranch;
23448
- const defaultTarget = String(wsVcs.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : cfg.defaultTargetBranch ?? policyDefault) ?? "develop");
23884
+ const workspaceDefault = workspaceDefaultTarget(root, cfg.defaultTargetBranch);
23449
23885
  const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
23450
23886
  const youtrackBaseUrl = typeof wsYt.baseUrl === "string" ? wsYt.baseUrl : null;
23451
23887
  let issuesProvider = null;
@@ -23457,11 +23893,24 @@ function vcsConfig(mode, cwd) {
23457
23893
  if (mode === "resolve") {
23458
23894
  if (cfgStatus === "malformed")
23459
23895
  return { ok: false, error: cfgError, configPath: cfgPath };
23896
+ const trackResolution = resolveTrackFor(root, {
23897
+ track: options.track,
23898
+ ...options.branch !== undefined ? { branch: options.branch } : {},
23899
+ defaultBranch: workspaceDefault
23900
+ });
23901
+ if (trackResolution.status === "invalid")
23902
+ return { ok: false, error: trackResolution.error, configPath: workspacesPath() };
23903
+ const releaseTrack = trackSummary(trackResolution);
23904
+ const defaultTarget = releaseTrack?.track?.pullRequestTarget ?? workspaceDefault;
23905
+ const baseBranch = releaseTrack?.track?.baseBranch ?? defaultTarget;
23460
23906
  return {
23461
23907
  ok: true,
23462
23908
  workspace_name: ws?.name ?? null,
23463
23909
  provider,
23464
23910
  defaultTargetBranch: defaultTarget,
23911
+ workspaceDefaultTargetBranch: workspaceDefault,
23912
+ baseBranch,
23913
+ releaseTrack,
23465
23914
  link_issues: linkIssues,
23466
23915
  youtrack_base_url: youtrackBaseUrl,
23467
23916
  issues_provider: issuesProvider,
@@ -23485,7 +23934,7 @@ function vcsConfig(mode, cwd) {
23485
23934
  ok: true,
23486
23935
  configPath: path14.resolve(cfgPath),
23487
23936
  provider,
23488
- defaultTargetBranch: defaultTarget,
23937
+ defaultTargetBranch: workspaceDefault,
23489
23938
  pr: cfg.pr ?? {},
23490
23939
  workspace_name: ws?.name ?? null,
23491
23940
  link_issues: linkIssues,
@@ -23521,7 +23970,7 @@ function mergedPrStyle(limit = 6, cwd) {
23521
23970
  `).filter((l) => l.startsWith("## ")).map((l) => l.trim()),
23522
23971
  descriptionPreview: desc.slice(0, 600)
23523
23972
  });
23524
- const remoteResult = spawnSync7("git", ["remote", "get-url", "--push", "--all", "origin"], {
23973
+ const remoteResult = spawnSync8("git", ["remote", "get-url", "--push", "--all", "origin"], {
23525
23974
  cwd,
23526
23975
  encoding: "utf8"
23527
23976
  });
@@ -23537,7 +23986,7 @@ function mergedPrStyle(limit = 6, cwd) {
23537
23986
  if (!hostingApiHostMatches(remote, host))
23538
23987
  return { ok: false, error: "PR style target does not match the provider host" };
23539
23988
  if (provider === "gitlab") {
23540
- const run = (args) => spawnSync7("glab", ["api", ...args], {
23989
+ const run = (args) => spawnSync8("glab", ["api", ...args], {
23541
23990
  cwd,
23542
23991
  encoding: "utf8",
23543
23992
  env
@@ -23557,7 +24006,7 @@ function mergedPrStyle(limit = 6, cwd) {
23557
24006
  });
23558
24007
  }
23559
24008
  } else if (provider === "github") {
23560
- const r = spawnSync7("gh", [
24009
+ const r = spawnSync8("gh", [
23561
24010
  "pr",
23562
24011
  "list",
23563
24012
  "--repo",
@@ -23588,20 +24037,6 @@ function mergedPrStyle(limit = 6, cwd) {
23588
24037
  examples
23589
24038
  };
23590
24039
  }
23591
-
23592
- // packages/workit-core/src/core/branch.ts
23593
- function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
23594
- const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
23595
- const config = readConfig();
23596
- return kind === "branch" ? {
23597
- branchPolicy: resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null),
23598
- provenance: { branchPolicy: selected.source }
23599
- } : {
23600
- commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
23601
- provenance: { commitPolicy: selected.source }
23602
- };
23603
- }
23604
- var resolveBranchPolicyFor = (workspaceRoot, profileName) => effectiveWorkspacePolicy(workspaceRoot, "branch", profileName).branchPolicy;
23605
24040
  // packages/workit-core/src/core/task-engine.ts
23606
24041
  import { realpathSync as realpathSync4 } from "node:fs";
23607
24042
 
@@ -23809,10 +24244,51 @@ var DEFAULT_GRANTS = Object.freeze({
23809
24244
  release: false,
23810
24245
  rerun: true
23811
24246
  });
24247
+ var DEFAULT_ENDPOINTS = ["commit", "pr", "green", "merged"];
23812
24248
  var DEFAULT_ENDPOINT = "commit";
24249
+ var isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value);
24250
+ function endpointOf(entry) {
24251
+ const raw = entry?.defaultEndpoint;
24252
+ if (raw === undefined)
24253
+ return { raw, endpoint: DEFAULT_ENDPOINT };
24254
+ if (isDefaultEndpoint(raw))
24255
+ return { raw, endpoint: raw };
24256
+ return {
24257
+ raw,
24258
+ endpoint: DEFAULT_ENDPOINT,
24259
+ issue: `defaultEndpoint ${JSON.stringify(raw)} is not one of ${DEFAULT_ENDPOINTS.join(", ")}; using ${DEFAULT_ENDPOINT}`
24260
+ };
24261
+ }
24262
+ function effectiveEndpoint(endpoint, context) {
24263
+ if (endpoint === "commit")
24264
+ return { endpoint };
24265
+ const missing = (kind) => `${kind} grant missing; ${grantHint(context.workspace, kind)}`;
24266
+ if (context.grants.push === false)
24267
+ return { endpoint: "commit", reason: missing("push") };
24268
+ if (context.grants.pr === false)
24269
+ return { endpoint: "commit", reason: missing("pr") };
24270
+ if (context.configured.length > 0 && !context.accountConfigured)
24271
+ return {
24272
+ endpoint: "commit",
24273
+ reason: `vcs.account missing; set vcs.account for workspace "${context.workspace ?? "?"}" in ~/.config/workit/workspaces.json`
24274
+ };
24275
+ if (endpoint === "merged" && context.grants.merge === false)
24276
+ return { endpoint: "green", reason: missing("merge") };
24277
+ return { endpoint };
24278
+ }
24279
+ function endpointView(entry, context) {
24280
+ const { raw, endpoint, issue } = endpointOf(entry);
24281
+ const effective = effectiveEndpoint(endpoint, context);
24282
+ return {
24283
+ defaultEndpoint: endpoint,
24284
+ configuredEndpoint: raw ?? null,
24285
+ effectiveEndpoint: effective.endpoint,
24286
+ ...effective.reason ? { endpointReason: effective.reason } : {},
24287
+ ...issue ? { endpointIssue: issue } : {}
24288
+ };
24289
+ }
23813
24290
  var DEFAULT_VERIFICATION = "self";
23814
24291
  var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
23815
- var endpointOf = (entry) => entry?.defaultEndpoint === "pr" ? "pr" : "commit";
23816
24292
  var isGrantValue = (value) => value === true || value === false || value === "verified";
23817
24293
  var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
23818
24294
  var fromAutoApprove = (value) => {
@@ -23853,21 +24329,33 @@ function resolveAutonomy(cwd) {
23853
24329
  source: "default",
23854
24330
  accountConfigured: false,
23855
24331
  defaultEndpoint: DEFAULT_ENDPOINT,
24332
+ configuredEndpoint: null,
24333
+ effectiveEndpoint: DEFAULT_ENDPOINT,
23856
24334
  verification: DEFAULT_VERIFICATION,
23857
24335
  note: override
23858
24336
  };
23859
24337
  const workspace = resolveWorkspaceFrom(cwd, grantsDir(), process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
23860
24338
  const { grants, source } = configuredGrants(workspace);
24339
+ const full = { ...DEFAULT_GRANTS, ...grants };
24340
+ const configured = GRANT_KINDS.filter((kind) => grants[kind] !== undefined);
24341
+ const accountConfigured = Boolean(workspace?.vcs?.account);
23861
24342
  return {
23862
24343
  workspace: workspace?.name ?? null,
23863
- grants: { ...DEFAULT_GRANTS, ...grants },
23864
- configured: GRANT_KINDS.filter((kind) => grants[kind] !== undefined),
24344
+ grants: full,
24345
+ configured,
23865
24346
  source,
23866
- accountConfigured: Boolean(workspace?.vcs?.account),
23867
- defaultEndpoint: endpointOf(workspace),
24347
+ accountConfigured,
24348
+ ...endpointView(workspace, {
24349
+ workspace: workspace?.name ?? null,
24350
+ grants: full,
24351
+ configured,
24352
+ accountConfigured
24353
+ }),
23868
24354
  verification: verificationOf(workspace)
23869
24355
  };
23870
24356
  }
24357
+ var suggested = (kind) => kind === "merge" ? "verified" : "true";
24358
+ var grantHint = (workspace, kind) => `ask the user to run, in their own terminal: workit grant set ${workspace ?? "<workspace>"} ${kind}=${suggested(kind)}`;
23871
24359
 
23872
24360
  // packages/workit-core/src/core/task-engine.ts
23873
24361
  var workspaceVerification = (root) => {
@@ -25455,7 +25943,7 @@ class WorkitCore {
25455
25943
  }
25456
25944
  }
25457
25945
  // packages/workit-core/src/core/repo-context.ts
25458
- import { spawnSync as spawnSync8 } from "node:child_process";
25946
+ import { spawnSync as spawnSync9 } from "node:child_process";
25459
25947
  import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
25460
25948
  import path16 from "node:path";
25461
25949
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
@@ -25484,7 +25972,7 @@ var invalidRange = (cwd) => ({
25484
25972
  cwd
25485
25973
  });
25486
25974
  var runGit = (cwd, args) => {
25487
- const result = spawnSync8("git", args, { cwd, encoding: "utf8" });
25975
+ const result = spawnSync9("git", args, { cwd, encoding: "utf8" });
25488
25976
  return {
25489
25977
  stdout: (result.stdout ?? "").trimEnd(),
25490
25978
  stderr: (result.stderr ?? "").trimEnd(),
@@ -25925,12 +26413,12 @@ function releaseNotesContext(root, rangeOrTag) {
25925
26413
  }
25926
26414
 
25927
26415
  // packages/workit-core/src/core/tracker-issues.ts
25928
- import { spawnSync as spawnSync10 } from "node:child_process";
26416
+ import { spawnSync as spawnSync11 } from "node:child_process";
25929
26417
 
25930
26418
  // packages/workit-core/src/core/pr-create.ts
25931
26419
  import fs13 from "node:fs";
25932
26420
  import path17 from "node:path";
25933
- import { spawnSync as spawnSync9 } from "node:child_process";
26421
+ import { spawnSync as spawnSync10 } from "node:child_process";
25934
26422
  // packages/workit-core/src/forge/pr-body.ts
25935
26423
  function parseGhIssue(value) {
25936
26424
  const m = /issues\/(\d+)/.exec(value);
@@ -25955,7 +26443,7 @@ function whichOnPath(tool) {
25955
26443
  }
25956
26444
  var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
25957
26445
  var pushRemote = (cwd) => {
25958
- const result = spawnSync9("git", ["remote", "get-url", "--push", "--all", "origin"], {
26446
+ const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
25959
26447
  cwd,
25960
26448
  encoding: "utf8"
25961
26449
  });
@@ -25986,7 +26474,7 @@ var defaultCli = (bin, available) => {
25986
26474
  if (!available)
25987
26475
  return null;
25988
26476
  return (args, root) => {
25989
- const out = spawnSync10(bin, args, {
26477
+ const out = spawnSync11(bin, args, {
25990
26478
  cwd: root,
25991
26479
  encoding: "utf8",
25992
26480
  env: { ...process.env, PATH: process.env.PATH ?? "" }
@@ -26504,7 +26992,7 @@ function resolveInside(root, candidate) {
26504
26992
  }
26505
26993
  function run2(root, executable, args, env = {}) {
26506
26994
  const cwd = realpathSync5(root);
26507
- const result = spawnSync11(executable, args, {
26995
+ const result = spawnSync12(executable, args, {
26508
26996
  cwd,
26509
26997
  encoding: "utf8",
26510
26998
  env: { ...process.env, ...env }
@@ -26560,8 +27048,8 @@ var SENSITIVE_WORDS = new Set([
26560
27048
  "query"
26561
27049
  ]);
26562
27050
  var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
26563
- var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26564
- var homePattern = new RegExp(`${escapeRegExp(os4.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
27051
+ var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
27052
+ var homePattern = new RegExp(`${escapeRegExp2(os4.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
26565
27053
  var applyPatterns = (value) => {
26566
27054
  let out = value;
26567
27055
  out = out.replace(SECRET_VALUE, REDACTED);