@fern-api/generator-cli 0.9.30 → 0.9.32

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/api.d.ts CHANGED
@@ -580,8 +580,6 @@ interface ReplayRunResult {
580
580
  previousGenerationSha: string | null;
581
581
  /** SHA of the [fern-generated] commit created by this replay run (null if replay didn't run or unreadable) */
582
582
  currentGenerationSha: string | null;
583
- /** SHA of main's HEAD before replay ran. Always on main's lineage, stable after squash merges. */
584
- baseBranchHead: string | null;
585
583
  /** True when this run inlined `bootstrap()` to create the lockfile (auto-init from `fern generate`). */
586
584
  autoBootstrapped: boolean;
587
585
  /**
package/dist/api.js CHANGED
@@ -10356,19 +10356,10 @@ async function replayResolve(params) {
10356
10356
 
10357
10357
  // src/replay/replay-run.ts
10358
10358
  var import_replay4 = require("@fern-api/replay");
10359
- var import_child_process3 = require("child_process");
10360
10359
  var import_fs3 = require("fs");
10361
10360
  var import_path5 = require("path");
10362
10361
  async function replayPrepare(params, state) {
10363
- const {
10364
- outputDir,
10365
- cliVersion,
10366
- generatorVersions,
10367
- stageOnly = false,
10368
- generatorName,
10369
- skipApplication,
10370
- logger
10371
- } = params;
10362
+ const { outputDir, cliVersion, generatorVersions, stageOnly = false, skipApplication, logger } = params;
10372
10363
  const lockfilePath = (0, import_path5.join)(outputDir, ".fern", "replay.lock");
10373
10364
  let autoBootstrapped = false;
10374
10365
  let bootstrapAttempted = false;
@@ -10401,63 +10392,6 @@ async function replayPrepare(params, state) {
10401
10392
  return null;
10402
10393
  }
10403
10394
  }
10404
- const baseBranchHead = gitRevParse(outputDir, "HEAD");
10405
- let previousGenerationSha = null;
10406
- let prevBaseBranchHead = null;
10407
- try {
10408
- const lockManager = new import_replay4.LockfileManager(outputDir);
10409
- if (lockManager.exists()) {
10410
- const lock = lockManager.read();
10411
- previousGenerationSha = lock.current_generation;
10412
- const latestGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
10413
- prevBaseBranchHead = latestGen?.base_branch_head ?? null;
10414
- }
10415
- } catch {
10416
- }
10417
- if (previousGenerationSha != null) {
10418
- const sanitizedName = generatorName?.replace(/\//g, "--");
10419
- const namespacedTag = sanitizedName != null ? `fern-generation-base--${sanitizedName}` : null;
10420
- const tagSha = (namespacedTag != null ? gitRevParse(outputDir, namespacedTag) : null) ?? gitRevParse(outputDir, "fern-generation-base");
10421
- let shouldSync = false;
10422
- if (tagSha != null) {
10423
- const tagParent = gitRevParse(outputDir, `${tagSha}^`);
10424
- if (tagParent === prevBaseBranchHead || tagParent === previousGenerationSha) {
10425
- const tagDistance = gitDiffNameOnly(outputDir, tagSha, "HEAD").length;
10426
- const lockDistance = gitDiffNameOnly(
10427
- outputDir,
10428
- prevBaseBranchHead ?? previousGenerationSha,
10429
- "HEAD"
10430
- ).length;
10431
- shouldSync = tagDistance < lockDistance;
10432
- }
10433
- }
10434
- if (shouldSync && tagSha != null) {
10435
- if (!isTagMergedIntoHead(outputDir, tagSha)) {
10436
- logger?.warn(
10437
- `fern-generation-base tag ${tagSha} is not reachable from HEAD \u2014 skipping divergent-merge sync. The tag likely points at an unmerged generation (PR closed without merge).`
10438
- );
10439
- } else {
10440
- try {
10441
- const syncService = new import_replay4.ReplayService(outputDir, { enabled: true });
10442
- await syncService.syncFromDivergentMerge(tagSha, {
10443
- cliVersion,
10444
- generatorVersions,
10445
- baseBranchHead: baseBranchHead ?? void 0
10446
- });
10447
- } catch (error) {
10448
- logger?.warn("Replay divergent-merge sync failed, continuing without sync: " + String(error));
10449
- throw new ReplayPrepareError(String(error), error);
10450
- }
10451
- try {
10452
- const freshLockManager = new import_replay4.LockfileManager(outputDir);
10453
- if (freshLockManager.exists()) {
10454
- previousGenerationSha = freshLockManager.read().current_generation;
10455
- }
10456
- } catch {
10457
- }
10458
- }
10459
- }
10460
- }
10461
10395
  const service = new import_replay4.ReplayService(outputDir, { enabled: true });
10462
10396
  let preparation;
10463
10397
  try {
@@ -10465,8 +10399,7 @@ async function replayPrepare(params, state) {
10465
10399
  cliVersion,
10466
10400
  generatorVersions,
10467
10401
  stageOnly,
10468
- skipApplication,
10469
- baseBranchHead: baseBranchHead ?? void 0
10402
+ skipApplication
10470
10403
  });
10471
10404
  } catch (error) {
10472
10405
  logger?.warn("Replay prepare failed, continuing without replay: " + String(error));
@@ -10477,9 +10410,8 @@ async function replayPrepare(params, state) {
10477
10410
  _preparation: preparation,
10478
10411
  outputDir,
10479
10412
  flow: preparation.flow,
10480
- previousGenerationSha,
10413
+ previousGenerationSha: preparation.previousGenerationSha,
10481
10414
  currentGenerationSha: preparation.currentGenerationSha,
10482
- baseBranchHead,
10483
10415
  autoBootstrapped,
10484
10416
  bootstrapAttempted
10485
10417
  };
@@ -10496,24 +10428,11 @@ async function replayApply(prepared, params = {}) {
10496
10428
  fernignoreUpdated: false,
10497
10429
  previousGenerationSha: prepared.previousGenerationSha,
10498
10430
  currentGenerationSha: prepared.currentGenerationSha,
10499
- baseBranchHead: prepared.baseBranchHead,
10500
10431
  autoBootstrapped: prepared.autoBootstrapped,
10501
10432
  bootstrapAttempted: prepared.bootstrapAttempted,
10502
10433
  failureReason: String(error)
10503
10434
  };
10504
10435
  }
10505
- let resolvedBaseBranchHead = prepared.baseBranchHead;
10506
- try {
10507
- const freshLockManager = new import_replay4.LockfileManager(prepared.outputDir);
10508
- if (freshLockManager.exists()) {
10509
- const freshLock = freshLockManager.read();
10510
- const latestGen = freshLock.generations.find((g) => g.commit_sha === freshLock.current_generation);
10511
- if (latestGen?.base_branch_head) {
10512
- resolvedBaseBranchHead = latestGen.base_branch_head;
10513
- }
10514
- }
10515
- } catch {
10516
- }
10517
10436
  const fernignoreUpdated = await ensureReplayFernignoreEntries(prepared.outputDir);
10518
10437
  await ensureGitattributesEntries(prepared.outputDir);
10519
10438
  return {
@@ -10521,7 +10440,6 @@ async function replayApply(prepared, params = {}) {
10521
10440
  fernignoreUpdated,
10522
10441
  previousGenerationSha: prepared.previousGenerationSha,
10523
10442
  currentGenerationSha: prepared.currentGenerationSha,
10524
- baseBranchHead: resolvedBaseBranchHead,
10525
10443
  autoBootstrapped: prepared.autoBootstrapped,
10526
10444
  bootstrapAttempted: prepared.bootstrapAttempted
10527
10445
  };
@@ -10537,7 +10455,6 @@ async function replayRun(params) {
10537
10455
  fernignoreUpdated: false,
10538
10456
  previousGenerationSha: null,
10539
10457
  currentGenerationSha: null,
10540
- baseBranchHead: null,
10541
10458
  autoBootstrapped: false,
10542
10459
  bootstrapAttempted: prepareState.bootstrapAttempted,
10543
10460
  failureReason: error instanceof ReplayPrepareError ? error.reason : String(error)
@@ -10549,7 +10466,6 @@ async function replayRun(params) {
10549
10466
  fernignoreUpdated: false,
10550
10467
  previousGenerationSha: null,
10551
10468
  currentGenerationSha: null,
10552
- baseBranchHead: null,
10553
10469
  autoBootstrapped: false,
10554
10470
  bootstrapAttempted: prepareState.bootstrapAttempted
10555
10471
  };
@@ -10568,53 +10484,6 @@ var ReplayPrepareError = class extends Error {
10568
10484
  this.reason = reason;
10569
10485
  }
10570
10486
  };
10571
- function isTagMergedIntoHead(cwd2, tagSha) {
10572
- try {
10573
- (0, import_child_process3.execFileSync)("git", ["merge-base", "--is-ancestor", tagSha, "HEAD"], {
10574
- cwd: cwd2,
10575
- stdio: "pipe"
10576
- });
10577
- return true;
10578
- } catch {
10579
- }
10580
- const tagTree = gitRevParse(cwd2, `${tagSha}^{tree}`);
10581
- if (tagTree == null) {
10582
- return false;
10583
- }
10584
- try {
10585
- const trees = (0, import_child_process3.execFileSync)("git", ["log", "HEAD", "--format=%T", "--max-count=500"], {
10586
- cwd: cwd2,
10587
- encoding: "utf-8",
10588
- stdio: "pipe"
10589
- });
10590
- return trees.split("\n").some((t2) => t2.trim() === tagTree);
10591
- } catch {
10592
- return false;
10593
- }
10594
- }
10595
- function gitRevParse(cwd2, rev) {
10596
- try {
10597
- return (0, import_child_process3.execFileSync)("git", ["rev-parse", "--verify", rev], {
10598
- cwd: cwd2,
10599
- encoding: "utf-8",
10600
- stdio: "pipe"
10601
- }).trim();
10602
- } catch {
10603
- return null;
10604
- }
10605
- }
10606
- function gitDiffNameOnly(cwd2, from, to) {
10607
- try {
10608
- const output = (0, import_child_process3.execFileSync)("git", ["diff", "--name-only", from, to], {
10609
- cwd: cwd2,
10610
- encoding: "utf-8",
10611
- stdio: "pipe"
10612
- });
10613
- return output.trim().split("\n").filter(Boolean);
10614
- } catch {
10615
- return [];
10616
- }
10617
- }
10618
10487
 
10619
10488
  // src/replay/replay-status.ts
10620
10489
  var import_replay5 = require("@fern-api/replay");
package/dist/cli.js CHANGED
@@ -2021,7 +2021,7 @@ var init_esm = __esm({
2021
2021
  }
2022
2022
  });
2023
2023
 
2024
- // ../../node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/dist/esm/index.js
2024
+ // ../../node_modules/.pnpm/brace-expansion@5.0.6/node_modules/brace-expansion/dist/esm/index.js
2025
2025
  function numeric(str) {
2026
2026
  return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
2027
2027
  }
@@ -2124,7 +2124,7 @@ function expand_(str, max, isTop) {
2124
2124
  }
2125
2125
  const pad = n.some(isPadded);
2126
2126
  N2 = [];
2127
- for (let i2 = x2; test(i2, y2); i2 += incr) {
2127
+ for (let i2 = x2; test(i2, y2) && N2.length < max; i2 += incr) {
2128
2128
  let c3;
2129
2129
  if (isAlphaSequence) {
2130
2130
  c3 = String.fromCharCode(i2);
@@ -2166,7 +2166,7 @@ function expand_(str, max, isTop) {
2166
2166
  }
2167
2167
  var escSlash, escOpen, escClose, escComma, escPeriod, escSlashPattern, escOpenPattern, escClosePattern, escCommaPattern, escPeriodPattern, slashPattern, openPattern, closePattern, commaPattern, periodPattern, EXPANSION_MAX;
2168
2168
  var init_esm2 = __esm({
2169
- "../../node_modules/.pnpm/brace-expansion@5.0.5/node_modules/brace-expansion/dist/esm/index.js"() {
2169
+ "../../node_modules/.pnpm/brace-expansion@5.0.6/node_modules/brace-expansion/dist/esm/index.js"() {
2170
2170
  "use strict";
2171
2171
  init_esm();
2172
2172
  escSlash = "\0SLASH" + Math.random() + "\0";
@@ -22126,7 +22126,7 @@ var init_diff3 = __esm({
22126
22126
  }
22127
22127
  });
22128
22128
 
22129
- // ../../node_modules/.pnpm/@fern-api+replay@0.15.2/node_modules/@fern-api/replay/dist/index.js
22129
+ // ../../node_modules/.pnpm/@fern-api+replay@0.16.0/node_modules/@fern-api/replay/dist/index.js
22130
22130
  var dist_exports = {};
22131
22131
  __export(dist_exports, {
22132
22132
  CREDENTIAL_PATTERNS: () => CREDENTIAL_PATTERNS,
@@ -22451,9 +22451,22 @@ function isGenerationCommit(commit) {
22451
22451
  const hasGenerationMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.startsWith("[fern-autoversion]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || // Squash merge of a Fern-generated PR uses the PR title as commit message.
22452
22452
  // The default PR title is "SDK Generation" (from GithubStep's commitMessage default).
22453
22453
  // GitHub appends "(#N)" for the PR number, e.g. "SDK Generation (#70)".
22454
- commit.message.startsWith("SDK Generation");
22454
+ commit.message.startsWith("SDK Generation") || // Merge commit (GitHub's "Create a merge commit" option) of a fern-bot
22455
+ // regen PR. First-parent walking lands on this commit, not on the
22456
+ // generation commit on the side branch, so the classifier must treat
22457
+ // it as a generation boundary. GitHub's default subject is
22458
+ // "Merge pull request #N from <owner>/<branch>"; fern-bot branches are
22459
+ // named "<owner>/fern-bot/<...>".
22460
+ /^Merge pull request #\d+ from [^/]+\/fern-bot\//.test(commit.message);
22455
22461
  return isBotAuthor || hasGenerationMarker;
22456
22462
  }
22463
+ function isGenerationBoundary(commit) {
22464
+ const isFernSupport = FERN_SUPPORT_NAMES.includes(commit.authorName);
22465
+ const isBotAuthor = !isFernSupport && (commit.authorLogin === FERN_BOT_LOGIN || commit.authorEmail === FERN_BOT_EMAIL || commit.authorName === FERN_BOT_NAME);
22466
+ const isAutoversion = commit.message.startsWith("[fern-autoversion]");
22467
+ const hasBoundaryMarker = commit.message.startsWith("[fern-generated]") || commit.message.startsWith("[fern-replay]") || commit.message.includes("Generated by Fern") || commit.message.includes("\u{1F916} Generated with Fern") || commit.message.startsWith("SDK Generation");
22468
+ return isBotAuthor && !isAutoversion || hasBoundaryMarker;
22469
+ }
22457
22470
  function isReplayCommit(commit) {
22458
22471
  return commit.message.startsWith("[fern-replay]");
22459
22472
  }
@@ -23934,7 +23947,7 @@ function status(outputDir) {
23934
23947
  }
23935
23948
  var import_promises3, import_os, import_path7, import_fs6, import_path8, import_yaml, import_crypto, import_path9, import_promises4, import_os2, import_path10, import_promises5, import_path11, import_promises6, import_path12, import_fs7, import_promises7, import_path13, import_promises8, import_os3, import_path14, import_child_process3, import_crypto2, import_fs8, import_path15, import_yaml2, import_crypto3, import_fs9, import_path16, import_fs10, import_promises9, import_path17, __defProp3, __getOwnPropNames3, __esm3, __export3, GitClient_exports, GitClient, init_GitClient, HybridReconstruction_exports, init_HybridReconstruction, PatchApplyTheirs_exports, init_PatchApplyTheirs, CREDENTIAL_PATTERNS, SENSITIVE_FILE_PATTERNS, FERN_BOT_NAME, FERN_BOT_EMAIL, FERN_BOT_LOGIN, FERN_SUPPORT_NAMES, LOCKFILE_HEADER, LockfileNotFoundError, LockfileManager, BINARY_EXTENSIONS, INFRASTRUCTURE_FILES, ReplayDetector, MergeAccumulator, CONFLICT_OPENER, CONFLICT_SEPARATOR, CONFLICT_CLOSER, ReplayApplicator, ReplayCommitter, FileOwnership, FirstGenerationFlow, SkipApplicationFlow, NoPatchesFlow, NormalRegenerationFlow, ReplayService, FernignoreMigrator, REPLAY_FERNIGNORE_ENTRIES, GITATTRIBUTES_ENTRIES, EMPTY_RESULT;
23936
23949
  var init_dist3 = __esm({
23937
- "../../node_modules/.pnpm/@fern-api+replay@0.15.2/node_modules/@fern-api/replay/dist/index.js"() {
23950
+ "../../node_modules/.pnpm/@fern-api+replay@0.16.0/node_modules/@fern-api/replay/dist/index.js"() {
23938
23951
  "use strict";
23939
23952
  init_esm4();
23940
23953
  import_promises3 = require("fs/promises");
@@ -24414,8 +24427,48 @@ var init_dist3 = __esm({
24414
24427
  this.lockManager = lockManager;
24415
24428
  this.sdkOutputDir = sdkOutputDir;
24416
24429
  }
24430
+ /**
24431
+ * Derive the previous-generation SHA from git history instead of trusting
24432
+ * `lock.current_generation`.
24433
+ *
24434
+ * Walks `git log HEAD --first-parent` and returns the SHA of the most recent
24435
+ * commit that `isGenerationBoundary` classifies as a customization-baseline
24436
+ * boundary, or null if no such commit is reachable from HEAD on the mainline.
24437
+ *
24438
+ * `isGenerationBoundary` is intentionally narrower than `isGenerationCommit`:
24439
+ * it excludes `[fern-autoversion]` (lightweight bumps that don't reset the
24440
+ * baseline) and the GitHub merge-commit subject for fern-bot regen PRs
24441
+ * (which sits on first-parent but where the customer fix-up commits live
24442
+ * on second-parent — stopping at the merge would hide them).
24443
+ *
24444
+ * See docs/adr/0001-derived-scan-boundary.md.
24445
+ */
24446
+ async findPreviousGenerationFromHistory() {
24447
+ let log;
24448
+ try {
24449
+ log = await this.git.exec([
24450
+ "log",
24451
+ "--first-parent",
24452
+ "--format=%H%x00%an%x00%ae%x00%s",
24453
+ "HEAD"
24454
+ ]);
24455
+ } catch {
24456
+ return null;
24457
+ }
24458
+ for (const commit of this.parseGitLog(log)) {
24459
+ if (isGenerationBoundary(commit)) {
24460
+ return commit.sha;
24461
+ }
24462
+ }
24463
+ return null;
24464
+ }
24417
24465
  async detectNewPatches() {
24418
24466
  const lock = this.lockManager.read();
24467
+ const derivedSha = await this.findPreviousGenerationFromHistory();
24468
+ if (derivedSha !== null) {
24469
+ const derivedRecord = await this.synthesizeGenerationRecord(derivedSha);
24470
+ return this.detectPatchesInRange(derivedSha, derivedRecord, lock);
24471
+ }
24419
24472
  const lastGen = this.getLastGeneration(lock);
24420
24473
  if (!lastGen) {
24421
24474
  return { patches: [], revertedPatchIds: [] };
@@ -24423,7 +24476,7 @@ var init_dist3 = __esm({
24423
24476
  const exists2 = await this.git.commitExists(lastGen.commit_sha);
24424
24477
  if (!exists2) {
24425
24478
  this.warnings.push(
24426
- `Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Falling back to alternate detection.`
24479
+ `Generation commit ${lastGen.commit_sha.slice(0, 7)} not found in git history. Falling back to tree-diff detection (likely a shallow clone).`
24427
24480
  );
24428
24481
  return this.detectPatchesViaTreeDiff(
24429
24482
  lastGen,
@@ -24431,44 +24484,8 @@ var init_dist3 = __esm({
24431
24484
  true
24432
24485
  );
24433
24486
  }
24434
- const isAncestor = await this.git.isAncestor(lastGen.commit_sha, "HEAD");
24435
- if (!isAncestor) {
24436
- return this.detectPatchesViaMergeBase(lastGen, lock);
24437
- }
24438
24487
  return this.detectPatchesInRange(lastGen.commit_sha, lastGen, lock);
24439
24488
  }
24440
- /**
24441
- * Non-linear-history detection via `merge-base(prevGen, HEAD)`.
24442
- *
24443
- * After a squash-merge of a Fern-bot PR, `lastGen.commit_sha` (the previous
24444
- * `[fern-generated]`) is orphaned but still in git's object database. The
24445
- * merge-base is the commit on main from which the bot's branch was created —
24446
- * a reachable ancestor of HEAD. Walking that range and classifying each
24447
- * commit via `isGenerationCommit` mirrors the linear path and eliminates
24448
- * the bug class where pipeline-driven changes (autoversion, replay,
24449
- * generation) get bundled as customer customizations.
24450
- *
24451
- * Falls through to the legacy composite path when no common ancestor exists
24452
- * (truly disjoint history — orphan branches with no shared root).
24453
- */
24454
- async detectPatchesViaMergeBase(lastGen, lock) {
24455
- let mergeBase = "";
24456
- try {
24457
- mergeBase = (await this.git.exec(["merge-base", lastGen.commit_sha, "HEAD"])).trim();
24458
- } catch {
24459
- }
24460
- if (!mergeBase) {
24461
- this.warnings.push(
24462
- `No common ancestor between previous generation ${lastGen.commit_sha.slice(0, 7)} and HEAD. Falling back to composite tree-diff detection.`
24463
- );
24464
- return this.detectPatchesViaTreeDiff(
24465
- lastGen,
24466
- /* commitKnownMissing */
24467
- false
24468
- );
24469
- }
24470
- return this.detectPatchesInRange(mergeBase, lastGen, lock);
24471
- }
24472
24489
  /**
24473
24490
  * Walk `${rangeStart}..HEAD`, classify each commit, emit one
24474
24491
  * `StoredPatch` per customer commit. Body shared by the linear path
@@ -24904,6 +24921,26 @@ var init_dist3 = __esm({
24904
24921
  getLastGeneration(lock) {
24905
24922
  return lock.generations.find((g) => g.commit_sha === lock.current_generation);
24906
24923
  }
24924
+ /**
24925
+ * Build a transient `GenerationRecord` from a SHA derived by walking git
24926
+ * history. Only `commit_sha` (and `tree_hash` when needed downstream) is
24927
+ * load-bearing here; the rest are filled with defensible placeholders.
24928
+ * This record is consumed by `detectPatchesInRange` and is never persisted.
24929
+ */
24930
+ async synthesizeGenerationRecord(sha) {
24931
+ let tree_hash = "";
24932
+ try {
24933
+ tree_hash = await this.git.getTreeHash(sha);
24934
+ } catch {
24935
+ }
24936
+ return {
24937
+ commit_sha: sha,
24938
+ tree_hash,
24939
+ timestamp: (/* @__PURE__ */ new Date(0)).toISOString(),
24940
+ cli_version: "",
24941
+ generator_versions: {}
24942
+ };
24943
+ }
24907
24944
  };
24908
24945
  MergeAccumulator = class {
24909
24946
  constructor(mode, sharedFiles) {
@@ -25526,8 +25563,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25526
25563
  tree_hash: treeHash,
25527
25564
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
25528
25565
  cli_version: options?.cliVersion ?? "unknown",
25529
- generator_versions: options?.generatorVersions ?? {},
25530
- base_branch_head: options?.baseBranchHead
25566
+ generator_versions: options?.generatorVersions ?? {}
25531
25567
  };
25532
25568
  }
25533
25569
  async stageAll() {
@@ -25598,7 +25634,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25598
25634
  flow: "first-generation",
25599
25635
  previousGenerationSha: null,
25600
25636
  currentGenerationSha: headSha,
25601
- baseBranchHead: options.baseBranchHead ?? null,
25602
25637
  _prepared: {
25603
25638
  kind: "terminal",
25604
25639
  flow: "first-generation",
@@ -25608,8 +25643,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25608
25643
  }
25609
25644
  const commitOpts = options ? {
25610
25645
  cliVersion: options.cliVersion ?? "unknown",
25611
- generatorVersions: options.generatorVersions ?? {},
25612
- baseBranchHead: options.baseBranchHead
25646
+ generatorVersions: options.generatorVersions ?? {}
25613
25647
  } : void 0;
25614
25648
  await this.service.committer.commitGeneration("Initial SDK generation", commitOpts);
25615
25649
  const genRecord = await this.service.committer.createGenerationRecord(commitOpts);
@@ -25618,7 +25652,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25618
25652
  flow: "first-generation",
25619
25653
  previousGenerationSha: null,
25620
25654
  currentGenerationSha: genRecord.commit_sha,
25621
- baseBranchHead: options?.baseBranchHead ?? null,
25622
25655
  _prepared: {
25623
25656
  kind: "active",
25624
25657
  flow: "first-generation",
@@ -25643,8 +25676,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25643
25676
  async prepare(options) {
25644
25677
  const commitOpts = options ? {
25645
25678
  cliVersion: options.cliVersion ?? "unknown",
25646
- generatorVersions: options.generatorVersions ?? {},
25647
- baseBranchHead: options.baseBranchHead
25679
+ generatorVersions: options.generatorVersions ?? {}
25648
25680
  } : void 0;
25649
25681
  await this.service.committer.commitGeneration("Update SDK (replay skipped)", commitOpts);
25650
25682
  await this.service.cleanupStaleConflictMarkers();
@@ -25666,7 +25698,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25666
25698
  flow: "skip-application",
25667
25699
  previousGenerationSha,
25668
25700
  currentGenerationSha: genRecord.commit_sha,
25669
- baseBranchHead: options?.baseBranchHead ?? null,
25670
25701
  _prepared: {
25671
25702
  kind: "active",
25672
25703
  flow: "skip-application",
@@ -25725,7 +25756,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25725
25756
  flow: "no-patches",
25726
25757
  previousGenerationSha,
25727
25758
  currentGenerationSha: headSha,
25728
- baseBranchHead: options.baseBranchHead ?? null,
25729
25759
  _prepared: {
25730
25760
  kind: "terminal",
25731
25761
  flow: "no-patches",
@@ -25757,8 +25787,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25757
25787
  }
25758
25788
  const commitOpts = options ? {
25759
25789
  cliVersion: options.cliVersion ?? "unknown",
25760
- generatorVersions: options.generatorVersions ?? {},
25761
- baseBranchHead: options.baseBranchHead
25790
+ generatorVersions: options.generatorVersions ?? {}
25762
25791
  } : void 0;
25763
25792
  await this.service.committer.commitGeneration("Update SDK", commitOpts);
25764
25793
  await this.service.cleanupStaleConflictMarkers();
@@ -25768,7 +25797,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25768
25797
  flow: "no-patches",
25769
25798
  previousGenerationSha,
25770
25799
  currentGenerationSha: genRecord.commit_sha,
25771
- baseBranchHead: options?.baseBranchHead ?? null,
25772
25800
  _prepared: {
25773
25801
  kind: "active",
25774
25802
  flow: "no-patches",
@@ -25856,7 +25884,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25856
25884
  flow: "normal-regeneration",
25857
25885
  previousGenerationSha,
25858
25886
  currentGenerationSha: headSha,
25859
- baseBranchHead: options.baseBranchHead ?? null,
25860
25887
  _prepared: {
25861
25888
  kind: "terminal",
25862
25889
  flow: "normal-regeneration",
@@ -25874,14 +25901,16 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25874
25901
  existingPatches = this.service.lockManager.getPatches();
25875
25902
  const seenHashes = /* @__PURE__ */ new Map();
25876
25903
  for (const p2 of existingPatches) {
25877
- const priorPatchId = seenHashes.get(p2.content_hash);
25878
- if (priorPatchId !== void 0) {
25879
- this.service.lockManager.removePatch(p2.id);
25880
- this.service.warnings.push(
25881
- `Consolidated patch ${p2.id} (commit ${(p2.original_commit || "<missing>").slice(0, 7)}) into prior patch ${priorPatchId}: byte-identical patch_content. Per-commit attribution preserved in git log; lockfile collapsed to avoid duplicate-apply corruption on next regen.`
25882
- );
25883
- } else {
25884
- seenHashes.set(p2.content_hash, p2.id);
25904
+ if (!p2.original_commit || p2.original_commit === "") {
25905
+ const priorPatchId = seenHashes.get(p2.content_hash);
25906
+ if (priorPatchId !== void 0) {
25907
+ this.service.lockManager.removePatch(p2.id);
25908
+ this.service.warnings.push(
25909
+ `Consolidated patch ${p2.id} into prior patch ${priorPatchId}: byte-identical patch_content. Lockfile collapsed to avoid duplicate-apply corruption on next regen.`
25910
+ );
25911
+ } else {
25912
+ seenHashes.set(p2.content_hash, p2.id);
25913
+ }
25885
25914
  }
25886
25915
  }
25887
25916
  existingPatches = this.service.lockManager.getPatches();
@@ -25910,8 +25939,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25910
25939
  const allPatches = [...existingPatches, ...newPatches];
25911
25940
  const commitOpts = options ? {
25912
25941
  cliVersion: options.cliVersion ?? "unknown",
25913
- generatorVersions: options.generatorVersions ?? {},
25914
- baseBranchHead: options.baseBranchHead
25942
+ generatorVersions: options.generatorVersions ?? {}
25915
25943
  } : void 0;
25916
25944
  await this.service.committer.commitGeneration("Update SDK", commitOpts);
25917
25945
  await this.service.cleanupStaleConflictMarkers();
@@ -25921,7 +25949,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25921
25949
  flow: "normal-regeneration",
25922
25950
  previousGenerationSha,
25923
25951
  currentGenerationSha: genRecord.commit_sha,
25924
- baseBranchHead: options?.baseBranchHead ?? null,
25925
25952
  _prepared: {
25926
25953
  kind: "active",
25927
25954
  flow: "normal-regeneration",
@@ -26105,68 +26132,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
26105
26132
  const prep = await this.prepareReplay(options);
26106
26133
  return this.applyPreparedReplay(prep, options);
26107
26134
  }
26108
- /**
26109
- * Sync the lockfile after a divergent PR was squash-merged.
26110
- * Call this BEFORE runReplay() when the CLI detects a merged divergent PR.
26111
- *
26112
- * After updating the generation record, re-detects customer patches via
26113
- * tree diff between the generation tag (pure generation tree) and HEAD
26114
- * (which includes customer customizations after squash merge). This ensures
26115
- * patches survive the squash merge → regenerate cycle even when the lockfile
26116
- * was restored from the base branch during conflict PR creation.
26117
- */
26118
- async syncFromDivergentMerge(generationCommitSha, options) {
26119
- const treeHash = await this.git.getTreeHash(generationCommitSha);
26120
- const timestamp = (await this.git.exec(["log", "-1", "--format=%aI", generationCommitSha])).trim();
26121
- const record2 = {
26122
- commit_sha: generationCommitSha,
26123
- tree_hash: treeHash,
26124
- timestamp,
26125
- cli_version: options?.cliVersion ?? "unknown",
26126
- generator_versions: options?.generatorVersions ?? {},
26127
- base_branch_head: options?.baseBranchHead
26128
- };
26129
- let resolvedPatches;
26130
- if (!this.lockManager.exists()) {
26131
- this.lockManager.initializeInMemory(record2);
26132
- } else {
26133
- this.lockManager.read();
26134
- const unresolvedPatches = [
26135
- ...this.lockManager.getUnresolvedPatches(),
26136
- ...this.lockManager.getResolvingPatches()
26137
- ];
26138
- resolvedPatches = this.lockManager.getPatches().filter((p2) => p2.status == null);
26139
- this.lockManager.addGeneration(record2);
26140
- this.lockManager.clearPatches();
26141
- for (const patch of unresolvedPatches) {
26142
- this.lockManager.addPatch(patch);
26143
- }
26144
- }
26145
- try {
26146
- const { patches: redetectedPatches } = await this.detector.detectNewPatches();
26147
- if (redetectedPatches.length > 0) {
26148
- const redetectedFiles = new Set(redetectedPatches.flatMap((p2) => p2.files));
26149
- const currentPatches = this.lockManager.getPatches();
26150
- for (const patch of currentPatches) {
26151
- if (patch.status != null && patch.files.some((f) => redetectedFiles.has(f))) {
26152
- this.lockManager.removePatch(patch.id);
26153
- }
26154
- }
26155
- for (const patch of redetectedPatches) {
26156
- this.lockManager.addPatch(patch);
26157
- }
26158
- }
26159
- } catch (error) {
26160
- for (const patch of resolvedPatches ?? []) {
26161
- this.lockManager.addPatch(patch);
26162
- }
26163
- this.detector.warnings.push(
26164
- `Patch re-detection failed after divergent merge sync. ${(resolvedPatches ?? []).length} previously resolved patch(es) preserved. Error: ${error instanceof Error ? error.message : String(error)}`
26165
- );
26166
- }
26167
- this.lockManager.save();
26168
- this.detector.warnings.push(...this.lockManager.warnings);
26169
- }
26170
26135
  determineFlow() {
26171
26136
  try {
26172
26137
  const lock = this.lockManager.read();
@@ -39645,19 +39610,10 @@ init_dist3();
39645
39610
 
39646
39611
  // src/replay/replay-run.ts
39647
39612
  init_dist3();
39648
- var import_child_process4 = require("child_process");
39649
39613
  var import_fs12 = require("fs");
39650
39614
  var import_path20 = require("path");
39651
39615
  async function replayPrepare(params, state) {
39652
- const {
39653
- outputDir,
39654
- cliVersion,
39655
- generatorVersions,
39656
- stageOnly = false,
39657
- generatorName,
39658
- skipApplication,
39659
- logger
39660
- } = params;
39616
+ const { outputDir, cliVersion, generatorVersions, stageOnly = false, skipApplication, logger } = params;
39661
39617
  const lockfilePath = (0, import_path20.join)(outputDir, ".fern", "replay.lock");
39662
39618
  let autoBootstrapped = false;
39663
39619
  let bootstrapAttempted = false;
@@ -39690,63 +39646,6 @@ async function replayPrepare(params, state) {
39690
39646
  return null;
39691
39647
  }
39692
39648
  }
39693
- const baseBranchHead = gitRevParse(outputDir, "HEAD");
39694
- let previousGenerationSha = null;
39695
- let prevBaseBranchHead = null;
39696
- try {
39697
- const lockManager = new LockfileManager(outputDir);
39698
- if (lockManager.exists()) {
39699
- const lock = lockManager.read();
39700
- previousGenerationSha = lock.current_generation;
39701
- const latestGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
39702
- prevBaseBranchHead = latestGen?.base_branch_head ?? null;
39703
- }
39704
- } catch {
39705
- }
39706
- if (previousGenerationSha != null) {
39707
- const sanitizedName = generatorName?.replace(/\//g, "--");
39708
- const namespacedTag = sanitizedName != null ? `fern-generation-base--${sanitizedName}` : null;
39709
- const tagSha = (namespacedTag != null ? gitRevParse(outputDir, namespacedTag) : null) ?? gitRevParse(outputDir, "fern-generation-base");
39710
- let shouldSync = false;
39711
- if (tagSha != null) {
39712
- const tagParent = gitRevParse(outputDir, `${tagSha}^`);
39713
- if (tagParent === prevBaseBranchHead || tagParent === previousGenerationSha) {
39714
- const tagDistance = gitDiffNameOnly(outputDir, tagSha, "HEAD").length;
39715
- const lockDistance = gitDiffNameOnly(
39716
- outputDir,
39717
- prevBaseBranchHead ?? previousGenerationSha,
39718
- "HEAD"
39719
- ).length;
39720
- shouldSync = tagDistance < lockDistance;
39721
- }
39722
- }
39723
- if (shouldSync && tagSha != null) {
39724
- if (!isTagMergedIntoHead(outputDir, tagSha)) {
39725
- logger?.warn(
39726
- `fern-generation-base tag ${tagSha} is not reachable from HEAD \u2014 skipping divergent-merge sync. The tag likely points at an unmerged generation (PR closed without merge).`
39727
- );
39728
- } else {
39729
- try {
39730
- const syncService = new ReplayService(outputDir, { enabled: true });
39731
- await syncService.syncFromDivergentMerge(tagSha, {
39732
- cliVersion,
39733
- generatorVersions,
39734
- baseBranchHead: baseBranchHead ?? void 0
39735
- });
39736
- } catch (error) {
39737
- logger?.warn("Replay divergent-merge sync failed, continuing without sync: " + String(error));
39738
- throw new ReplayPrepareError(String(error), error);
39739
- }
39740
- try {
39741
- const freshLockManager = new LockfileManager(outputDir);
39742
- if (freshLockManager.exists()) {
39743
- previousGenerationSha = freshLockManager.read().current_generation;
39744
- }
39745
- } catch {
39746
- }
39747
- }
39748
- }
39749
- }
39750
39649
  const service = new ReplayService(outputDir, { enabled: true });
39751
39650
  let preparation;
39752
39651
  try {
@@ -39754,8 +39653,7 @@ async function replayPrepare(params, state) {
39754
39653
  cliVersion,
39755
39654
  generatorVersions,
39756
39655
  stageOnly,
39757
- skipApplication,
39758
- baseBranchHead: baseBranchHead ?? void 0
39656
+ skipApplication
39759
39657
  });
39760
39658
  } catch (error) {
39761
39659
  logger?.warn("Replay prepare failed, continuing without replay: " + String(error));
@@ -39766,9 +39664,8 @@ async function replayPrepare(params, state) {
39766
39664
  _preparation: preparation,
39767
39665
  outputDir,
39768
39666
  flow: preparation.flow,
39769
- previousGenerationSha,
39667
+ previousGenerationSha: preparation.previousGenerationSha,
39770
39668
  currentGenerationSha: preparation.currentGenerationSha,
39771
- baseBranchHead,
39772
39669
  autoBootstrapped,
39773
39670
  bootstrapAttempted
39774
39671
  };
@@ -39785,24 +39682,11 @@ async function replayApply(prepared, params = {}) {
39785
39682
  fernignoreUpdated: false,
39786
39683
  previousGenerationSha: prepared.previousGenerationSha,
39787
39684
  currentGenerationSha: prepared.currentGenerationSha,
39788
- baseBranchHead: prepared.baseBranchHead,
39789
39685
  autoBootstrapped: prepared.autoBootstrapped,
39790
39686
  bootstrapAttempted: prepared.bootstrapAttempted,
39791
39687
  failureReason: String(error)
39792
39688
  };
39793
39689
  }
39794
- let resolvedBaseBranchHead = prepared.baseBranchHead;
39795
- try {
39796
- const freshLockManager = new LockfileManager(prepared.outputDir);
39797
- if (freshLockManager.exists()) {
39798
- const freshLock = freshLockManager.read();
39799
- const latestGen = freshLock.generations.find((g) => g.commit_sha === freshLock.current_generation);
39800
- if (latestGen?.base_branch_head) {
39801
- resolvedBaseBranchHead = latestGen.base_branch_head;
39802
- }
39803
- }
39804
- } catch {
39805
- }
39806
39690
  const fernignoreUpdated = await ensureReplayFernignoreEntries(prepared.outputDir);
39807
39691
  await ensureGitattributesEntries2(prepared.outputDir);
39808
39692
  return {
@@ -39810,7 +39694,6 @@ async function replayApply(prepared, params = {}) {
39810
39694
  fernignoreUpdated,
39811
39695
  previousGenerationSha: prepared.previousGenerationSha,
39812
39696
  currentGenerationSha: prepared.currentGenerationSha,
39813
- baseBranchHead: resolvedBaseBranchHead,
39814
39697
  autoBootstrapped: prepared.autoBootstrapped,
39815
39698
  bootstrapAttempted: prepared.bootstrapAttempted
39816
39699
  };
@@ -39826,7 +39709,6 @@ async function replayRun(params) {
39826
39709
  fernignoreUpdated: false,
39827
39710
  previousGenerationSha: null,
39828
39711
  currentGenerationSha: null,
39829
- baseBranchHead: null,
39830
39712
  autoBootstrapped: false,
39831
39713
  bootstrapAttempted: prepareState.bootstrapAttempted,
39832
39714
  failureReason: error instanceof ReplayPrepareError ? error.reason : String(error)
@@ -39838,7 +39720,6 @@ async function replayRun(params) {
39838
39720
  fernignoreUpdated: false,
39839
39721
  previousGenerationSha: null,
39840
39722
  currentGenerationSha: null,
39841
- baseBranchHead: null,
39842
39723
  autoBootstrapped: false,
39843
39724
  bootstrapAttempted: prepareState.bootstrapAttempted
39844
39725
  };
@@ -39857,53 +39738,6 @@ var ReplayPrepareError = class extends Error {
39857
39738
  this.reason = reason;
39858
39739
  }
39859
39740
  };
39860
- function isTagMergedIntoHead(cwd2, tagSha) {
39861
- try {
39862
- (0, import_child_process4.execFileSync)("git", ["merge-base", "--is-ancestor", tagSha, "HEAD"], {
39863
- cwd: cwd2,
39864
- stdio: "pipe"
39865
- });
39866
- return true;
39867
- } catch {
39868
- }
39869
- const tagTree = gitRevParse(cwd2, `${tagSha}^{tree}`);
39870
- if (tagTree == null) {
39871
- return false;
39872
- }
39873
- try {
39874
- const trees = (0, import_child_process4.execFileSync)("git", ["log", "HEAD", "--format=%T", "--max-count=500"], {
39875
- cwd: cwd2,
39876
- encoding: "utf-8",
39877
- stdio: "pipe"
39878
- });
39879
- return trees.split("\n").some((t2) => t2.trim() === tagTree);
39880
- } catch {
39881
- return false;
39882
- }
39883
- }
39884
- function gitRevParse(cwd2, rev) {
39885
- try {
39886
- return (0, import_child_process4.execFileSync)("git", ["rev-parse", "--verify", rev], {
39887
- cwd: cwd2,
39888
- encoding: "utf-8",
39889
- stdio: "pipe"
39890
- }).trim();
39891
- } catch {
39892
- return null;
39893
- }
39894
- }
39895
- function gitDiffNameOnly(cwd2, from, to) {
39896
- try {
39897
- const output = (0, import_child_process4.execFileSync)("git", ["diff", "--name-only", from, to], {
39898
- cwd: cwd2,
39899
- encoding: "utf-8",
39900
- stdio: "pipe"
39901
- });
39902
- return output.trim().split("\n").filter(Boolean);
39903
- } catch {
39904
- return [];
39905
- }
39906
- }
39907
39741
 
39908
39742
  // src/replay/replay-status.ts
39909
39743
  init_dist3();
@@ -39951,7 +39785,7 @@ var consolePipelineLogger = {
39951
39785
  };
39952
39786
 
39953
39787
  // src/pipeline/PostGenerationPipeline.ts
39954
- var import_child_process7 = require("child_process");
39788
+ var import_child_process6 = require("child_process");
39955
39789
 
39956
39790
  // src/pipeline/github/constants.ts
39957
39791
  var FERN_BOT_NAME2 = "fern-api";
@@ -39959,7 +39793,7 @@ var FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
39959
39793
  var FERN_BOT_LOGIN2 = "fern-api[bot]";
39960
39794
 
39961
39795
  // src/pipeline/steps/AutoVersionStep.ts
39962
- var import_child_process5 = require("child_process");
39796
+ var import_child_process4 = require("child_process");
39963
39797
  var import_fs14 = require("fs");
39964
39798
  var import_promises15 = require("fs/promises");
39965
39799
  var import_path22 = require("path");
@@ -41333,7 +41167,7 @@ var AutoVersionStep = class extends BaseStep {
41333
41167
  }
41334
41168
  async readVersionFromMetadata() {
41335
41169
  try {
41336
- const output = (0, import_child_process5.execFileSync)("git", ["show", "HEAD~1:.fern/metadata.json"], {
41170
+ const output = (0, import_child_process4.execFileSync)("git", ["show", "HEAD~1:.fern/metadata.json"], {
41337
41171
  cwd: this.outputDir,
41338
41172
  encoding: "utf-8",
41339
41173
  stdio: "pipe"
@@ -41349,7 +41183,7 @@ var AutoVersionStep = class extends BaseStep {
41349
41183
  return mappedMagicVersion.startsWith("v") ? `v${stripped}` : stripped;
41350
41184
  }
41351
41185
  gitDiff(from, to) {
41352
- return (0, import_child_process5.execFileSync)("git", ["diff", from, to, "--", ".", ":(exclude).fern/metadata.json"], {
41186
+ return (0, import_child_process4.execFileSync)("git", ["diff", from, to, "--", ".", ":(exclude).fern/metadata.json"], {
41353
41187
  cwd: this.outputDir,
41354
41188
  encoding: "utf-8",
41355
41189
  stdio: "pipe",
@@ -41362,12 +41196,12 @@ var AutoVersionStep = class extends BaseStep {
41362
41196
  const fullMessage = body.length > 0 ? `${COMMIT_MARKER} ${subject}
41363
41197
 
41364
41198
  ${body}` : `${COMMIT_MARKER} ${subject}`;
41365
- (0, import_child_process5.execFileSync)("git", ["add", "-A"], { cwd: this.outputDir, stdio: "pipe" });
41366
- (0, import_child_process5.execFileSync)("git", ["commit", "--allow-empty", "-m", fullMessage], {
41199
+ (0, import_child_process4.execFileSync)("git", ["add", "-A"], { cwd: this.outputDir, stdio: "pipe" });
41200
+ (0, import_child_process4.execFileSync)("git", ["commit", "--allow-empty", "-m", fullMessage], {
41367
41201
  cwd: this.outputDir,
41368
41202
  stdio: "pipe"
41369
41203
  });
41370
- return (0, import_child_process5.execFileSync)("git", ["rev-parse", "HEAD"], {
41204
+ return (0, import_child_process4.execFileSync)("git", ["rev-parse", "HEAD"], {
41371
41205
  cwd: this.outputDir,
41372
41206
  encoding: "utf-8",
41373
41207
  stdio: "pipe"
@@ -41542,19 +41376,17 @@ ${newBlock}${remainder}`;
41542
41376
  };
41543
41377
 
41544
41378
  // src/pipeline/steps/GenerationCommitStep.ts
41545
- var import_child_process6 = require("child_process");
41379
+ var import_child_process5 = require("child_process");
41546
41380
  var GenerationCommitStep = class extends BaseStep {
41547
- constructor(outputDir, logger, config, cliVersion, generatorVersions, generatorName) {
41381
+ constructor(outputDir, logger, config, cliVersion, generatorVersions) {
41548
41382
  super(outputDir, logger);
41549
41383
  this.config = config;
41550
41384
  this.cliVersion = cliVersion;
41551
41385
  this.generatorVersions = generatorVersions;
41552
- this.generatorName = generatorName;
41553
41386
  }
41554
41387
  config;
41555
41388
  cliVersion;
41556
41389
  generatorVersions;
41557
- generatorName;
41558
41390
  name = "generationCommit";
41559
41391
  async execute(_context) {
41560
41392
  const headBeforePrepare = tryRevParse(this.outputDir, "HEAD");
@@ -41566,7 +41398,6 @@ var GenerationCommitStep = class extends BaseStep {
41566
41398
  outputDir: this.outputDir,
41567
41399
  cliVersion: this.cliVersion,
41568
41400
  generatorVersions: this.generatorVersions,
41569
- generatorName: this.generatorName,
41570
41401
  skipApplication: this.config.skipApplication,
41571
41402
  logger: this.logger
41572
41403
  },
@@ -41576,7 +41407,7 @@ var GenerationCommitStep = class extends BaseStep {
41576
41407
  const reason = error instanceof ReplayPrepareError ? error.reason : String(error);
41577
41408
  if (headBeforePrepare != null) {
41578
41409
  try {
41579
- (0, import_child_process6.execFileSync)("git", ["reset", "--hard", headBeforePrepare], {
41410
+ (0, import_child_process5.execFileSync)("git", ["reset", "--hard", headBeforePrepare], {
41580
41411
  cwd: this.outputDir,
41581
41412
  stdio: "pipe"
41582
41413
  });
@@ -41605,7 +41436,6 @@ var GenerationCommitStep = class extends BaseStep {
41605
41436
  preparedReplay: prepared,
41606
41437
  previousGenerationSha: prepared.previousGenerationSha ?? void 0,
41607
41438
  currentGenerationSha: prepared.currentGenerationSha,
41608
- baseBranchHead: prepared.baseBranchHead ?? void 0,
41609
41439
  flow: prepared.flow,
41610
41440
  bootstrapAttempted: prepareState.bootstrapAttempted
41611
41441
  };
@@ -41613,7 +41443,7 @@ var GenerationCommitStep = class extends BaseStep {
41613
41443
  };
41614
41444
  function tryRevParse(cwd2, rev) {
41615
41445
  try {
41616
- return (0, import_child_process6.execFileSync)("git", ["rev-parse", "--verify", rev], {
41446
+ return (0, import_child_process5.execFileSync)("git", ["rev-parse", "--verify", rev], {
41617
41447
  cwd: cwd2,
41618
41448
  encoding: "utf-8",
41619
41449
  stdio: "pipe"
@@ -41787,18 +41617,16 @@ async function pushSignedCommit({
41787
41617
  await repository.pushObjectToRef(localHeadSha, tempRef);
41788
41618
  tempRefPushed = true;
41789
41619
  for (let attempt2 = 0; attempt2 < MAX_CONCURRENT_PUSH_RETRIES; attempt2++) {
41790
- const commitAuthor = {
41791
- name: author?.name ?? FERN_BOT_NAME2,
41792
- email: author?.email ?? FERN_BOT_EMAIL2
41793
- };
41620
+ const resolvedAuthor = author ?? { name: FERN_BOT_NAME2, email: FERN_BOT_EMAIL2 };
41621
+ const committerField = author != null ? { committer: author } : {};
41794
41622
  const { data: signedCommit } = await octokit.git.createCommit({
41795
41623
  owner,
41796
41624
  repo,
41797
41625
  message,
41798
41626
  tree: treeSha,
41799
41627
  parents,
41800
- author: commitAuthor,
41801
- committer: commitAuthor
41628
+ author: resolvedAuthor,
41629
+ ...committerField
41802
41630
  });
41803
41631
  const signedSha = signedCommit.sha;
41804
41632
  try {
@@ -42360,17 +42188,15 @@ function resolveBranchAction({
42360
42188
 
42361
42189
  // src/pipeline/steps/ReplayStep.ts
42362
42190
  var ReplayStep = class extends BaseStep {
42363
- constructor(outputDir, logger, config, cliVersion, generatorVersions, generatorName) {
42191
+ constructor(outputDir, logger, config, cliVersion, generatorVersions) {
42364
42192
  super(outputDir, logger);
42365
42193
  this.config = config;
42366
42194
  this.cliVersion = cliVersion;
42367
42195
  this.generatorVersions = generatorVersions;
42368
- this.generatorName = generatorName;
42369
42196
  }
42370
42197
  config;
42371
42198
  cliVersion;
42372
42199
  generatorVersions;
42373
- generatorName;
42374
42200
  name = "replay";
42375
42201
  async execute(context) {
42376
42202
  const generationCommit = context.previousStepResults.generationCommit;
@@ -42409,7 +42235,6 @@ var ReplayStep = class extends BaseStep {
42409
42235
  cliVersion: this.cliVersion,
42410
42236
  generatorVersions: this.generatorVersions,
42411
42237
  stageOnly: this.config.stageOnly ?? false,
42412
- generatorName: this.generatorName,
42413
42238
  skipApplication: this.config.skipApplication,
42414
42239
  logger: this.logger
42415
42240
  });
@@ -42421,7 +42246,6 @@ var ReplayStep = class extends BaseStep {
42421
42246
  errorMessage: result.failureReason,
42422
42247
  previousGenerationSha: result.previousGenerationSha ?? void 0,
42423
42248
  currentGenerationSha: result.currentGenerationSha ?? void 0,
42424
- baseBranchHead: result.baseBranchHead ?? void 0,
42425
42249
  autoBootstrapped: result.autoBootstrapped,
42426
42250
  bootstrapAttempted: result.bootstrapAttempted,
42427
42251
  flow: "normal-regeneration",
@@ -42436,7 +42260,6 @@ var ReplayStep = class extends BaseStep {
42436
42260
  success: true,
42437
42261
  previousGenerationSha: result.previousGenerationSha ?? void 0,
42438
42262
  currentGenerationSha: result.currentGenerationSha ?? void 0,
42439
- baseBranchHead: result.baseBranchHead ?? void 0,
42440
42263
  autoBootstrapped: result.autoBootstrapped,
42441
42264
  bootstrapAttempted: result.bootstrapAttempted,
42442
42265
  flow: "first-generation",
@@ -42451,7 +42274,6 @@ var ReplayStep = class extends BaseStep {
42451
42274
  success: true,
42452
42275
  previousGenerationSha: result.previousGenerationSha ?? void 0,
42453
42276
  currentGenerationSha: result.currentGenerationSha ?? void 0,
42454
- baseBranchHead: result.baseBranchHead ?? void 0,
42455
42277
  autoBootstrapped: result.autoBootstrapped,
42456
42278
  bootstrapAttempted: result.bootstrapAttempted,
42457
42279
  flow: report.flow,
@@ -42723,8 +42545,7 @@ var PostGenerationPipeline = class {
42723
42545
  this.logger,
42724
42546
  { enabled: true, skipApplication: config.replay.skipApplication },
42725
42547
  config.cliVersion,
42726
- config.generatorVersions,
42727
- config.generatorName
42548
+ config.generatorVersions
42728
42549
  )
42729
42550
  );
42730
42551
  }
@@ -42738,8 +42559,7 @@ var PostGenerationPipeline = class {
42738
42559
  this.logger,
42739
42560
  config.replay,
42740
42561
  config.cliVersion,
42741
- config.generatorVersions,
42742
- config.generatorName
42562
+ config.generatorVersions
42743
42563
  )
42744
42564
  );
42745
42565
  }
@@ -42764,8 +42584,8 @@ var PostGenerationPipeline = class {
42764
42584
  async run() {
42765
42585
  if (this.config.github?.enabled) {
42766
42586
  try {
42767
- (0, import_child_process7.execFileSync)("git", ["config", "user.name", FERN_BOT_NAME2], { cwd: this.config.outputDir });
42768
- (0, import_child_process7.execFileSync)("git", ["config", "user.email", FERN_BOT_EMAIL2], { cwd: this.config.outputDir });
42587
+ (0, import_child_process6.execFileSync)("git", ["config", "user.name", FERN_BOT_NAME2], { cwd: this.config.outputDir });
42588
+ (0, import_child_process6.execFileSync)("git", ["config", "user.email", FERN_BOT_EMAIL2], { cwd: this.config.outputDir });
42769
42589
  } catch {
42770
42590
  }
42771
42591
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fern-api/generator-cli",
3
- "version": "0.9.30",
3
+ "version": "0.9.32",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/fern-api/fern.git",
@@ -23,7 +23,7 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@boundaryml/baml": "^0.219.0",
26
- "@fern-api/replay": "0.15.2",
26
+ "@fern-api/replay": "0.16.0",
27
27
  "@octokit/rest": "^22.0.1",
28
28
  "es-toolkit": "^1.45.1",
29
29
  "semver": "^7.6.3",