@riconext/hermes-repo 0.13.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -3735,27 +3735,101 @@ var claudeCodeAdapter = {
3735
3735
  }
3736
3736
  };
3737
3737
 
3738
- // src/init/assistants/codebuddy.ts
3738
+ // src/init/assistants/codex.ts
3739
3739
  import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync14 } from "fs";
3740
3740
  import { join as join27 } from "path";
3741
3741
 
3742
- // src/init/mergeCodebuddySettings.ts
3742
+ // src/init/mergeCodexConfig.ts
3743
3743
  import { existsSync as existsSync24, readFileSync as readFileSync24 } from "fs";
3744
3744
  import { join as join26 } from "path";
3745
+ var CODEX_CONFIG_REL = ".codex/config.toml";
3746
+ var CODEX_HERMES_START_MARKER = "# >>> hermes-repo codex (do not edit this block manually)";
3747
+ var CODEX_HERMES_END_MARKER = "# <<< hermes-repo codex";
3748
+ function buildCodexHermesBlock() {
3749
+ return [
3750
+ CODEX_HERMES_START_MARKER,
3751
+ "# Hermes uses AGENTS.md as the shared Codex project guidance entry.",
3752
+ "# Run `npx @riconext/hermes-repo search <keyword>` to inspect project memory.",
3753
+ '# Run `npx @riconext/hermes-repo ref --capture <path> --reason "..."` after using memory.',
3754
+ CODEX_HERMES_END_MARKER
3755
+ ].join("\n");
3756
+ }
3757
+ function codexConfigPath(repoRoot) {
3758
+ return join26(repoRoot, ".codex", "config.toml");
3759
+ }
3760
+ function spliceHermesBlock(existing, block) {
3761
+ const startIdx = existing.indexOf(CODEX_HERMES_START_MARKER);
3762
+ const endIdx = existing.indexOf(CODEX_HERMES_END_MARKER);
3763
+ if (startIdx >= 0 && endIdx >= startIdx) {
3764
+ const before = existing.slice(0, startIdx).trimEnd();
3765
+ const after = existing.slice(endIdx + CODEX_HERMES_END_MARKER.length).trimStart();
3766
+ return `${before ? `${before}
3767
+
3768
+ ` : ""}${block}${after ? `
3769
+
3770
+ ${after}` : ""}
3771
+ `;
3772
+ }
3773
+ const trimmed = existing.trimEnd();
3774
+ return `${trimmed ? `${trimmed}
3775
+
3776
+ ` : ""}${block}
3777
+ `;
3778
+ }
3779
+ function mergeCodexConfig(repoRoot) {
3780
+ const configPath = codexConfigPath(repoRoot);
3781
+ const existed = existsSync24(configPath);
3782
+ const block = buildCodexHermesBlock();
3783
+ if (!existed) {
3784
+ return {
3785
+ content: `${block}
3786
+ `,
3787
+ action: "created"
3788
+ };
3789
+ }
3790
+ const existing = readFileSync24(configPath, "utf8");
3791
+ const hasBlock = existing.includes(CODEX_HERMES_START_MARKER) && existing.includes(CODEX_HERMES_END_MARKER);
3792
+ return {
3793
+ content: spliceHermesBlock(existing, block),
3794
+ action: hasBlock ? "replaced" : "appended"
3795
+ };
3796
+ }
3797
+
3798
+ // src/init/assistants/codex.ts
3799
+ var codexAdapter = {
3800
+ id: "codex",
3801
+ label: "OpenAI Codex\uFF08AGENTS.md + .codex/config.toml\uFF09",
3802
+ available: true,
3803
+ scaffoldPaths: [CODEX_CONFIG_REL],
3804
+ write(ctx) {
3805
+ mkdirSync9(join27(ctx.repoRoot, ".codex"), { recursive: true });
3806
+ const { content, action } = mergeCodexConfig(ctx.repoRoot);
3807
+ writeFileSync14(codexConfigPath(ctx.repoRoot), content, "utf8");
3808
+ ctx.report.files.push({ path: CODEX_CONFIG_REL, action });
3809
+ }
3810
+ };
3811
+
3812
+ // src/init/assistants/codebuddy.ts
3813
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync15 } from "fs";
3814
+ import { join as join29 } from "path";
3815
+
3816
+ // src/init/mergeCodebuddySettings.ts
3817
+ import { existsSync as existsSync25, readFileSync as readFileSync25 } from "fs";
3818
+ import { join as join28 } from "path";
3745
3819
  var CODEBUDDY_SETTINGS_LOCAL_REL = ".codebuddy/settings.local.json";
3746
3820
  function codebuddySettingsLocalPath(repoRoot) {
3747
- return join26(repoRoot, ".codebuddy", "settings.local.json");
3821
+ return join28(repoRoot, ".codebuddy", "settings.local.json");
3748
3822
  }
3749
3823
  function mergeCodebuddyLocalSettings(repoRoot) {
3750
3824
  const settingsPath = codebuddySettingsLocalPath(repoRoot);
3751
- const existed = existsSync24(settingsPath);
3825
+ const existed = existsSync25(settingsPath);
3752
3826
  const templateParsed = JSON.parse(
3753
3827
  renderTemplate("hooks.codebuddy.json.tpl")
3754
3828
  );
3755
3829
  let existing = {};
3756
3830
  if (existed) {
3757
3831
  try {
3758
- existing = JSON.parse(readFileSync24(settingsPath, "utf8"));
3832
+ existing = JSON.parse(readFileSync25(settingsPath, "utf8"));
3759
3833
  } catch {
3760
3834
  existing = {};
3761
3835
  }
@@ -3783,32 +3857,32 @@ var codebuddyAdapter = {
3783
3857
  available: true,
3784
3858
  scaffoldPaths: [CODEBUDDY_SETTINGS_LOCAL_REL],
3785
3859
  write(ctx) {
3786
- mkdirSync9(join27(ctx.repoRoot, ".codebuddy"), { recursive: true });
3860
+ mkdirSync10(join29(ctx.repoRoot, ".codebuddy"), { recursive: true });
3787
3861
  const { content, action } = mergeCodebuddyLocalSettings(ctx.repoRoot);
3788
- writeFileSync14(codebuddySettingsLocalPath(ctx.repoRoot), content, "utf8");
3862
+ writeFileSync15(codebuddySettingsLocalPath(ctx.repoRoot), content, "utf8");
3789
3863
  ctx.report.files.push({ path: CODEBUDDY_SETTINGS_LOCAL_REL, action });
3790
3864
  }
3791
3865
  };
3792
3866
 
3793
3867
  // src/init/assistants/cursor.ts
3794
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync15 } from "fs";
3795
- import { join as join29 } from "path";
3868
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync16 } from "fs";
3869
+ import { join as join31 } from "path";
3796
3870
 
3797
3871
  // src/init/mergeCursorHooks.ts
3798
- import { existsSync as existsSync25, readFileSync as readFileSync25 } from "fs";
3799
- import { join as join28 } from "path";
3872
+ import { existsSync as existsSync26, readFileSync as readFileSync26 } from "fs";
3873
+ import { join as join30 } from "path";
3800
3874
  var CURSOR_HOOKS_REL = ".cursor/hooks.json";
3801
3875
  function cursorHooksPath(repoRoot) {
3802
- return join28(repoRoot, ".cursor", "hooks.json");
3876
+ return join30(repoRoot, ".cursor", "hooks.json");
3803
3877
  }
3804
3878
  function mergeCursorHooks(repoRoot) {
3805
3879
  const hooksPath = cursorHooksPath(repoRoot);
3806
- const existed = existsSync25(hooksPath);
3880
+ const existed = existsSync26(hooksPath);
3807
3881
  const templateParsed = JSON.parse(renderTemplate("hooks.cursor.json.tpl"));
3808
3882
  let existing = {};
3809
3883
  if (existed) {
3810
3884
  try {
3811
- existing = JSON.parse(readFileSync25(hooksPath, "utf8"));
3885
+ existing = JSON.parse(readFileSync26(hooksPath, "utf8"));
3812
3886
  } catch {
3813
3887
  existing = {};
3814
3888
  }
@@ -3837,9 +3911,9 @@ var cursorAdapter = {
3837
3911
  available: true,
3838
3912
  scaffoldPaths: [CURSOR_HOOKS_REL],
3839
3913
  write(ctx) {
3840
- mkdirSync10(join29(ctx.repoRoot, ".cursor"), { recursive: true });
3914
+ mkdirSync11(join31(ctx.repoRoot, ".cursor"), { recursive: true });
3841
3915
  const { content, action } = mergeCursorHooks(ctx.repoRoot);
3842
- writeFileSync15(cursorHooksPath(ctx.repoRoot), content, "utf8");
3916
+ writeFileSync16(cursorHooksPath(ctx.repoRoot), content, "utf8");
3843
3917
  ctx.report.files.push({ path: CURSOR_HOOKS_REL, action });
3844
3918
  }
3845
3919
  };
@@ -3849,7 +3923,8 @@ var DEFAULT_ASSISTANT_IDS = ["claude-code"];
3849
3923
  var ALL_ADAPTERS = [
3850
3924
  claudeCodeAdapter,
3851
3925
  cursorAdapter,
3852
- codebuddyAdapter
3926
+ codebuddyAdapter,
3927
+ codexAdapter
3853
3928
  ];
3854
3929
  var ADAPTER_BY_ID = new Map(
3855
3930
  ALL_ADAPTERS.map((a) => [a.id, a])
@@ -3898,30 +3973,30 @@ function validateAssistantSelection(ids) {
3898
3973
  }
3899
3974
 
3900
3975
  // src/init/ensureDirs.ts
3901
- import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync16 } from "fs";
3902
- import { join as join30 } from "path";
3976
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync17 } from "fs";
3977
+ import { join as join32 } from "path";
3903
3978
  function ensureMemoryTree(repoRoot) {
3904
- const memoryRoot = join30(repoRoot, MEMORY_DIR);
3905
- mkdirSync11(memoryRoot, { recursive: true });
3979
+ const memoryRoot = join32(repoRoot, MEMORY_DIR);
3980
+ mkdirSync12(memoryRoot, { recursive: true });
3906
3981
  for (const sub of MEMORY_SUBDIRS) {
3907
- mkdirSync11(join30(memoryRoot, sub), { recursive: true });
3982
+ mkdirSync12(join32(memoryRoot, sub), { recursive: true });
3908
3983
  }
3909
- mkdirSync11(join30(repoRoot, ".claude"), { recursive: true });
3984
+ mkdirSync12(join32(repoRoot, ".claude"), { recursive: true });
3910
3985
  for (const sub of GITKEEP_DIRS) {
3911
- const keepPath = join30(memoryRoot, sub, ".gitkeep");
3912
- writeFileSync16(keepPath, "", { flag: "a" });
3986
+ const keepPath = join32(memoryRoot, sub, ".gitkeep");
3987
+ writeFileSync17(keepPath, "", { flag: "a" });
3913
3988
  }
3914
3989
  }
3915
3990
 
3916
3991
  // src/init/mergeAssistants.ts
3917
- import { existsSync as existsSync26, readFileSync as readFileSync26 } from "fs";
3992
+ import { existsSync as existsSync27, readFileSync as readFileSync27 } from "fs";
3918
3993
  function readExistingAssistants(repoRoot) {
3919
3994
  const configPath = memoryPath(repoRoot, "config.json");
3920
- if (!existsSync26(configPath)) {
3995
+ if (!existsSync27(configPath)) {
3921
3996
  return [];
3922
3997
  }
3923
3998
  try {
3924
- const config = JSON.parse(readFileSync26(configPath, "utf8"));
3999
+ const config = JSON.parse(readFileSync27(configPath, "utf8"));
3925
4000
  if (!Array.isArray(config.assistants)) {
3926
4001
  return [];
3927
4002
  }
@@ -3936,17 +4011,17 @@ function mergeAssistants(repoRoot, selected) {
3936
4011
  }
3937
4012
 
3938
4013
  // src/init/mergeGitignore.ts
3939
- import { existsSync as existsSync27, readFileSync as readFileSync27, writeFileSync as writeFileSync17 } from "fs";
3940
- import { join as join31 } from "path";
4014
+ import { existsSync as existsSync28, readFileSync as readFileSync28, writeFileSync as writeFileSync18 } from "fs";
4015
+ import { join as join33 } from "path";
3941
4016
  var START_MARKER = "# >>> hermes-repo memory (do not edit this block manually)";
3942
4017
  var END_MARKER = "# <<< hermes-repo memory";
3943
4018
  function mergeHermesGitignore(repoRoot) {
3944
4019
  const block = readTemplate("gitignore-block.txt").trimEnd() + "\n";
3945
- const gitignorePath = join31(repoRoot, ".gitignore");
3946
- const contentBefore = existsSync27(gitignorePath) ? readFileSync27(gitignorePath, "utf8") : "";
4020
+ const gitignorePath = join33(repoRoot, ".gitignore");
4021
+ const contentBefore = existsSync28(gitignorePath) ? readFileSync28(gitignorePath, "utf8") : "";
3947
4022
  const warnBroadMemoryIgnore = contentBefore.length > 0 && !contentBefore.includes(START_MARKER) && /(^|\n)\.memory\/\s*$/m.test(contentBefore);
3948
- if (!existsSync27(gitignorePath)) {
3949
- writeFileSync17(gitignorePath, `${block}
4023
+ if (!existsSync28(gitignorePath)) {
4024
+ writeFileSync18(gitignorePath, `${block}
3950
4025
  `, "utf8");
3951
4026
  return { action: "created", warnBroadMemoryIgnore: false };
3952
4027
  }
@@ -3956,7 +4031,7 @@ function mergeHermesGitignore(repoRoot) {
3956
4031
  const before = contentBefore.slice(0, startIdx);
3957
4032
  const after = contentBefore.slice(endIdx + END_MARKER.length);
3958
4033
  const next = `${before}${block}${after}`.replace(/\n{3,}/g, "\n\n");
3959
- writeFileSync17(gitignorePath, next.endsWith("\n") ? next : `${next}
4034
+ writeFileSync18(gitignorePath, next.endsWith("\n") ? next : `${next}
3960
4035
  `, "utf8");
3961
4036
  return { action: "replaced", warnBroadMemoryIgnore };
3962
4037
  }
@@ -3964,11 +4039,11 @@ function mergeHermesGitignore(repoRoot) {
3964
4039
  const before = contentBefore.slice(0, startIdx);
3965
4040
  const next = `${before}${block}
3966
4041
  `;
3967
- writeFileSync17(gitignorePath, next, "utf8");
4042
+ writeFileSync18(gitignorePath, next, "utf8");
3968
4043
  return { action: "updated", warnBroadMemoryIgnore };
3969
4044
  }
3970
4045
  const separator = contentBefore.endsWith("\n") || contentBefore.length === 0 ? "\n" : "\n\n";
3971
- writeFileSync17(gitignorePath, `${contentBefore}${separator}${block}
4046
+ writeFileSync18(gitignorePath, `${contentBefore}${separator}${block}
3972
4047
  `, "utf8");
3973
4048
  return { action: "appended", warnBroadMemoryIgnore };
3974
4049
  }
@@ -4039,8 +4114,8 @@ async function withSpinnerProgress(label, fn, formatDone, stream = process.stder
4039
4114
  }
4040
4115
 
4041
4116
  // src/coldstart/collectors/existingRules.ts
4042
- import { existsSync as existsSync28, readFileSync as readFileSync28, readdirSync as readdirSync9 } from "fs";
4043
- import { join as join32 } from "path";
4117
+ import { existsSync as existsSync29, readFileSync as readFileSync29, readdirSync as readdirSync9 } from "fs";
4118
+ import { join as join34 } from "path";
4044
4119
  var MAX_EXCERPT = 3500;
4045
4120
  var RULE_CANDIDATES = [
4046
4121
  "AGENTS.md",
@@ -4048,12 +4123,12 @@ var RULE_CANDIDATES = [
4048
4123
  ".cursorrules"
4049
4124
  ];
4050
4125
  function readExcerpt(repoRoot, rel) {
4051
- const full = join32(repoRoot, rel);
4052
- if (!existsSync28(full)) {
4126
+ const full = join34(repoRoot, rel);
4127
+ if (!existsSync29(full)) {
4053
4128
  return null;
4054
4129
  }
4055
4130
  try {
4056
- const raw = readFileSync28(full, "utf8");
4131
+ const raw = readFileSync29(full, "utf8");
4057
4132
  return raw.length > MAX_EXCERPT ? `${raw.slice(0, MAX_EXCERPT)}
4058
4133
  ...(truncated)` : raw;
4059
4134
  } catch {
@@ -4061,8 +4136,8 @@ function readExcerpt(repoRoot, rel) {
4061
4136
  }
4062
4137
  }
4063
4138
  function collectCursorRules(repoRoot) {
4064
- const dir = join32(repoRoot, ".cursor", "rules");
4065
- if (!existsSync28(dir)) {
4139
+ const dir = join34(repoRoot, ".cursor", "rules");
4140
+ if (!existsSync29(dir)) {
4066
4141
  return [];
4067
4142
  }
4068
4143
  const out = [];
@@ -4113,8 +4188,8 @@ function collectGitLog(repoRoot, limit = 50) {
4113
4188
  }
4114
4189
 
4115
4190
  // src/coldstart/collectors/packageJson.ts
4116
- import { existsSync as existsSync29, readFileSync as readFileSync29 } from "fs";
4117
- import { join as join33 } from "path";
4191
+ import { existsSync as existsSync30, readFileSync as readFileSync30 } from "fs";
4192
+ import { join as join35 } from "path";
4118
4193
  var STACK_HINTS = {
4119
4194
  react: "react",
4120
4195
  vue: "vue",
@@ -4147,12 +4222,12 @@ function inferStackTags(deps) {
4147
4222
  return [...tags];
4148
4223
  }
4149
4224
  function collectPackageJson(repoRoot) {
4150
- const path = join33(repoRoot, "package.json");
4151
- if (!existsSync29(path)) {
4225
+ const path = join35(repoRoot, "package.json");
4226
+ if (!existsSync30(path)) {
4152
4227
  return null;
4153
4228
  }
4154
4229
  try {
4155
- const raw = JSON.parse(readFileSync29(path, "utf8"));
4230
+ const raw = JSON.parse(readFileSync30(path, "utf8"));
4156
4231
  return {
4157
4232
  name: raw.name,
4158
4233
  dependencies: depKeys(raw.dependencies),
@@ -4164,8 +4239,8 @@ function collectPackageJson(repoRoot) {
4164
4239
  }
4165
4240
 
4166
4241
  // src/coldstart/collectors/repoSignals.ts
4167
- import { existsSync as existsSync30, readdirSync as readdirSync10 } from "fs";
4168
- import { join as join34 } from "path";
4242
+ import { existsSync as existsSync31, readdirSync as readdirSync10 } from "fs";
4243
+ import { join as join36 } from "path";
4169
4244
  var SIGNAL_FILES = [
4170
4245
  "Dockerfile",
4171
4246
  "Makefile",
@@ -4177,12 +4252,12 @@ var SIGNAL_FILES = [
4177
4252
  function collectRepoSignals(repoRoot) {
4178
4253
  const signals = [];
4179
4254
  for (const rel of SIGNAL_FILES) {
4180
- const full = join34(repoRoot, rel);
4181
- if (existsSync30(full)) {
4255
+ const full = join36(repoRoot, rel);
4256
+ if (existsSync31(full)) {
4182
4257
  signals.push(rel);
4183
4258
  }
4184
4259
  }
4185
- if (existsSync30(join34(repoRoot, ".gitignore"))) {
4260
+ if (existsSync31(join36(repoRoot, ".gitignore"))) {
4186
4261
  signals.push(".gitignore");
4187
4262
  }
4188
4263
  try {
@@ -4327,7 +4402,7 @@ function runProjectScan(repoRoot) {
4327
4402
 
4328
4403
  // src/init/prompts.ts
4329
4404
  import { checkbox, confirm, input, password } from "@inquirer/prompts";
4330
- import { existsSync as existsSync31, readFileSync as readFileSync30 } from "fs";
4405
+ import { existsSync as existsSync32, readFileSync as readFileSync31 } from "fs";
4331
4406
  import { resolve as resolve6 } from "path";
4332
4407
 
4333
4408
  // src/coldstart/countCaptures.ts
@@ -4338,11 +4413,11 @@ function countExistingCaptures(repoRoot) {
4338
4413
  // src/init/prompts.ts
4339
4414
  function isInitialized(targetDir) {
4340
4415
  const configPath = memoryPath(targetDir, "config.json");
4341
- if (!existsSync31(configPath)) {
4416
+ if (!existsSync32(configPath)) {
4342
4417
  return false;
4343
4418
  }
4344
4419
  try {
4345
- const config = JSON.parse(readFileSync30(configPath, "utf8"));
4420
+ const config = JSON.parse(readFileSync31(configPath, "utf8"));
4346
4421
  return config.version === 1;
4347
4422
  } catch {
4348
4423
  return false;
@@ -4441,7 +4516,7 @@ async function promptLlmFields(defaults = {}, options = {}) {
4441
4516
  }
4442
4517
  async function gatherLlmInitInput(targetDir) {
4443
4518
  const llmPath = memoryPath(targetDir, "llm.json");
4444
- if (existsSync31(llmPath)) {
4519
+ if (existsSync32(llmPath)) {
4445
4520
  const overwrite = await confirm({
4446
4521
  message: "\u68C0\u6D4B\u5230\u5DF2\u6709 .memory/llm.json\uFF0C\u662F\u5426\u8986\u76D6\u5E76\u91CD\u65B0\u914D\u7F6E\uFF1F",
4447
4522
  default: false
@@ -4472,17 +4547,17 @@ async function gatherLlmInitInput(targetDir) {
4472
4547
  }
4473
4548
 
4474
4549
  // src/init/writeScaffoldFile.ts
4475
- import { copyFileSync, writeFileSync as writeFileSync21 } from "fs";
4550
+ import { copyFileSync, writeFileSync as writeFileSync22 } from "fs";
4476
4551
 
4477
4552
  // src/init/mergeConfig.ts
4478
- import { existsSync as existsSync32, readFileSync as readFileSync31 } from "fs";
4553
+ import { existsSync as existsSync33, readFileSync as readFileSync32 } from "fs";
4479
4554
  function mergeConfigForInit(repoRoot, assistants) {
4480
4555
  const configPath = memoryPath(repoRoot, "config.json");
4481
- const existed = existsSync32(configPath);
4556
+ const existed = existsSync33(configPath);
4482
4557
  let existing = {};
4483
4558
  if (existed) {
4484
4559
  try {
4485
- existing = JSON.parse(readFileSync31(configPath, "utf8"));
4560
+ existing = JSON.parse(readFileSync32(configPath, "utf8"));
4486
4561
  } catch {
4487
4562
  existing = {};
4488
4563
  }
@@ -4506,8 +4581,8 @@ function mergeConfigForInit(repoRoot, assistants) {
4506
4581
  }
4507
4582
 
4508
4583
  // src/init/mergeAgentsMd.ts
4509
- import { existsSync as existsSync33, readFileSync as readFileSync32, writeFileSync as writeFileSync18 } from "fs";
4510
- import { join as join35 } from "path";
4584
+ import { existsSync as existsSync34, readFileSync as readFileSync33, writeFileSync as writeFileSync19 } from "fs";
4585
+ import { join as join37 } from "path";
4511
4586
  var HERMES_AGENTS_START_MARKER = "<!-- >>> hermes-repo agents (do not edit this block manually) -->";
4512
4587
  var HERMES_AGENTS_END_MARKER = "<!-- <<< hermes-repo agents -->";
4513
4588
  function buildHermesAgentsBlockBody() {
@@ -4544,7 +4619,7 @@ function withGapBeforeHermesBlock(prefix) {
4544
4619
  }
4545
4620
  return `${trimmed}${GAP_BEFORE_HERMES_BLOCK}`;
4546
4621
  }
4547
- function spliceHermesBlock(existing, block) {
4622
+ function spliceHermesBlock2(existing, block) {
4548
4623
  const startIdx = existing.indexOf(HERMES_AGENTS_START_MARKER);
4549
4624
  const endIdx = existing.indexOf(HERMES_AGENTS_END_MARKER);
4550
4625
  if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
@@ -4563,32 +4638,32 @@ function spliceHermesBlock(existing, block) {
4563
4638
  `;
4564
4639
  }
4565
4640
  function mergeAgentsMd(repoRoot, force) {
4566
- const agentsPath = join35(repoRoot, "AGENTS.md");
4641
+ const agentsPath = join37(repoRoot, "AGENTS.md");
4567
4642
  const block = buildHermesAgentsMarkedBlock();
4568
- if (!existsSync33(agentsPath)) {
4569
- writeFileSync18(agentsPath, buildNewAgentsMd(), "utf8");
4643
+ if (!existsSync34(agentsPath)) {
4644
+ writeFileSync19(agentsPath, buildNewAgentsMd(), "utf8");
4570
4645
  return "created";
4571
4646
  }
4572
- const content = readFileSync32(agentsPath, "utf8");
4647
+ const content = readFileSync33(agentsPath, "utf8");
4573
4648
  if (agentsMdHasHermesBlock(content)) {
4574
4649
  if (!force) {
4575
4650
  return "skipped";
4576
4651
  }
4577
- writeFileSync18(agentsPath, spliceHermesBlock(content, block), "utf8");
4652
+ writeFileSync19(agentsPath, spliceHermesBlock2(content, block), "utf8");
4578
4653
  return "replaced";
4579
4654
  }
4580
4655
  if (agentsMdHasLegacyHermesContent(content)) {
4581
4656
  return "skipped";
4582
4657
  }
4583
- writeFileSync18(agentsPath, spliceHermesBlock(content, block), "utf8");
4658
+ writeFileSync19(agentsPath, spliceHermesBlock2(content, block), "utf8");
4584
4659
  return "appended";
4585
4660
  }
4586
4661
 
4587
4662
  // src/init/mergeLlmConfig.ts
4588
- import { existsSync as existsSync34, writeFileSync as writeFileSync19 } from "fs";
4663
+ import { existsSync as existsSync35, writeFileSync as writeFileSync20 } from "fs";
4589
4664
  function mergeLlmConfigForInit(repoRoot, input2) {
4590
4665
  const llmPath = memoryPath(repoRoot, "llm.json");
4591
- const existed = existsSync34(llmPath);
4666
+ const existed = existsSync35(llmPath);
4592
4667
  let existing = {};
4593
4668
  if (existed) {
4594
4669
  try {
@@ -4617,14 +4692,14 @@ function mergeLlmConfigForInit(repoRoot, input2) {
4617
4692
  }
4618
4693
  function writeLlmJson(repoRoot, input2) {
4619
4694
  const { content, action } = mergeLlmConfigForInit(repoRoot, input2);
4620
- writeFileSync19(memoryPath(repoRoot, "llm.json"), content, "utf8");
4695
+ writeFileSync20(memoryPath(repoRoot, "llm.json"), content, "utf8");
4621
4696
  return action;
4622
4697
  }
4623
4698
 
4624
4699
  // src/init/scaffoldWrite.ts
4625
- import { existsSync as existsSync35, writeFileSync as writeFileSync20 } from "fs";
4700
+ import { existsSync as existsSync36, writeFileSync as writeFileSync21 } from "fs";
4626
4701
  function shouldWriteFile(absolutePath, force) {
4627
- if (!existsSync35(absolutePath)) {
4702
+ if (!existsSync36(absolutePath)) {
4628
4703
  return { write: true, action: "created" };
4629
4704
  }
4630
4705
  if (force) {
@@ -4638,7 +4713,7 @@ function writeIfAllowed(report, absolutePath, relativePath, content, force) {
4638
4713
  report.files.push({ path: relativePath, action });
4639
4714
  return;
4640
4715
  }
4641
- writeFileSync20(absolutePath, content, "utf8");
4716
+ writeFileSync21(absolutePath, content, "utf8");
4642
4717
  report.files.push({ path: relativePath, action });
4643
4718
  }
4644
4719
 
@@ -4646,7 +4721,7 @@ function writeIfAllowed(report, absolutePath, relativePath, content, force) {
4646
4721
  function writeConfigJson(report, repoRoot, assistants) {
4647
4722
  const { content, action } = mergeConfigForInit(repoRoot, assistants);
4648
4723
  const absolutePath = memoryPath(repoRoot, "config.json");
4649
- writeFileSync21(absolutePath, content, "utf8");
4724
+ writeFileSync22(absolutePath, content, "utf8");
4650
4725
  report.files.push({ path: ".memory/config.json", action });
4651
4726
  }
4652
4727
  function copyTemplateIfAllowed(report, templateName, destAbsolute, relativePath, force) {
@@ -4933,10 +5008,10 @@ async function runInitCommand(opts) {
4933
5008
  }
4934
5009
 
4935
5010
  // src/feedback/writeRef.ts
4936
- import { existsSync as existsSync36, mkdirSync as mkdirSync12, writeFileSync as writeFileSync22 } from "fs";
4937
- import { join as join36 } from "path";
5011
+ import { existsSync as existsSync37, mkdirSync as mkdirSync13, writeFileSync as writeFileSync23 } from "fs";
5012
+ import { join as join38 } from "path";
4938
5013
  function targetExists(repoRoot, target) {
4939
- return existsSync36(join36(repoRoot, ".memory", target));
5014
+ return existsSync37(join38(repoRoot, ".memory", target));
4940
5015
  }
4941
5016
  function writeRef(opts) {
4942
5017
  const { repoRoot, reason, session } = opts;
@@ -4958,16 +5033,16 @@ function writeRef(opts) {
4958
5033
  date,
4959
5034
  ...session ? { session } : {}
4960
5035
  };
4961
- mkdirSync12(refsDir(repoRoot), { recursive: true });
5036
+ mkdirSync13(refsDir(repoRoot), { recursive: true });
4962
5037
  const filePath = refFilePath(repoRoot, target, date);
4963
5038
  const base = filePath.replace(/\.json$/, "");
4964
5039
  let finalPath = `${filePath}`;
4965
5040
  let n = 0;
4966
- while (existsSync36(finalPath)) {
5041
+ while (existsSync37(finalPath)) {
4967
5042
  n++;
4968
5043
  finalPath = `${base}-${n}.json`;
4969
5044
  }
4970
- writeFileSync22(finalPath, `${JSON.stringify(record, null, 2)}
5045
+ writeFileSync23(finalPath, `${JSON.stringify(record, null, 2)}
4971
5046
  `, "utf8");
4972
5047
  const file = finalPath.split("/refs/").pop() ?? finalPath;
4973
5048
  return { target, file: `refs/${file}` };
@@ -5007,15 +5082,15 @@ function runRefCommand(opts) {
5007
5082
  }
5008
5083
 
5009
5084
  // src/search/runSearch.ts
5010
- import { existsSync as existsSync37, readdirSync as readdirSync11, readFileSync as readFileSync34 } from "fs";
5011
- import { join as join37 } from "path";
5085
+ import { existsSync as existsSync38, readdirSync as readdirSync11, readFileSync as readFileSync35 } from "fs";
5086
+ import { join as join39 } from "path";
5012
5087
  function walkMdFiles(dir) {
5013
- if (!existsSync37(dir)) {
5088
+ if (!existsSync38(dir)) {
5014
5089
  return [];
5015
5090
  }
5016
5091
  const out = [];
5017
5092
  for (const name of readdirSync11(dir)) {
5018
- const full = join37(dir, name);
5093
+ const full = join39(dir, name);
5019
5094
  if (name.endsWith(".md")) {
5020
5095
  out.push(full);
5021
5096
  } else if (!name.startsWith(".")) {
@@ -5024,7 +5099,7 @@ function walkMdFiles(dir) {
5024
5099
  if (Array.isArray(st)) {
5025
5100
  for (const child of readdirSync11(full)) {
5026
5101
  if (child.endsWith(".md")) {
5027
- out.push(join37(full, child));
5102
+ out.push(join39(full, child));
5028
5103
  }
5029
5104
  }
5030
5105
  }
@@ -5036,13 +5111,13 @@ function walkMdFiles(dir) {
5036
5111
  }
5037
5112
  function listSkillMd(repoRoot) {
5038
5113
  const skillsDir = memoryPath(repoRoot, "skills");
5039
- if (!existsSync37(skillsDir)) {
5114
+ if (!existsSync38(skillsDir)) {
5040
5115
  return [];
5041
5116
  }
5042
5117
  const out = [];
5043
5118
  for (const slug of readdirSync11(skillsDir)) {
5044
- const f = join37(skillsDir, slug, "SKILL.md");
5045
- if (existsSync37(f)) {
5119
+ const f = join39(skillsDir, slug, "SKILL.md");
5120
+ if (existsSync38(f)) {
5046
5121
  out.push(f);
5047
5122
  }
5048
5123
  }
@@ -5050,7 +5125,7 @@ function listSkillMd(repoRoot) {
5050
5125
  }
5051
5126
  function summaryFromFile(absPath, relFromMemory) {
5052
5127
  try {
5053
- const content = readFileSync34(absPath, "utf8");
5128
+ const content = readFileSync35(absPath, "utf8");
5054
5129
  if (relFromMemory.startsWith("captures/")) {
5055
5130
  const parsed = parseCaptureMarkdown(content, relFromMemory, absPath);
5056
5131
  if (parsed) {
@@ -5073,10 +5148,10 @@ function runSearch(opts) {
5073
5148
  const memRoot = memoryPath(opts.repoRoot);
5074
5149
  const captureTypes = opts.type ? [opts.type] : ["semantic", "episodic", "procedural"];
5075
5150
  for (const t of captureTypes) {
5076
- const dir = join37(memRoot, "captures", t);
5151
+ const dir = join39(memRoot, "captures", t);
5077
5152
  for (const abs of walkMdFiles(dir)) {
5078
5153
  const rel = abs.replace(memRoot + "/", "").replace(/\\/g, "/");
5079
- const content = readFileSync34(abs, "utf8").toLowerCase();
5154
+ const content = readFileSync35(abs, "utf8").toLowerCase();
5080
5155
  if (content.includes(kw)) {
5081
5156
  hits.push({
5082
5157
  path: rel,
@@ -5088,10 +5163,10 @@ function runSearch(opts) {
5088
5163
  }
5089
5164
  }
5090
5165
  }
5091
- const topicsDir = join37(memRoot, "topics");
5166
+ const topicsDir = join39(memRoot, "topics");
5092
5167
  for (const abs of walkMdFiles(topicsDir)) {
5093
5168
  const rel = abs.replace(memRoot + "/", "").replace(/\\/g, "/");
5094
- if (readFileSync34(abs, "utf8").toLowerCase().includes(kw)) {
5169
+ if (readFileSync35(abs, "utf8").toLowerCase().includes(kw)) {
5095
5170
  hits.push({ path: rel, summary: summaryFromFile(abs, rel) });
5096
5171
  }
5097
5172
  if (hits.length >= limit) {
@@ -5100,7 +5175,7 @@ function runSearch(opts) {
5100
5175
  }
5101
5176
  for (const abs of listSkillMd(opts.repoRoot)) {
5102
5177
  const rel = abs.replace(memRoot + "/", "").replace(/\\/g, "/");
5103
- if (readFileSync34(abs, "utf8").toLowerCase().includes(kw)) {
5178
+ if (readFileSync35(abs, "utf8").toLowerCase().includes(kw)) {
5104
5179
  hits.push({ path: rel, summary: summaryFromFile(abs, rel) });
5105
5180
  }
5106
5181
  if (hits.length >= limit) {
@@ -5153,7 +5228,7 @@ function runSearchCommand(opts) {
5153
5228
  }
5154
5229
 
5155
5230
  // src/stats/runStats.ts
5156
- import { existsSync as existsSync38, statSync as statSync6 } from "fs";
5231
+ import { existsSync as existsSync39, statSync as statSync6 } from "fs";
5157
5232
  function collectStats(repoRoot, nowMs = Date.now()) {
5158
5233
  const all = listAllCaptures(repoRoot);
5159
5234
  const active = filterActiveCaptures(all);
@@ -5183,7 +5258,7 @@ function collectStats(repoRoot, nowMs = Date.now()) {
5183
5258
  }
5184
5259
  }
5185
5260
  const memoryFile = memoryPath(repoRoot, "MEMORY.md");
5186
- const memoryBytes = existsSync38(memoryFile) ? statSync6(memoryFile).size : 0;
5261
+ const memoryBytes = existsSync39(memoryFile) ? statSync6(memoryFile).size : 0;
5187
5262
  const allSkills = listSkillIndex(repoRoot);
5188
5263
  const skillUsage = readSkillUsage(repoRoot);
5189
5264
  const inMemory = filterSkillIndexForMemory(allSkills, skillUsage, repoRoot, nowMs);
@@ -5250,11 +5325,11 @@ function runStatsCommand(opts) {
5250
5325
  }
5251
5326
 
5252
5327
  // src/promote/runPromote.ts
5253
- import { existsSync as existsSync44, mkdirSync as mkdirSync14, writeFileSync as writeFileSync24 } from "fs";
5328
+ import { existsSync as existsSync45, mkdirSync as mkdirSync15, writeFileSync as writeFileSync25 } from "fs";
5254
5329
  import { resolve as resolve8 } from "path";
5255
5330
 
5256
5331
  // src/promote/buildTopicDraft.ts
5257
- import { existsSync as existsSync39, readFileSync as readFileSync35 } from "fs";
5332
+ import { existsSync as existsSync40, readFileSync as readFileSync36 } from "fs";
5258
5333
  function ruleTopicDraftBody(tag, captures, existing) {
5259
5334
  const lines = captures.map(
5260
5335
  (c) => `- [${c.date}] [${c.type}] ${c.summary.slice(0, 120)} (${c.path}) [\u664B\u5347\u5019\u9009]`
@@ -5281,9 +5356,9 @@ async function buildTopicDraftBody(repoRoot, captures, llm) {
5281
5356
  const slug = tagToSlug(tag);
5282
5357
  const abs = memoryPath(repoRoot, "topics", `${slug}.md`);
5283
5358
  let existing = "";
5284
- if (existsSync39(abs)) {
5359
+ if (existsSync40(abs)) {
5285
5360
  try {
5286
- existing = readFileSync35(abs, "utf8");
5361
+ existing = readFileSync36(abs, "utf8");
5287
5362
  } catch {
5288
5363
  existing = "";
5289
5364
  }
@@ -5308,7 +5383,7 @@ ${c.findings.slice(0, 300)}`
5308
5383
  }
5309
5384
 
5310
5385
  // src/promote/detectTopicConflict.ts
5311
- import { existsSync as existsSync40, readFileSync as readFileSync36 } from "fs";
5386
+ import { existsSync as existsSync41, readFileSync as readFileSync37 } from "fs";
5312
5387
  var MUTEX_PAIRS2 = [
5313
5388
  ["localstorage", "httponly"],
5314
5389
  ["local storage", "httponly"],
@@ -5338,12 +5413,12 @@ function detectTopicConflict(repoRoot, capture) {
5338
5413
  const slug = tagToSlug(tag);
5339
5414
  const topicPath = memoryPath(repoRoot, "topics", `${slug}.md`);
5340
5415
  const relTopic = `topics/${slug}.md`;
5341
- if (!existsSync40(topicPath)) {
5416
+ if (!existsSync41(topicPath)) {
5342
5417
  return { hasConflict: false, reason: "none" };
5343
5418
  }
5344
5419
  let existing = "";
5345
5420
  try {
5346
- existing = readFileSync36(topicPath, "utf8");
5421
+ existing = readFileSync37(topicPath, "utf8");
5347
5422
  } catch {
5348
5423
  return { hasConflict: false, reason: "none" };
5349
5424
  }
@@ -5509,17 +5584,17 @@ async function buildMergedStagingDrafts(repoRoot, analyses, llm) {
5509
5584
 
5510
5585
  // src/promote/applyDecisions.ts
5511
5586
  import {
5512
- existsSync as existsSync41,
5513
- mkdirSync as mkdirSync13,
5587
+ existsSync as existsSync42,
5588
+ mkdirSync as mkdirSync14,
5514
5589
  readdirSync as readdirSync12,
5515
- readFileSync as readFileSync37,
5590
+ readFileSync as readFileSync38,
5516
5591
  unlinkSync as unlinkSync3,
5517
- writeFileSync as writeFileSync23
5592
+ writeFileSync as writeFileSync24
5518
5593
  } from "fs";
5519
- import { join as join39 } from "path";
5594
+ import { join as join41 } from "path";
5520
5595
 
5521
5596
  // src/promote/paths.ts
5522
- import { join as join38 } from "path";
5597
+ import { join as join40 } from "path";
5523
5598
  function promoteDir(repoRoot) {
5524
5599
  return memoryPath(repoRoot, "promote");
5525
5600
  }
@@ -5537,7 +5612,7 @@ function resolvePromoteTemplatePath(repoRoot) {
5537
5612
  return inMemory;
5538
5613
  }
5539
5614
  function stagingTopicPath(repoRoot, slug) {
5540
- return join38(promoteStagingTopicsDir(repoRoot), `${slug}.md`);
5615
+ return join40(promoteStagingTopicsDir(repoRoot), `${slug}.md`);
5541
5616
  }
5542
5617
 
5543
5618
  // src/promote/applyDecisions.ts
@@ -5573,17 +5648,17 @@ function buildManifestTemplate(capturePaths, dateIso) {
5573
5648
  }
5574
5649
  function removePromoteMarker(repoRoot, capturePath) {
5575
5650
  const marker = promoteMarkerPath(repoRoot, capturePath);
5576
- if (existsSync41(marker)) {
5651
+ if (existsSync42(marker)) {
5577
5652
  unlinkSync3(marker);
5578
5653
  }
5579
5654
  }
5580
5655
  function annotateReject(repoRoot, capturePath, note) {
5581
- const abs = join39(repoRoot, ".memory", capturePath);
5582
- if (!existsSync41(abs)) {
5656
+ const abs = join41(repoRoot, ".memory", capturePath);
5657
+ if (!existsSync42(abs)) {
5583
5658
  return;
5584
5659
  }
5585
5660
  try {
5586
- let content = readFileSync37(abs, "utf8");
5661
+ let content = readFileSync38(abs, "utf8");
5587
5662
  const fields = {
5588
5663
  promote_rejected_at: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
5589
5664
  };
@@ -5591,22 +5666,22 @@ function annotateReject(repoRoot, capturePath, note) {
5591
5666
  fields.promote_note = note.trim().slice(0, 200);
5592
5667
  }
5593
5668
  content = setFrontmatterScalars(content, fields);
5594
- writeFileSync23(abs, content, "utf8");
5669
+ writeFileSync24(abs, content, "utf8");
5595
5670
  } catch {
5596
5671
  }
5597
5672
  }
5598
5673
  function mergeTopicFromStaging(repoRoot, slug, dryRun) {
5599
5674
  const staging = stagingTopicPath(repoRoot, slug);
5600
- if (!existsSync41(staging)) {
5675
+ if (!existsSync42(staging)) {
5601
5676
  return null;
5602
5677
  }
5603
- const draft = readFileSync37(staging, "utf8");
5678
+ const draft = readFileSync38(staging, "utf8");
5604
5679
  const dest = memoryPath(repoRoot, "topics", `${slug}.md`);
5605
5680
  if (dryRun) {
5606
5681
  return `topics/${slug}.md`;
5607
5682
  }
5608
- mkdirSync13(memoryPath(repoRoot, "topics"), { recursive: true });
5609
- writeFileSync23(dest, draft.endsWith("\n") ? draft : `${draft}
5683
+ mkdirSync14(memoryPath(repoRoot, "topics"), { recursive: true });
5684
+ writeFileSync24(dest, draft.endsWith("\n") ? draft : `${draft}
5610
5685
  `, "utf8");
5611
5686
  return `topics/${slug}.md`;
5612
5687
  }
@@ -5642,7 +5717,7 @@ function applyDecisions(repoRoot, manifest, opts) {
5642
5717
  }
5643
5718
  if (slugsToMerge.size === 0 && result.approved.length > 0) {
5644
5719
  const stagingDir = promoteStagingTopicsDir(repoRoot);
5645
- if (existsSync41(stagingDir)) {
5720
+ if (existsSync42(stagingDir)) {
5646
5721
  for (const name of readdirSync12(stagingDir)) {
5647
5722
  if (name.endsWith(".md")) {
5648
5723
  slugsToMerge.add(name.replace(/\.md$/, ""));
@@ -5659,21 +5734,21 @@ function applyDecisions(repoRoot, manifest, opts) {
5659
5734
  return result;
5660
5735
  }
5661
5736
  function readManifestFile(manifestPath) {
5662
- const raw = readFileSync37(manifestPath, "utf8");
5737
+ const raw = readFileSync38(manifestPath, "utf8");
5663
5738
  return parseManifestJson(raw);
5664
5739
  }
5665
5740
  function writeManifestTemplate(repoRoot, capturePaths) {
5666
5741
  const dateIso = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5667
5742
  const manifest = buildManifestTemplate(capturePaths, dateIso);
5668
5743
  const path = decisionsTemplatePath(repoRoot);
5669
- mkdirSync13(memoryPath(repoRoot, "promote"), { recursive: true });
5670
- writeFileSync23(path, `${JSON.stringify(manifest, null, 2)}
5744
+ mkdirSync14(memoryPath(repoRoot, "promote"), { recursive: true });
5745
+ writeFileSync24(path, `${JSON.stringify(manifest, null, 2)}
5671
5746
  `, "utf8");
5672
5747
  return path;
5673
5748
  }
5674
5749
 
5675
5750
  // src/promote/buildPrBody.ts
5676
- import { existsSync as existsSync42, readFileSync as readFileSync38 } from "fs";
5751
+ import { existsSync as existsSync43, readFileSync as readFileSync39 } from "fs";
5677
5752
  function actionLabel(action) {
5678
5753
  if (action === "approve") {
5679
5754
  return "\u6279\u51C6\u664B\u5347";
@@ -5713,9 +5788,9 @@ ${conflictLine}
5713
5788
  }
5714
5789
  function loadTemplate(repoRoot) {
5715
5790
  const path = resolvePromoteTemplatePath(repoRoot);
5716
- if (existsSync42(path)) {
5791
+ if (existsSync43(path)) {
5717
5792
  try {
5718
- return readFileSync38(path, "utf8");
5793
+ return readFileSync39(path, "utf8");
5719
5794
  } catch {
5720
5795
  }
5721
5796
  }
@@ -5763,7 +5838,7 @@ ${items}
5763
5838
  }
5764
5839
 
5765
5840
  // src/promote/listPromoteCandidates.ts
5766
- import { existsSync as existsSync43, readdirSync as readdirSync13 } from "fs";
5841
+ import { existsSync as existsSync44, readdirSync as readdirSync13 } from "fs";
5767
5842
  var TYPES2 = ["semantic", "episodic", "procedural"];
5768
5843
  function normalizeCapturePath(input2) {
5769
5844
  let p = input2.replace(/\\/g, "/").trim();
@@ -5780,7 +5855,7 @@ function listPromoteCandidates(repoRoot, filterPaths) {
5780
5855
  const results = [];
5781
5856
  for (const type of TYPES2) {
5782
5857
  const dir = memoryPath(repoRoot, "captures", type);
5783
- if (!existsSync43(dir)) {
5858
+ if (!existsSync44(dir)) {
5784
5859
  continue;
5785
5860
  }
5786
5861
  for (const name of readdirSync13(dir)) {
@@ -5807,8 +5882,8 @@ function listPromoteCandidates(repoRoot, filterPaths) {
5807
5882
 
5808
5883
  // src/promote/runPromote.ts
5809
5884
  function ensurePromoteDirs(repoRoot) {
5810
- mkdirSync14(promoteDir(repoRoot), { recursive: true });
5811
- mkdirSync14(promoteStagingTopicsDir(repoRoot), { recursive: true });
5885
+ mkdirSync15(promoteDir(repoRoot), { recursive: true });
5886
+ mkdirSync15(promoteStagingTopicsDir(repoRoot), { recursive: true });
5812
5887
  }
5813
5888
  function formatPreviewTable(analyses) {
5814
5889
  const lines = [
@@ -5852,15 +5927,15 @@ async function runPromote(opts) {
5852
5927
  const stagingTopicPaths = [];
5853
5928
  for (const [slug, body] of mergedDrafts) {
5854
5929
  const path = stagingTopicPath(repoRoot, slug);
5855
- writeFileSync24(path, body, "utf8");
5930
+ writeFileSync25(path, body, "utf8");
5856
5931
  stagingTopicPaths.push(
5857
5932
  `.memory/promote/staging/topics/${slug}.md`
5858
5933
  );
5859
5934
  }
5860
5935
  const prBody = buildPrBody(repoRoot, analyses);
5861
5936
  const prBodyPath = opts.outPath ? resolve8(opts.outPath) : defaultPrBodyPath(repoRoot, dateIso);
5862
- mkdirSync14(memoryPath(repoRoot, "promote"), { recursive: true });
5863
- writeFileSync24(prBodyPath, prBody, "utf8");
5937
+ mkdirSync15(memoryPath(repoRoot, "promote"), { recursive: true });
5938
+ writeFileSync25(prBodyPath, prBody, "utf8");
5864
5939
  const manifestTemplatePath = writeManifestTemplate(
5865
5940
  repoRoot,
5866
5941
  candidates.map((c) => c.path)