@riconext/hermes-repo 0.13.0 → 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
@@ -201,10 +201,36 @@ function serializeLlmConfig(cfg) {
201
201
  import { readFileSync as readFileSync3 } from "fs";
202
202
  import { basename } from "path";
203
203
  var FILE_CHANGE_TOOLS = /^(Write|Edit|MultiEdit|NotebookEdit|write|edit)$/i;
204
+ var SKIP_LINE_TYPES = /* @__PURE__ */ new Set([
205
+ "file-history-snapshot",
206
+ "summary",
207
+ "function_call_result"
208
+ ]);
209
+ function textFromContentParts(content) {
210
+ if (!Array.isArray(content)) {
211
+ return "";
212
+ }
213
+ return content.map((part) => {
214
+ if (!part || typeof part !== "object") {
215
+ return "";
216
+ }
217
+ const p = part;
218
+ if (typeof p.text === "string") {
219
+ return p.text;
220
+ }
221
+ return "";
222
+ }).filter(Boolean).join("\n");
223
+ }
204
224
  function extractText(record) {
205
225
  if (typeof record.content === "string") {
206
226
  return record.content;
207
227
  }
228
+ if (Array.isArray(record.content)) {
229
+ const top = textFromContentParts(record.content);
230
+ if (top) {
231
+ return top;
232
+ }
233
+ }
208
234
  const message = record.message;
209
235
  if (message && typeof message === "object") {
210
236
  const msg = message;
@@ -212,12 +238,7 @@ function extractText(record) {
212
238
  return msg.content;
213
239
  }
214
240
  if (Array.isArray(msg.content)) {
215
- return msg.content.map((part) => {
216
- if (part && typeof part === "object" && "text" in part) {
217
- return String(part.text);
218
- }
219
- return "";
220
- }).join("\n");
241
+ return textFromContentParts(msg.content);
221
242
  }
222
243
  }
223
244
  return "";
@@ -233,9 +254,13 @@ function inferRole(record) {
233
254
  }
234
255
  return "unknown";
235
256
  }
257
+ function isSkippedLine(record) {
258
+ const t = String(record.type ?? "").toLowerCase();
259
+ return SKIP_LINE_TYPES.has(t);
260
+ }
236
261
  function isToolUse(record) {
237
262
  const t = String(record.type ?? "").toLowerCase();
238
- return t === "tool_use" || t === "tool";
263
+ return t === "tool_use" || t === "tool" || t === "function_call";
239
264
  }
240
265
  function toolName(record) {
241
266
  if (typeof record.name === "string") return record.name;
@@ -284,6 +309,9 @@ function parseJsonlFile(jsonlPath) {
284
309
  if (!trimmed) continue;
285
310
  try {
286
311
  const record = JSON.parse(trimmed);
312
+ if (isSkippedLine(record)) {
313
+ continue;
314
+ }
287
315
  if (isToolUse(record)) {
288
316
  toolCalls += 1;
289
317
  const name = toolName(record);
@@ -907,6 +935,7 @@ function parseHookInputJson(raw) {
907
935
  const transcriptPath = transcriptRaw && existsSync6(transcriptRaw) ? resolve2(transcriptRaw) : void 0;
908
936
  return {
909
937
  transcriptPath,
938
+ transcriptPathRaw: transcriptRaw,
910
939
  hookEventName: pickString(parsed, "hook_event_name", "hookEventName"),
911
940
  sessionId: pickString(parsed, "session_id", "sessionId"),
912
941
  conversationId: pickString(parsed, "conversation_id", "conversationId"),
@@ -932,7 +961,7 @@ function isCodebuddyCaptureHook(hook) {
932
961
  if (!hook) {
933
962
  return false;
934
963
  }
935
- return isTranscriptUnderAssistant(hook.transcriptPath, ".codebuddy");
964
+ return isTranscriptUnderAssistant(hook.transcriptPath, ".codebuddy") || isTranscriptUnderAssistant(hook.transcriptPathRaw, ".codebuddy");
936
965
  }
937
966
  function isClaudeCaptureHook(hook) {
938
967
  if (!hook) {
@@ -3498,6 +3527,14 @@ function runCaptureCommand(opts) {
3498
3527
  const debug = ctx?.config.debug === true;
3499
3528
  configureDebugLogging(ctx?.repoRoot ?? null, debug);
3500
3529
  const hookInput = readHookInputSync();
3530
+ if (hookInput && isCodebuddyCaptureHook(hookInput)) {
3531
+ const stdinPath = hookInput.transcriptPathRaw ?? hookInput.transcriptPath ?? "(missing)";
3532
+ debugLog(
3533
+ debug,
3534
+ "capture",
3535
+ `codebuddy stop stdin transcript_path=${stdinPath}`
3536
+ );
3537
+ }
3501
3538
  finalizeHookCommand(async () => {
3502
3539
  await runCapture({
3503
3540
  cwd: opts.cwd,
@@ -3698,27 +3735,101 @@ var claudeCodeAdapter = {
3698
3735
  }
3699
3736
  };
3700
3737
 
3701
- // src/init/assistants/codebuddy.ts
3738
+ // src/init/assistants/codex.ts
3702
3739
  import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync14 } from "fs";
3703
3740
  import { join as join27 } from "path";
3704
3741
 
3705
- // src/init/mergeCodebuddySettings.ts
3742
+ // src/init/mergeCodexConfig.ts
3706
3743
  import { existsSync as existsSync24, readFileSync as readFileSync24 } from "fs";
3707
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";
3708
3819
  var CODEBUDDY_SETTINGS_LOCAL_REL = ".codebuddy/settings.local.json";
3709
3820
  function codebuddySettingsLocalPath(repoRoot) {
3710
- return join26(repoRoot, ".codebuddy", "settings.local.json");
3821
+ return join28(repoRoot, ".codebuddy", "settings.local.json");
3711
3822
  }
3712
3823
  function mergeCodebuddyLocalSettings(repoRoot) {
3713
3824
  const settingsPath = codebuddySettingsLocalPath(repoRoot);
3714
- const existed = existsSync24(settingsPath);
3825
+ const existed = existsSync25(settingsPath);
3715
3826
  const templateParsed = JSON.parse(
3716
3827
  renderTemplate("hooks.codebuddy.json.tpl")
3717
3828
  );
3718
3829
  let existing = {};
3719
3830
  if (existed) {
3720
3831
  try {
3721
- existing = JSON.parse(readFileSync24(settingsPath, "utf8"));
3832
+ existing = JSON.parse(readFileSync25(settingsPath, "utf8"));
3722
3833
  } catch {
3723
3834
  existing = {};
3724
3835
  }
@@ -3746,32 +3857,32 @@ var codebuddyAdapter = {
3746
3857
  available: true,
3747
3858
  scaffoldPaths: [CODEBUDDY_SETTINGS_LOCAL_REL],
3748
3859
  write(ctx) {
3749
- mkdirSync9(join27(ctx.repoRoot, ".codebuddy"), { recursive: true });
3860
+ mkdirSync10(join29(ctx.repoRoot, ".codebuddy"), { recursive: true });
3750
3861
  const { content, action } = mergeCodebuddyLocalSettings(ctx.repoRoot);
3751
- writeFileSync14(codebuddySettingsLocalPath(ctx.repoRoot), content, "utf8");
3862
+ writeFileSync15(codebuddySettingsLocalPath(ctx.repoRoot), content, "utf8");
3752
3863
  ctx.report.files.push({ path: CODEBUDDY_SETTINGS_LOCAL_REL, action });
3753
3864
  }
3754
3865
  };
3755
3866
 
3756
3867
  // src/init/assistants/cursor.ts
3757
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync15 } from "fs";
3758
- import { join as join29 } from "path";
3868
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync16 } from "fs";
3869
+ import { join as join31 } from "path";
3759
3870
 
3760
3871
  // src/init/mergeCursorHooks.ts
3761
- import { existsSync as existsSync25, readFileSync as readFileSync25 } from "fs";
3762
- import { join as join28 } from "path";
3872
+ import { existsSync as existsSync26, readFileSync as readFileSync26 } from "fs";
3873
+ import { join as join30 } from "path";
3763
3874
  var CURSOR_HOOKS_REL = ".cursor/hooks.json";
3764
3875
  function cursorHooksPath(repoRoot) {
3765
- return join28(repoRoot, ".cursor", "hooks.json");
3876
+ return join30(repoRoot, ".cursor", "hooks.json");
3766
3877
  }
3767
3878
  function mergeCursorHooks(repoRoot) {
3768
3879
  const hooksPath = cursorHooksPath(repoRoot);
3769
- const existed = existsSync25(hooksPath);
3880
+ const existed = existsSync26(hooksPath);
3770
3881
  const templateParsed = JSON.parse(renderTemplate("hooks.cursor.json.tpl"));
3771
3882
  let existing = {};
3772
3883
  if (existed) {
3773
3884
  try {
3774
- existing = JSON.parse(readFileSync25(hooksPath, "utf8"));
3885
+ existing = JSON.parse(readFileSync26(hooksPath, "utf8"));
3775
3886
  } catch {
3776
3887
  existing = {};
3777
3888
  }
@@ -3800,9 +3911,9 @@ var cursorAdapter = {
3800
3911
  available: true,
3801
3912
  scaffoldPaths: [CURSOR_HOOKS_REL],
3802
3913
  write(ctx) {
3803
- mkdirSync10(join29(ctx.repoRoot, ".cursor"), { recursive: true });
3914
+ mkdirSync11(join31(ctx.repoRoot, ".cursor"), { recursive: true });
3804
3915
  const { content, action } = mergeCursorHooks(ctx.repoRoot);
3805
- writeFileSync15(cursorHooksPath(ctx.repoRoot), content, "utf8");
3916
+ writeFileSync16(cursorHooksPath(ctx.repoRoot), content, "utf8");
3806
3917
  ctx.report.files.push({ path: CURSOR_HOOKS_REL, action });
3807
3918
  }
3808
3919
  };
@@ -3812,7 +3923,8 @@ var DEFAULT_ASSISTANT_IDS = ["claude-code"];
3812
3923
  var ALL_ADAPTERS = [
3813
3924
  claudeCodeAdapter,
3814
3925
  cursorAdapter,
3815
- codebuddyAdapter
3926
+ codebuddyAdapter,
3927
+ codexAdapter
3816
3928
  ];
3817
3929
  var ADAPTER_BY_ID = new Map(
3818
3930
  ALL_ADAPTERS.map((a) => [a.id, a])
@@ -3861,30 +3973,30 @@ function validateAssistantSelection(ids) {
3861
3973
  }
3862
3974
 
3863
3975
  // src/init/ensureDirs.ts
3864
- import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync16 } from "fs";
3865
- import { join as join30 } from "path";
3976
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync17 } from "fs";
3977
+ import { join as join32 } from "path";
3866
3978
  function ensureMemoryTree(repoRoot) {
3867
- const memoryRoot = join30(repoRoot, MEMORY_DIR);
3868
- mkdirSync11(memoryRoot, { recursive: true });
3979
+ const memoryRoot = join32(repoRoot, MEMORY_DIR);
3980
+ mkdirSync12(memoryRoot, { recursive: true });
3869
3981
  for (const sub of MEMORY_SUBDIRS) {
3870
- mkdirSync11(join30(memoryRoot, sub), { recursive: true });
3982
+ mkdirSync12(join32(memoryRoot, sub), { recursive: true });
3871
3983
  }
3872
- mkdirSync11(join30(repoRoot, ".claude"), { recursive: true });
3984
+ mkdirSync12(join32(repoRoot, ".claude"), { recursive: true });
3873
3985
  for (const sub of GITKEEP_DIRS) {
3874
- const keepPath = join30(memoryRoot, sub, ".gitkeep");
3875
- writeFileSync16(keepPath, "", { flag: "a" });
3986
+ const keepPath = join32(memoryRoot, sub, ".gitkeep");
3987
+ writeFileSync17(keepPath, "", { flag: "a" });
3876
3988
  }
3877
3989
  }
3878
3990
 
3879
3991
  // src/init/mergeAssistants.ts
3880
- import { existsSync as existsSync26, readFileSync as readFileSync26 } from "fs";
3992
+ import { existsSync as existsSync27, readFileSync as readFileSync27 } from "fs";
3881
3993
  function readExistingAssistants(repoRoot) {
3882
3994
  const configPath = memoryPath(repoRoot, "config.json");
3883
- if (!existsSync26(configPath)) {
3995
+ if (!existsSync27(configPath)) {
3884
3996
  return [];
3885
3997
  }
3886
3998
  try {
3887
- const config = JSON.parse(readFileSync26(configPath, "utf8"));
3999
+ const config = JSON.parse(readFileSync27(configPath, "utf8"));
3888
4000
  if (!Array.isArray(config.assistants)) {
3889
4001
  return [];
3890
4002
  }
@@ -3899,17 +4011,17 @@ function mergeAssistants(repoRoot, selected) {
3899
4011
  }
3900
4012
 
3901
4013
  // src/init/mergeGitignore.ts
3902
- import { existsSync as existsSync27, readFileSync as readFileSync27, writeFileSync as writeFileSync17 } from "fs";
3903
- 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";
3904
4016
  var START_MARKER = "# >>> hermes-repo memory (do not edit this block manually)";
3905
4017
  var END_MARKER = "# <<< hermes-repo memory";
3906
4018
  function mergeHermesGitignore(repoRoot) {
3907
4019
  const block = readTemplate("gitignore-block.txt").trimEnd() + "\n";
3908
- const gitignorePath = join31(repoRoot, ".gitignore");
3909
- const contentBefore = existsSync27(gitignorePath) ? readFileSync27(gitignorePath, "utf8") : "";
4020
+ const gitignorePath = join33(repoRoot, ".gitignore");
4021
+ const contentBefore = existsSync28(gitignorePath) ? readFileSync28(gitignorePath, "utf8") : "";
3910
4022
  const warnBroadMemoryIgnore = contentBefore.length > 0 && !contentBefore.includes(START_MARKER) && /(^|\n)\.memory\/\s*$/m.test(contentBefore);
3911
- if (!existsSync27(gitignorePath)) {
3912
- writeFileSync17(gitignorePath, `${block}
4023
+ if (!existsSync28(gitignorePath)) {
4024
+ writeFileSync18(gitignorePath, `${block}
3913
4025
  `, "utf8");
3914
4026
  return { action: "created", warnBroadMemoryIgnore: false };
3915
4027
  }
@@ -3919,7 +4031,7 @@ function mergeHermesGitignore(repoRoot) {
3919
4031
  const before = contentBefore.slice(0, startIdx);
3920
4032
  const after = contentBefore.slice(endIdx + END_MARKER.length);
3921
4033
  const next = `${before}${block}${after}`.replace(/\n{3,}/g, "\n\n");
3922
- writeFileSync17(gitignorePath, next.endsWith("\n") ? next : `${next}
4034
+ writeFileSync18(gitignorePath, next.endsWith("\n") ? next : `${next}
3923
4035
  `, "utf8");
3924
4036
  return { action: "replaced", warnBroadMemoryIgnore };
3925
4037
  }
@@ -3927,11 +4039,11 @@ function mergeHermesGitignore(repoRoot) {
3927
4039
  const before = contentBefore.slice(0, startIdx);
3928
4040
  const next = `${before}${block}
3929
4041
  `;
3930
- writeFileSync17(gitignorePath, next, "utf8");
4042
+ writeFileSync18(gitignorePath, next, "utf8");
3931
4043
  return { action: "updated", warnBroadMemoryIgnore };
3932
4044
  }
3933
4045
  const separator = contentBefore.endsWith("\n") || contentBefore.length === 0 ? "\n" : "\n\n";
3934
- writeFileSync17(gitignorePath, `${contentBefore}${separator}${block}
4046
+ writeFileSync18(gitignorePath, `${contentBefore}${separator}${block}
3935
4047
  `, "utf8");
3936
4048
  return { action: "appended", warnBroadMemoryIgnore };
3937
4049
  }
@@ -4002,8 +4114,8 @@ async function withSpinnerProgress(label, fn, formatDone, stream = process.stder
4002
4114
  }
4003
4115
 
4004
4116
  // src/coldstart/collectors/existingRules.ts
4005
- import { existsSync as existsSync28, readFileSync as readFileSync28, readdirSync as readdirSync9 } from "fs";
4006
- 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";
4007
4119
  var MAX_EXCERPT = 3500;
4008
4120
  var RULE_CANDIDATES = [
4009
4121
  "AGENTS.md",
@@ -4011,12 +4123,12 @@ var RULE_CANDIDATES = [
4011
4123
  ".cursorrules"
4012
4124
  ];
4013
4125
  function readExcerpt(repoRoot, rel) {
4014
- const full = join32(repoRoot, rel);
4015
- if (!existsSync28(full)) {
4126
+ const full = join34(repoRoot, rel);
4127
+ if (!existsSync29(full)) {
4016
4128
  return null;
4017
4129
  }
4018
4130
  try {
4019
- const raw = readFileSync28(full, "utf8");
4131
+ const raw = readFileSync29(full, "utf8");
4020
4132
  return raw.length > MAX_EXCERPT ? `${raw.slice(0, MAX_EXCERPT)}
4021
4133
  ...(truncated)` : raw;
4022
4134
  } catch {
@@ -4024,8 +4136,8 @@ function readExcerpt(repoRoot, rel) {
4024
4136
  }
4025
4137
  }
4026
4138
  function collectCursorRules(repoRoot) {
4027
- const dir = join32(repoRoot, ".cursor", "rules");
4028
- if (!existsSync28(dir)) {
4139
+ const dir = join34(repoRoot, ".cursor", "rules");
4140
+ if (!existsSync29(dir)) {
4029
4141
  return [];
4030
4142
  }
4031
4143
  const out = [];
@@ -4076,8 +4188,8 @@ function collectGitLog(repoRoot, limit = 50) {
4076
4188
  }
4077
4189
 
4078
4190
  // src/coldstart/collectors/packageJson.ts
4079
- import { existsSync as existsSync29, readFileSync as readFileSync29 } from "fs";
4080
- import { join as join33 } from "path";
4191
+ import { existsSync as existsSync30, readFileSync as readFileSync30 } from "fs";
4192
+ import { join as join35 } from "path";
4081
4193
  var STACK_HINTS = {
4082
4194
  react: "react",
4083
4195
  vue: "vue",
@@ -4110,12 +4222,12 @@ function inferStackTags(deps) {
4110
4222
  return [...tags];
4111
4223
  }
4112
4224
  function collectPackageJson(repoRoot) {
4113
- const path = join33(repoRoot, "package.json");
4114
- if (!existsSync29(path)) {
4225
+ const path = join35(repoRoot, "package.json");
4226
+ if (!existsSync30(path)) {
4115
4227
  return null;
4116
4228
  }
4117
4229
  try {
4118
- const raw = JSON.parse(readFileSync29(path, "utf8"));
4230
+ const raw = JSON.parse(readFileSync30(path, "utf8"));
4119
4231
  return {
4120
4232
  name: raw.name,
4121
4233
  dependencies: depKeys(raw.dependencies),
@@ -4127,8 +4239,8 @@ function collectPackageJson(repoRoot) {
4127
4239
  }
4128
4240
 
4129
4241
  // src/coldstart/collectors/repoSignals.ts
4130
- import { existsSync as existsSync30, readdirSync as readdirSync10 } from "fs";
4131
- import { join as join34 } from "path";
4242
+ import { existsSync as existsSync31, readdirSync as readdirSync10 } from "fs";
4243
+ import { join as join36 } from "path";
4132
4244
  var SIGNAL_FILES = [
4133
4245
  "Dockerfile",
4134
4246
  "Makefile",
@@ -4140,12 +4252,12 @@ var SIGNAL_FILES = [
4140
4252
  function collectRepoSignals(repoRoot) {
4141
4253
  const signals = [];
4142
4254
  for (const rel of SIGNAL_FILES) {
4143
- const full = join34(repoRoot, rel);
4144
- if (existsSync30(full)) {
4255
+ const full = join36(repoRoot, rel);
4256
+ if (existsSync31(full)) {
4145
4257
  signals.push(rel);
4146
4258
  }
4147
4259
  }
4148
- if (existsSync30(join34(repoRoot, ".gitignore"))) {
4260
+ if (existsSync31(join36(repoRoot, ".gitignore"))) {
4149
4261
  signals.push(".gitignore");
4150
4262
  }
4151
4263
  try {
@@ -4290,7 +4402,7 @@ function runProjectScan(repoRoot) {
4290
4402
 
4291
4403
  // src/init/prompts.ts
4292
4404
  import { checkbox, confirm, input, password } from "@inquirer/prompts";
4293
- import { existsSync as existsSync31, readFileSync as readFileSync30 } from "fs";
4405
+ import { existsSync as existsSync32, readFileSync as readFileSync31 } from "fs";
4294
4406
  import { resolve as resolve6 } from "path";
4295
4407
 
4296
4408
  // src/coldstart/countCaptures.ts
@@ -4301,11 +4413,11 @@ function countExistingCaptures(repoRoot) {
4301
4413
  // src/init/prompts.ts
4302
4414
  function isInitialized(targetDir) {
4303
4415
  const configPath = memoryPath(targetDir, "config.json");
4304
- if (!existsSync31(configPath)) {
4416
+ if (!existsSync32(configPath)) {
4305
4417
  return false;
4306
4418
  }
4307
4419
  try {
4308
- const config = JSON.parse(readFileSync30(configPath, "utf8"));
4420
+ const config = JSON.parse(readFileSync31(configPath, "utf8"));
4309
4421
  return config.version === 1;
4310
4422
  } catch {
4311
4423
  return false;
@@ -4404,7 +4516,7 @@ async function promptLlmFields(defaults = {}, options = {}) {
4404
4516
  }
4405
4517
  async function gatherLlmInitInput(targetDir) {
4406
4518
  const llmPath = memoryPath(targetDir, "llm.json");
4407
- if (existsSync31(llmPath)) {
4519
+ if (existsSync32(llmPath)) {
4408
4520
  const overwrite = await confirm({
4409
4521
  message: "\u68C0\u6D4B\u5230\u5DF2\u6709 .memory/llm.json\uFF0C\u662F\u5426\u8986\u76D6\u5E76\u91CD\u65B0\u914D\u7F6E\uFF1F",
4410
4522
  default: false
@@ -4435,17 +4547,17 @@ async function gatherLlmInitInput(targetDir) {
4435
4547
  }
4436
4548
 
4437
4549
  // src/init/writeScaffoldFile.ts
4438
- import { copyFileSync, writeFileSync as writeFileSync21 } from "fs";
4550
+ import { copyFileSync, writeFileSync as writeFileSync22 } from "fs";
4439
4551
 
4440
4552
  // src/init/mergeConfig.ts
4441
- import { existsSync as existsSync32, readFileSync as readFileSync31 } from "fs";
4553
+ import { existsSync as existsSync33, readFileSync as readFileSync32 } from "fs";
4442
4554
  function mergeConfigForInit(repoRoot, assistants) {
4443
4555
  const configPath = memoryPath(repoRoot, "config.json");
4444
- const existed = existsSync32(configPath);
4556
+ const existed = existsSync33(configPath);
4445
4557
  let existing = {};
4446
4558
  if (existed) {
4447
4559
  try {
4448
- existing = JSON.parse(readFileSync31(configPath, "utf8"));
4560
+ existing = JSON.parse(readFileSync32(configPath, "utf8"));
4449
4561
  } catch {
4450
4562
  existing = {};
4451
4563
  }
@@ -4469,8 +4581,8 @@ function mergeConfigForInit(repoRoot, assistants) {
4469
4581
  }
4470
4582
 
4471
4583
  // src/init/mergeAgentsMd.ts
4472
- import { existsSync as existsSync33, readFileSync as readFileSync32, writeFileSync as writeFileSync18 } from "fs";
4473
- 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";
4474
4586
  var HERMES_AGENTS_START_MARKER = "<!-- >>> hermes-repo agents (do not edit this block manually) -->";
4475
4587
  var HERMES_AGENTS_END_MARKER = "<!-- <<< hermes-repo agents -->";
4476
4588
  function buildHermesAgentsBlockBody() {
@@ -4507,7 +4619,7 @@ function withGapBeforeHermesBlock(prefix) {
4507
4619
  }
4508
4620
  return `${trimmed}${GAP_BEFORE_HERMES_BLOCK}`;
4509
4621
  }
4510
- function spliceHermesBlock(existing, block) {
4622
+ function spliceHermesBlock2(existing, block) {
4511
4623
  const startIdx = existing.indexOf(HERMES_AGENTS_START_MARKER);
4512
4624
  const endIdx = existing.indexOf(HERMES_AGENTS_END_MARKER);
4513
4625
  if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
@@ -4526,32 +4638,32 @@ function spliceHermesBlock(existing, block) {
4526
4638
  `;
4527
4639
  }
4528
4640
  function mergeAgentsMd(repoRoot, force) {
4529
- const agentsPath = join35(repoRoot, "AGENTS.md");
4641
+ const agentsPath = join37(repoRoot, "AGENTS.md");
4530
4642
  const block = buildHermesAgentsMarkedBlock();
4531
- if (!existsSync33(agentsPath)) {
4532
- writeFileSync18(agentsPath, buildNewAgentsMd(), "utf8");
4643
+ if (!existsSync34(agentsPath)) {
4644
+ writeFileSync19(agentsPath, buildNewAgentsMd(), "utf8");
4533
4645
  return "created";
4534
4646
  }
4535
- const content = readFileSync32(agentsPath, "utf8");
4647
+ const content = readFileSync33(agentsPath, "utf8");
4536
4648
  if (agentsMdHasHermesBlock(content)) {
4537
4649
  if (!force) {
4538
4650
  return "skipped";
4539
4651
  }
4540
- writeFileSync18(agentsPath, spliceHermesBlock(content, block), "utf8");
4652
+ writeFileSync19(agentsPath, spliceHermesBlock2(content, block), "utf8");
4541
4653
  return "replaced";
4542
4654
  }
4543
4655
  if (agentsMdHasLegacyHermesContent(content)) {
4544
4656
  return "skipped";
4545
4657
  }
4546
- writeFileSync18(agentsPath, spliceHermesBlock(content, block), "utf8");
4658
+ writeFileSync19(agentsPath, spliceHermesBlock2(content, block), "utf8");
4547
4659
  return "appended";
4548
4660
  }
4549
4661
 
4550
4662
  // src/init/mergeLlmConfig.ts
4551
- import { existsSync as existsSync34, writeFileSync as writeFileSync19 } from "fs";
4663
+ import { existsSync as existsSync35, writeFileSync as writeFileSync20 } from "fs";
4552
4664
  function mergeLlmConfigForInit(repoRoot, input2) {
4553
4665
  const llmPath = memoryPath(repoRoot, "llm.json");
4554
- const existed = existsSync34(llmPath);
4666
+ const existed = existsSync35(llmPath);
4555
4667
  let existing = {};
4556
4668
  if (existed) {
4557
4669
  try {
@@ -4580,14 +4692,14 @@ function mergeLlmConfigForInit(repoRoot, input2) {
4580
4692
  }
4581
4693
  function writeLlmJson(repoRoot, input2) {
4582
4694
  const { content, action } = mergeLlmConfigForInit(repoRoot, input2);
4583
- writeFileSync19(memoryPath(repoRoot, "llm.json"), content, "utf8");
4695
+ writeFileSync20(memoryPath(repoRoot, "llm.json"), content, "utf8");
4584
4696
  return action;
4585
4697
  }
4586
4698
 
4587
4699
  // src/init/scaffoldWrite.ts
4588
- import { existsSync as existsSync35, writeFileSync as writeFileSync20 } from "fs";
4700
+ import { existsSync as existsSync36, writeFileSync as writeFileSync21 } from "fs";
4589
4701
  function shouldWriteFile(absolutePath, force) {
4590
- if (!existsSync35(absolutePath)) {
4702
+ if (!existsSync36(absolutePath)) {
4591
4703
  return { write: true, action: "created" };
4592
4704
  }
4593
4705
  if (force) {
@@ -4601,7 +4713,7 @@ function writeIfAllowed(report, absolutePath, relativePath, content, force) {
4601
4713
  report.files.push({ path: relativePath, action });
4602
4714
  return;
4603
4715
  }
4604
- writeFileSync20(absolutePath, content, "utf8");
4716
+ writeFileSync21(absolutePath, content, "utf8");
4605
4717
  report.files.push({ path: relativePath, action });
4606
4718
  }
4607
4719
 
@@ -4609,7 +4721,7 @@ function writeIfAllowed(report, absolutePath, relativePath, content, force) {
4609
4721
  function writeConfigJson(report, repoRoot, assistants) {
4610
4722
  const { content, action } = mergeConfigForInit(repoRoot, assistants);
4611
4723
  const absolutePath = memoryPath(repoRoot, "config.json");
4612
- writeFileSync21(absolutePath, content, "utf8");
4724
+ writeFileSync22(absolutePath, content, "utf8");
4613
4725
  report.files.push({ path: ".memory/config.json", action });
4614
4726
  }
4615
4727
  function copyTemplateIfAllowed(report, templateName, destAbsolute, relativePath, force) {
@@ -4896,10 +5008,10 @@ async function runInitCommand(opts) {
4896
5008
  }
4897
5009
 
4898
5010
  // src/feedback/writeRef.ts
4899
- import { existsSync as existsSync36, mkdirSync as mkdirSync12, writeFileSync as writeFileSync22 } from "fs";
4900
- 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";
4901
5013
  function targetExists(repoRoot, target) {
4902
- return existsSync36(join36(repoRoot, ".memory", target));
5014
+ return existsSync37(join38(repoRoot, ".memory", target));
4903
5015
  }
4904
5016
  function writeRef(opts) {
4905
5017
  const { repoRoot, reason, session } = opts;
@@ -4921,16 +5033,16 @@ function writeRef(opts) {
4921
5033
  date,
4922
5034
  ...session ? { session } : {}
4923
5035
  };
4924
- mkdirSync12(refsDir(repoRoot), { recursive: true });
5036
+ mkdirSync13(refsDir(repoRoot), { recursive: true });
4925
5037
  const filePath = refFilePath(repoRoot, target, date);
4926
5038
  const base = filePath.replace(/\.json$/, "");
4927
5039
  let finalPath = `${filePath}`;
4928
5040
  let n = 0;
4929
- while (existsSync36(finalPath)) {
5041
+ while (existsSync37(finalPath)) {
4930
5042
  n++;
4931
5043
  finalPath = `${base}-${n}.json`;
4932
5044
  }
4933
- writeFileSync22(finalPath, `${JSON.stringify(record, null, 2)}
5045
+ writeFileSync23(finalPath, `${JSON.stringify(record, null, 2)}
4934
5046
  `, "utf8");
4935
5047
  const file = finalPath.split("/refs/").pop() ?? finalPath;
4936
5048
  return { target, file: `refs/${file}` };
@@ -4970,15 +5082,15 @@ function runRefCommand(opts) {
4970
5082
  }
4971
5083
 
4972
5084
  // src/search/runSearch.ts
4973
- import { existsSync as existsSync37, readdirSync as readdirSync11, readFileSync as readFileSync34 } from "fs";
4974
- 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";
4975
5087
  function walkMdFiles(dir) {
4976
- if (!existsSync37(dir)) {
5088
+ if (!existsSync38(dir)) {
4977
5089
  return [];
4978
5090
  }
4979
5091
  const out = [];
4980
5092
  for (const name of readdirSync11(dir)) {
4981
- const full = join37(dir, name);
5093
+ const full = join39(dir, name);
4982
5094
  if (name.endsWith(".md")) {
4983
5095
  out.push(full);
4984
5096
  } else if (!name.startsWith(".")) {
@@ -4987,7 +5099,7 @@ function walkMdFiles(dir) {
4987
5099
  if (Array.isArray(st)) {
4988
5100
  for (const child of readdirSync11(full)) {
4989
5101
  if (child.endsWith(".md")) {
4990
- out.push(join37(full, child));
5102
+ out.push(join39(full, child));
4991
5103
  }
4992
5104
  }
4993
5105
  }
@@ -4999,13 +5111,13 @@ function walkMdFiles(dir) {
4999
5111
  }
5000
5112
  function listSkillMd(repoRoot) {
5001
5113
  const skillsDir = memoryPath(repoRoot, "skills");
5002
- if (!existsSync37(skillsDir)) {
5114
+ if (!existsSync38(skillsDir)) {
5003
5115
  return [];
5004
5116
  }
5005
5117
  const out = [];
5006
5118
  for (const slug of readdirSync11(skillsDir)) {
5007
- const f = join37(skillsDir, slug, "SKILL.md");
5008
- if (existsSync37(f)) {
5119
+ const f = join39(skillsDir, slug, "SKILL.md");
5120
+ if (existsSync38(f)) {
5009
5121
  out.push(f);
5010
5122
  }
5011
5123
  }
@@ -5013,7 +5125,7 @@ function listSkillMd(repoRoot) {
5013
5125
  }
5014
5126
  function summaryFromFile(absPath, relFromMemory) {
5015
5127
  try {
5016
- const content = readFileSync34(absPath, "utf8");
5128
+ const content = readFileSync35(absPath, "utf8");
5017
5129
  if (relFromMemory.startsWith("captures/")) {
5018
5130
  const parsed = parseCaptureMarkdown(content, relFromMemory, absPath);
5019
5131
  if (parsed) {
@@ -5036,10 +5148,10 @@ function runSearch(opts) {
5036
5148
  const memRoot = memoryPath(opts.repoRoot);
5037
5149
  const captureTypes = opts.type ? [opts.type] : ["semantic", "episodic", "procedural"];
5038
5150
  for (const t of captureTypes) {
5039
- const dir = join37(memRoot, "captures", t);
5151
+ const dir = join39(memRoot, "captures", t);
5040
5152
  for (const abs of walkMdFiles(dir)) {
5041
5153
  const rel = abs.replace(memRoot + "/", "").replace(/\\/g, "/");
5042
- const content = readFileSync34(abs, "utf8").toLowerCase();
5154
+ const content = readFileSync35(abs, "utf8").toLowerCase();
5043
5155
  if (content.includes(kw)) {
5044
5156
  hits.push({
5045
5157
  path: rel,
@@ -5051,10 +5163,10 @@ function runSearch(opts) {
5051
5163
  }
5052
5164
  }
5053
5165
  }
5054
- const topicsDir = join37(memRoot, "topics");
5166
+ const topicsDir = join39(memRoot, "topics");
5055
5167
  for (const abs of walkMdFiles(topicsDir)) {
5056
5168
  const rel = abs.replace(memRoot + "/", "").replace(/\\/g, "/");
5057
- if (readFileSync34(abs, "utf8").toLowerCase().includes(kw)) {
5169
+ if (readFileSync35(abs, "utf8").toLowerCase().includes(kw)) {
5058
5170
  hits.push({ path: rel, summary: summaryFromFile(abs, rel) });
5059
5171
  }
5060
5172
  if (hits.length >= limit) {
@@ -5063,7 +5175,7 @@ function runSearch(opts) {
5063
5175
  }
5064
5176
  for (const abs of listSkillMd(opts.repoRoot)) {
5065
5177
  const rel = abs.replace(memRoot + "/", "").replace(/\\/g, "/");
5066
- if (readFileSync34(abs, "utf8").toLowerCase().includes(kw)) {
5178
+ if (readFileSync35(abs, "utf8").toLowerCase().includes(kw)) {
5067
5179
  hits.push({ path: rel, summary: summaryFromFile(abs, rel) });
5068
5180
  }
5069
5181
  if (hits.length >= limit) {
@@ -5116,7 +5228,7 @@ function runSearchCommand(opts) {
5116
5228
  }
5117
5229
 
5118
5230
  // src/stats/runStats.ts
5119
- import { existsSync as existsSync38, statSync as statSync6 } from "fs";
5231
+ import { existsSync as existsSync39, statSync as statSync6 } from "fs";
5120
5232
  function collectStats(repoRoot, nowMs = Date.now()) {
5121
5233
  const all = listAllCaptures(repoRoot);
5122
5234
  const active = filterActiveCaptures(all);
@@ -5146,7 +5258,7 @@ function collectStats(repoRoot, nowMs = Date.now()) {
5146
5258
  }
5147
5259
  }
5148
5260
  const memoryFile = memoryPath(repoRoot, "MEMORY.md");
5149
- const memoryBytes = existsSync38(memoryFile) ? statSync6(memoryFile).size : 0;
5261
+ const memoryBytes = existsSync39(memoryFile) ? statSync6(memoryFile).size : 0;
5150
5262
  const allSkills = listSkillIndex(repoRoot);
5151
5263
  const skillUsage = readSkillUsage(repoRoot);
5152
5264
  const inMemory = filterSkillIndexForMemory(allSkills, skillUsage, repoRoot, nowMs);
@@ -5213,11 +5325,11 @@ function runStatsCommand(opts) {
5213
5325
  }
5214
5326
 
5215
5327
  // src/promote/runPromote.ts
5216
- 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";
5217
5329
  import { resolve as resolve8 } from "path";
5218
5330
 
5219
5331
  // src/promote/buildTopicDraft.ts
5220
- import { existsSync as existsSync39, readFileSync as readFileSync35 } from "fs";
5332
+ import { existsSync as existsSync40, readFileSync as readFileSync36 } from "fs";
5221
5333
  function ruleTopicDraftBody(tag, captures, existing) {
5222
5334
  const lines = captures.map(
5223
5335
  (c) => `- [${c.date}] [${c.type}] ${c.summary.slice(0, 120)} (${c.path}) [\u664B\u5347\u5019\u9009]`
@@ -5244,9 +5356,9 @@ async function buildTopicDraftBody(repoRoot, captures, llm) {
5244
5356
  const slug = tagToSlug(tag);
5245
5357
  const abs = memoryPath(repoRoot, "topics", `${slug}.md`);
5246
5358
  let existing = "";
5247
- if (existsSync39(abs)) {
5359
+ if (existsSync40(abs)) {
5248
5360
  try {
5249
- existing = readFileSync35(abs, "utf8");
5361
+ existing = readFileSync36(abs, "utf8");
5250
5362
  } catch {
5251
5363
  existing = "";
5252
5364
  }
@@ -5271,7 +5383,7 @@ ${c.findings.slice(0, 300)}`
5271
5383
  }
5272
5384
 
5273
5385
  // src/promote/detectTopicConflict.ts
5274
- import { existsSync as existsSync40, readFileSync as readFileSync36 } from "fs";
5386
+ import { existsSync as existsSync41, readFileSync as readFileSync37 } from "fs";
5275
5387
  var MUTEX_PAIRS2 = [
5276
5388
  ["localstorage", "httponly"],
5277
5389
  ["local storage", "httponly"],
@@ -5301,12 +5413,12 @@ function detectTopicConflict(repoRoot, capture) {
5301
5413
  const slug = tagToSlug(tag);
5302
5414
  const topicPath = memoryPath(repoRoot, "topics", `${slug}.md`);
5303
5415
  const relTopic = `topics/${slug}.md`;
5304
- if (!existsSync40(topicPath)) {
5416
+ if (!existsSync41(topicPath)) {
5305
5417
  return { hasConflict: false, reason: "none" };
5306
5418
  }
5307
5419
  let existing = "";
5308
5420
  try {
5309
- existing = readFileSync36(topicPath, "utf8");
5421
+ existing = readFileSync37(topicPath, "utf8");
5310
5422
  } catch {
5311
5423
  return { hasConflict: false, reason: "none" };
5312
5424
  }
@@ -5472,17 +5584,17 @@ async function buildMergedStagingDrafts(repoRoot, analyses, llm) {
5472
5584
 
5473
5585
  // src/promote/applyDecisions.ts
5474
5586
  import {
5475
- existsSync as existsSync41,
5476
- mkdirSync as mkdirSync13,
5587
+ existsSync as existsSync42,
5588
+ mkdirSync as mkdirSync14,
5477
5589
  readdirSync as readdirSync12,
5478
- readFileSync as readFileSync37,
5590
+ readFileSync as readFileSync38,
5479
5591
  unlinkSync as unlinkSync3,
5480
- writeFileSync as writeFileSync23
5592
+ writeFileSync as writeFileSync24
5481
5593
  } from "fs";
5482
- import { join as join39 } from "path";
5594
+ import { join as join41 } from "path";
5483
5595
 
5484
5596
  // src/promote/paths.ts
5485
- import { join as join38 } from "path";
5597
+ import { join as join40 } from "path";
5486
5598
  function promoteDir(repoRoot) {
5487
5599
  return memoryPath(repoRoot, "promote");
5488
5600
  }
@@ -5500,7 +5612,7 @@ function resolvePromoteTemplatePath(repoRoot) {
5500
5612
  return inMemory;
5501
5613
  }
5502
5614
  function stagingTopicPath(repoRoot, slug) {
5503
- return join38(promoteStagingTopicsDir(repoRoot), `${slug}.md`);
5615
+ return join40(promoteStagingTopicsDir(repoRoot), `${slug}.md`);
5504
5616
  }
5505
5617
 
5506
5618
  // src/promote/applyDecisions.ts
@@ -5536,17 +5648,17 @@ function buildManifestTemplate(capturePaths, dateIso) {
5536
5648
  }
5537
5649
  function removePromoteMarker(repoRoot, capturePath) {
5538
5650
  const marker = promoteMarkerPath(repoRoot, capturePath);
5539
- if (existsSync41(marker)) {
5651
+ if (existsSync42(marker)) {
5540
5652
  unlinkSync3(marker);
5541
5653
  }
5542
5654
  }
5543
5655
  function annotateReject(repoRoot, capturePath, note) {
5544
- const abs = join39(repoRoot, ".memory", capturePath);
5545
- if (!existsSync41(abs)) {
5656
+ const abs = join41(repoRoot, ".memory", capturePath);
5657
+ if (!existsSync42(abs)) {
5546
5658
  return;
5547
5659
  }
5548
5660
  try {
5549
- let content = readFileSync37(abs, "utf8");
5661
+ let content = readFileSync38(abs, "utf8");
5550
5662
  const fields = {
5551
5663
  promote_rejected_at: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
5552
5664
  };
@@ -5554,22 +5666,22 @@ function annotateReject(repoRoot, capturePath, note) {
5554
5666
  fields.promote_note = note.trim().slice(0, 200);
5555
5667
  }
5556
5668
  content = setFrontmatterScalars(content, fields);
5557
- writeFileSync23(abs, content, "utf8");
5669
+ writeFileSync24(abs, content, "utf8");
5558
5670
  } catch {
5559
5671
  }
5560
5672
  }
5561
5673
  function mergeTopicFromStaging(repoRoot, slug, dryRun) {
5562
5674
  const staging = stagingTopicPath(repoRoot, slug);
5563
- if (!existsSync41(staging)) {
5675
+ if (!existsSync42(staging)) {
5564
5676
  return null;
5565
5677
  }
5566
- const draft = readFileSync37(staging, "utf8");
5678
+ const draft = readFileSync38(staging, "utf8");
5567
5679
  const dest = memoryPath(repoRoot, "topics", `${slug}.md`);
5568
5680
  if (dryRun) {
5569
5681
  return `topics/${slug}.md`;
5570
5682
  }
5571
- mkdirSync13(memoryPath(repoRoot, "topics"), { recursive: true });
5572
- writeFileSync23(dest, draft.endsWith("\n") ? draft : `${draft}
5683
+ mkdirSync14(memoryPath(repoRoot, "topics"), { recursive: true });
5684
+ writeFileSync24(dest, draft.endsWith("\n") ? draft : `${draft}
5573
5685
  `, "utf8");
5574
5686
  return `topics/${slug}.md`;
5575
5687
  }
@@ -5605,7 +5717,7 @@ function applyDecisions(repoRoot, manifest, opts) {
5605
5717
  }
5606
5718
  if (slugsToMerge.size === 0 && result.approved.length > 0) {
5607
5719
  const stagingDir = promoteStagingTopicsDir(repoRoot);
5608
- if (existsSync41(stagingDir)) {
5720
+ if (existsSync42(stagingDir)) {
5609
5721
  for (const name of readdirSync12(stagingDir)) {
5610
5722
  if (name.endsWith(".md")) {
5611
5723
  slugsToMerge.add(name.replace(/\.md$/, ""));
@@ -5622,21 +5734,21 @@ function applyDecisions(repoRoot, manifest, opts) {
5622
5734
  return result;
5623
5735
  }
5624
5736
  function readManifestFile(manifestPath) {
5625
- const raw = readFileSync37(manifestPath, "utf8");
5737
+ const raw = readFileSync38(manifestPath, "utf8");
5626
5738
  return parseManifestJson(raw);
5627
5739
  }
5628
5740
  function writeManifestTemplate(repoRoot, capturePaths) {
5629
5741
  const dateIso = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5630
5742
  const manifest = buildManifestTemplate(capturePaths, dateIso);
5631
5743
  const path = decisionsTemplatePath(repoRoot);
5632
- mkdirSync13(memoryPath(repoRoot, "promote"), { recursive: true });
5633
- writeFileSync23(path, `${JSON.stringify(manifest, null, 2)}
5744
+ mkdirSync14(memoryPath(repoRoot, "promote"), { recursive: true });
5745
+ writeFileSync24(path, `${JSON.stringify(manifest, null, 2)}
5634
5746
  `, "utf8");
5635
5747
  return path;
5636
5748
  }
5637
5749
 
5638
5750
  // src/promote/buildPrBody.ts
5639
- import { existsSync as existsSync42, readFileSync as readFileSync38 } from "fs";
5751
+ import { existsSync as existsSync43, readFileSync as readFileSync39 } from "fs";
5640
5752
  function actionLabel(action) {
5641
5753
  if (action === "approve") {
5642
5754
  return "\u6279\u51C6\u664B\u5347";
@@ -5676,9 +5788,9 @@ ${conflictLine}
5676
5788
  }
5677
5789
  function loadTemplate(repoRoot) {
5678
5790
  const path = resolvePromoteTemplatePath(repoRoot);
5679
- if (existsSync42(path)) {
5791
+ if (existsSync43(path)) {
5680
5792
  try {
5681
- return readFileSync38(path, "utf8");
5793
+ return readFileSync39(path, "utf8");
5682
5794
  } catch {
5683
5795
  }
5684
5796
  }
@@ -5726,7 +5838,7 @@ ${items}
5726
5838
  }
5727
5839
 
5728
5840
  // src/promote/listPromoteCandidates.ts
5729
- import { existsSync as existsSync43, readdirSync as readdirSync13 } from "fs";
5841
+ import { existsSync as existsSync44, readdirSync as readdirSync13 } from "fs";
5730
5842
  var TYPES2 = ["semantic", "episodic", "procedural"];
5731
5843
  function normalizeCapturePath(input2) {
5732
5844
  let p = input2.replace(/\\/g, "/").trim();
@@ -5743,7 +5855,7 @@ function listPromoteCandidates(repoRoot, filterPaths) {
5743
5855
  const results = [];
5744
5856
  for (const type of TYPES2) {
5745
5857
  const dir = memoryPath(repoRoot, "captures", type);
5746
- if (!existsSync43(dir)) {
5858
+ if (!existsSync44(dir)) {
5747
5859
  continue;
5748
5860
  }
5749
5861
  for (const name of readdirSync13(dir)) {
@@ -5770,8 +5882,8 @@ function listPromoteCandidates(repoRoot, filterPaths) {
5770
5882
 
5771
5883
  // src/promote/runPromote.ts
5772
5884
  function ensurePromoteDirs(repoRoot) {
5773
- mkdirSync14(promoteDir(repoRoot), { recursive: true });
5774
- mkdirSync14(promoteStagingTopicsDir(repoRoot), { recursive: true });
5885
+ mkdirSync15(promoteDir(repoRoot), { recursive: true });
5886
+ mkdirSync15(promoteStagingTopicsDir(repoRoot), { recursive: true });
5775
5887
  }
5776
5888
  function formatPreviewTable(analyses) {
5777
5889
  const lines = [
@@ -5815,15 +5927,15 @@ async function runPromote(opts) {
5815
5927
  const stagingTopicPaths = [];
5816
5928
  for (const [slug, body] of mergedDrafts) {
5817
5929
  const path = stagingTopicPath(repoRoot, slug);
5818
- writeFileSync24(path, body, "utf8");
5930
+ writeFileSync25(path, body, "utf8");
5819
5931
  stagingTopicPaths.push(
5820
5932
  `.memory/promote/staging/topics/${slug}.md`
5821
5933
  );
5822
5934
  }
5823
5935
  const prBody = buildPrBody(repoRoot, analyses);
5824
5936
  const prBodyPath = opts.outPath ? resolve8(opts.outPath) : defaultPrBodyPath(repoRoot, dateIso);
5825
- mkdirSync14(memoryPath(repoRoot, "promote"), { recursive: true });
5826
- writeFileSync24(prBodyPath, prBody, "utf8");
5937
+ mkdirSync15(memoryPath(repoRoot, "promote"), { recursive: true });
5938
+ writeFileSync25(prBodyPath, prBody, "utf8");
5827
5939
  const manifestTemplatePath = writeManifestTemplate(
5828
5940
  repoRoot,
5829
5941
  candidates.map((c) => c.path)