@kb-labs/release-manager-core 2.116.13 → 2.117.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.
package/dist/index.d.ts CHANGED
@@ -9,6 +9,19 @@ interface PluginLogger {
9
9
  warn?(message: string, meta?: Record<string, unknown>): void;
10
10
  error?(message: string, error?: Error, meta?: Record<string, unknown>): void;
11
11
  }
12
+ /** Governed process facade supplied by the plugin runtime. */
13
+ interface ReleaseShell {
14
+ exec(command: string, args?: string[], options?: {
15
+ cwd?: string;
16
+ timeout?: number;
17
+ env?: Record<string, string>;
18
+ }): Promise<{
19
+ code: number;
20
+ stdout: string;
21
+ stderr: string;
22
+ ok: boolean;
23
+ }>;
24
+ }
12
25
  type ReleaseStage = 'planning' | 'checking' | 'versioning' | 'publishing' | 'verifying' | 'rollback';
13
26
  type VersionBump = 'patch' | 'minor' | 'major' | 'auto';
14
27
  /**
@@ -38,6 +51,14 @@ interface PackageVersion {
38
51
  bump: VersionBump;
39
52
  isPublished: boolean;
40
53
  dependencies?: string[];
54
+ /**
55
+ * `nextVersion` was adopted as-is from a bump that already exists on disk
56
+ * (see the trust-disk branch in planner.ts) rather than derived by bumping
57
+ * `currentVersion`. Downstream version resolution — notably lockstep — must
58
+ * treat it as final: re-deriving it would bump a second time on top of an
59
+ * already-applied bump.
60
+ */
61
+ versionPinned?: boolean;
41
62
  }
42
63
  interface ReleasePlan {
43
64
  packages: PackageVersion[];
@@ -45,6 +66,14 @@ interface ReleasePlan {
45
66
  registry: string;
46
67
  rollbackEnabled: boolean;
47
68
  channel: ReleaseChannel;
69
+ /**
70
+ * The flow/scope this plan was computed for. Persisted with the plan
71
+ * artifact so a later pipeline step can tell whether the plan on disk is
72
+ * the one it is supposed to consume, instead of silently reusing another
73
+ * flow's plan (all flows share one scope-derived artifact path).
74
+ */
75
+ flow?: string;
76
+ scope?: string;
48
77
  }
49
78
  interface CheckResultDetails {
50
79
  /** Which package path this failure came from (for perPackage checks). */
@@ -61,6 +90,8 @@ interface CheckResultDetails {
61
90
  interface CheckResult {
62
91
  id: CheckId;
63
92
  ok: boolean;
93
+ /** Mirrors CustomCheckConfig.optional — a failed optional check must not fail the overall run. */
94
+ optional?: boolean;
64
95
  /** Structured failure details — present when ok=false. */
65
96
  details?: CheckResultDetails;
66
97
  hint?: string;
@@ -360,6 +391,7 @@ interface PipelineOptions {
360
391
  /** Pass --no-verify to git push and pushTags. Default: false (hooks run normally). */
361
392
  noVerify?: boolean;
362
393
  logger?: PluginLogger;
394
+ shell: ReleaseShell;
363
395
  onProgress?: (stage: ReleaseStage, message: string) => void;
364
396
  }
365
397
  interface PipelineResult {
@@ -655,29 +687,20 @@ declare function runReleasePipeline(options: PipelineOptions): Promise<PipelineR
655
687
  * dependant can fail to resolve the dependency's subpath exports in a
656
688
  * fresh worktree where nothing has a pre-existing dist/ yet.
657
689
  */
658
- declare function buildPackages(packages: PackageVersion[], options?: {
690
+ declare function buildPackages(packages: PackageVersion[], options: {
659
691
  logger?: PluginLogger;
692
+ shell: ReleaseShell;
660
693
  onProgress?: (pkg: string, result: BuildResult) => void;
661
694
  }): Promise<BuildResult[]>;
662
695
  /**
663
696
  * Run build for a single package using safe temp-dir strategy when tsup is detected.
664
697
  * Falls back to regular `pnpm run build` for non-tsup packages.
665
698
  */
666
- declare function runSafeBuild(packagePath: string, packageName: string): Promise<BuildResult>;
699
+ declare function runSafeBuild(packagePath: string, packageName: string, shell: ReleaseShell): Promise<BuildResult>;
667
700
  /**
668
701
  * Check if a shell command is a build command that should use safe build.
669
702
  */
670
703
  declare function isBuildCommand(command: string, args?: string[]): boolean;
671
- interface SpawnResult extends Omit<BuildResult, 'name'> {
672
- stdout: string;
673
- stderr: string;
674
- exitCode: number;
675
- }
676
- /**
677
- * Spawn a shell command and collect results.
678
- * Captures both stdout and stderr — build tools often write errors to stdout.
679
- */
680
- declare function spawnCommand(command: string, cwd: string, timeoutMs?: number): Promise<SpawnResult>;
681
704
 
682
705
  /**
683
706
  * Unified check runner for release manager.
@@ -689,7 +712,21 @@ interface CheckRunnerOptions {
689
712
  packagePaths: string[];
690
713
  scopePath?: string;
691
714
  logger?: Pick<PluginLogger, 'info' | 'warn'>;
715
+ shell: ReleaseShell;
692
716
  }
717
+ /**
718
+ * Max parallel shell.exec calls for perPackage checks.
719
+ * Must match the plugin manifest's `shell.maxConcurrent` permission
720
+ * (plugins/release/manager-cli/src/manifest.ts) — the platform's process
721
+ * broker admits at most that many concurrent shells for this plugin, so
722
+ * batching above it just queues and can blow the per-check timeout.
723
+ *
724
+ * Kept low (not e.g. 8) because pack-install is not a cheap script: it packs
725
+ * the tarball and runs a real `npm install` of it into a throwaway consumer
726
+ * per package. At higher concurrency those installs contend for CPU/disk/npm
727
+ * registry and start blowing their own per-check timeout under load.
728
+ */
729
+ declare const CHECKS_CONCURRENCY = 2;
693
730
  /**
694
731
  * Run all configured checks against packages.
695
732
  * Handles: parser evaluation, script path resolution, perPackage/scopePath/repoRoot routing.
@@ -821,4 +858,4 @@ declare function verifyCleanInstall(tarballPath: string, packageName: string, ad
821
858
  */
822
859
  declare function resolveScopePath(repoRoot: string, scope: string): Promise<string>;
823
860
 
824
- export { type AuditSummary, type BuildConfig, type BuildResult, type ChangelogGenerator, type CheckId, type CheckResult, type CheckResultDetails, type CleanInstallResult, type CustomCheckConfig, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, type FlowConfig, type PackagePublisher, type PackageVersion, type PackagesFilter, type PipelineOptions, type PipelineResult, type PlannerOptions, type PluginLogger, type PublishResult, type PublishablePackage, type ReleaseChannel, type ReleaseConfig, type ReleaseContext, type ReleasePlan, type ReleaseReport, type ReleaseResult, type ReleaseStage, type RollbackSnapshot, type StrategyOptions, type VerifyResult, type VersionBump, type VersionStrategy, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, spawnCommand, updatePackageVersion, updatePackageVersions, verifyAgainstRegistry, verifyCleanInstall, verifyExtractedTarball, verifyPackage, verifyPackages };
861
+ export { type AuditSummary, type BuildConfig, type BuildResult, CHECKS_CONCURRENCY, type ChangelogGenerator, type CheckId, type CheckResult, type CheckResultDetails, type CleanInstallResult, type CustomCheckConfig, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, type FlowConfig, type PackagePublisher, type PackageVersion, type PackagesFilter, type PipelineOptions, type PipelineResult, type PlannerOptions, type PluginLogger, type PublishResult, type PublishablePackage, type ReleaseChannel, type ReleaseConfig, type ReleaseContext, type ReleasePlan, type ReleaseReport, type ReleaseResult, type ReleaseShell, type ReleaseStage, type RollbackSnapshot, type StrategyOptions, type VerifyResult, type VersionBump, type VersionStrategy, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, updatePackageVersion, updatePackageVersions, verifyAgainstRegistry, verifyCleanInstall, verifyExtractedTarball, verifyPackage, verifyPackages };
package/dist/index.js CHANGED
@@ -6,9 +6,9 @@ import semver2 from 'semver';
6
6
  import globby from 'globby';
7
7
  import { discoverSubRepoPaths, useEnv } from '@kb-labs/sdk';
8
8
  import { execa } from 'execa';
9
- import { spawn, spawnSync } from 'child_process';
10
9
  import { tmpdir } from 'os';
11
10
  import { randomBytes } from 'crypto';
11
+ import { spawnSync } from 'child_process';
12
12
 
13
13
  // src/planner.ts
14
14
  function applyVersionStrategy(packages, options) {
@@ -24,12 +24,16 @@ function applyLockstep(packages) {
24
24
  if (packages.length === 0) {
25
25
  return packages;
26
26
  }
27
- const alreadyPublished = packages.filter((p) => p.isPublished);
28
- if (alreadyPublished.length > 0) {
29
- const sharedVersion = alreadyPublished.reduce(
30
- (max, p) => semver2.gt(p.nextVersion, max) ? p.nextVersion : max,
31
- alreadyPublished[0].nextVersion
32
- );
27
+ const pinned = packages.filter((p) => p.isPublished || p.versionPinned);
28
+ if (pinned.length > 0) {
29
+ const resolved = [...new Set(pinned.map((p) => p.nextVersion))];
30
+ if (resolved.length > 1) {
31
+ const detail = pinned.map((p) => `${p.name}@${p.nextVersion}`).join(", ");
32
+ throw new Error(
33
+ `Lockstep release has conflicting already-resolved versions: ${resolved.join(", ")} (${detail}). Reconcile package.json versions before releasing.`
34
+ );
35
+ }
36
+ const sharedVersion = resolved[0];
33
37
  return packages.map((pkg) => ({ ...pkg, nextVersion: sharedVersion }));
34
38
  }
35
39
  const maxBump = getMaxBump(packages);
@@ -214,16 +218,19 @@ async function planRelease(options) {
214
218
  })() : null;
215
219
  if (headVersion && headVersion !== pkg.currentVersion) {
216
220
  const alreadyPublished = await isVersionPublished(pkg.name, pkg.currentVersion, registry);
217
- if (alreadyPublished) {
218
- planPackages.push({
219
- ...pkg,
220
- gitRoot,
221
- nextVersion: pkg.currentVersion,
222
- bump: detectBumpType(headVersion, pkg.currentVersion),
223
- isPublished: true
224
- });
225
- continue;
226
- }
221
+ planPackages.push({
222
+ ...pkg,
223
+ gitRoot,
224
+ nextVersion: pkg.currentVersion,
225
+ bump: detectBumpType(headVersion, pkg.currentVersion),
226
+ isPublished: alreadyPublished,
227
+ // Mark the version as final so lockstep/adaptive resolution below
228
+ // doesn't re-derive (and thus re-bump) it. `isPublished` alone is not
229
+ // enough to signal this: the bump can legitimately be on disk but not
230
+ // yet published — exactly the `release:version` → `release:git` case.
231
+ versionPinned: true
232
+ });
233
+ continue;
227
234
  }
228
235
  const nextVersion = await computeNextVersion(
229
236
  pkg.path,
@@ -256,7 +263,9 @@ async function planRelease(options) {
256
263
  strategy: config.strategy || "semver",
257
264
  registry: config.registry || "https://registry.npmjs.org",
258
265
  rollbackEnabled: config.rollback?.enabled ?? true,
259
- channel
266
+ channel,
267
+ flow: options.flow,
268
+ scope
260
269
  };
261
270
  }
262
271
  function mapBumpStrategyToVersionStrategy(bumpStrategy) {
@@ -625,6 +634,12 @@ function mergeChangelogBlock(existingChangelog, newBlock, versionPattern) {
625
634
  }
626
635
  return newBlock + (existingChangelog ? "\n" + existingChangelog : "");
627
636
  }
637
+ function removeHistoricalDuplicateBullets(existingChangelog, newBlock) {
638
+ const historicalBullets = new Set(
639
+ existingChangelog.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("- "))
640
+ );
641
+ return newBlock.split("\n").filter((line) => !line.trim().startsWith("- ") || !historicalBullets.has(line.trim())).join("\n");
642
+ }
628
643
  var DEFAULT_ROOT_CHANGELOG_PATH = ".kb/release/CHANGELOG.md";
629
644
  function resolveRootChangelogRelPath(outputPath) {
630
645
  return outputPath && outputPath.trim().length > 0 ? outputPath : DEFAULT_ROOT_CHANGELOG_PATH;
@@ -647,7 +662,8 @@ async function mergeRootChangelog(options) {
647
662
  existingChangelog = await readFile(changelogPath, "utf-8");
648
663
  } catch {
649
664
  }
650
- const updatedChangelog = mergeChangelogBlock(existingChangelog, changelog.trim(), versionPattern);
665
+ const deduplicatedBlock = versionPattern.test(existingChangelog) ? changelog.trim() : removeHistoricalDuplicateBullets(existingChangelog, changelog.trim());
666
+ const updatedChangelog = mergeChangelogBlock(existingChangelog, deduplicatedBlock, versionPattern);
651
667
  await mkdir(dirname(changelogPath), { recursive: true });
652
668
  await writeFile(changelogPath, updatedChangelog.trim() + "\n", "utf-8");
653
669
  }
@@ -1101,7 +1117,7 @@ async function buildPackages(packages, options) {
1101
1117
  const ordered = topoSortForBuild(packages);
1102
1118
  for (const pkg of ordered) {
1103
1119
  options?.logger?.info?.(`Building ${pkg.name}...`);
1104
- const result = await runSafeBuild(pkg.path, pkg.name);
1120
+ const result = await runSafeBuild(pkg.path, pkg.name, options.shell);
1105
1121
  results.push({ ...result, name: pkg.name });
1106
1122
  options?.onProgress?.(pkg.name, { ...result, name: pkg.name });
1107
1123
  if (!result.success) {
@@ -1112,25 +1128,25 @@ async function buildPackages(packages, options) {
1112
1128
  }
1113
1129
  return results;
1114
1130
  }
1115
- async function runSafeBuild(packagePath, packageName) {
1131
+ async function runSafeBuild(packagePath, packageName, shell) {
1116
1132
  const usesTsup = existsSync(join(packagePath, "tsup.config.ts")) || existsSync(join(packagePath, "tsup.config.js"));
1117
1133
  if (usesTsup) {
1118
- return runTsupSafeBuild(packagePath, packageName);
1134
+ return runTsupSafeBuild(packagePath, packageName, shell);
1119
1135
  }
1120
- return runDirectBuild(packagePath, packageName);
1136
+ return runDirectBuild(packagePath, packageName, shell);
1121
1137
  }
1122
1138
  function isBuildCommand(command, args) {
1123
1139
  const full = [command, ...args ?? []].join(" ").trim();
1124
1140
  return /\b(pnpm|npm|yarn)\s+(run\s+)?build\b/.test(full);
1125
1141
  }
1126
- async function runTsupSafeBuild(packagePath, packageName) {
1142
+ async function runTsupSafeBuild(packagePath, packageName, shell) {
1127
1143
  const startTime = Date.now();
1128
1144
  const buildId = randomBytes(6).toString("hex");
1129
1145
  const tempDir = join(tmpdir(), `kb-release-build-${buildId}`);
1130
1146
  const distDir = join(packagePath, "dist");
1131
1147
  const backupDir = join(packagePath, `dist.bak-${buildId}`);
1132
1148
  try {
1133
- const buildResult = await spawnCommand(`npx tsup -d ${tempDir}`, packagePath);
1149
+ const buildResult = await executeCommand(shell, "npx", ["tsup", "-d", tempDir], packagePath, 5 * 60 * 1e3);
1134
1150
  if (!buildResult.success) {
1135
1151
  await rm(tempDir, { recursive: true, force: true }).catch(() => {
1136
1152
  });
@@ -1164,54 +1180,25 @@ async function runTsupSafeBuild(packagePath, packageName) {
1164
1180
  };
1165
1181
  }
1166
1182
  }
1167
- async function runDirectBuild(packagePath, packageName) {
1168
- const result = await spawnCommand("pnpm run build", packagePath);
1183
+ async function runDirectBuild(packagePath, packageName, shell) {
1184
+ const result = await executeCommand(shell, "pnpm", ["run", "build"], packagePath, 5 * 60 * 1e3);
1169
1185
  return { ...result, name: packageName };
1170
1186
  }
1171
- function spawnCommand(command, cwd, timeoutMs = 5 * 60 * 1e3) {
1187
+ async function executeCommand(shell, command, args, cwd, timeoutMs) {
1172
1188
  const startTime = Date.now();
1173
- return new Promise((resolve3) => {
1174
- const child = spawn(command, [], {
1175
- cwd,
1176
- stdio: "pipe",
1177
- shell: true,
1178
- env: { ...process.env }
1179
- });
1180
- let stdout = "";
1181
- let stderr = "";
1182
- child.stdout?.on("data", (data) => {
1183
- stdout += data.toString();
1184
- });
1185
- child.stderr?.on("data", (data) => {
1186
- stderr += data.toString();
1187
- });
1188
- child.on("close", (code) => {
1189
- const exitCode = code ?? 1;
1190
- const durationMs = Date.now() - startTime;
1191
- if (exitCode === 0) {
1192
- resolve3({ success: true, durationMs, stdout, stderr, exitCode });
1193
- return;
1194
- }
1195
- const combined = (stderr || stdout).trim();
1196
- const tail = combined.split("\n").slice(-30).join("\n");
1197
- resolve3({
1198
- success: false,
1199
- error: tail || `Build failed with exit code ${exitCode}`,
1200
- durationMs,
1201
- stdout,
1202
- stderr,
1203
- exitCode
1204
- });
1205
- });
1206
- child.on("error", (err) => {
1207
- resolve3({ success: false, error: err.message, durationMs: Date.now() - startTime, stdout: "", stderr: "", exitCode: 1 });
1208
- });
1209
- setTimeout(() => {
1210
- child.kill();
1211
- resolve3({ success: false, error: `Timed out after ${timeoutMs / 1e3}s`, durationMs: Date.now() - startTime, stdout: "", stderr: "", exitCode: 1 });
1212
- }, timeoutMs);
1213
- });
1189
+ const result = await shell.exec(command, args, { cwd, timeout: timeoutMs });
1190
+ const exitCode = result.code;
1191
+ const combined = (result.stderr || result.stdout).trim();
1192
+ return {
1193
+ success: result.ok,
1194
+ error: result.ok ? void 0 : combined.split("\n").slice(-30).join("\n") || `Build failed with exit code ${exitCode}`,
1195
+ durationMs: Date.now() - startTime,
1196
+ stdout: result.stdout,
1197
+ stderr: result.stderr,
1198
+ exitCode
1199
+ };
1214
1200
  }
1201
+ var CHECKS_CONCURRENCY = 2;
1215
1202
  async function runReleaseChecks(checks, options) {
1216
1203
  const results = [];
1217
1204
  for (const check of checks) {
@@ -1234,33 +1221,32 @@ async function runSingleCheck(check, options) {
1234
1221
  } else {
1235
1222
  pathsToRun = options.packagePaths.length > 0 ? options.packagePaths : [options.repoRoot];
1236
1223
  }
1237
- const CONCURRENCY = 8;
1238
1224
  const resolvedArgs = (check.args ?? []).map(
1239
1225
  (arg) => arg.match(/\.(sh|js|ts|mjs|cjs)$/) ? join(options.repoRoot, arg) : arg
1240
1226
  );
1241
- const fullCommand = [check.command, ...resolvedArgs].join(" ");
1242
1227
  const timeoutMs = check.timeoutMs ?? 12e4;
1243
1228
  async function runForPath(pkgPath) {
1244
- const result = await spawnCommand(fullCommand, pkgPath, timeoutMs);
1245
- const ok = evaluateParser(check, result.stdout, result.stderr, result.exitCode);
1229
+ const startedAt = Date.now();
1230
+ const result = await options.shell.exec(check.command, resolvedArgs, { cwd: pkgPath, timeout: timeoutMs });
1231
+ const ok = evaluateParser(check, result.stdout, result.stderr, result.code);
1246
1232
  return {
1247
1233
  path: pkgPath,
1248
1234
  ok,
1249
- durationMs: result.durationMs,
1235
+ durationMs: Date.now() - startedAt,
1250
1236
  details: {
1251
1237
  packagePath: pkgPath,
1252
1238
  stdout: result.stdout || void 0,
1253
1239
  stderr: result.stderr || void 0,
1254
- exitCode: result.exitCode,
1255
- error: result.error ?? (!ok ? `exit code ${result.exitCode}` : void 0)
1240
+ exitCode: result.code,
1241
+ error: !ok ? `exit code ${result.code}` : void 0
1256
1242
  }
1257
1243
  };
1258
1244
  }
1259
1245
  let pkgResults;
1260
1246
  if (runIn === "perPackage" && pathsToRun.length > 1) {
1261
1247
  pkgResults = [];
1262
- for (let i = 0; i < pathsToRun.length; i += CONCURRENCY) {
1263
- const batch = pathsToRun.slice(i, i + CONCURRENCY);
1248
+ for (let i = 0; i < pathsToRun.length; i += CHECKS_CONCURRENCY) {
1249
+ const batch = pathsToRun.slice(i, i + CHECKS_CONCURRENCY);
1264
1250
  pkgResults.push(...await Promise.all(batch.map(runForPath)));
1265
1251
  }
1266
1252
  } else {
@@ -1273,6 +1259,7 @@ async function runSingleCheck(check, options) {
1273
1259
  return {
1274
1260
  id: check.id,
1275
1261
  ok: allOk,
1262
+ optional: check.optional,
1276
1263
  details: firstFailure,
1277
1264
  hint: check.optional ? "optional" : void 0,
1278
1265
  timingMs: totalDurationMs,
@@ -1662,7 +1649,8 @@ async function _runPipeline(ctx) {
1662
1649
  changelogGen,
1663
1650
  logger,
1664
1651
  startTime,
1665
- progress
1652
+ progress,
1653
+ options
1666
1654
  } = ctx;
1667
1655
  const channel = config.channel ?? "stable";
1668
1656
  const publishTag = resolvePublishTag(config, channel);
@@ -1746,7 +1734,8 @@ async function _runPipeline(ctx) {
1746
1734
  repoRoot,
1747
1735
  packagePaths,
1748
1736
  scopePath: scopeCwd,
1749
- logger
1737
+ logger,
1738
+ shell: options.shell
1750
1739
  });
1751
1740
  const failed = checkResults.filter((r) => !r.ok && r.hint !== "optional");
1752
1741
  if (failed.length > 0) {
@@ -1789,7 +1778,7 @@ async function _runPipeline(ctx) {
1789
1778
  }
1790
1779
  if (!skipBuild && !dryRun) {
1791
1780
  progress("versioning", `Building ${plan.packages.length} package(s)...`);
1792
- const buildResults = await buildPackages(plan.packages, { logger });
1781
+ const buildResults = await buildPackages(plan.packages, { logger, shell: options.shell });
1793
1782
  const buildFailed = buildResults.filter((r) => !r.success);
1794
1783
  if (buildFailed.length > 0) {
1795
1784
  await restoreSnapshot(repoRoot);
@@ -2090,6 +2079,6 @@ async function resolveScopePath(repoRoot, scope) {
2090
2079
  return join(repoRoot, scope);
2091
2080
  }
2092
2081
 
2093
- export { DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, spawnCommand, updatePackageVersion, updatePackageVersions, verifyAgainstRegistry, verifyCleanInstall, verifyExtractedTarball, verifyPackage, verifyPackages };
2082
+ export { CHECKS_CONCURRENCY, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, copyChangelogToPackages, createExecaShellAdapter, discoverCurrentPackages, findForbiddenDependencyProtocols, isBuildCommand, isVersionPublished, matchesPackagePattern, mergeConfigWithFlow, mergeRootChangelog, planRelease, renderJson, renderMarkdown, renderText, resolveFlowFromTag, resolvePublishRegistry, resolvePublishTag, resolveRootChangelogRelPath, resolveScopePath, restoreSnapshot, runReleaseChecks, runReleasePipeline, runSafeBuild, saveSnapshot, updatePackageVersion, updatePackageVersions, verifyAgainstRegistry, verifyCleanInstall, verifyExtractedTarball, verifyPackage, verifyPackages };
2094
2083
  //# sourceMappingURL=index.js.map
2095
2084
  //# sourceMappingURL=index.js.map