@kb-labs/release-manager-core 2.118.2 → 2.119.0-canary.0b4b21a55

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
@@ -357,6 +357,14 @@ interface ChangelogGenerator {
357
357
  repoRoot: string;
358
358
  gitCwd: string;
359
359
  config: ReleaseConfig;
360
+ /** Named flow whose release tag pattern bounds the changelog. */
361
+ flow?: string;
362
+ /** Explicit git boundaries; these take precedence over the flow baseline. */
363
+ range?: {
364
+ from?: string;
365
+ to?: string;
366
+ sinceTag?: string;
367
+ };
360
368
  }): Promise<string>;
361
369
  }
362
370
  interface PipelineOptions {
@@ -656,6 +664,60 @@ declare function resolveFlowFromTag(config: ReleaseConfig, tag: string): {
656
664
  channel: ReleaseChannel;
657
665
  } | null;
658
666
 
667
+ /**
668
+ * Release status — a read-only "what is actually true right now" view for a
669
+ * flow, cross-checking the surfaces that the 2026-08-13 release-system audit
670
+ * found drifting apart independently: the latest stable git tag, and the
671
+ * real npm dist-tags packages currently resolve to.
672
+ *
673
+ * This does not replace the receipt/state-machine model from the breaking
674
+ * control-plane cutover plan — it is the cheap, non-breaking piece of that
675
+ * diagnosis that can ship today: make "a tag/npm entry exists" and "this was
676
+ * actually verified and promoted" visibly different without any new storage.
677
+ */
678
+
679
+ interface NpmDistTagInfo {
680
+ name: string;
681
+ stableVersion: string | null;
682
+ canaryVersion: string | null;
683
+ error?: string;
684
+ }
685
+ interface StableTagInfo {
686
+ tag: string | null;
687
+ version: string | null;
688
+ commit: string | null;
689
+ committedAt: string | null;
690
+ }
691
+ interface FlowReleaseStatus {
692
+ flow: string;
693
+ packages: string[];
694
+ git: StableTagInfo;
695
+ npm: {
696
+ registry: string;
697
+ stableDistTag: string;
698
+ canaryDistTag: string;
699
+ perPackage: NpmDistTagInfo[];
700
+ /** Agreed version across all sampled packages, or null if they disagree or none resolved. */
701
+ stableVersion: string | null;
702
+ canaryVersion: string | null;
703
+ stableDrift: boolean;
704
+ canaryDrift: boolean;
705
+ };
706
+ verdict: {
707
+ ok: boolean;
708
+ warnings: string[];
709
+ };
710
+ }
711
+ interface ComputeFlowReleaseStatusOptions {
712
+ cwd: string;
713
+ config: ReleaseConfig;
714
+ flow: string;
715
+ shell: ShellAPI;
716
+ /** How many of the flow's packages to sample against npm. Lockstep flows only need enough to detect drift. Default 3. */
717
+ maxPackagesToCheck?: number;
718
+ }
719
+ declare function computeFlowReleaseStatus(opts: ComputeFlowReleaseStatusOptions): Promise<FlowReleaseStatus>;
720
+
659
721
  /**
660
722
  * Unified release pipeline — single orchestrator for CLI and REST.
661
723
  *
@@ -744,12 +806,26 @@ declare function runReleaseChecks(checks: CustomCheckConfig[], options: CheckRun
744
806
  declare function verifyPackages(packages: PackageVersion[], options?: {
745
807
  logger?: Pick<PluginLogger, 'info'>;
746
808
  onProgress?: (pkg: string, result: VerifyResult) => void;
809
+ packageManager?: 'pnpm' | 'npm' | 'yarn';
747
810
  }): Promise<VerifyResult[]>;
748
811
  /**
749
812
  * Verify a single package is publishable.
750
- * npm pack → extract → check exports, directory imports, test leaks, syntax.
751
- */
752
- declare function verifyPackage(packagePath: string, packageName?: string): VerifyResult;
813
+ * pack → extract → check exports, directory imports, test leaks, syntax.
814
+ *
815
+ * Packing tool must match what the real publish step will actually use:
816
+ * `pnpm pack` resolves `workspace:`/`link:` protocol refs to real version
817
+ * ranges natively (confirmed: `pnpm pack` on a package with
818
+ * `peerDependencies: { "@kb-labs/sdk": "workspace:^" }` produces a tarball
819
+ * with `"@kb-labs/sdk": "^2.115.4"`). `npm pack` does not — it packs the
820
+ * manifest byte-for-byte, so an unrewritten `workspace:*`/`link:` ref
821
+ * survives into the tarball and gets correctly flagged by
822
+ * findForbiddenDependencyProtocols() below. Defaulting to 'npm' here when
823
+ * the caller doesn't say otherwise is deliberately the strict reading (catch
824
+ * it even if we don't know yet what will actually publish); passing 'pnpm'
825
+ * for a pipeline that really does pack with pnpm avoids false positives on
826
+ * refs pnpm already resolves for free.
827
+ */
828
+ declare function verifyPackage(packagePath: string, packageName?: string, packageManager?: 'pnpm' | 'npm' | 'yarn'): VerifyResult;
753
829
  /**
754
830
  * Run the static artifact checks (test-file leaks, exports existence,
755
831
  * directory-import detection, syntax validation) against an already
@@ -798,6 +874,13 @@ interface VerifyAgainstRegistryOptions {
798
874
  * Default: 0 (single attempt, matches pre-existing Verdaccio behavior).
799
875
  */
800
876
  retries?: number;
877
+ /**
878
+ * Total time to wait for npm metadata and tarballs to propagate after a
879
+ * publish. When provided this supersedes the legacy fixed retry count, so
880
+ * an idempotent re-run resumes verification of already-published tarballs
881
+ * instead of requiring a new publish or a workflow-owned sleep.
882
+ */
883
+ visibilityDeadlineMs?: number;
801
884
  retryDelaysMs?: readonly number[];
802
885
  logger?: Pick<PluginLogger, 'info' | 'warn'>;
803
886
  }
@@ -858,4 +941,4 @@ declare function verifyCleanInstall(tarballPath: string, packageName: string, ad
858
941
  */
859
942
  declare function resolveScopePath(repoRoot: string, scope: string): Promise<string>;
860
943
 
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 };
944
+ export { type AuditSummary, type BuildConfig, type BuildResult, CHECKS_CONCURRENCY, type ChangelogGenerator, type CheckId, type CheckResult, type CheckResultDetails, type CleanInstallResult, type ComputeFlowReleaseStatusOptions, type CustomCheckConfig, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, type FlowConfig, type FlowReleaseStatus, type NpmDistTagInfo, 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 StableTagInfo, type StrategyOptions, type VerifyResult, type VersionBump, type VersionStrategy, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, computeFlowReleaseStatus, 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
@@ -1050,6 +1050,133 @@ function resolvePublishRegistry(config, channel) {
1050
1050
  }
1051
1051
  return config.registry ?? DEFAULT_NPM_REGISTRY;
1052
1052
  }
1053
+
1054
+ // src/status.ts
1055
+ var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/;
1056
+ function compareSemver(a, b) {
1057
+ const ma = a.match(SEMVER_RE);
1058
+ const mb = b.match(SEMVER_RE);
1059
+ if (!ma || !mb) {
1060
+ return 0;
1061
+ }
1062
+ for (let i = 1; i <= 3; i++) {
1063
+ const diff = Number(ma[i]) - Number(mb[i]);
1064
+ if (diff !== 0) {
1065
+ return diff;
1066
+ }
1067
+ }
1068
+ return 0;
1069
+ }
1070
+ function escapeRegex2(str) {
1071
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1072
+ }
1073
+ async function fetchDistTags(name, registry) {
1074
+ try {
1075
+ const encoded = name.startsWith("@") ? `@${encodeURIComponent(name.slice(1))}` : name;
1076
+ const url = `${registry.replace(/\/$/, "")}/${encoded}`;
1077
+ const res = await fetch(url, {
1078
+ headers: { Accept: "application/vnd.npm.install-v1+json" },
1079
+ signal: AbortSignal.timeout(8e3)
1080
+ });
1081
+ if (!res.ok) {
1082
+ return { error: `HTTP ${res.status}` };
1083
+ }
1084
+ const body = await res.json();
1085
+ return body["dist-tags"] ?? {};
1086
+ } catch (err) {
1087
+ return { error: err instanceof Error ? err.message : String(err) };
1088
+ }
1089
+ }
1090
+ async function findLatestStableTag(shell, cwd, flowName, tagPattern) {
1091
+ const empty = { tag: null, version: null, commit: null, committedAt: null };
1092
+ const prefix = tagPattern.split("{version}")[0]?.replace("{flow}", flowName) ?? `${flowName}-v`;
1093
+ const listRes = await shell.exec("git", ["tag", "-l", `${prefix}*`], { cwd });
1094
+ const tags = listRes.stdout.split("\n").map((t) => t.trim()).filter(Boolean);
1095
+ if (tags.length === 0) {
1096
+ return empty;
1097
+ }
1098
+ const versionRe = new RegExp(`^${escapeRegex2(prefix)}(\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?)$`);
1099
+ const parsed = tags.map((t) => ({ tag: t, version: t.match(versionRe)?.[1] })).filter((t) => Boolean(t.version));
1100
+ if (parsed.length === 0) {
1101
+ return empty;
1102
+ }
1103
+ parsed.sort((a, b) => compareSemver(a.version, b.version));
1104
+ const latest = parsed[parsed.length - 1];
1105
+ const [shaRes, dateRes] = await Promise.all([
1106
+ shell.exec("git", ["rev-list", "-n", "1", latest.tag], { cwd }),
1107
+ shell.exec("git", ["log", "-1", "--format=%cI", latest.tag], { cwd })
1108
+ ]);
1109
+ return {
1110
+ tag: latest.tag,
1111
+ version: latest.version,
1112
+ commit: shaRes.stdout.trim() || null,
1113
+ committedAt: dateRes.stdout.trim() || null
1114
+ };
1115
+ }
1116
+ async function computeFlowReleaseStatus(opts) {
1117
+ const { cwd, config, flow, shell, maxPackagesToCheck = 3 } = opts;
1118
+ const flowConfig = mergeConfigWithFlow(config, flow);
1119
+ const tagPattern = config.flows?.[flow]?.tagPattern ?? DEFAULT_TAG_PATTERN;
1120
+ const packages = await discoverCurrentPackages(cwd, void 0, flowConfig);
1121
+ const registry = resolvePublishRegistry(config, "canary");
1122
+ const stableDistTag = resolvePublishTag(config, "stable");
1123
+ const canaryDistTag = resolvePublishTag(config, "canary");
1124
+ const sampled = packages.slice(0, maxPackagesToCheck);
1125
+ const perPackage = [];
1126
+ for (const pkg of sampled) {
1127
+ const result = await fetchDistTags(pkg.name, registry);
1128
+ if ("error" in result) {
1129
+ perPackage.push({ name: pkg.name, stableVersion: null, canaryVersion: null, error: result.error });
1130
+ } else {
1131
+ perPackage.push({
1132
+ name: pkg.name,
1133
+ stableVersion: result[stableDistTag] ?? null,
1134
+ canaryVersion: result[canaryDistTag] ?? null
1135
+ });
1136
+ }
1137
+ }
1138
+ const stableVersions = new Set(perPackage.map((p) => p.stableVersion).filter((v) => Boolean(v)));
1139
+ const canaryVersions = new Set(perPackage.map((p) => p.canaryVersion).filter((v) => Boolean(v)));
1140
+ const git = await findLatestStableTag(shell, cwd, flow, tagPattern);
1141
+ const warnings = [];
1142
+ if (stableVersions.size > 1) {
1143
+ warnings.push(`Packages disagree on npm "${stableDistTag}" version: ${[...stableVersions].join(", ")}`);
1144
+ }
1145
+ if (canaryVersions.size > 1) {
1146
+ warnings.push(`Packages disagree on npm "${canaryDistTag}" version: ${[...canaryVersions].join(", ")}`);
1147
+ }
1148
+ const stableVersion = stableVersions.size === 1 ? [...stableVersions][0] : null;
1149
+ const canaryVersion = canaryVersions.size === 1 ? [...canaryVersions][0] : null;
1150
+ if (git.version && stableVersion && git.version !== stableVersion) {
1151
+ warnings.push(
1152
+ `Latest git tag ${git.tag} (${git.version}) does not match npm "${stableDistTag}" (${stableVersion})`
1153
+ );
1154
+ }
1155
+ if (stableVersion && canaryVersion && compareSemver(canaryVersion, stableVersion) > 0) {
1156
+ warnings.push(
1157
+ `npm "${canaryDistTag}" (${canaryVersion}) is ahead of "${stableDistTag}" (${stableVersion}) \u2014 treat as an unverified candidate, not a release, until it has a green delivery + smoke run and has been explicitly promoted`
1158
+ );
1159
+ }
1160
+ return {
1161
+ flow,
1162
+ packages: packages.map((p) => p.name),
1163
+ git,
1164
+ npm: {
1165
+ registry,
1166
+ stableDistTag,
1167
+ canaryDistTag,
1168
+ perPackage,
1169
+ stableVersion,
1170
+ canaryVersion,
1171
+ stableDrift: stableVersions.size > 1,
1172
+ canaryDrift: canaryVersions.size > 1
1173
+ },
1174
+ verdict: {
1175
+ ok: warnings.length === 0,
1176
+ warnings
1177
+ }
1178
+ };
1179
+ }
1053
1180
  function buildIntraDeps(packages, nameSet) {
1054
1181
  const deps = /* @__PURE__ */ new Map();
1055
1182
  for (const pkg of packages) {
@@ -1287,13 +1414,13 @@ function evaluateParser(check, stdout, stderr, exitCode) {
1287
1414
  async function verifyPackages(packages, options) {
1288
1415
  const results = [];
1289
1416
  for (const pkg of packages) {
1290
- const result = verifyPackage(pkg.path, pkg.name);
1417
+ const result = verifyPackage(pkg.path, pkg.name, options?.packageManager);
1291
1418
  results.push(result);
1292
1419
  options?.onProgress?.(pkg.name, result);
1293
1420
  }
1294
1421
  return results;
1295
1422
  }
1296
- function verifyPackage(packagePath, packageName) {
1423
+ function verifyPackage(packagePath, packageName, packageManager = "npm") {
1297
1424
  const pkgJsonPath = join(packagePath, "package.json");
1298
1425
  if (!existsSync(pkgJsonPath)) {
1299
1426
  return { name: packageName ?? packagePath, success: true, issues: [] };
@@ -1310,23 +1437,26 @@ function verifyPackage(packagePath, packageName) {
1310
1437
  const tmpDir = join(tmpdir(), `kb-verify-${randomBytes(6).toString("hex")}`);
1311
1438
  try {
1312
1439
  mkdirSync(tmpDir, { recursive: true });
1440
+ const isPnpm = packageManager === "pnpm";
1313
1441
  const origPkg = readFileSync(pkgJsonPath, "utf-8");
1314
- const modPkg = JSON.parse(origPkg);
1315
- for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
1316
- const deps = modPkg[section];
1317
- if (!deps) {
1318
- continue;
1319
- }
1320
- for (const [k, v] of Object.entries(deps)) {
1321
- if (typeof v === "string" && v.startsWith("link:")) {
1322
- deps[k] = "*";
1442
+ if (!isPnpm) {
1443
+ const modPkg = JSON.parse(origPkg);
1444
+ for (const section of ["dependencies", "devDependencies", "peerDependencies"]) {
1445
+ const deps = modPkg[section];
1446
+ if (!deps) {
1447
+ continue;
1448
+ }
1449
+ for (const [k, v] of Object.entries(deps)) {
1450
+ if (typeof v === "string" && v.startsWith("link:")) {
1451
+ deps[k] = "*";
1452
+ }
1323
1453
  }
1324
1454
  }
1455
+ writeFileSync(pkgJsonPath, JSON.stringify(modPkg, null, 2) + "\n");
1325
1456
  }
1326
- writeFileSync(pkgJsonPath, JSON.stringify(modPkg, null, 2) + "\n");
1327
1457
  let tgzFile;
1328
1458
  try {
1329
- spawnSync("npm", ["pack", "--pack-destination", tmpDir], { cwd: packagePath, stdio: "pipe", timeout: 3e4 });
1459
+ spawnSync(isPnpm ? "pnpm" : "npm", ["pack", "--pack-destination", tmpDir], { cwd: packagePath, stdio: "pipe", timeout: 3e4 });
1330
1460
  const files = readdirSync(tmpDir).filter((f) => f.endsWith(".tgz"));
1331
1461
  tgzFile = files[0] ? join(tmpDir, files[0]) : void 0;
1332
1462
  } finally {
@@ -1483,31 +1613,35 @@ async function verifyAgainstRegistry(packages, options) {
1483
1613
  const { registry, timeout = DEFAULT_TIMEOUT_MS, retries = 0, retryDelaysMs = DEFAULT_POLL_RETRY_DELAYS_MS, logger } = options;
1484
1614
  const results = [];
1485
1615
  for (const pkg of packages) {
1486
- results.push(await verifyOneAgainstRegistry(pkg, registry, timeout, retries, retryDelaysMs, logger));
1616
+ results.push(await verifyOneAgainstRegistry(pkg, registry, timeout, retries, retryDelaysMs, options.visibilityDeadlineMs, logger));
1487
1617
  }
1488
1618
  return results;
1489
1619
  }
1490
- async function waitUntilPublished(pkg, registry, retries, retryDelaysMs, logger) {
1491
- for (let attempt = 0; attempt <= retries; attempt++) {
1620
+ async function waitUntilPublished(pkg, registry, retries, retryDelaysMs, visibilityDeadlineMs, logger) {
1621
+ const deadline = visibilityDeadlineMs === void 0 ? void 0 : Date.now() + visibilityDeadlineMs;
1622
+ for (let attempt = 0; deadline === void 0 ? attempt <= retries : Date.now() <= deadline; attempt++) {
1492
1623
  if (await isVersionPublished(pkg.name, pkg.version, registry)) {
1493
1624
  return true;
1494
1625
  }
1495
- if (attempt < retries) {
1626
+ if (deadline === void 0 ? attempt < retries : Date.now() < deadline) {
1496
1627
  const delay = retryDelaysMs[Math.min(attempt, retryDelaysMs.length - 1)];
1628
+ const remaining = deadline === void 0 ? void 0 : deadline - Date.now();
1629
+ const waitMs = remaining === void 0 ? delay : Math.min(delay, Math.max(0, remaining));
1497
1630
  logger?.warn?.(
1498
- `${pkg.name}@${pkg.version} not yet visible on ${registry} (attempt ${attempt + 1}/${retries + 1}), retrying in ${(delay / 1e3).toFixed(0)}s \u2014 likely registry propagation lag`
1631
+ `${pkg.name}@${pkg.version} not yet visible on ${registry} (attempt ${attempt + 1}${deadline === void 0 ? `/${retries + 1}` : ""}), retrying in ${(waitMs / 1e3).toFixed(0)}s${remaining === void 0 ? "" : `; ${(Math.max(0, remaining) / 1e3).toFixed(0)}s remain`} \u2014 likely registry propagation lag`
1499
1632
  );
1500
1633
  await new Promise((r) => {
1501
- setTimeout(r, delay);
1634
+ setTimeout(r, waitMs);
1502
1635
  });
1503
1636
  }
1504
1637
  }
1505
1638
  return false;
1506
1639
  }
1507
- async function verifyOneAgainstRegistry(pkg, registry, timeout, retries, retryDelaysMs, logger) {
1508
- const published = await waitUntilPublished(pkg, registry, retries, retryDelaysMs, logger);
1640
+ async function verifyOneAgainstRegistry(pkg, registry, timeout, retries, retryDelaysMs, visibilityDeadlineMs, logger) {
1641
+ const published = await waitUntilPublished(pkg, registry, retries, retryDelaysMs, visibilityDeadlineMs, logger);
1509
1642
  if (!published) {
1510
- return { name: pkg.name, success: false, issues: [`${pkg.name}@${pkg.version} was not found on ${registry} after publish (waited through ${retries} retr${retries === 1 ? "y" : "ies"})`] };
1643
+ const waited = visibilityDeadlineMs === void 0 ? `waited through ${retries} retr${retries === 1 ? "y" : "ies"}` : `visibility deadline of ${(visibilityDeadlineMs / 1e3).toFixed(0)}s elapsed`;
1644
+ return { name: pkg.name, success: false, issues: [`${pkg.name}@${pkg.version} was not found on ${registry} after publish (${waited})`] };
1511
1645
  }
1512
1646
  logger?.info?.(`${pkg.name}@${pkg.version} confirmed on ${registry}`);
1513
1647
  const tmpDir = join(tmpdir(), `kb-verdaccio-verify-${randomBytes(6).toString("hex")}`);
@@ -1809,7 +1943,8 @@ async function _runPipeline(ctx) {
1809
1943
  }
1810
1944
  if (!skipVerify && !dryRun) {
1811
1945
  progress("verifying", "Verifying package artifacts...");
1812
- const verifyResults = await verifyPackages(plan.packages, { logger });
1946
+ const packageManager = config.workspace?.type ?? config.publish?.packageManager ?? "pnpm";
1947
+ const verifyResults = await verifyPackages(plan.packages, { logger, packageManager });
1813
1948
  const verifyFailed = verifyResults.filter((r) => !r.success);
1814
1949
  if (verifyFailed.length > 0) {
1815
1950
  await restoreSnapshot(repoRoot);
@@ -1851,7 +1986,7 @@ async function _runPipeline(ctx) {
1851
1986
  if (changelogGen && channel === "stable") {
1852
1987
  progress("versioning", "Generating changelog...");
1853
1988
  try {
1854
- changelogMd = await changelogGen.generate(plan, { repoRoot, gitCwd: scopeCwd, config });
1989
+ changelogMd = await changelogGen.generate(plan, { repoRoot, gitCwd: scopeCwd, config, flow });
1855
1990
  } catch (err) {
1856
1991
  logger?.warn?.(`Changelog generation failed: ${err instanceof Error ? err.message : String(err)}`);
1857
1992
  }
@@ -2093,6 +2228,6 @@ async function resolveScopePath(repoRoot, scope) {
2093
2228
  return join(repoRoot, scope);
2094
2229
  }
2095
2230
 
2096
- 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 };
2231
+ export { CHECKS_CONCURRENCY, DEFAULT_ROOT_CHANGELOG_PATH, DEFAULT_TAG_PATTERN, applyCanarySuffix, applyVersionStrategy, buildPackages, buildReleaseTag, commitAndTagRelease, computeFlowReleaseStatus, 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 };
2097
2232
  //# sourceMappingURL=index.js.map
2098
2233
  //# sourceMappingURL=index.js.map