@fern-api/generator-cli 0.9.29 → 0.9.31

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
@@ -22126,7 +22126,7 @@ var init_diff3 = __esm({
22126
22126
  }
22127
22127
  });
22128
22128
 
22129
- // ../../node_modules/.pnpm/@fern-api+replay@0.15.1/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.1/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
@@ -24481,7 +24498,7 @@ var init_dist3 = __esm({
24481
24498
  async detectPatchesInRange(rangeStart, lastGen, lock) {
24482
24499
  const log = await this.git.exec([
24483
24500
  "log",
24484
- "--first-parent",
24501
+ "--no-merges",
24485
24502
  "--format=%H%x00%an%x00%ae%x00%s",
24486
24503
  `${rangeStart}..HEAD`,
24487
24504
  "--",
@@ -24501,18 +24518,6 @@ var init_dist3 = __esm({
24501
24518
  continue;
24502
24519
  }
24503
24520
  const parents = await this.git.getCommitParents(commit.sha);
24504
- if (parents.length > 1) {
24505
- const compositePatch = await this.createMergeCompositePatch({
24506
- mergeCommit: commit,
24507
- firstParent: parents[0],
24508
- lastGen,
24509
- lock
24510
- });
24511
- if (compositePatch) {
24512
- newPatches.push(compositePatch);
24513
- }
24514
- continue;
24515
- }
24516
24521
  let patchContent;
24517
24522
  try {
24518
24523
  patchContent = await this.git.formatPatch(commit.sha);
@@ -24650,9 +24655,7 @@ var init_dist3 = __esm({
24650
24655
  * within the current linear detection window, and are absent from
24651
24656
  * HEAD at the end of the window.
24652
24657
  *
24653
- * Rationale: on a merge commit, createMergeCompositePatch already diffs
24654
- * firstParent..mergeCommit so net-zero files never enter the composite. On
24655
- * linear history each commit becomes its own patch, so a file that was
24658
+ * Rationale: each commit becomes its own patch, so a file that was
24656
24659
  * briefly added and later removed survives as a create+delete pair whose
24657
24660
  * cumulative diff is empty. We drop such patches before they reach the
24658
24661
  * lockfile.
@@ -24719,54 +24722,6 @@ var init_dist3 = __esm({
24719
24722
  return /* @__PURE__ */ new Set();
24720
24723
  }
24721
24724
  }
24722
- /**
24723
- * Create a single composite patch for a merge commit by diffing the merge
24724
- * commit against its first parent. This captures the net change of the
24725
- * entire merged branch as one patch, eliminating accumulator chaining and
24726
- * zero-net-change ghost conflicts.
24727
- */
24728
- async createMergeCompositePatch(input) {
24729
- const { mergeCommit, firstParent, lastGen, lock } = input;
24730
- const forgottenHashes = new Set(lock.forgotten_hashes ?? []);
24731
- const filesOutput = await this.git.exec([
24732
- "diff",
24733
- "--name-only",
24734
- firstParent,
24735
- mergeCommit.sha
24736
- ]);
24737
- const { files, sensitiveFiles } = filterInfrastructureAndSensitiveFiles(filesOutput);
24738
- if (sensitiveFiles.length > 0) {
24739
- this.warnings.push(
24740
- `Sensitive file(s) excluded from merge patch for commit ${mergeCommit.sha.slice(0, 7)}: ${sensitiveFiles.join(", ")}. These files will not be tracked by replay.`
24741
- );
24742
- }
24743
- if (files.length === 0) return null;
24744
- const diff = await this.git.exec([
24745
- "diff",
24746
- firstParent,
24747
- mergeCommit.sha,
24748
- "--",
24749
- ...files
24750
- ]);
24751
- if (!diff.trim()) return null;
24752
- const contentHash = this.computeContentHash(diff);
24753
- if (lock.patches.some((p2) => p2.content_hash === contentHash) || forgottenHashes.has(contentHash)) {
24754
- return null;
24755
- }
24756
- const theirsSnapshot = await capturePatchSnapshot(this.git, files, mergeCommit.sha);
24757
- return {
24758
- id: `patch-merge-${mergeCommit.sha.slice(0, 8)}`,
24759
- content_hash: contentHash,
24760
- original_commit: mergeCommit.sha,
24761
- original_message: mergeCommit.message,
24762
- original_author: `${mergeCommit.authorName} <${mergeCommit.authorEmail}>`,
24763
- base_generation: lastGen.commit_sha,
24764
- files,
24765
- patch_content: diff,
24766
- ...Object.keys(theirsSnapshot).length > 0 ? { theirs_snapshot: theirsSnapshot } : {},
24767
- ...this.isCreationOnlyPatch(diff) ? { user_owned: true } : {}
24768
- };
24769
- }
24770
24725
  /**
24771
24726
  * Detect patches via tree diff for non-linear history. Returns a composite patch.
24772
24727
  * Revert reconciliation is skipped here because tree-diff produces a single composite
@@ -24966,6 +24921,26 @@ var init_dist3 = __esm({
24966
24921
  getLastGeneration(lock) {
24967
24922
  return lock.generations.find((g) => g.commit_sha === lock.current_generation);
24968
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
+ }
24969
24944
  };
24970
24945
  MergeAccumulator = class {
24971
24946
  constructor(mode, sharedFiles) {
@@ -25588,8 +25563,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25588
25563
  tree_hash: treeHash,
25589
25564
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
25590
25565
  cli_version: options?.cliVersion ?? "unknown",
25591
- generator_versions: options?.generatorVersions ?? {},
25592
- base_branch_head: options?.baseBranchHead
25566
+ generator_versions: options?.generatorVersions ?? {}
25593
25567
  };
25594
25568
  }
25595
25569
  async stageAll() {
@@ -25660,7 +25634,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25660
25634
  flow: "first-generation",
25661
25635
  previousGenerationSha: null,
25662
25636
  currentGenerationSha: headSha,
25663
- baseBranchHead: options.baseBranchHead ?? null,
25664
25637
  _prepared: {
25665
25638
  kind: "terminal",
25666
25639
  flow: "first-generation",
@@ -25670,8 +25643,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25670
25643
  }
25671
25644
  const commitOpts = options ? {
25672
25645
  cliVersion: options.cliVersion ?? "unknown",
25673
- generatorVersions: options.generatorVersions ?? {},
25674
- baseBranchHead: options.baseBranchHead
25646
+ generatorVersions: options.generatorVersions ?? {}
25675
25647
  } : void 0;
25676
25648
  await this.service.committer.commitGeneration("Initial SDK generation", commitOpts);
25677
25649
  const genRecord = await this.service.committer.createGenerationRecord(commitOpts);
@@ -25680,7 +25652,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25680
25652
  flow: "first-generation",
25681
25653
  previousGenerationSha: null,
25682
25654
  currentGenerationSha: genRecord.commit_sha,
25683
- baseBranchHead: options?.baseBranchHead ?? null,
25684
25655
  _prepared: {
25685
25656
  kind: "active",
25686
25657
  flow: "first-generation",
@@ -25705,8 +25676,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25705
25676
  async prepare(options) {
25706
25677
  const commitOpts = options ? {
25707
25678
  cliVersion: options.cliVersion ?? "unknown",
25708
- generatorVersions: options.generatorVersions ?? {},
25709
- baseBranchHead: options.baseBranchHead
25679
+ generatorVersions: options.generatorVersions ?? {}
25710
25680
  } : void 0;
25711
25681
  await this.service.committer.commitGeneration("Update SDK (replay skipped)", commitOpts);
25712
25682
  await this.service.cleanupStaleConflictMarkers();
@@ -25728,7 +25698,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25728
25698
  flow: "skip-application",
25729
25699
  previousGenerationSha,
25730
25700
  currentGenerationSha: genRecord.commit_sha,
25731
- baseBranchHead: options?.baseBranchHead ?? null,
25732
25701
  _prepared: {
25733
25702
  kind: "active",
25734
25703
  flow: "skip-application",
@@ -25787,7 +25756,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25787
25756
  flow: "no-patches",
25788
25757
  previousGenerationSha,
25789
25758
  currentGenerationSha: headSha,
25790
- baseBranchHead: options.baseBranchHead ?? null,
25791
25759
  _prepared: {
25792
25760
  kind: "terminal",
25793
25761
  flow: "no-patches",
@@ -25819,8 +25787,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25819
25787
  }
25820
25788
  const commitOpts = options ? {
25821
25789
  cliVersion: options.cliVersion ?? "unknown",
25822
- generatorVersions: options.generatorVersions ?? {},
25823
- baseBranchHead: options.baseBranchHead
25790
+ generatorVersions: options.generatorVersions ?? {}
25824
25791
  } : void 0;
25825
25792
  await this.service.committer.commitGeneration("Update SDK", commitOpts);
25826
25793
  await this.service.cleanupStaleConflictMarkers();
@@ -25830,7 +25797,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25830
25797
  flow: "no-patches",
25831
25798
  previousGenerationSha,
25832
25799
  currentGenerationSha: genRecord.commit_sha,
25833
- baseBranchHead: options?.baseBranchHead ?? null,
25834
25800
  _prepared: {
25835
25801
  kind: "active",
25836
25802
  flow: "no-patches",
@@ -25918,7 +25884,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25918
25884
  flow: "normal-regeneration",
25919
25885
  previousGenerationSha,
25920
25886
  currentGenerationSha: headSha,
25921
- baseBranchHead: options.baseBranchHead ?? null,
25922
25887
  _prepared: {
25923
25888
  kind: "terminal",
25924
25889
  flow: "normal-regeneration",
@@ -25936,14 +25901,16 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25936
25901
  existingPatches = this.service.lockManager.getPatches();
25937
25902
  const seenHashes = /* @__PURE__ */ new Map();
25938
25903
  for (const p2 of existingPatches) {
25939
- const priorPatchId = seenHashes.get(p2.content_hash);
25940
- if (priorPatchId !== void 0) {
25941
- this.service.lockManager.removePatch(p2.id);
25942
- this.service.warnings.push(
25943
- `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.`
25944
- );
25945
- } else {
25946
- 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
+ }
25947
25914
  }
25948
25915
  }
25949
25916
  existingPatches = this.service.lockManager.getPatches();
@@ -25972,8 +25939,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25972
25939
  const allPatches = [...existingPatches, ...newPatches];
25973
25940
  const commitOpts = options ? {
25974
25941
  cliVersion: options.cliVersion ?? "unknown",
25975
- generatorVersions: options.generatorVersions ?? {},
25976
- baseBranchHead: options.baseBranchHead
25942
+ generatorVersions: options.generatorVersions ?? {}
25977
25943
  } : void 0;
25978
25944
  await this.service.committer.commitGeneration("Update SDK", commitOpts);
25979
25945
  await this.service.cleanupStaleConflictMarkers();
@@ -25983,7 +25949,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
25983
25949
  flow: "normal-regeneration",
25984
25950
  previousGenerationSha,
25985
25951
  currentGenerationSha: genRecord.commit_sha,
25986
- baseBranchHead: options?.baseBranchHead ?? null,
25987
25952
  _prepared: {
25988
25953
  kind: "active",
25989
25954
  flow: "normal-regeneration",
@@ -26167,68 +26132,6 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
26167
26132
  const prep = await this.prepareReplay(options);
26168
26133
  return this.applyPreparedReplay(prep, options);
26169
26134
  }
26170
- /**
26171
- * Sync the lockfile after a divergent PR was squash-merged.
26172
- * Call this BEFORE runReplay() when the CLI detects a merged divergent PR.
26173
- *
26174
- * After updating the generation record, re-detects customer patches via
26175
- * tree diff between the generation tag (pure generation tree) and HEAD
26176
- * (which includes customer customizations after squash merge). This ensures
26177
- * patches survive the squash merge → regenerate cycle even when the lockfile
26178
- * was restored from the base branch during conflict PR creation.
26179
- */
26180
- async syncFromDivergentMerge(generationCommitSha, options) {
26181
- const treeHash = await this.git.getTreeHash(generationCommitSha);
26182
- const timestamp = (await this.git.exec(["log", "-1", "--format=%aI", generationCommitSha])).trim();
26183
- const record2 = {
26184
- commit_sha: generationCommitSha,
26185
- tree_hash: treeHash,
26186
- timestamp,
26187
- cli_version: options?.cliVersion ?? "unknown",
26188
- generator_versions: options?.generatorVersions ?? {},
26189
- base_branch_head: options?.baseBranchHead
26190
- };
26191
- let resolvedPatches;
26192
- if (!this.lockManager.exists()) {
26193
- this.lockManager.initializeInMemory(record2);
26194
- } else {
26195
- this.lockManager.read();
26196
- const unresolvedPatches = [
26197
- ...this.lockManager.getUnresolvedPatches(),
26198
- ...this.lockManager.getResolvingPatches()
26199
- ];
26200
- resolvedPatches = this.lockManager.getPatches().filter((p2) => p2.status == null);
26201
- this.lockManager.addGeneration(record2);
26202
- this.lockManager.clearPatches();
26203
- for (const patch of unresolvedPatches) {
26204
- this.lockManager.addPatch(patch);
26205
- }
26206
- }
26207
- try {
26208
- const { patches: redetectedPatches } = await this.detector.detectNewPatches();
26209
- if (redetectedPatches.length > 0) {
26210
- const redetectedFiles = new Set(redetectedPatches.flatMap((p2) => p2.files));
26211
- const currentPatches = this.lockManager.getPatches();
26212
- for (const patch of currentPatches) {
26213
- if (patch.status != null && patch.files.some((f) => redetectedFiles.has(f))) {
26214
- this.lockManager.removePatch(patch.id);
26215
- }
26216
- }
26217
- for (const patch of redetectedPatches) {
26218
- this.lockManager.addPatch(patch);
26219
- }
26220
- }
26221
- } catch (error) {
26222
- for (const patch of resolvedPatches ?? []) {
26223
- this.lockManager.addPatch(patch);
26224
- }
26225
- this.detector.warnings.push(
26226
- `Patch re-detection failed after divergent merge sync. ${(resolvedPatches ?? []).length} previously resolved patch(es) preserved. Error: ${error instanceof Error ? error.message : String(error)}`
26227
- );
26228
- }
26229
- this.lockManager.save();
26230
- this.detector.warnings.push(...this.lockManager.warnings);
26231
- }
26232
26135
  determineFlow() {
26233
26136
  try {
26234
26137
  const lock = this.lockManager.read();
@@ -39707,19 +39610,10 @@ init_dist3();
39707
39610
 
39708
39611
  // src/replay/replay-run.ts
39709
39612
  init_dist3();
39710
- var import_child_process4 = require("child_process");
39711
39613
  var import_fs12 = require("fs");
39712
39614
  var import_path20 = require("path");
39713
39615
  async function replayPrepare(params, state) {
39714
- const {
39715
- outputDir,
39716
- cliVersion,
39717
- generatorVersions,
39718
- stageOnly = false,
39719
- generatorName,
39720
- skipApplication,
39721
- logger
39722
- } = params;
39616
+ const { outputDir, cliVersion, generatorVersions, stageOnly = false, skipApplication, logger } = params;
39723
39617
  const lockfilePath = (0, import_path20.join)(outputDir, ".fern", "replay.lock");
39724
39618
  let autoBootstrapped = false;
39725
39619
  let bootstrapAttempted = false;
@@ -39752,63 +39646,6 @@ async function replayPrepare(params, state) {
39752
39646
  return null;
39753
39647
  }
39754
39648
  }
39755
- const baseBranchHead = gitRevParse(outputDir, "HEAD");
39756
- let previousGenerationSha = null;
39757
- let prevBaseBranchHead = null;
39758
- try {
39759
- const lockManager = new LockfileManager(outputDir);
39760
- if (lockManager.exists()) {
39761
- const lock = lockManager.read();
39762
- previousGenerationSha = lock.current_generation;
39763
- const latestGen = lock.generations.find((g) => g.commit_sha === lock.current_generation);
39764
- prevBaseBranchHead = latestGen?.base_branch_head ?? null;
39765
- }
39766
- } catch {
39767
- }
39768
- if (previousGenerationSha != null) {
39769
- const sanitizedName = generatorName?.replace(/\//g, "--");
39770
- const namespacedTag = sanitizedName != null ? `fern-generation-base--${sanitizedName}` : null;
39771
- const tagSha = (namespacedTag != null ? gitRevParse(outputDir, namespacedTag) : null) ?? gitRevParse(outputDir, "fern-generation-base");
39772
- let shouldSync = false;
39773
- if (tagSha != null) {
39774
- const tagParent = gitRevParse(outputDir, `${tagSha}^`);
39775
- if (tagParent === prevBaseBranchHead || tagParent === previousGenerationSha) {
39776
- const tagDistance = gitDiffNameOnly(outputDir, tagSha, "HEAD").length;
39777
- const lockDistance = gitDiffNameOnly(
39778
- outputDir,
39779
- prevBaseBranchHead ?? previousGenerationSha,
39780
- "HEAD"
39781
- ).length;
39782
- shouldSync = tagDistance < lockDistance;
39783
- }
39784
- }
39785
- if (shouldSync && tagSha != null) {
39786
- if (!isTagMergedIntoHead(outputDir, tagSha)) {
39787
- logger?.warn(
39788
- `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).`
39789
- );
39790
- } else {
39791
- try {
39792
- const syncService = new ReplayService(outputDir, { enabled: true });
39793
- await syncService.syncFromDivergentMerge(tagSha, {
39794
- cliVersion,
39795
- generatorVersions,
39796
- baseBranchHead: baseBranchHead ?? void 0
39797
- });
39798
- } catch (error) {
39799
- logger?.warn("Replay divergent-merge sync failed, continuing without sync: " + String(error));
39800
- throw new ReplayPrepareError(String(error), error);
39801
- }
39802
- try {
39803
- const freshLockManager = new LockfileManager(outputDir);
39804
- if (freshLockManager.exists()) {
39805
- previousGenerationSha = freshLockManager.read().current_generation;
39806
- }
39807
- } catch {
39808
- }
39809
- }
39810
- }
39811
- }
39812
39649
  const service = new ReplayService(outputDir, { enabled: true });
39813
39650
  let preparation;
39814
39651
  try {
@@ -39816,8 +39653,7 @@ async function replayPrepare(params, state) {
39816
39653
  cliVersion,
39817
39654
  generatorVersions,
39818
39655
  stageOnly,
39819
- skipApplication,
39820
- baseBranchHead: baseBranchHead ?? void 0
39656
+ skipApplication
39821
39657
  });
39822
39658
  } catch (error) {
39823
39659
  logger?.warn("Replay prepare failed, continuing without replay: " + String(error));
@@ -39828,9 +39664,8 @@ async function replayPrepare(params, state) {
39828
39664
  _preparation: preparation,
39829
39665
  outputDir,
39830
39666
  flow: preparation.flow,
39831
- previousGenerationSha,
39667
+ previousGenerationSha: preparation.previousGenerationSha,
39832
39668
  currentGenerationSha: preparation.currentGenerationSha,
39833
- baseBranchHead,
39834
39669
  autoBootstrapped,
39835
39670
  bootstrapAttempted
39836
39671
  };
@@ -39847,24 +39682,11 @@ async function replayApply(prepared, params = {}) {
39847
39682
  fernignoreUpdated: false,
39848
39683
  previousGenerationSha: prepared.previousGenerationSha,
39849
39684
  currentGenerationSha: prepared.currentGenerationSha,
39850
- baseBranchHead: prepared.baseBranchHead,
39851
39685
  autoBootstrapped: prepared.autoBootstrapped,
39852
39686
  bootstrapAttempted: prepared.bootstrapAttempted,
39853
39687
  failureReason: String(error)
39854
39688
  };
39855
39689
  }
39856
- let resolvedBaseBranchHead = prepared.baseBranchHead;
39857
- try {
39858
- const freshLockManager = new LockfileManager(prepared.outputDir);
39859
- if (freshLockManager.exists()) {
39860
- const freshLock = freshLockManager.read();
39861
- const latestGen = freshLock.generations.find((g) => g.commit_sha === freshLock.current_generation);
39862
- if (latestGen?.base_branch_head) {
39863
- resolvedBaseBranchHead = latestGen.base_branch_head;
39864
- }
39865
- }
39866
- } catch {
39867
- }
39868
39690
  const fernignoreUpdated = await ensureReplayFernignoreEntries(prepared.outputDir);
39869
39691
  await ensureGitattributesEntries2(prepared.outputDir);
39870
39692
  return {
@@ -39872,7 +39694,6 @@ async function replayApply(prepared, params = {}) {
39872
39694
  fernignoreUpdated,
39873
39695
  previousGenerationSha: prepared.previousGenerationSha,
39874
39696
  currentGenerationSha: prepared.currentGenerationSha,
39875
- baseBranchHead: resolvedBaseBranchHead,
39876
39697
  autoBootstrapped: prepared.autoBootstrapped,
39877
39698
  bootstrapAttempted: prepared.bootstrapAttempted
39878
39699
  };
@@ -39888,7 +39709,6 @@ async function replayRun(params) {
39888
39709
  fernignoreUpdated: false,
39889
39710
  previousGenerationSha: null,
39890
39711
  currentGenerationSha: null,
39891
- baseBranchHead: null,
39892
39712
  autoBootstrapped: false,
39893
39713
  bootstrapAttempted: prepareState.bootstrapAttempted,
39894
39714
  failureReason: error instanceof ReplayPrepareError ? error.reason : String(error)
@@ -39900,7 +39720,6 @@ async function replayRun(params) {
39900
39720
  fernignoreUpdated: false,
39901
39721
  previousGenerationSha: null,
39902
39722
  currentGenerationSha: null,
39903
- baseBranchHead: null,
39904
39723
  autoBootstrapped: false,
39905
39724
  bootstrapAttempted: prepareState.bootstrapAttempted
39906
39725
  };
@@ -39919,53 +39738,6 @@ var ReplayPrepareError = class extends Error {
39919
39738
  this.reason = reason;
39920
39739
  }
39921
39740
  };
39922
- function isTagMergedIntoHead(cwd2, tagSha) {
39923
- try {
39924
- (0, import_child_process4.execFileSync)("git", ["merge-base", "--is-ancestor", tagSha, "HEAD"], {
39925
- cwd: cwd2,
39926
- stdio: "pipe"
39927
- });
39928
- return true;
39929
- } catch {
39930
- }
39931
- const tagTree = gitRevParse(cwd2, `${tagSha}^{tree}`);
39932
- if (tagTree == null) {
39933
- return false;
39934
- }
39935
- try {
39936
- const trees = (0, import_child_process4.execFileSync)("git", ["log", "HEAD", "--format=%T", "--max-count=500"], {
39937
- cwd: cwd2,
39938
- encoding: "utf-8",
39939
- stdio: "pipe"
39940
- });
39941
- return trees.split("\n").some((t2) => t2.trim() === tagTree);
39942
- } catch {
39943
- return false;
39944
- }
39945
- }
39946
- function gitRevParse(cwd2, rev) {
39947
- try {
39948
- return (0, import_child_process4.execFileSync)("git", ["rev-parse", "--verify", rev], {
39949
- cwd: cwd2,
39950
- encoding: "utf-8",
39951
- stdio: "pipe"
39952
- }).trim();
39953
- } catch {
39954
- return null;
39955
- }
39956
- }
39957
- function gitDiffNameOnly(cwd2, from, to) {
39958
- try {
39959
- const output = (0, import_child_process4.execFileSync)("git", ["diff", "--name-only", from, to], {
39960
- cwd: cwd2,
39961
- encoding: "utf-8",
39962
- stdio: "pipe"
39963
- });
39964
- return output.trim().split("\n").filter(Boolean);
39965
- } catch {
39966
- return [];
39967
- }
39968
- }
39969
39741
 
39970
39742
  // src/replay/replay-status.ts
39971
39743
  init_dist3();
@@ -40013,7 +39785,7 @@ var consolePipelineLogger = {
40013
39785
  };
40014
39786
 
40015
39787
  // src/pipeline/PostGenerationPipeline.ts
40016
- var import_child_process7 = require("child_process");
39788
+ var import_child_process6 = require("child_process");
40017
39789
 
40018
39790
  // src/pipeline/github/constants.ts
40019
39791
  var FERN_BOT_NAME2 = "fern-api";
@@ -40021,7 +39793,7 @@ var FERN_BOT_EMAIL2 = "115122769+fern-api[bot]@users.noreply.github.com";
40021
39793
  var FERN_BOT_LOGIN2 = "fern-api[bot]";
40022
39794
 
40023
39795
  // src/pipeline/steps/AutoVersionStep.ts
40024
- var import_child_process5 = require("child_process");
39796
+ var import_child_process4 = require("child_process");
40025
39797
  var import_fs14 = require("fs");
40026
39798
  var import_promises15 = require("fs/promises");
40027
39799
  var import_path22 = require("path");
@@ -41395,7 +41167,7 @@ var AutoVersionStep = class extends BaseStep {
41395
41167
  }
41396
41168
  async readVersionFromMetadata() {
41397
41169
  try {
41398
- 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"], {
41399
41171
  cwd: this.outputDir,
41400
41172
  encoding: "utf-8",
41401
41173
  stdio: "pipe"
@@ -41411,7 +41183,7 @@ var AutoVersionStep = class extends BaseStep {
41411
41183
  return mappedMagicVersion.startsWith("v") ? `v${stripped}` : stripped;
41412
41184
  }
41413
41185
  gitDiff(from, to) {
41414
- 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"], {
41415
41187
  cwd: this.outputDir,
41416
41188
  encoding: "utf-8",
41417
41189
  stdio: "pipe",
@@ -41424,12 +41196,12 @@ var AutoVersionStep = class extends BaseStep {
41424
41196
  const fullMessage = body.length > 0 ? `${COMMIT_MARKER} ${subject}
41425
41197
 
41426
41198
  ${body}` : `${COMMIT_MARKER} ${subject}`;
41427
- (0, import_child_process5.execFileSync)("git", ["add", "-A"], { cwd: this.outputDir, stdio: "pipe" });
41428
- (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], {
41429
41201
  cwd: this.outputDir,
41430
41202
  stdio: "pipe"
41431
41203
  });
41432
- return (0, import_child_process5.execFileSync)("git", ["rev-parse", "HEAD"], {
41204
+ return (0, import_child_process4.execFileSync)("git", ["rev-parse", "HEAD"], {
41433
41205
  cwd: this.outputDir,
41434
41206
  encoding: "utf-8",
41435
41207
  stdio: "pipe"
@@ -41604,19 +41376,17 @@ ${newBlock}${remainder}`;
41604
41376
  };
41605
41377
 
41606
41378
  // src/pipeline/steps/GenerationCommitStep.ts
41607
- var import_child_process6 = require("child_process");
41379
+ var import_child_process5 = require("child_process");
41608
41380
  var GenerationCommitStep = class extends BaseStep {
41609
- constructor(outputDir, logger, config, cliVersion, generatorVersions, generatorName) {
41381
+ constructor(outputDir, logger, config, cliVersion, generatorVersions) {
41610
41382
  super(outputDir, logger);
41611
41383
  this.config = config;
41612
41384
  this.cliVersion = cliVersion;
41613
41385
  this.generatorVersions = generatorVersions;
41614
- this.generatorName = generatorName;
41615
41386
  }
41616
41387
  config;
41617
41388
  cliVersion;
41618
41389
  generatorVersions;
41619
- generatorName;
41620
41390
  name = "generationCommit";
41621
41391
  async execute(_context) {
41622
41392
  const headBeforePrepare = tryRevParse(this.outputDir, "HEAD");
@@ -41628,7 +41398,6 @@ var GenerationCommitStep = class extends BaseStep {
41628
41398
  outputDir: this.outputDir,
41629
41399
  cliVersion: this.cliVersion,
41630
41400
  generatorVersions: this.generatorVersions,
41631
- generatorName: this.generatorName,
41632
41401
  skipApplication: this.config.skipApplication,
41633
41402
  logger: this.logger
41634
41403
  },
@@ -41638,7 +41407,7 @@ var GenerationCommitStep = class extends BaseStep {
41638
41407
  const reason = error instanceof ReplayPrepareError ? error.reason : String(error);
41639
41408
  if (headBeforePrepare != null) {
41640
41409
  try {
41641
- (0, import_child_process6.execFileSync)("git", ["reset", "--hard", headBeforePrepare], {
41410
+ (0, import_child_process5.execFileSync)("git", ["reset", "--hard", headBeforePrepare], {
41642
41411
  cwd: this.outputDir,
41643
41412
  stdio: "pipe"
41644
41413
  });
@@ -41667,7 +41436,6 @@ var GenerationCommitStep = class extends BaseStep {
41667
41436
  preparedReplay: prepared,
41668
41437
  previousGenerationSha: prepared.previousGenerationSha ?? void 0,
41669
41438
  currentGenerationSha: prepared.currentGenerationSha,
41670
- baseBranchHead: prepared.baseBranchHead ?? void 0,
41671
41439
  flow: prepared.flow,
41672
41440
  bootstrapAttempted: prepareState.bootstrapAttempted
41673
41441
  };
@@ -41675,7 +41443,7 @@ var GenerationCommitStep = class extends BaseStep {
41675
41443
  };
41676
41444
  function tryRevParse(cwd2, rev) {
41677
41445
  try {
41678
- return (0, import_child_process6.execFileSync)("git", ["rev-parse", "--verify", rev], {
41446
+ return (0, import_child_process5.execFileSync)("git", ["rev-parse", "--verify", rev], {
41679
41447
  cwd: cwd2,
41680
41448
  encoding: "utf-8",
41681
41449
  stdio: "pipe"
@@ -42422,17 +42190,15 @@ function resolveBranchAction({
42422
42190
 
42423
42191
  // src/pipeline/steps/ReplayStep.ts
42424
42192
  var ReplayStep = class extends BaseStep {
42425
- constructor(outputDir, logger, config, cliVersion, generatorVersions, generatorName) {
42193
+ constructor(outputDir, logger, config, cliVersion, generatorVersions) {
42426
42194
  super(outputDir, logger);
42427
42195
  this.config = config;
42428
42196
  this.cliVersion = cliVersion;
42429
42197
  this.generatorVersions = generatorVersions;
42430
- this.generatorName = generatorName;
42431
42198
  }
42432
42199
  config;
42433
42200
  cliVersion;
42434
42201
  generatorVersions;
42435
- generatorName;
42436
42202
  name = "replay";
42437
42203
  async execute(context) {
42438
42204
  const generationCommit = context.previousStepResults.generationCommit;
@@ -42471,7 +42237,6 @@ var ReplayStep = class extends BaseStep {
42471
42237
  cliVersion: this.cliVersion,
42472
42238
  generatorVersions: this.generatorVersions,
42473
42239
  stageOnly: this.config.stageOnly ?? false,
42474
- generatorName: this.generatorName,
42475
42240
  skipApplication: this.config.skipApplication,
42476
42241
  logger: this.logger
42477
42242
  });
@@ -42483,7 +42248,6 @@ var ReplayStep = class extends BaseStep {
42483
42248
  errorMessage: result.failureReason,
42484
42249
  previousGenerationSha: result.previousGenerationSha ?? void 0,
42485
42250
  currentGenerationSha: result.currentGenerationSha ?? void 0,
42486
- baseBranchHead: result.baseBranchHead ?? void 0,
42487
42251
  autoBootstrapped: result.autoBootstrapped,
42488
42252
  bootstrapAttempted: result.bootstrapAttempted,
42489
42253
  flow: "normal-regeneration",
@@ -42498,7 +42262,6 @@ var ReplayStep = class extends BaseStep {
42498
42262
  success: true,
42499
42263
  previousGenerationSha: result.previousGenerationSha ?? void 0,
42500
42264
  currentGenerationSha: result.currentGenerationSha ?? void 0,
42501
- baseBranchHead: result.baseBranchHead ?? void 0,
42502
42265
  autoBootstrapped: result.autoBootstrapped,
42503
42266
  bootstrapAttempted: result.bootstrapAttempted,
42504
42267
  flow: "first-generation",
@@ -42513,7 +42276,6 @@ var ReplayStep = class extends BaseStep {
42513
42276
  success: true,
42514
42277
  previousGenerationSha: result.previousGenerationSha ?? void 0,
42515
42278
  currentGenerationSha: result.currentGenerationSha ?? void 0,
42516
- baseBranchHead: result.baseBranchHead ?? void 0,
42517
42279
  autoBootstrapped: result.autoBootstrapped,
42518
42280
  bootstrapAttempted: result.bootstrapAttempted,
42519
42281
  flow: report.flow,
@@ -42785,8 +42547,7 @@ var PostGenerationPipeline = class {
42785
42547
  this.logger,
42786
42548
  { enabled: true, skipApplication: config.replay.skipApplication },
42787
42549
  config.cliVersion,
42788
- config.generatorVersions,
42789
- config.generatorName
42550
+ config.generatorVersions
42790
42551
  )
42791
42552
  );
42792
42553
  }
@@ -42800,8 +42561,7 @@ var PostGenerationPipeline = class {
42800
42561
  this.logger,
42801
42562
  config.replay,
42802
42563
  config.cliVersion,
42803
- config.generatorVersions,
42804
- config.generatorName
42564
+ config.generatorVersions
42805
42565
  )
42806
42566
  );
42807
42567
  }
@@ -42826,8 +42586,8 @@ var PostGenerationPipeline = class {
42826
42586
  async run() {
42827
42587
  if (this.config.github?.enabled) {
42828
42588
  try {
42829
- (0, import_child_process7.execFileSync)("git", ["config", "user.name", FERN_BOT_NAME2], { cwd: this.config.outputDir });
42830
- (0, import_child_process7.execFileSync)("git", ["config", "user.email", FERN_BOT_EMAIL2], { cwd: this.config.outputDir });
42589
+ (0, import_child_process6.execFileSync)("git", ["config", "user.name", FERN_BOT_NAME2], { cwd: this.config.outputDir });
42590
+ (0, import_child_process6.execFileSync)("git", ["config", "user.email", FERN_BOT_EMAIL2], { cwd: this.config.outputDir });
42831
42591
  } catch {
42832
42592
  }
42833
42593
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fern-api/generator-cli",
3
- "version": "0.9.29",
3
+ "version": "0.9.31",
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.1",
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",