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