@brainervirus/workit-codex 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.
@@ -6625,7 +6625,7 @@ import { existsSync as existsSync9, realpathSync as realpathSync7, statSync as s
6625
6625
  import path21 from "node:path";
6626
6626
 
6627
6627
  // packages/workit-core/src/core.ts
6628
- import { spawnSync as spawnSync11 } from "node:child_process";
6628
+ import { spawnSync as spawnSync12 } from "node:child_process";
6629
6629
  import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
6630
6630
  import path19 from "node:path";
6631
6631
 
@@ -18884,6 +18884,11 @@ function worktreeSignal(cwd, options = {}) {
18884
18884
  }
18885
18885
  return `sig:${hash.digest("hex")}`;
18886
18886
  }
18887
+ function mergeBase(cwd, a, b) {
18888
+ if (!safeArg(a) || !safeArg(b))
18889
+ return null;
18890
+ return line(git2(cwd, ["merge-base", a, b]));
18891
+ }
18887
18892
  function patchId(cwd, base, head) {
18888
18893
  if (!safeArg(base) || !safeArg(head))
18889
18894
  return null;
@@ -18907,9 +18912,33 @@ function patchId(cwd, base, head) {
18907
18912
  const id = git2(cwd, ["patch-id", "--stable"], { input: diff.stdout });
18908
18913
  return line(id)?.split(/\s+/u)[0] ?? null;
18909
18914
  }
18915
+ function remoteNames(cwd) {
18916
+ return (git2(cwd, ["remote"]).stdout ?? "").split(/\r?\n/u).map((value) => value.trim()).filter(Boolean);
18917
+ }
18918
+ function resolveRef(cwd, ref) {
18919
+ if (!safeArg(ref))
18920
+ return null;
18921
+ return line(git2(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
18922
+ }
18923
+ var config2 = (cwd, key) => line(git2(cwd, ["config", "--get", key]));
18910
18924
  function currentBranch(cwd) {
18911
18925
  return line(git2(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
18912
18926
  }
18927
+ function pushRemoteName(cwd, branch) {
18928
+ const name = branch ?? currentBranch(cwd);
18929
+ const remotes = remoteNames(cwd);
18930
+ const candidates = [
18931
+ name ? config2(cwd, `branch.${name}.pushRemote`) : null,
18932
+ config2(cwd, "remote.pushDefault"),
18933
+ name ? config2(cwd, `branch.${name}.remote`) : null
18934
+ ];
18935
+ for (const candidate of candidates)
18936
+ if (candidate && candidate !== "." && remotes.includes(candidate))
18937
+ return candidate;
18938
+ if (remotes.includes("origin"))
18939
+ return "origin";
18940
+ return remotes.length === 1 ? remotes[0] : null;
18941
+ }
18913
18942
 
18914
18943
  // packages/workit-core/src/core/policy/derive.ts
18915
18944
  import { existsSync as existsSync3 } from "node:fs";
@@ -20523,6 +20552,8 @@ var readConfig = () => {
20523
20552
  throw new Error(result.error);
20524
20553
  return result.config ?? DEFAULTS;
20525
20554
  };
20555
+ var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path12.join(configDir(), "vcs.json");
20556
+ var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
20526
20557
  var resolveBranchPolicy = (config, workspace) => {
20527
20558
  const wp = workspace?.branchPolicy ?? {};
20528
20559
  const preset = Object.hasOwn(PRESETS, wp.preset) ? wp.preset : config.branchPolicy?.preset ?? "gitflow";
@@ -20530,7 +20561,7 @@ var resolveBranchPolicy = (config, workspace) => {
20530
20561
  allowed: wp.allowed,
20531
20562
  protectedNames: wp.protected
20532
20563
  }, config);
20533
- const allowed = merged.allowed.map((p) => new RegExp(`^${p.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i"));
20564
+ const allowed = merged.allowed.map(branchGlobPattern);
20534
20565
  return {
20535
20566
  preset,
20536
20567
  allowed,
@@ -20547,16 +20578,6 @@ var COMMIT_PRESETS = [
20547
20578
  "custom",
20548
20579
  "auto"
20549
20580
  ];
20550
- var resolveCommitPolicy = (config, workspace) => {
20551
- const wp = workspace?.commitPolicy ?? {};
20552
- if (COMMIT_PRESETS.includes(String(wp.preset ?? ""))) {
20553
- return {
20554
- preset: wp.preset,
20555
- ...typeof wp.pattern === "string" ? { pattern: wp.pattern } : {}
20556
- };
20557
- }
20558
- return config.commitPolicy ?? { preset: "conventional" };
20559
- };
20560
20581
 
20561
20582
  // packages/workit-core/src/core/workspaces.ts
20562
20583
  import { createHash as createHash8 } from "node:crypto";
@@ -20595,26 +20616,31 @@ var versionSourceSchema = discriminatedUnion("kind", [
20595
20616
  object({ kind: literal("manual") }).strict()
20596
20617
  ]);
20597
20618
  var releaseTrackSchema = object({
20598
- strategy: branchPreset,
20619
+ strategy: branchPreset.optional(),
20599
20620
  productionBranch: nonBlank,
20600
20621
  integrationBranch: nonBlank,
20601
- naming: object({ feature: nonBlank, release: nonBlank, hotfix: nonBlank }).strict(),
20602
- baseBranch: nonBlank,
20603
- mergeBackBranches: array(nonBlank),
20604
- pullRequestTarget: nonBlank,
20605
- tagNamespace: string2(),
20606
- versionSource: versionSourceSchema,
20607
- requiredChecks: array(nonBlank)
20608
- }).strict().superRefine((track, context) => {
20622
+ naming: object({
20623
+ feature: nonBlank.optional(),
20624
+ release: nonBlank.optional(),
20625
+ hotfix: nonBlank.optional()
20626
+ }).passthrough().optional(),
20627
+ baseBranch: nonBlank.optional(),
20628
+ mergeBackBranches: array(nonBlank).optional(),
20629
+ pullRequestTarget: nonBlank.optional(),
20630
+ tagNamespace: string2().optional(),
20631
+ versionSource: versionSourceSchema.optional(),
20632
+ requiredChecks: array(nonBlank).optional(),
20633
+ critical: array(nonBlank).optional()
20634
+ }).passthrough().superRefine((track, context) => {
20609
20635
  for (const [field, values] of [
20610
- ["mergeBackBranches", track.mergeBackBranches],
20611
- ["requiredChecks", track.requiredChecks]
20636
+ ["mergeBackBranches", track.mergeBackBranches ?? []],
20637
+ ["requiredChecks", track.requiredChecks ?? []]
20612
20638
  ]) {
20613
20639
  if (new Set(values).size !== values.length) {
20614
20640
  context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
20615
20641
  }
20616
20642
  }
20617
- 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(".."))) {
20643
+ 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(".."))) {
20618
20644
  context.addIssue({
20619
20645
  code: "custom",
20620
20646
  path: ["versionSource", "path"],
@@ -20632,7 +20658,7 @@ var workspaceConfigSchema = object({
20632
20658
  account: nonBlank.optional()
20633
20659
  }).passthrough().optional(),
20634
20660
  autoApprove: union([boolean2(), array(nonBlank)]).optional(),
20635
- defaultEndpoint: _enum(["commit", "pr"]).optional(),
20661
+ defaultEndpoint: unknown().optional(),
20636
20662
  verification: _enum(["self", "independent"]).optional(),
20637
20663
  autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
20638
20664
  kind,
@@ -20882,7 +20908,7 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
20882
20908
  var runtimeWorkspaceIndexSchema = object({
20883
20909
  workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
20884
20910
  }).passthrough();
20885
- var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
20911
+ var matchRuntimeWorkspace = (cwd) => {
20886
20912
  const file = path13.join(configDir(), "workspaces.json");
20887
20913
  let raw;
20888
20914
  try {
@@ -20917,8 +20943,17 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
20917
20943
  });
20918
20944
  const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
20919
20945
  const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
20920
- if (!selected)
20946
+ return selected ? { file, selected } : null;
20947
+ };
20948
+ var resolveRuntimeReleaseTracks = (cwd) => {
20949
+ const matched = matchRuntimeWorkspace(cwd);
20950
+ return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
20951
+ };
20952
+ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
20953
+ const matched = matchRuntimeWorkspace(cwd);
20954
+ if (!matched)
20921
20955
  return null;
20956
+ const { file, selected } = matched;
20922
20957
  const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
20923
20958
  if (!policy.success) {
20924
20959
  const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
@@ -20944,15 +20979,410 @@ var resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
20944
20979
  source: profilePolicy ? `profile:${profileName}` : workspacePolicy ? `workspace:${candidate.name}` : "user-default"
20945
20980
  };
20946
20981
  };
20982
+ function workspaceDefaultTarget(cwd, globalDefault) {
20983
+ const ws = resolveRuntimeWorkspaceVcs(cwd);
20984
+ const wp = ws?.branchPolicy ?? {};
20985
+ const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
20986
+ const selected = resolveRuntimeWorkspacePolicy(cwd, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined);
20987
+ const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null).defaultTargetBranch;
20988
+ return String(ws?.vcs?.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : globalDefault ?? policyDefault) ?? "develop");
20989
+ }
20947
20990
 
20948
20991
  // packages/workit-core/src/core/vcs-config.ts
20949
20992
  import fs12 from "node:fs";
20950
20993
  import path14 from "node:path";
20994
+ import { spawnSync as spawnSync8 } from "node:child_process";
20995
+
20996
+ // packages/workit-core/src/core/release-tracks.ts
20997
+ import { createHash as createHash9 } from "node:crypto";
20951
20998
  import { spawnSync as spawnSync7 } from "node:child_process";
20952
- var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path14.join(configDir(), "vcs.json");
20999
+ var KNOWN_FIELDS = new Set([
21000
+ "strategy",
21001
+ "productionBranch",
21002
+ "integrationBranch",
21003
+ "naming",
21004
+ "baseBranch",
21005
+ "mergeBackBranches",
21006
+ "pullRequestTarget",
21007
+ "tagNamespace",
21008
+ "versionSource",
21009
+ "requiredChecks",
21010
+ "critical"
21011
+ ]);
21012
+ var BRANCH_FIELDS = ["productionBranch", "integrationBranch", "baseBranch", "pullRequestTarget"];
21013
+ var PLACEHOLDER = /\{[^}]*\}/gu;
21014
+ var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21015
+ var branchName = (value) => typeof value === "string" && value.trim() && !value.trim().startsWith("-") ? value.trim() : null;
21016
+ var namedBranches = (entry) => [
21017
+ ...BRANCH_FIELDS.map((field) => branchName(entry[field])),
21018
+ ...Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : []
21019
+ ].filter((name) => name !== null);
21020
+ var literalOf = (template) => template.replace(PLACEHOLDER, "").replace(/[*/]/gu, "").trim();
21021
+ function readReleaseTracks(raw) {
21022
+ const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
21023
+ if (raw === undefined || raw === null)
21024
+ return out;
21025
+ if (!isRecord3(raw)) {
21026
+ out.issues.push("releaseTracks is not an object; ignored");
21027
+ return out;
21028
+ }
21029
+ const fatal = [];
21030
+ const protectedNames = new Set;
21031
+ for (const [name, entry] of Object.entries(raw).toSorted(([a], [b]) => a < b ? -1 : 1)) {
21032
+ const label = `release track ${JSON.stringify(name)}`;
21033
+ if (!isRecord3(entry)) {
21034
+ out.issues.push(`${label} is not an object; ignored`);
21035
+ continue;
21036
+ }
21037
+ for (const branch of namedBranches(entry))
21038
+ protectedNames.add(branch);
21039
+ if (!name.trim()) {
21040
+ out.issues.push("a release track with a blank name was ignored");
21041
+ continue;
21042
+ }
21043
+ let critical = [];
21044
+ if (Array.isArray(entry.critical))
21045
+ critical = entry.critical.filter((item) => typeof item === "string");
21046
+ else if (entry.critical !== undefined)
21047
+ out.issues.push(`${label} critical: must be a list of field names; ignored`);
21048
+ const isCritical = (field) => critical.some((item) => field === item || field.startsWith(`${item}.`));
21049
+ const problem = (field, message) => {
21050
+ if (isCritical(field))
21051
+ fatal.push(`${label} ${field}: ${message}`);
21052
+ else
21053
+ out.issues.push(`${label} ${field}: ${message}`);
21054
+ };
21055
+ for (const key of Object.keys(entry))
21056
+ if (!KNOWN_FIELDS.has(key))
21057
+ problem(key, "unknown field, ignored");
21058
+ const productionBranch = branchName(entry.productionBranch);
21059
+ const integrationBranch = branchName(entry.integrationBranch);
21060
+ if (!productionBranch)
21061
+ problem("productionBranch", "missing or not a branch name");
21062
+ if (!integrationBranch)
21063
+ problem("integrationBranch", "missing or not a branch name");
21064
+ const optionalBranch = (field) => {
21065
+ if (entry[field] === undefined)
21066
+ return null;
21067
+ const value = branchName(entry[field]);
21068
+ if (!value)
21069
+ problem(field, "not a branch name; using the integration branch");
21070
+ return value;
21071
+ };
21072
+ const baseBranch = optionalBranch("baseBranch");
21073
+ const pullRequestTarget = optionalBranch("pullRequestTarget");
21074
+ let mergeBackBranches = [];
21075
+ if (entry.mergeBackBranches !== undefined) {
21076
+ const list = Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : [null];
21077
+ if (list.some((item) => item === null))
21078
+ problem("mergeBackBranches", "must be a list of branch names; ignored");
21079
+ else
21080
+ mergeBackBranches = [...new Set(list)];
21081
+ }
21082
+ const naming = {};
21083
+ if (entry.naming !== undefined) {
21084
+ if (!isRecord3(entry.naming))
21085
+ problem("naming", "not an object; ignored");
21086
+ else
21087
+ for (const kind of ["feature", "release", "hotfix"]) {
21088
+ const template = entry.naming[kind];
21089
+ if (template === undefined)
21090
+ continue;
21091
+ if (typeof template !== "string" || !template.trim())
21092
+ problem(`naming.${kind}`, "not a template string; ignored");
21093
+ else if (!literalOf(template))
21094
+ problem(`naming.${kind}`, "needs literal text besides placeholders; ignored");
21095
+ else
21096
+ naming[kind] = template.trim();
21097
+ }
21098
+ }
21099
+ if (!productionBranch || !integrationBranch) {
21100
+ out.issues.push(`${label} was skipped: it needs a productionBranch and integrationBranch`);
21101
+ continue;
21102
+ }
21103
+ out.tracks.push({
21104
+ name,
21105
+ productionBranch,
21106
+ integrationBranch,
21107
+ baseBranch: baseBranch ?? integrationBranch,
21108
+ pullRequestTarget: pullRequestTarget ?? integrationBranch,
21109
+ mergeBackBranches,
21110
+ naming
21111
+ });
21112
+ }
21113
+ out.protectedBranches = [...protectedNames];
21114
+ if (fatal.length)
21115
+ out.error = `workspace releaseTracks cannot be read by this Workit (${fatal.join("; ")}); upgrade Workit or fix the track`;
21116
+ return out;
21117
+ }
21118
+ var IMPLICIT = "";
21119
+ var ownedBy = (tracks, branch) => tracks.filter((track) => [track.integrationBranch, track.productionBranch, track.baseBranch].includes(branch));
21120
+ var shortRef = (ref, remotes) => {
21121
+ const bare = ref.replace(/^refs\/heads\//u, "").replace(/^refs\/remotes\/[^/]+\//u, "");
21122
+ const remote = remotes.find((name) => bare.startsWith(`${name}/`));
21123
+ return remote ? bare.slice(remote.length + 1) : bare;
21124
+ };
21125
+ var MAX_RECORDED_HOPS = 10;
21126
+ function resolveReleaseTrack(input) {
21127
+ const tracks = [...input.tracks];
21128
+ const issues = [...input.issues ?? []];
21129
+ const requested = input.requested?.trim();
21130
+ if (tracks.length === 0) {
21131
+ if (requested)
21132
+ return {
21133
+ status: "invalid",
21134
+ error: `no release tracks configured for this workspace; --track ${requested} cannot apply`,
21135
+ issues
21136
+ };
21137
+ return { status: "none", issues };
21138
+ }
21139
+ const names = tracks.map((track) => track.name).join(", ");
21140
+ let envProblem = null;
21141
+ const done = (track, source, detail, warnings = [], ambiguous = null) => ({
21142
+ status: "resolved",
21143
+ track: track && track.name !== IMPLICIT ? track : null,
21144
+ source,
21145
+ detail,
21146
+ warnings: [...issues, ...envProblem ? [envProblem] : [], ...warnings],
21147
+ tracks,
21148
+ blocking: envProblem ?? ambiguous
21149
+ });
21150
+ if (requested) {
21151
+ const named = tracks.find((track) => track.name === requested);
21152
+ if (!named)
21153
+ return {
21154
+ status: "invalid",
21155
+ error: `no release track ${JSON.stringify(requested)}; configured: ${names}`,
21156
+ issues
21157
+ };
21158
+ return done(named, "flag", `track ${named.name} was requested explicitly`);
21159
+ }
21160
+ const owned = (branch) => branch !== null && tracks.some((track) => [
21161
+ track.integrationBranch,
21162
+ track.productionBranch,
21163
+ track.baseBranch,
21164
+ track.pullRequestTarget
21165
+ ].includes(branch));
21166
+ const implicit = input.defaultBranch && !owned(input.defaultBranch) ? {
21167
+ name: IMPLICIT,
21168
+ productionBranch: input.defaultBranch,
21169
+ integrationBranch: input.defaultBranch,
21170
+ baseBranch: input.defaultBranch,
21171
+ pullRequestTarget: input.defaultBranch,
21172
+ mergeBackBranches: [],
21173
+ naming: {}
21174
+ } : null;
21175
+ const candidates = implicit ? [...tracks, implicit] : tracks;
21176
+ const label = (track) => track.name === IMPLICIT ? `the workspace default line (${track.integrationBranch})` : `track ${track.name}`;
21177
+ const fallback = (why) => {
21178
+ const byDefault = input.defaultBranch ? tracks.filter((track) => track.integrationBranch === input.defaultBranch || track.pullRequestTarget === input.defaultBranch) : [];
21179
+ const track = byDefault.length === 1 ? byDefault[0] : null;
21180
+ const target = track ? `track ${track.name}` : `default target ${input.defaultBranch ?? "(none)"}`;
21181
+ 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;
21182
+ return done(track, "default", `${why}; using the workspace ${target}`, [
21183
+ `release track not determined: ${why}; using the workspace ${target} (pass --track <name> to choose)`
21184
+ ], ambiguous);
21185
+ };
21186
+ const branch = input.branch;
21187
+ if (branch) {
21188
+ const owners = ownedBy(candidates, branch);
21189
+ if (owners.length === 1)
21190
+ return done(owners[0], "branch", `${branch} is a branch of ${label(owners[0])}`);
21191
+ if (owners.length > 1)
21192
+ return fallback(`${branch} belongs to more than one track (${owners.map((track) => track.name).join(", ")})`);
21193
+ }
21194
+ const env = input.envRequested?.trim();
21195
+ if (env) {
21196
+ const named = tracks.find((track) => track.name === env);
21197
+ if (named)
21198
+ return done(named, "env", `WORKFLOW_RELEASE_TRACK selects track ${named.name}`);
21199
+ envProblem = `WORKFLOW_RELEASE_TRACK=${env} names no release track of this workspace (${names}); ignored`;
21200
+ }
21201
+ if (!branch)
21202
+ return fallback("HEAD is detached");
21203
+ if (tracks.length === 1 && !implicit)
21204
+ return done(tracks[0], "only-track", `${tracks[0].name} is the only track`);
21205
+ let remotes = null;
21206
+ const short = (ref) => shortRef(ref, remotes ??= input.probe.remotes());
21207
+ const ownerOf = (ref) => {
21208
+ const owner = ownedBy(candidates, short(ref));
21209
+ return owner.length === 1 ? owner[0] : null;
21210
+ };
21211
+ const followRecorded = (start) => {
21212
+ let cursor = start;
21213
+ const seen = new Set([start]);
21214
+ for (let hop = 0;hop < MAX_RECORDED_HOPS; hop += 1) {
21215
+ const recorded = input.probe.recordedBase(cursor);
21216
+ if (!recorded)
21217
+ return null;
21218
+ const base = short(recorded);
21219
+ const owner = ownerOf(base);
21220
+ if (owner)
21221
+ return owner;
21222
+ if (ownedBy(candidates, base).length > 1 || seen.has(base))
21223
+ return null;
21224
+ seen.add(base);
21225
+ cursor = base;
21226
+ }
21227
+ return null;
21228
+ };
21229
+ const recordedOwner = followRecorded(branch);
21230
+ if (recordedOwner)
21231
+ return done(recordedOwner, "recorded-base", `${branch} was created on ${label(recordedOwner)}'s line (recorded base)`);
21232
+ for (const source of ["reflog", "checkout"]) {
21233
+ const ref = source === "reflog" ? input.probe.createdFrom(branch) : input.probe.checkedOutFrom(branch);
21234
+ if (!ref)
21235
+ continue;
21236
+ const owner = ownerOf(ref) ?? followRecorded(short(ref));
21237
+ if (owner)
21238
+ return done(owner, source, `${branch} was created from ${short(ref)} (${source === "reflog" ? "branch reflog" : "HEAD reflog"})`);
21239
+ }
21240
+ const forks = [];
21241
+ for (const track of candidates)
21242
+ for (const ref of new Set([track.integrationBranch, track.baseBranch])) {
21243
+ const sha = input.probe.mergeBase(branch, ref);
21244
+ if (sha)
21245
+ forks.push({ track, ref, sha });
21246
+ }
21247
+ if (forks.length === 0)
21248
+ return fallback(`no track branch could be compared with ${branch} (fetch the track branches)`);
21249
+ const ancestry = new Map;
21250
+ const descends = (older, newer) => {
21251
+ if (older === newer)
21252
+ return false;
21253
+ const key = `${older}>${newer}`;
21254
+ if (!ancestry.has(key))
21255
+ ancestry.set(key, input.probe.isAncestor(older, newer));
21256
+ return ancestry.get(key);
21257
+ };
21258
+ const winners = forks.filter((fork) => forks.every((other) => other.track === fork.track || descends(other.sha, fork.sha)));
21259
+ const winningTracks = [...new Set(winners.map((fork) => fork.track))];
21260
+ if (winningTracks.length === 1 && forks.some((fork) => fork.track !== winningTracks[0])) {
21261
+ const win = winners[0];
21262
+ return done(win.track, "ancestry", `${branch} forked from ${win.ref} at ${win.sha.slice(0, 12)}, after every other line's fork point`);
21263
+ }
21264
+ if (winningTracks.length === 1)
21265
+ return fallback(`only ${label(winningTracks[0])} could be compared with ${branch}`);
21266
+ const newest = forks.filter((fork) => !forks.some((other) => descends(fork.sha, other.sha)));
21267
+ 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 ")}`);
21268
+ }
21269
+ var git4 = (cwd, args) => {
21270
+ const run = spawnSync7("git", args, {
21271
+ cwd,
21272
+ encoding: "utf8",
21273
+ timeout: 20000,
21274
+ windowsHide: true,
21275
+ stdio: ["ignore", "pipe", "ignore"]
21276
+ });
21277
+ return run.status === 0 ? (run.stdout ?? "").trim() : null;
21278
+ };
21279
+ var recordedBaseKey = (branch) => `branch.${branch}.workitBase`;
21280
+ var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
21281
+ var reflog = (cwd, ref) => (git4(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
21282
+ `).map((line) => {
21283
+ const [sha = "", selector = "", ...subject] = line.split("\t");
21284
+ return {
21285
+ sha,
21286
+ time: Number(/@\{(\d+)\}$/u.exec(selector)?.[1] ?? Number.NaN),
21287
+ subject: subject.join("\t")
21288
+ };
21289
+ }).filter((entry) => entry.sha && Number.isFinite(entry.time));
21290
+ function gitTrackProbe(cwd) {
21291
+ let remote;
21292
+ let remotes;
21293
+ const tip = (branch) => {
21294
+ remote ??= pushRemoteName(cwd) ?? "origin";
21295
+ return resolveRef(cwd, `refs/remotes/${remote}/${branch}`) ?? resolveRef(cwd, `refs/heads/${branch}`);
21296
+ };
21297
+ return {
21298
+ remotes: () => remotes ??= remoteNames(cwd),
21299
+ recordedBase: (branch) => git4(cwd, ["config", "--get", recordedBaseKey(branch)]) || null,
21300
+ createdFrom: (branch) => {
21301
+ const log = git4(cwd, ["reflog", "show", "--format=%gs", `refs/heads/${branch}`, "--"]);
21302
+ const oldest = log?.split(`
21303
+ `).findLast(Boolean) ?? "";
21304
+ const match = /^branch: Created from (\S+)$/u.exec(oldest);
21305
+ return match && match[1] !== "HEAD" ? match[1] : null;
21306
+ },
21307
+ checkedOutFrom: (branch) => {
21308
+ const own = reflog(cwd, `refs/heads/${branch}`);
21309
+ const created = own.at(-1);
21310
+ if (!created || created.subject !== "branch: Created from HEAD")
21311
+ return null;
21312
+ const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp(branch)}$`, "u");
21313
+ const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
21314
+ return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
21315
+ },
21316
+ mergeBase: (branch, trackBranch) => {
21317
+ const base = tip(trackBranch);
21318
+ return base && resolveRef(cwd, `refs/heads/${branch}`) ? mergeBase(cwd, base, `refs/heads/${branch}`) : null;
21319
+ },
21320
+ isAncestor: (ancestor, descendant) => git4(cwd, ["merge-base", "--is-ancestor", ancestor, descendant]) !== null
21321
+ };
21322
+ }
21323
+ function workspaceReleaseTracks(cwd) {
21324
+ const raw = resolveRuntimeReleaseTracks(cwd);
21325
+ return { workspace: raw?.workspace ?? null, ...readReleaseTracks(raw?.releaseTracks) };
21326
+ }
21327
+ var memo3 = new Map;
21328
+ var MEMO_LIMIT = 64;
21329
+ function resolveTrackFor(cwd, options) {
21330
+ const read = workspaceReleaseTracks(cwd);
21331
+ if (read.error)
21332
+ return { status: "invalid", error: read.error, issues: read.issues };
21333
+ if (read.tracks.length === 0 && !options.track?.trim())
21334
+ return { status: "none", issues: read.issues };
21335
+ const branch = options.branch === undefined ? currentBranch(cwd) : options.branch;
21336
+ const envRequested = process.env.WORKFLOW_RELEASE_TRACK?.trim() || null;
21337
+ const input = {
21338
+ tracks: read.tracks,
21339
+ requested: options.track ?? null,
21340
+ envRequested,
21341
+ branch,
21342
+ defaultBranch: options.defaultBranch,
21343
+ issues: read.issues
21344
+ };
21345
+ let key = null;
21346
+ if (!options.probe) {
21347
+ const refs = git4(cwd, [
21348
+ "for-each-ref",
21349
+ "--format=%(refname) %(objectname)",
21350
+ "refs/heads",
21351
+ "refs/remotes"
21352
+ ]) ?? "";
21353
+ const head = git4(cwd, ["reflog", "show", "-n", "1", "--format=%H %gs", "HEAD", "--"]) ?? "";
21354
+ const own = branch ? [
21355
+ git4(cwd, [
21356
+ "log",
21357
+ "-g",
21358
+ "-n",
21359
+ "1",
21360
+ "--date=unix",
21361
+ "--format=%H %gd %gs",
21362
+ `refs/heads/${branch}`,
21363
+ "--"
21364
+ ]) ?? "",
21365
+ git4(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
21366
+ ] : [];
21367
+ key = createHash9("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
21368
+ const hit = memo3.get(key);
21369
+ if (hit)
21370
+ return hit;
21371
+ }
21372
+ const resolution = resolveReleaseTrack({ ...input, probe: options.probe ?? gitTrackProbe(cwd) });
21373
+ if (key) {
21374
+ if (memo3.size >= MEMO_LIMIT)
21375
+ memo3.delete(memo3.keys().next().value);
21376
+ memo3.set(key, resolution);
21377
+ }
21378
+ return resolution;
21379
+ }
21380
+
21381
+ // packages/workit-core/src/core/vcs-config.ts
21382
+ var workspacesPath = () => path14.join(configDir(), "workspaces.json");
20953
21383
  var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
20954
21384
  var remoteProvider = (cwd) => {
20955
- const r = spawnSync7("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
21385
+ const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
20956
21386
  if (r.status !== 0)
20957
21387
  return null;
20958
21388
  const url = (r.stdout ?? "").trim();
@@ -20989,7 +21419,7 @@ var remoteEndpoint = (remote) => {
20989
21419
  var configuredSshEndpoint = (host) => {
20990
21420
  if (host.startsWith("-"))
20991
21421
  return null;
20992
- const resolved = spawnSync7("ssh", ["-G", host], {
21422
+ const resolved = spawnSync8("ssh", ["-G", host], {
20993
21423
  encoding: "utf8",
20994
21424
  timeout: 5000,
20995
21425
  maxBuffer: 1024 * 1024,
@@ -21054,7 +21484,16 @@ var readVcsConfig = () => {
21054
21484
  }
21055
21485
  return { status: "malformed", path: file, config: {}, error: `${file} is not a JSON object` };
21056
21486
  };
21057
- function vcsConfig(mode, cwd) {
21487
+ var trackSummary = (resolution) => resolution.status === "resolved" ? {
21488
+ name: resolution.track?.name ?? null,
21489
+ source: resolution.source,
21490
+ detail: resolution.detail,
21491
+ warnings: resolution.warnings,
21492
+ track: resolution.track,
21493
+ tracks: resolution.tracks,
21494
+ blocking: resolution.blocking
21495
+ } : null;
21496
+ function vcsConfig(mode, cwd, options = {}) {
21058
21497
  const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
21059
21498
  const wsVcs = ws?.vcs ?? {};
21060
21499
  const wsYt = ws?.youtrack ?? {};
@@ -21064,10 +21503,7 @@ function vcsConfig(mode, cwd) {
21064
21503
  const determinateRoot = cwd !== undefined || process.env.WORKFLOW_WORKSPACE_ROOT !== undefined;
21065
21504
  const rawProvider = wsVcs.provider ?? (determinateRoot ? remoteProvider(root) : null) ?? cfg.provider ?? null;
21066
21505
  const provider = rawProvider === null || rawProvider === undefined ? null : String(rawProvider).toLowerCase() || null;
21067
- const wp = ws?.branchPolicy ?? {};
21068
- const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
21069
- const policyDefault = resolveBranchPolicyFor(root).defaultTargetBranch;
21070
- const defaultTarget = String(wsVcs.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : cfg.defaultTargetBranch ?? policyDefault) ?? "develop");
21506
+ const workspaceDefault = workspaceDefaultTarget(root, cfg.defaultTargetBranch);
21071
21507
  const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
21072
21508
  const youtrackBaseUrl = typeof wsYt.baseUrl === "string" ? wsYt.baseUrl : null;
21073
21509
  let issuesProvider = null;
@@ -21079,11 +21515,24 @@ function vcsConfig(mode, cwd) {
21079
21515
  if (mode === "resolve") {
21080
21516
  if (cfgStatus === "malformed")
21081
21517
  return { ok: false, error: cfgError, configPath: cfgPath };
21518
+ const trackResolution = resolveTrackFor(root, {
21519
+ track: options.track,
21520
+ ...options.branch !== undefined ? { branch: options.branch } : {},
21521
+ defaultBranch: workspaceDefault
21522
+ });
21523
+ if (trackResolution.status === "invalid")
21524
+ return { ok: false, error: trackResolution.error, configPath: workspacesPath() };
21525
+ const releaseTrack = trackSummary(trackResolution);
21526
+ const defaultTarget = releaseTrack?.track?.pullRequestTarget ?? workspaceDefault;
21527
+ const baseBranch = releaseTrack?.track?.baseBranch ?? defaultTarget;
21082
21528
  return {
21083
21529
  ok: true,
21084
21530
  workspace_name: ws?.name ?? null,
21085
21531
  provider,
21086
21532
  defaultTargetBranch: defaultTarget,
21533
+ workspaceDefaultTargetBranch: workspaceDefault,
21534
+ baseBranch,
21535
+ releaseTrack,
21087
21536
  link_issues: linkIssues,
21088
21537
  youtrack_base_url: youtrackBaseUrl,
21089
21538
  issues_provider: issuesProvider,
@@ -21107,7 +21556,7 @@ function vcsConfig(mode, cwd) {
21107
21556
  ok: true,
21108
21557
  configPath: path14.resolve(cfgPath),
21109
21558
  provider,
21110
- defaultTargetBranch: defaultTarget,
21559
+ defaultTargetBranch: workspaceDefault,
21111
21560
  pr: cfg.pr ?? {},
21112
21561
  workspace_name: ws?.name ?? null,
21113
21562
  link_issues: linkIssues,
@@ -21143,7 +21592,7 @@ function mergedPrStyle(limit = 6, cwd) {
21143
21592
  `).filter((l) => l.startsWith("## ")).map((l) => l.trim()),
21144
21593
  descriptionPreview: desc.slice(0, 600)
21145
21594
  });
21146
- const remoteResult = spawnSync7("git", ["remote", "get-url", "--push", "--all", "origin"], {
21595
+ const remoteResult = spawnSync8("git", ["remote", "get-url", "--push", "--all", "origin"], {
21147
21596
  cwd,
21148
21597
  encoding: "utf8"
21149
21598
  });
@@ -21159,7 +21608,7 @@ function mergedPrStyle(limit = 6, cwd) {
21159
21608
  if (!hostingApiHostMatches(remote, host))
21160
21609
  return { ok: false, error: "PR style target does not match the provider host" };
21161
21610
  if (provider === "gitlab") {
21162
- const run = (args) => spawnSync7("glab", ["api", ...args], {
21611
+ const run = (args) => spawnSync8("glab", ["api", ...args], {
21163
21612
  cwd,
21164
21613
  encoding: "utf8",
21165
21614
  env
@@ -21179,7 +21628,7 @@ function mergedPrStyle(limit = 6, cwd) {
21179
21628
  });
21180
21629
  }
21181
21630
  } else if (provider === "github") {
21182
- const r = spawnSync7("gh", [
21631
+ const r = spawnSync8("gh", [
21183
21632
  "pr",
21184
21633
  "list",
21185
21634
  "--repo",
@@ -21210,20 +21659,6 @@ function mergedPrStyle(limit = 6, cwd) {
21210
21659
  examples
21211
21660
  };
21212
21661
  }
21213
-
21214
- // packages/workit-core/src/core/branch.ts
21215
- function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
21216
- const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
21217
- const config = readConfig();
21218
- return kind === "branch" ? {
21219
- branchPolicy: resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null),
21220
- provenance: { branchPolicy: selected.source }
21221
- } : {
21222
- commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
21223
- provenance: { commitPolicy: selected.source }
21224
- };
21225
- }
21226
- var resolveBranchPolicyFor = (workspaceRoot, profileName) => effectiveWorkspacePolicy(workspaceRoot, "branch", profileName).branchPolicy;
21227
21662
  // packages/workit-core/src/core/task-engine.ts
21228
21663
  import { realpathSync as realpathSync4 } from "node:fs";
21229
21664
 
@@ -21431,10 +21866,51 @@ var DEFAULT_GRANTS = Object.freeze({
21431
21866
  release: false,
21432
21867
  rerun: true
21433
21868
  });
21869
+ var DEFAULT_ENDPOINTS = ["commit", "pr", "green", "merged"];
21434
21870
  var DEFAULT_ENDPOINT = "commit";
21871
+ var isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value);
21872
+ function endpointOf(entry) {
21873
+ const raw = entry?.defaultEndpoint;
21874
+ if (raw === undefined)
21875
+ return { raw, endpoint: DEFAULT_ENDPOINT };
21876
+ if (isDefaultEndpoint(raw))
21877
+ return { raw, endpoint: raw };
21878
+ return {
21879
+ raw,
21880
+ endpoint: DEFAULT_ENDPOINT,
21881
+ issue: `defaultEndpoint ${JSON.stringify(raw)} is not one of ${DEFAULT_ENDPOINTS.join(", ")}; using ${DEFAULT_ENDPOINT}`
21882
+ };
21883
+ }
21884
+ function effectiveEndpoint(endpoint, context) {
21885
+ if (endpoint === "commit")
21886
+ return { endpoint };
21887
+ const missing = (kind) => `${kind} grant missing; ${grantHint(context.workspace, kind)}`;
21888
+ if (context.grants.push === false)
21889
+ return { endpoint: "commit", reason: missing("push") };
21890
+ if (context.grants.pr === false)
21891
+ return { endpoint: "commit", reason: missing("pr") };
21892
+ if (context.configured.length > 0 && !context.accountConfigured)
21893
+ return {
21894
+ endpoint: "commit",
21895
+ reason: `vcs.account missing; set vcs.account for workspace "${context.workspace ?? "?"}" in ~/.config/workit/workspaces.json`
21896
+ };
21897
+ if (endpoint === "merged" && context.grants.merge === false)
21898
+ return { endpoint: "green", reason: missing("merge") };
21899
+ return { endpoint };
21900
+ }
21901
+ function endpointView(entry, context) {
21902
+ const { raw, endpoint, issue } = endpointOf(entry);
21903
+ const effective = effectiveEndpoint(endpoint, context);
21904
+ return {
21905
+ defaultEndpoint: endpoint,
21906
+ configuredEndpoint: raw ?? null,
21907
+ effectiveEndpoint: effective.endpoint,
21908
+ ...effective.reason ? { endpointReason: effective.reason } : {},
21909
+ ...issue ? { endpointIssue: issue } : {}
21910
+ };
21911
+ }
21435
21912
  var DEFAULT_VERIFICATION = "self";
21436
21913
  var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
21437
- var endpointOf = (entry) => entry?.defaultEndpoint === "pr" ? "pr" : "commit";
21438
21914
  var isGrantValue = (value) => value === true || value === false || value === "verified";
21439
21915
  var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
21440
21916
  var fromAutoApprove = (value) => {
@@ -21475,21 +21951,33 @@ function resolveAutonomy(cwd) {
21475
21951
  source: "default",
21476
21952
  accountConfigured: false,
21477
21953
  defaultEndpoint: DEFAULT_ENDPOINT,
21954
+ configuredEndpoint: null,
21955
+ effectiveEndpoint: DEFAULT_ENDPOINT,
21478
21956
  verification: DEFAULT_VERIFICATION,
21479
21957
  note: override
21480
21958
  };
21481
21959
  const workspace = resolveWorkspaceFrom(cwd, grantsDir(), process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
21482
21960
  const { grants, source } = configuredGrants(workspace);
21961
+ const full = { ...DEFAULT_GRANTS, ...grants };
21962
+ const configured = GRANT_KINDS.filter((kind) => grants[kind] !== undefined);
21963
+ const accountConfigured = Boolean(workspace?.vcs?.account);
21483
21964
  return {
21484
21965
  workspace: workspace?.name ?? null,
21485
- grants: { ...DEFAULT_GRANTS, ...grants },
21486
- configured: GRANT_KINDS.filter((kind) => grants[kind] !== undefined),
21966
+ grants: full,
21967
+ configured,
21487
21968
  source,
21488
- accountConfigured: Boolean(workspace?.vcs?.account),
21489
- defaultEndpoint: endpointOf(workspace),
21969
+ accountConfigured,
21970
+ ...endpointView(workspace, {
21971
+ workspace: workspace?.name ?? null,
21972
+ grants: full,
21973
+ configured,
21974
+ accountConfigured
21975
+ }),
21490
21976
  verification: verificationOf(workspace)
21491
21977
  };
21492
21978
  }
21979
+ var suggested = (kind) => kind === "merge" ? "verified" : "true";
21980
+ var grantHint = (workspace, kind) => `ask the user to run, in their own terminal: workit grant set ${workspace ?? "<workspace>"} ${kind}=${suggested(kind)}`;
21493
21981
 
21494
21982
  // packages/workit-core/src/core/task-engine.ts
21495
21983
  var workspaceVerification = (root) => {
@@ -23077,7 +23565,7 @@ class WorkitCore {
23077
23565
  }
23078
23566
  }
23079
23567
  // packages/workit-core/src/core/repo-context.ts
23080
- import { spawnSync as spawnSync8 } from "node:child_process";
23568
+ import { spawnSync as spawnSync9 } from "node:child_process";
23081
23569
  import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
23082
23570
  import path16 from "node:path";
23083
23571
  var isSafeContextRange = (value) => value.length <= 4096 && (() => {
@@ -23106,7 +23594,7 @@ var invalidRange = (cwd) => ({
23106
23594
  cwd
23107
23595
  });
23108
23596
  var runGit = (cwd, args) => {
23109
- const result = spawnSync8("git", args, { cwd, encoding: "utf8" });
23597
+ const result = spawnSync9("git", args, { cwd, encoding: "utf8" });
23110
23598
  return {
23111
23599
  stdout: (result.stdout ?? "").trimEnd(),
23112
23600
  stderr: (result.stderr ?? "").trimEnd(),
@@ -23547,12 +24035,12 @@ function releaseNotesContext(root, rangeOrTag) {
23547
24035
  }
23548
24036
 
23549
24037
  // packages/workit-core/src/core/tracker-issues.ts
23550
- import { spawnSync as spawnSync10 } from "node:child_process";
24038
+ import { spawnSync as spawnSync11 } from "node:child_process";
23551
24039
 
23552
24040
  // packages/workit-core/src/core/pr-create.ts
23553
24041
  import fs13 from "node:fs";
23554
24042
  import path17 from "node:path";
23555
- import { spawnSync as spawnSync9 } from "node:child_process";
24043
+ import { spawnSync as spawnSync10 } from "node:child_process";
23556
24044
  // packages/workit-core/src/forge/pr-body.ts
23557
24045
  function parseGhIssue(value) {
23558
24046
  const m = /issues\/(\d+)/.exec(value);
@@ -23577,7 +24065,7 @@ function whichOnPath(tool) {
23577
24065
  }
23578
24066
  var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
23579
24067
  var pushRemote = (cwd) => {
23580
- const result = spawnSync9("git", ["remote", "get-url", "--push", "--all", "origin"], {
24068
+ const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
23581
24069
  cwd,
23582
24070
  encoding: "utf8"
23583
24071
  });
@@ -23608,7 +24096,7 @@ var defaultCli = (bin, available) => {
23608
24096
  if (!available)
23609
24097
  return null;
23610
24098
  return (args, root) => {
23611
- const out = spawnSync10(bin, args, {
24099
+ const out = spawnSync11(bin, args, {
23612
24100
  cwd: root,
23613
24101
  encoding: "utf8",
23614
24102
  env: { ...process.env, PATH: process.env.PATH ?? "" }
@@ -24126,7 +24614,7 @@ function resolveInside(root, candidate) {
24126
24614
  }
24127
24615
  function run2(root, executable, args, env = {}) {
24128
24616
  const cwd = realpathSync5(root);
24129
- const result = spawnSync11(executable, args, {
24617
+ const result = spawnSync12(executable, args, {
24130
24618
  cwd,
24131
24619
  encoding: "utf8",
24132
24620
  env: { ...process.env, ...env }
@@ -26572,8 +27060,8 @@ var SENSITIVE_WORDS = new Set([
26572
27060
  "query"
26573
27061
  ]);
26574
27062
  var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
26575
- var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26576
- var homePattern = new RegExp(`${escapeRegExp(os4.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
27063
+ var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
27064
+ var homePattern = new RegExp(`${escapeRegExp2(os4.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
26577
27065
  var applyPatterns = (value) => {
26578
27066
  let out = value;
26579
27067
  out = out.replace(SECRET_VALUE, REDACTED);