@fern-api/fern-api-dev 5.46.0 → 5.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/cli.cjs +362 -67
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -422153,30 +422153,30 @@ var require_AutoVersionStep = __commonJS({
422153
422153
  }
422154
422154
  async execute(context3) {
422155
422155
  const prepared = context3.previousStepResults.generationCommit?.preparedReplay;
422156
- if (!prepared) {
422157
- this.logger.info("AutoVersionStep: no replay preparation available (replay uninitialized or prepare failed); skipping.");
422158
- return { executed: true, success: true };
422159
- }
422160
- if (prepared.flow === "skip-application") {
422161
- this.logger.info("AutoVersionStep: replay flow is skip-application; skipping autoversion.");
422162
- return { executed: true, success: true };
422163
- }
422164
- const language = this.config.language;
422165
- const mappedMagicVersion = (0, index_1.mapMagicVersionForLanguage)(index_1.MAGIC_VERSION, language);
422166
- const service = new index_1.AutoVersioningService({ logger: this.toTaskLogger() });
422167
- if (prepared.previousGenerationSha == null) {
422168
- return await this.handleFirstGeneration({ service, language, mappedMagicVersion });
422156
+ if (prepared) {
422157
+ if (prepared.flow === "skip-application") {
422158
+ this.logger.info("AutoVersionStep: replay flow is skip-application; skipping autoversion.");
422159
+ return { executed: true, success: true };
422160
+ }
422161
+ const language = this.config.language;
422162
+ const mappedMagicVersion = (0, index_1.mapMagicVersionForLanguage)(index_1.MAGIC_VERSION, language);
422163
+ const service = new index_1.AutoVersioningService({ logger: this.toTaskLogger() });
422164
+ if (prepared.previousGenerationSha == null) {
422165
+ return await this.handleFirstGeneration({ service, language, mappedMagicVersion, commit: true });
422166
+ }
422167
+ return await this.handleNormalFlow({
422168
+ prepared,
422169
+ service,
422170
+ language,
422171
+ mappedMagicVersion,
422172
+ previousGenerationSha: prepared.previousGenerationSha
422173
+ });
422169
422174
  }
422170
- return await this.handleNormalFlow({
422171
- prepared,
422172
- service,
422173
- language,
422174
- mappedMagicVersion,
422175
- previousGenerationSha: prepared.previousGenerationSha
422176
- });
422175
+ this.logger.info("AutoVersionStep: running in non-replay mode (git diff HEAD).");
422176
+ return await this.handleNonReplayFlow();
422177
422177
  }
422178
422178
  async handleFirstGeneration(params2) {
422179
- const { service, language, mappedMagicVersion } = params2;
422179
+ const { service, language, mappedMagicVersion, commit } = params2;
422180
422180
  const initialVersion = this.config.baseVersion ?? (mappedMagicVersion.startsWith("v") ? "v0.0.1" : "0.0.1");
422181
422181
  if (!(0, index_1.isValidSemver)(initialVersion)) {
422182
422182
  const errorMessage = `AutoVersionStep: baseVersion ${JSON.stringify(initialVersion)} is not a valid semver string (expected e.g. "1.2.3" or "v1.2.3"). Refusing to run to avoid shell injection into the placeholder-rewrite step.`;
@@ -422193,7 +422193,7 @@ var require_AutoVersionStep = __commonJS({
422193
422193
  await service.addGoMajorVersionSuffix(this.outputDir, initialVersion);
422194
422194
  }
422195
422195
  const commitMessage = this.brandMessage("Initial SDK generation");
422196
- const commitSha = this.commitAutoversion(commitMessage);
422196
+ const commitSha = commit ? this.commitAutoversion(commitMessage) : void 0;
422197
422197
  return {
422198
422198
  executed: true,
422199
422199
  success: true,
@@ -422212,7 +422212,7 @@ var require_AutoVersionStep = __commonJS({
422212
422212
  baseVersion: this.config.baseVersion
422213
422213
  });
422214
422214
  if (previousVersion == null) {
422215
- return await this.handleFirstGeneration({ service, language, mappedMagicVersion });
422215
+ return await this.handleFirstGeneration({ service, language, mappedMagicVersion, commit: true });
422216
422216
  }
422217
422217
  if (rawDiff.trim().length === 0) {
422218
422218
  this.logger.info(`AutoVersionStep: empty diff between generations; rewriting placeholder to ${previousVersion}.`);
@@ -422283,6 +422283,94 @@ var require_AutoVersionStep = __commonJS({
422283
422283
  analysis
422284
422284
  });
422285
422285
  }
422286
+ /**
422287
+ * Non-replay autoversion: diffs HEAD (committed SDK) vs the working tree
422288
+ * (freshly generated files). Does NOT commit — GithubStep will commit all
422289
+ * changes (including the rewritten placeholder) in a single generation commit.
422290
+ */
422291
+ async handleNonReplayFlow() {
422292
+ const language = this.config.language;
422293
+ const mappedMagicVersion = (0, index_1.mapMagicVersionForLanguage)(index_1.MAGIC_VERSION, language);
422294
+ const service = new index_1.AutoVersioningService({ logger: this.toTaskLogger() });
422295
+ const rawDiff = this.gitDiffHead();
422296
+ const previousVersion = await this.resolvePreviousVersionNonReplay({
422297
+ service,
422298
+ rawDiff,
422299
+ mappedMagicVersion,
422300
+ baseVersion: this.config.baseVersion
422301
+ });
422302
+ if (previousVersion == null) {
422303
+ return await this.handleFirstGeneration({ service, language, mappedMagicVersion, commit: false });
422304
+ }
422305
+ if (rawDiff.trim().length === 0) {
422306
+ this.logger.info(`AutoVersionStep: empty diff (non-replay); rewriting placeholder to ${previousVersion}.`);
422307
+ return await this.finalizeNoChangeNonReplay({
422308
+ service,
422309
+ language,
422310
+ mappedMagicVersion,
422311
+ previousVersion,
422312
+ reason: "no diff between generations"
422313
+ });
422314
+ }
422315
+ const cleanedDiff = service.cleanDiffForAI(rawDiff, mappedMagicVersion);
422316
+ const rawBytes = Buffer.byteLength(rawDiff, "utf-8");
422317
+ const cleanedBytes = Buffer.byteLength(cleanedDiff, "utf-8");
422318
+ this.logger.debug(`AutoVersionStep (non-replay): raw=${(0, index_1.formatSizeKB)(rawBytes)}KB (${(0, index_1.countFilesInDiff)(rawDiff)} files), cleaned=${(0, index_1.formatSizeKB)(cleanedBytes)}KB (${(0, index_1.countFilesInDiff)(cleanedDiff)} files)`);
422319
+ if (cleanedDiff.trim().length === 0) {
422320
+ this.logger.info(`AutoVersionStep: cleaned diff empty (non-replay); rewriting placeholder to ${previousVersion}.`);
422321
+ return await this.finalizeNoChangeNonReplay({
422322
+ service,
422323
+ language,
422324
+ mappedMagicVersion,
422325
+ previousVersion,
422326
+ reason: "no semantic changes"
422327
+ });
422328
+ }
422329
+ if (cleanedBytes > index_1.MAX_RAW_DIFF_BYTES) {
422330
+ this.logger.warn(`AutoVersionStep (non-replay): diff too large (${(0, index_1.formatSizeKB)(cleanedBytes)}KB). Falling back to PATCH.`);
422331
+ return await this.finalizeWithBumpNonReplay({
422332
+ service,
422333
+ language,
422334
+ mappedMagicVersion,
422335
+ previousVersion,
422336
+ analysis: { versionBump: "PATCH", message: this.brandMessage("SDK regeneration") }
422337
+ });
422338
+ }
422339
+ let analysis;
422340
+ try {
422341
+ if (this.config.ai == null && this.config.fernToken != null) {
422342
+ analysis = await this.analyzeViaFaiService(cleanedDiff, language, previousVersion);
422343
+ } else {
422344
+ const chunks = service.chunkDiff(cleanedDiff, index_1.MAX_AI_DIFF_BYTES);
422345
+ const cappedChunks = chunks.slice(0, index_1.MAX_CHUNKS);
422346
+ const skippedChunks = chunks.length - cappedChunks.length;
422347
+ if (chunks.length > 1) {
422348
+ this.logger.info(`AutoVersionStep (non-replay): split diff into ${chunks.length} chunks` + (skippedChunks > 0 ? ` (capped at ${index_1.MAX_CHUNKS}, skipping ${skippedChunks})` : ""));
422349
+ }
422350
+ analysis = cappedChunks.length <= 1 ? await this.analyzeSingle(cleanedDiff, language, previousVersion) : await this.analyzeChunks(cappedChunks, language, previousVersion);
422351
+ }
422352
+ } catch (error50) {
422353
+ this.logger.warn(`AutoVersionStep (non-replay): FAI analysis failed (${String(error50)}); falling back to PATCH bump.`);
422354
+ analysis = { versionBump: "PATCH", message: this.brandMessage("SDK regeneration") };
422355
+ }
422356
+ if (analysis == null) {
422357
+ this.logger.info(`AutoVersionStep (non-replay): FAI returned NO_CHANGE; rewriting placeholder to ${previousVersion}.`);
422358
+ return await this.finalizeNoChangeNonReplay({
422359
+ service,
422360
+ language,
422361
+ mappedMagicVersion,
422362
+ previousVersion,
422363
+ reason: "FAI returned NO_CHANGE"
422364
+ });
422365
+ }
422366
+ return await this.finalizeWithBumpNonReplay({
422367
+ service,
422368
+ language,
422369
+ mappedMagicVersion,
422370
+ previousVersion,
422371
+ analysis
422372
+ });
422373
+ }
422286
422374
  /**
422287
422375
  * Terminal path for runs that determine no semver bump is needed. The
422288
422376
  * current working tree still contains `0.0.0-fern-placeholder` from this
@@ -422340,6 +422428,94 @@ var require_AutoVersionStep = __commonJS({
422340
422428
  commitSha
422341
422429
  };
422342
422430
  }
422431
+ /**
422432
+ * Non-replay variant of finalizeNoChange. Rewrites the placeholder to
422433
+ * `previousVersion` but does NOT commit — GithubStep handles the commit.
422434
+ */
422435
+ async finalizeNoChangeNonReplay(params2) {
422436
+ const { service, language, mappedMagicVersion, previousVersion, reason } = params2;
422437
+ if (!(0, index_1.isValidSemver)(previousVersion)) {
422438
+ const errorMessage = `AutoVersionStep: resolved previousVersion ${JSON.stringify(previousVersion)} is not a valid semver string. Refusing to rewrite placeholder to avoid shell injection.`;
422439
+ this.logger.error(errorMessage);
422440
+ return { executed: true, success: false, errorMessage };
422441
+ }
422442
+ await service.replaceMagicVersion(this.outputDir, mappedMagicVersion, previousVersion);
422443
+ if (language === "go") {
422444
+ await service.addGoMajorVersionSuffix(this.outputDir, previousVersion);
422445
+ }
422446
+ const commitMessage = this.brandMessage(`SDK regeneration (no semver change: ${reason})`);
422447
+ return {
422448
+ executed: true,
422449
+ success: true,
422450
+ version: previousVersion,
422451
+ previousVersion,
422452
+ versionBump: "NO_CHANGE",
422453
+ commitMessage
422454
+ };
422455
+ }
422456
+ /**
422457
+ * Non-replay variant of finalizeWithBump. Rewrites the placeholder to
422458
+ * the bumped version but does NOT commit — GithubStep handles the commit.
422459
+ */
422460
+ async finalizeWithBumpNonReplay(params2) {
422461
+ const { service, language, mappedMagicVersion, previousVersion, analysis } = params2;
422462
+ const newVersion = (0, index_1.incrementVersion)(previousVersion, analysis.versionBump);
422463
+ this.logger.info(`AutoVersionStep (non-replay): ${analysis.versionBump} bump: ${previousVersion} \u2192 ${newVersion}`);
422464
+ await service.replaceMagicVersion(this.outputDir, mappedMagicVersion, newVersion);
422465
+ if (language === "go") {
422466
+ await service.addGoMajorVersionSuffix(this.outputDir, newVersion);
422467
+ }
422468
+ if (analysis.changelogEntry && analysis.changelogEntry.trim().length > 0) {
422469
+ await this.prependChangelogEntry({ version: newVersion, entry: analysis.changelogEntry });
422470
+ }
422471
+ return {
422472
+ executed: true,
422473
+ success: true,
422474
+ version: newVersion,
422475
+ commitMessage: analysis.message,
422476
+ changelogEntry: analysis.changelogEntry,
422477
+ previousVersion,
422478
+ versionBump: analysis.versionBump,
422479
+ prDescription: analysis.prDescription,
422480
+ versionBumpReason: analysis.versionBumpReason
422481
+ };
422482
+ }
422483
+ /**
422484
+ * Resolves the previous version for non-replay mode. Reads HEAD:.fern/metadata.json
422485
+ * (not HEAD~1, since no generation commit exists yet) as the primary fallback.
422486
+ */
422487
+ async resolvePreviousVersionNonReplay(params2) {
422488
+ const { service, rawDiff, mappedMagicVersion, baseVersion } = params2;
422489
+ if (baseVersion != null && (0, index_1.isValidSemver)(baseVersion)) {
422490
+ this.logger.debug(`AutoVersionStep (non-replay): previous version from pipeline baseVersion: ${baseVersion}`);
422491
+ return this.normalizeVersionPrefix(baseVersion, mappedMagicVersion);
422492
+ }
422493
+ try {
422494
+ const extracted = service.extractPreviousVersion(rawDiff, mappedMagicVersion);
422495
+ if (extracted != null) {
422496
+ this.logger.debug(`AutoVersionStep (non-replay): previous version from diff: ${extracted}`);
422497
+ return extracted;
422498
+ }
422499
+ } catch (error50) {
422500
+ if (!(error50 instanceof index_1.AutoVersioningException) || !error50.magicVersionAbsent) {
422501
+ throw error50;
422502
+ }
422503
+ this.logger.info("AutoVersionStep (non-replay): magic version not in diff; trying metadata + git tags.");
422504
+ }
422505
+ const metadataVersion = this.readVersionFromMetadataAtHead();
422506
+ if (metadataVersion != null) {
422507
+ return this.normalizeVersionPrefix(metadataVersion, mappedMagicVersion);
422508
+ }
422509
+ try {
422510
+ const tagVersion = await service.getLatestVersionFromGitTags(this.outputDir);
422511
+ if (tagVersion != null) {
422512
+ return this.normalizeVersionPrefix(tagVersion, mappedMagicVersion);
422513
+ }
422514
+ } catch (error50) {
422515
+ this.logger.debug(`AutoVersionStep (non-replay): git-tags fallback failed (${String(error50)}); ignoring.`);
422516
+ }
422517
+ return null;
422518
+ }
422343
422519
  async resolvePreviousVersion(params2) {
422344
422520
  const { service, rawDiff, mappedMagicVersion, baseVersion } = params2;
422345
422521
  if (baseVersion != null && (0, index_1.isValidSemver)(baseVersion)) {
@@ -422389,6 +422565,42 @@ var require_AutoVersionStep = __commonJS({
422389
422565
  const stripped = version7.startsWith("v") ? version7.slice(1) : version7;
422390
422566
  return mappedMagicVersion.startsWith("v") ? `v${stripped}` : stripped;
422391
422567
  }
422568
+ /**
422569
+ * Reads the sdkVersion from the committed (HEAD) .fern/metadata.json.
422570
+ * Used by the non-replay path where no generation commit exists yet,
422571
+ * so HEAD is the unmodified SDK repository.
422572
+ */
422573
+ readVersionFromMetadataAtHead() {
422574
+ try {
422575
+ const output2 = (0, child_process_1.execFileSync)("git", ["show", "HEAD:.fern/metadata.json"], {
422576
+ cwd: this.outputDir,
422577
+ encoding: "utf-8",
422578
+ stdio: "pipe"
422579
+ });
422580
+ const parsed = JSON.parse(output2);
422581
+ return parsed.sdkVersion ?? void 0;
422582
+ } catch (error50) {
422583
+ this.logger.debug(`AutoVersionStep: failed to read HEAD:.fern/metadata.json (${String(error50)})`);
422584
+ return void 0;
422585
+ }
422586
+ }
422587
+ /**
422588
+ * Computes a diff between HEAD (committed SDK) and the working tree (new
422589
+ * generation). Marks untracked files as intent-to-add so they appear in
422590
+ * the diff, matching LocalTaskHandler.generateDiffFile() behavior.
422591
+ */
422592
+ gitDiffHead() {
422593
+ (0, child_process_1.execFileSync)("git", ["add", "-N", "."], {
422594
+ cwd: this.outputDir,
422595
+ stdio: "pipe"
422596
+ });
422597
+ return (0, child_process_1.execFileSync)("git", ["diff", "HEAD", "--", ".", ":(exclude).fern/metadata.json"], {
422598
+ cwd: this.outputDir,
422599
+ encoding: "utf-8",
422600
+ stdio: "pipe",
422601
+ maxBuffer: 256 * 1024 * 1024
422602
+ });
422603
+ }
422392
422604
  gitDiff(from4, to10) {
422393
422605
  return (0, child_process_1.execFileSync)("git", ["diff", from4, to10, "--", ".", ":(exclude).fern/metadata.json"], {
422394
422606
  cwd: this.outputDir,
@@ -428120,9 +428332,9 @@ var require_diff3 = __commonJS({
428120
428332
  }
428121
428333
  });
428122
428334
 
428123
- // ../../../node_modules/.pnpm/@fern-api+replay@0.16.2/node_modules/@fern-api/replay/dist/index.cjs
428335
+ // ../../../node_modules/.pnpm/@fern-api+replay@0.18.0/node_modules/@fern-api/replay/dist/index.cjs
428124
428336
  var require_dist24 = __commonJS({
428125
- "../../../node_modules/.pnpm/@fern-api+replay@0.16.2/node_modules/@fern-api/replay/dist/index.cjs"(exports2, module4) {
428337
+ "../../../node_modules/.pnpm/@fern-api+replay@0.18.0/node_modules/@fern-api/replay/dist/index.cjs"(exports2, module4) {
428126
428338
  "use strict";
428127
428339
  var __defProp4 = Object.defineProperty;
428128
428340
  var __getOwnPropDesc3 = Object.getOwnPropertyDescriptor;
@@ -428176,6 +428388,11 @@ var require_dist24 = __commonJS({
428176
428388
  proc2.stderr.on("data", (data2) => {
428177
428389
  stderr += data2.toString();
428178
428390
  });
428391
+ proc2.on("error", (err) => {
428392
+ reject(new Error(`git ${args.join(" ")} failed to spawn: ${err.message}`));
428393
+ });
428394
+ proc2.stdin.on("error", () => {
428395
+ });
428179
428396
  proc2.on("close", (code5) => {
428180
428397
  if (code5 === 0) {
428181
428398
  resolve22(stdout);
@@ -428959,7 +429176,8 @@ var require_dist24 = __commonJS({
428959
429176
  var INFRASTRUCTURE_FILES = /* @__PURE__ */ new Set([".fernignore"]);
428960
429177
  function matchesFernignorePattern(filePath, patterns) {
428961
429178
  if (patterns.length === 0) return false;
428962
- return patterns.some((p14) => {
429179
+ return patterns.some((rawPattern) => {
429180
+ const p14 = rawPattern.endsWith("/") ? rawPattern.slice(0, -1) : rawPattern;
428963
429181
  if (filePath === p14) return true;
428964
429182
  if ((0, import_minimatch22.minimatch)(filePath, p14)) return true;
428965
429183
  if (!p14.includes("*") && !p14.includes("?") && filePath.startsWith(p14 + "/")) return true;
@@ -429059,6 +429277,22 @@ var require_dist24 = __commonJS({
429059
429277
  return commit.sha;
429060
429278
  }
429061
429279
  }
429280
+ let fullLog;
429281
+ try {
429282
+ fullLog = await this.git.exec([
429283
+ "log",
429284
+ "--no-merges",
429285
+ "--format=%H%x00%an%x00%ae%x00%s",
429286
+ "HEAD"
429287
+ ]);
429288
+ } catch {
429289
+ return null;
429290
+ }
429291
+ for (const commit of this.parseGitLog(fullLog)) {
429292
+ if (isGenerationBoundary(commit)) {
429293
+ return commit.sha;
429294
+ }
429295
+ }
429062
429296
  return null;
429063
429297
  }
429064
429298
  async detectNewPatches() {
@@ -429070,6 +429304,11 @@ var require_dist24 = __commonJS({
429070
429304
  }
429071
429305
  const lastGen = this.getLastGeneration(lock);
429072
429306
  if (!lastGen) {
429307
+ if (lock.current_generation) {
429308
+ this.warnings.push(
429309
+ `No generation boundary found in git history and the lockfile's recorded generation (${lock.current_generation.slice(0, 7)}) matches no entry in its generation records. Customer customizations may differ from the last known generation and could be lost on the next regeneration. Run \`fern-replay bootstrap --force\` to re-initialize tracking.`
429310
+ );
429311
+ }
429073
429312
  return { patches: [], revertedPatchIds: [] };
429074
429313
  }
429075
429314
  const exists2 = await this.git.commitExists(lastGen.commit_sha);
@@ -429117,20 +429356,15 @@ var require_dist24 = __commonJS({
429117
429356
  continue;
429118
429357
  }
429119
429358
  const parents = await this.git.getCommitParents(commit.sha);
429120
- let patchContent;
429359
+ let filesOutput;
429121
429360
  try {
429122
- patchContent = await this.git.formatPatch(commit.sha);
429361
+ filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
429123
429362
  } catch {
429124
429363
  this.warnings.push(
429125
429364
  `Could not generate patch for commit ${commit.sha.slice(0, 7)} \u2014 it may be unreachable in a shallow clone. Skipping.`
429126
429365
  );
429127
429366
  continue;
429128
429367
  }
429129
- let contentHash = this.computeContentHash(patchContent);
429130
- if (lock.patches.find((p14) => p14.content_hash === contentHash) || forgottenHashes.has(contentHash)) {
429131
- continue;
429132
- }
429133
- const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
429134
429368
  const { files, sensitiveFiles, fernignoredFiles } = filterInfrastructureAndSensitiveFiles(
429135
429369
  filesOutput,
429136
429370
  this.fernignorePatterns
@@ -429145,19 +429379,31 @@ var require_dist24 = __commonJS({
429145
429379
  `.fernignore-protected file(s) excluded from patch for commit ${commit.sha.slice(0, 7)}: ${fernignoredFiles.join(", ")}. These files are managed by .fernignore, not Replay.`
429146
429380
  );
429147
429381
  }
429148
- if ((sensitiveFiles.length > 0 || fernignoredFiles.length > 0) && files.length > 0) {
429149
- const parentSha = parents[0];
429150
- if (parentSha) {
429151
- try {
429152
- patchContent = await this.git.exec(["diff", parentSha, commit.sha, "--", ...files]);
429153
- } catch {
429154
- continue;
429155
- }
429156
- if (!patchContent.trim()) continue;
429157
- contentHash = this.computeContentHash(patchContent);
429382
+ if (files.length === 0) {
429383
+ continue;
429384
+ }
429385
+ const wasFiltered = sensitiveFiles.length > 0 || fernignoredFiles.length > 0;
429386
+ const parentSha = parents[0];
429387
+ let patchContent;
429388
+ if (wasFiltered && parentSha) {
429389
+ try {
429390
+ patchContent = await this.git.exec(["diff", parentSha, commit.sha, "--", ...files]);
429391
+ } catch {
429392
+ continue;
429393
+ }
429394
+ if (!patchContent.trim()) continue;
429395
+ } else {
429396
+ try {
429397
+ patchContent = await this.git.formatPatch(commit.sha);
429398
+ } catch {
429399
+ this.warnings.push(
429400
+ `Could not generate patch for commit ${commit.sha.slice(0, 7)} \u2014 it may be unreachable in a shallow clone. Skipping.`
429401
+ );
429402
+ continue;
429158
429403
  }
429159
429404
  }
429160
- if (files.length === 0) {
429405
+ const contentHash = this.computeContentHash(patchContent);
429406
+ if (lock.patches.find((p14) => p14.content_hash === contentHash) || forgottenHashes.has(contentHash)) {
429161
429407
  continue;
429162
429408
  }
429163
429409
  const theirsSnapshot = await capturePatchSnapshot(this.git, files, commit.sha);
@@ -429816,16 +430062,20 @@ var require_dist24 = __commonJS({
429816
430062
  const oursPath = (0, import_node_path310.join)(outputDir, resolvedPath);
429817
430063
  const ours = await (0, import_promises208.readFile)(oursPath, "utf-8").catch(() => null);
429818
430064
  let ghostTheirs = null;
429819
- if (!base4 && ours && !renameSourcePath) {
430065
+ let baseTreeUnreachable = false;
430066
+ if (!base4 && !renameSourcePath) {
429820
430067
  const treeReachable = await isTreeReachable(baseGen.tree_hash);
429821
430068
  if (!treeReachable) {
429822
- const fileDiff = extractFileDiff2(patch5.patch_content, filePath);
429823
- if (fileDiff) {
429824
- const { reconstructFromGhostPatch: reconstructFromGhostPatch2 } = await Promise.resolve().then(() => (init_HybridReconstruction(), HybridReconstruction_exports));
429825
- const result = reconstructFromGhostPatch2(fileDiff, ours);
429826
- if (result) {
429827
- base4 = result.base;
429828
- ghostTheirs = result.theirs;
430069
+ baseTreeUnreachable = true;
430070
+ if (ours) {
430071
+ const fileDiff = extractFileDiff2(patch5.patch_content, filePath);
430072
+ if (fileDiff) {
430073
+ const { reconstructFromGhostPatch: reconstructFromGhostPatch2 } = await Promise.resolve().then(() => (init_HybridReconstruction(), HybridReconstruction_exports));
430074
+ const result = reconstructFromGhostPatch2(fileDiff, ours);
430075
+ if (result) {
430076
+ base4 = result.base;
430077
+ ghostTheirs = result.theirs;
430078
+ }
429829
430079
  }
429830
430080
  }
429831
430081
  }
@@ -429837,7 +430087,11 @@ var require_dist24 = __commonJS({
429837
430087
  ours,
429838
430088
  oursPath,
429839
430089
  renameSourcePath,
429840
- ghostTheirs
430090
+ ghostTheirs,
430091
+ // Only meaningful when ghost reconstruction did NOT recover a base; if it
430092
+ // did, `base` is non-null and the merge proceeds normally. We still set
430093
+ // the flag truthfully (the tree IS unreachable) so Phase 3 can decide.
430094
+ baseTreeUnreachable
429841
430095
  };
429842
430096
  }
429843
430097
  var CONFLICT_OPENER = "<<<<<<< Generated";
@@ -430016,7 +430270,11 @@ var require_dist24 = __commonJS({
430016
430270
  return { kind: "new-file-only-user", theirs: effective_theirs };
430017
430271
  }
430018
430272
  if (base4 == null && ours != null && effective_theirs != null && !useAccumulatorAsMergeBase) {
430019
- return { kind: "new-file-both", theirs: effective_theirs };
430273
+ return {
430274
+ kind: "new-file-both",
430275
+ theirs: effective_theirs,
430276
+ ...inputs.baseTreeUnreachable ? { baseTreeUnreachable: true } : {}
430277
+ };
430020
430278
  }
430021
430279
  if (effective_theirs == null) {
430022
430280
  return { kind: "skipped", reason: "missing-content" };
@@ -430062,17 +430320,19 @@ var require_dist24 = __commonJS({
430062
430320
  const merged2 = threeWayMerge("", ours, plan.theirs);
430063
430321
  await (0, import_promises210.mkdir)((0, import_node_path44.dirname)(oursPath), { recursive: true });
430064
430322
  await (0, import_promises210.writeFile)(oursPath, merged2.content);
430323
+ const unreachableFlag = plan.baseTreeUnreachable ? { baseTreeUnreachable: true } : {};
430065
430324
  if (merged2.hasConflicts) {
430066
430325
  return {
430067
430326
  file: resolvedPath,
430068
430327
  status: "conflict",
430069
430328
  conflicts: merged2.conflicts,
430070
430329
  conflictReason: "new-file-both",
430071
- conflictMetadata: metadata
430330
+ conflictMetadata: metadata,
430331
+ ...unreachableFlag
430072
430332
  };
430073
430333
  }
430074
430334
  accumulator.recordMerge(resolvedPath, merged2.content, patch5.base_generation);
430075
- return { file: resolvedPath, status: "merged" };
430335
+ return { file: resolvedPath, status: "merged", ...unreachableFlag };
430076
430336
  }
430077
430337
  const merged = threeWayMerge(plan.mergeBase, ours, plan.theirs);
430078
430338
  await (0, import_promises210.mkdir)((0, import_node_path44.dirname)(oursPath), { recursive: true });
@@ -431272,6 +431532,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
431272
431532
  results = await this.service.applicator.applyPatches(newPatches);
431273
431533
  this.service._lastApplyResults = results;
431274
431534
  this.service.recordDroppedContextLineWarnings(results);
431535
+ this.service.recordUnreachableBaseWarnings(results);
431275
431536
  this.service.revertConflictingFiles(results);
431276
431537
  for (const result of results) {
431277
431538
  if (result.status === "conflict") {
@@ -431425,6 +431686,7 @@ Patches absorbed by generator (${buckets.absorbed.length}):`;
431425
431686
  const results = await this.service.applicator.applyPatches(allPatches);
431426
431687
  this.service._lastApplyResults = results;
431427
431688
  this.service.recordDroppedContextLineWarnings(results);
431689
+ this.service.recordUnreachableBaseWarnings(results);
431428
431690
  this.service.revertConflictingFiles(results);
431429
431691
  for (const result of results) {
431430
431692
  if (result.status === "conflict") {
@@ -432342,6 +432604,37 @@ If you want to keep these lines, restore them in a follow-up commit and re-run r
432342
432604
  }
432343
432605
  }
432344
432606
  }
432607
+ /**
432608
+ * After applyPatches(), surface a warning for each (patch × file) where a
432609
+ * customization's BASE could not be read because the patch's
432610
+ * base-generation tree is unreachable in this clone (shallow-clone window
432611
+ * too small / pruned history). In that state the merge pipeline falls
432612
+ * through to `new-file-both` and the customer's edit can be dropped with NO
432613
+ * conflict and NO error — the INC-866 silent-loss class. This converts that
432614
+ * silence into an explicit, actionable warning naming the file and the
432615
+ * likely cause (insufficient clone window).
432616
+ *
432617
+ * Mirrors `recordDroppedContextLineWarnings`'s "surface, never silently
432618
+ * drop" contract. De-duplicated per file path so a single insufficient
432619
+ * window doesn't spam one warning per touched file repeatedly.
432620
+ */
432621
+ /** @internal Used by Flow implementations in `src/flows/`. */
432622
+ recordUnreachableBaseWarnings(results) {
432623
+ const warned2 = /* @__PURE__ */ new Set();
432624
+ for (const result of results) {
432625
+ if (!result.fileResults) continue;
432626
+ for (const fr9 of result.fileResults) {
432627
+ if (!fr9.baseTreeUnreachable) continue;
432628
+ if (warned2.has(fr9.file)) continue;
432629
+ warned2.add(fr9.file);
432630
+ const base4 = fr9.conflictMetadata?.baseGeneration;
432631
+ const baseRef = base4 ? ` (base generation ${base4.slice(0, 7)})` : "";
432632
+ this.warnings.push(
432633
+ `${fr9.file}: could not read the prior generation's version of this file${baseRef} because that generation's tree is outside the clone window (insufficient shallow-clone depth or pruned history). The customization was treated as a new file, which can drop your edits silently. Re-run with the prior generation in the clone window \u2014 e.g. \`git fetch --shallow-since=<date just before the prior [fern-generated] commit>\` or \`git fetch --unshallow\` \u2014 then re-run replay.`
432634
+ );
432635
+ }
432636
+ }
432637
+ }
432345
432638
  /**
432346
432639
  * After applyPatches(), strip conflict markers from conflicting files
432347
432640
  * so only clean content is committed. Keeps the Generated (OURS) side.
@@ -438844,10 +439137,6 @@ var require_PostGenerationPipeline = __commonJS({
438844
439137
  this.logger.warn(`Replay is not supported with GitHub ${config5.github.mode} mode. Disabling replay to prevent push to base branch.`);
438845
439138
  replayEnabled = false;
438846
439139
  }
438847
- if (autoVersionEnabled && !replayEnabled) {
438848
- this.logger.warn("AutoVersion requires Replay to be enabled. Disabling AutoVersion for this run.");
438849
- autoVersionEnabled = false;
438850
- }
438851
439140
  if (replayEnabled && config5.replay != null) {
438852
439141
  this.steps.push(new GenerationCommitStep_1.GenerationCommitStep(config5.outputDir, this.logger, { enabled: true, skipApplication: config5.replay.skipApplication }, config5.cliVersion, config5.generatorVersions));
438853
439142
  }
@@ -669270,7 +669559,7 @@ var AccessTokenPosthogManager = class {
669270
669559
  properties: {
669271
669560
  ...event,
669272
669561
  ...event.properties,
669273
- version: "5.46.0",
669562
+ version: "5.46.1",
669274
669563
  usingAccessToken: true,
669275
669564
  ...getRunIdProperties()
669276
669565
  }
@@ -669334,7 +669623,7 @@ var UserPosthogManager = class {
669334
669623
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
669335
669624
  event: "CLI",
669336
669625
  properties: {
669337
- version: "5.46.0",
669626
+ version: "5.46.1",
669338
669627
  ...event,
669339
669628
  ...event.properties,
669340
669629
  usingAccessToken: false,
@@ -861072,7 +861361,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
861072
861361
  var LOGS_FOLDER_NAME = "logs";
861073
861362
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
861074
861363
  function getCliSource() {
861075
- const version7 = "5.46.0";
861364
+ const version7 = "5.46.1";
861076
861365
  return `cli@${version7}`;
861077
861366
  }
861078
861367
  var DebugLogger = class {
@@ -892164,7 +892453,7 @@ var LegacyDocsPublisher = class {
892164
892453
  previewId,
892165
892454
  disableTemplates: void 0,
892166
892455
  skipUpload,
892167
- cliVersion: "5.46.0",
892456
+ cliVersion: "5.46.1",
892168
892457
  loginCommand: "fern auth login"
892169
892458
  });
892170
892459
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -916378,6 +916667,11 @@ var DynamicTypeInstantiationMapper = class {
916378
916667
  writer2.writeNode(collectionLiteral);
916379
916668
  }));
916380
916669
  }
916670
+ // Materializes a literal value (e.g. a literal path parameter), as opposed to
916671
+ // convert(), which treats literals as a no-op since they are usually omitted.
916672
+ convertLiteral(literal3) {
916673
+ return this.convertLiteralValue(literal3);
916674
+ }
916381
916675
  convertLiteralValue(literal3) {
916382
916676
  switch (literal3.type) {
916383
916677
  case "boolean":
@@ -917749,9 +918043,10 @@ var EndpointSnippetGenerator3 = class {
917749
918043
  values: snippet2.pathParameters ?? {}
917750
918044
  });
917751
918045
  for (const parameter6 of pathParameters) {
918046
+ const value2 = parameter6.typeReference.type === "literal" ? this.context.dynamicTypeInstantiationMapper.convertLiteral(parameter6.typeReference.value) : asPointer ? this.context.dynamicTypeInstantiationMapper.convertToPointerIfPossible(parameter6) : this.context.dynamicTypeInstantiationMapper.convert(parameter6);
917752
918047
  args.push({
917753
918048
  name: this.context.getTypeName(parameter6.name.name),
917754
- value: asPointer ? this.context.dynamicTypeInstantiationMapper.convertToPointerIfPossible(parameter6) : this.context.dynamicTypeInstantiationMapper.convert(parameter6)
918049
+ value: value2
917755
918050
  });
917756
918051
  }
917757
918052
  return args;
@@ -957348,7 +957643,7 @@ function getAutomationContextFromEnv() {
957348
957643
  config_branch: process.env.FERN_CONFIG_BRANCH,
957349
957644
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
957350
957645
  trigger: process.env.GITHUB_EVENT_NAME,
957351
- cli_version: "5.46.0"
957646
+ cli_version: "5.46.1"
957352
957647
  };
957353
957648
  }
957354
957649
  function isAutomationMode() {
@@ -958174,7 +958469,7 @@ var CliContext = class _CliContext {
958174
958469
  if (false) {
958175
958470
  this.logger.error("CLI_VERSION is not defined");
958176
958471
  }
958177
- return "5.46.0";
958472
+ return "5.46.1";
958178
958473
  }
958179
958474
  getCliName() {
958180
958475
  if (false) {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.46.0",
2
+ "version": "5.46.1",
3
3
  "repository": {
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/fern-api/fern.git",