@riconext/hermes-repo 1.2.4 → 1.2.5

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
@@ -5,7 +5,7 @@ import { Command } from "commander";
5
5
 
6
6
  // src/config/debugLog.ts
7
7
  import { appendFileSync, mkdirSync } from "fs";
8
- import { dirname } from "path";
8
+ import { join as join2 } from "path";
9
9
 
10
10
  // src/init/paths.ts
11
11
  import { join } from "path";
@@ -34,33 +34,52 @@ function memoryPath(root, ...segments) {
34
34
  }
35
35
 
36
36
  // src/config/debugLog.ts
37
- var DEBUG_LOG_FILE = "hermes-debug.log";
38
- var logFilePath = null;
37
+ var DEBUG_LOG_DIR = "logs";
38
+ var DEBUG_LOG_FILES = {
39
+ capture: "capture.log",
40
+ flush: "flush.log",
41
+ consolidate: "consolidate.log"
42
+ };
43
+ var logDirPath = null;
39
44
  function configureDebugLogging(repoRoot, enabled) {
40
45
  if (!enabled || !repoRoot) {
41
- logFilePath = null;
46
+ logDirPath = null;
42
47
  return;
43
48
  }
44
- logFilePath = memoryPath(repoRoot, DEBUG_LOG_FILE);
49
+ logDirPath = memoryPath(repoRoot, DEBUG_LOG_DIR);
45
50
  }
46
51
  function formatLine(phase, message) {
47
52
  return `${(/* @__PURE__ */ new Date()).toISOString()} hermes-repo [${phase}] ${message}`;
48
53
  }
49
- function writeToLogFile(line) {
50
- if (!logFilePath) {
54
+ function writeToLogFile(phase, line) {
55
+ if (!logDirPath) {
51
56
  return;
52
57
  }
53
- mkdirSync(dirname(logFilePath), { recursive: true });
54
- appendFileSync(logFilePath, `${line}
58
+ mkdirSync(logDirPath, { recursive: true });
59
+ appendFileSync(join2(logDirPath, logFileNameForPhase(phase)), `${line}
55
60
  `, "utf8");
56
61
  }
62
+ function logFileNameForPhase(phase) {
63
+ switch (phase) {
64
+ case "capture":
65
+ case "capture-llm":
66
+ return DEBUG_LOG_FILES.capture;
67
+ case "flush":
68
+ return DEBUG_LOG_FILES.flush;
69
+ case "consolidate":
70
+ case "llm":
71
+ return DEBUG_LOG_FILES.consolidate;
72
+ default:
73
+ return `${phase.replace(/[^a-z0-9_-]/gi, "-") || "debug"}.log`;
74
+ }
75
+ }
57
76
  function debugLog(enabled, phase, message) {
58
77
  if (!enabled) {
59
78
  return;
60
79
  }
61
80
  const line = formatLine(phase, message);
62
81
  console.error(line);
63
- writeToLogFile(line);
82
+ writeToLogFile(phase, line);
64
83
  }
65
84
  function debugLogBlock(enabled, phase, label, content) {
66
85
  if (!enabled) {
@@ -78,19 +97,19 @@ function debugFromContext(ctx, phase, message) {
78
97
 
79
98
  // src/config/readConfig.ts
80
99
  import { readFileSync } from "fs";
81
- import { join as join3 } from "path";
100
+ import { join as join4 } from "path";
82
101
 
83
102
  // src/config/findRepoRoot.ts
84
103
  import { existsSync } from "fs";
85
- import { dirname as dirname2, join as join2, resolve } from "path";
86
- var CONFIG_REL = join2(".memory", "config.json");
104
+ import { dirname, join as join3, resolve } from "path";
105
+ var CONFIG_REL = join3(".memory", "config.json");
87
106
  function findRepoRoot(startDir) {
88
107
  let dir = resolve(startDir ?? process.cwd());
89
108
  while (true) {
90
- if (existsSync(join2(dir, CONFIG_REL))) {
109
+ if (existsSync(join3(dir, CONFIG_REL))) {
91
110
  return dir;
92
111
  }
93
- const parent = dirname2(dir);
112
+ const parent = dirname(dir);
94
113
  if (parent === dir) {
95
114
  return null;
96
115
  }
@@ -129,7 +148,7 @@ function parseConsolidateConfig(raw) {
129
148
  };
130
149
  }
131
150
  function readConfigAtRepo(repoRoot) {
132
- const configPath = join3(repoRoot, ".memory", "config.json");
151
+ const configPath = join4(repoRoot, ".memory", "config.json");
133
152
  try {
134
153
  const raw = JSON.parse(readFileSync(configPath, "utf8"));
135
154
  const version = raw.version;
@@ -192,7 +211,7 @@ function loadRepoContext(cwd) {
192
211
 
193
212
  // src/capture/runLlmJob.ts
194
213
  import { existsSync as existsSync4, readFileSync as readFileSync5, renameSync, writeFileSync as writeFileSync3 } from "fs";
195
- import { join as join6 } from "path";
214
+ import { join as join7 } from "path";
196
215
 
197
216
  // src/config/llmConfig.ts
198
217
  function isLlmAvailable(cfg) {
@@ -359,13 +378,13 @@ import {
359
378
  rmSync,
360
379
  writeFileSync
361
380
  } from "fs";
362
- import { dirname as dirname3, join as join4 } from "path";
381
+ import { dirname as dirname2, join as join5 } from "path";
363
382
  import { fileURLToPath } from "url";
364
383
  function pendingDir(repoRoot) {
365
384
  return memoryPath(repoRoot, "captures", "pending");
366
385
  }
367
386
  function cliPath() {
368
- return join4(dirname3(fileURLToPath(import.meta.url)), "..", "cli.js");
387
+ return join5(dirname2(fileURLToPath(import.meta.url)), "..", "cli.js");
369
388
  }
370
389
  function makeJobId(sessionId) {
371
390
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 32);
@@ -382,10 +401,10 @@ function removeStaleJobsForSession(repoRoot, sessionId) {
382
401
  }
383
402
  try {
384
403
  const raw = JSON.parse(
385
- readFileSync3(join4(dir, name), "utf8")
404
+ readFileSync3(join5(dir, name), "utf8")
386
405
  );
387
406
  if (raw.sessionId === sessionId) {
388
- rmSync(join4(dir, name), { force: true });
407
+ rmSync(join5(dir, name), { force: true });
389
408
  }
390
409
  } catch {
391
410
  }
@@ -406,7 +425,7 @@ function enqueueLlmJob(opts) {
406
425
  enqueuedAt: (/* @__PURE__ */ new Date()).toISOString()
407
426
  };
408
427
  writeFileSync(
409
- join4(dir, `${jobId}.json`),
428
+ join5(dir, `${jobId}.json`),
410
429
  `${JSON.stringify(payload, null, 2)}
411
430
  `,
412
431
  "utf8"
@@ -425,7 +444,7 @@ function enqueueLlmJob(opts) {
425
444
  return true;
426
445
  }
427
446
  function readLlmJob(repoRoot, jobId) {
428
- const path = join4(pendingDir(repoRoot), `${jobId}.json`);
447
+ const path = join5(pendingDir(repoRoot), `${jobId}.json`);
429
448
  if (!existsSync2(path)) {
430
449
  return null;
431
450
  }
@@ -436,7 +455,7 @@ function readLlmJob(repoRoot, jobId) {
436
455
  }
437
456
  }
438
457
  function deleteLlmJob(repoRoot, jobId) {
439
- const path = join4(pendingDir(repoRoot), `${jobId}.json`);
458
+ const path = join5(pendingDir(repoRoot), `${jobId}.json`);
440
459
  if (existsSync2(path)) {
441
460
  rmSync(path, { force: true });
442
461
  }
@@ -453,7 +472,7 @@ function listPendingJobs(repoRoot) {
453
472
  }
454
473
  try {
455
474
  jobs.push(
456
- JSON.parse(readFileSync3(join4(dir, name), "utf8"))
475
+ JSON.parse(readFileSync3(join5(dir, name), "utf8"))
457
476
  );
458
477
  } catch {
459
478
  }
@@ -684,7 +703,7 @@ async function llmFormat(session, assistant, llm) {
684
703
 
685
704
  // src/capture/writeCapture.ts
686
705
  import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
687
- import { join as join5 } from "path";
706
+ import { join as join6 } from "path";
688
707
  function isoNow() {
689
708
  return (/* @__PURE__ */ new Date()).toISOString();
690
709
  }
@@ -735,7 +754,7 @@ function renderCaptureSection(formatted, index) {
735
754
  function resolveSessionFile(repoRoot, sessionId) {
736
755
  const filename = `session-${sessionId}.md`;
737
756
  const absolutePath = memoryPath(repoRoot, "captures", "raw", filename);
738
- const relativePath = join5(".memory", "captures", "raw", filename);
757
+ const relativePath = join6(".memory", "captures", "raw", filename);
739
758
  return { absolutePath, relativePath, exists: existsSync3(absolutePath) };
740
759
  }
741
760
  function renderCaptureMarkdown(formatted, date) {
@@ -759,7 +778,7 @@ function renderCaptureMarkdown(formatted, date) {
759
778
  function appendCaptureToSession(repoRoot, formatted) {
760
779
  const { absolutePath, relativePath, exists } = resolveSessionFile(repoRoot, formatted.sessionId);
761
780
  const filename = `session-${formatted.sessionId}.md`;
762
- mkdirSync3(join5(absolutePath, ".."), { recursive: true });
781
+ mkdirSync3(join6(absolutePath, ".."), { recursive: true });
763
782
  const now = isoNow();
764
783
  if (!exists) {
765
784
  const fm = {
@@ -856,7 +875,7 @@ function markSessionConsolidated(repoRoot, sessionId) {
856
875
 
857
876
  // src/capture/runLlmJob.ts
858
877
  function captureAlreadyUpgraded(repoRoot, captureFile) {
859
- const path = join6(repoRoot, captureFile);
878
+ const path = join7(repoRoot, captureFile);
860
879
  if (!existsSync4(path)) {
861
880
  return false;
862
881
  }
@@ -881,7 +900,7 @@ async function runLlmJob(repoRoot, job, debug) {
881
900
  debugLog(debug === true, "capture-llm", `llm job failed: ${job.jobId}`);
882
901
  return { ok: false, reason: "llm format failed" };
883
902
  }
884
- const target = join6(repoRoot, job.captureFile);
903
+ const target = join7(repoRoot, job.captureFile);
885
904
  const temp = `${target}.hermes-tmp`;
886
905
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
887
906
  writeFileSync3(temp, renderCaptureMarkdown(upgraded, date), "utf8");
@@ -1127,7 +1146,7 @@ function needsLlm(session) {
1127
1146
 
1128
1147
  // src/consolidate/scheduleConsolidate.ts
1129
1148
  import { spawn as spawn2 } from "child_process";
1130
- import { dirname as dirname5, join as join11 } from "path";
1149
+ import { dirname as dirname4, join as join12 } from "path";
1131
1150
  import { fileURLToPath as fileURLToPath2 } from "url";
1132
1151
 
1133
1152
  // src/consolidate/state.ts
@@ -1222,7 +1241,7 @@ function isLockStale(lock, ttlMs) {
1222
1241
 
1223
1242
  // src/consolidate/sessionScanner.ts
1224
1243
  import { readdirSync as readdirSync2, readFileSync as readFileSync8 } from "fs";
1225
- import { join as join7 } from "path";
1244
+ import { join as join8 } from "path";
1226
1245
  function parseSessionFrontmatter(content) {
1227
1246
  const match = content.match(/^---\n([\s\S]*?)\n---/);
1228
1247
  if (!match) return null;
@@ -1250,7 +1269,7 @@ function scanAllSessions(repoRoot) {
1250
1269
  }
1251
1270
  const sessions = [];
1252
1271
  for (const file of files) {
1253
- const absolutePath = join7(rawDir, file);
1272
+ const absolutePath = join8(rawDir, file);
1254
1273
  try {
1255
1274
  const content = readFileSync8(absolutePath, "utf8");
1256
1275
  const fm = parseSessionFrontmatter(content);
@@ -1262,7 +1281,7 @@ function scanAllSessions(repoRoot) {
1262
1281
  sessionId: fm.sessionId,
1263
1282
  filename: file,
1264
1283
  absolutePath,
1265
- relativePath: join7(".memory", "captures", "raw", file),
1284
+ relativePath: join8(".memory", "captures", "raw", file),
1266
1285
  frontmatter: fm,
1267
1286
  bodyContent: bodyContent.trim()
1268
1287
  });
@@ -1282,7 +1301,7 @@ function filterPendingSessions(sessions) {
1282
1301
 
1283
1302
  // src/consolidate/llmConsolidateV2.ts
1284
1303
  import { readFileSync as readFileSync9, readdirSync as readdirSync3 } from "fs";
1285
- import { join as join8 } from "path";
1304
+ import { join as join9 } from "path";
1286
1305
  var CONSOLIDATE_SYSTEM_PROMPT = `\u4F60\u662F\u4E00\u4E2A\u9879\u76EE\u77E5\u8BC6\u6574\u7406\u4E13\u5BB6\u3002\u4F60\u7684\u4EFB\u52A1\u662F\u4ECE AI \u7F16\u7A0B\u52A9\u624B\u7684\u5BF9\u8BDD\u8BB0\u5F55\u4E2D\u63D0\u70BC\u51FA\u7ED3\u6784\u5316\u7684\u77E5\u8BC6\u5E93\u3002
1287
1306
 
1288
1307
  ## \u5DE5\u4F5C\u6D41\u7A0B
@@ -1372,7 +1391,7 @@ function scanExistingKnowledge(repoRoot) {
1372
1391
  try {
1373
1392
  const subdirs = readdirSync3(domainsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1374
1393
  for (const domain of subdirs) {
1375
- const domainAbsDir = join8(domainsDir, domain);
1394
+ const domainAbsDir = join9(domainsDir, domain);
1376
1395
  scanMarkdownDirectory(
1377
1396
  domainAbsDir,
1378
1397
  `domains/${domain}`,
@@ -1394,7 +1413,7 @@ function scanMarkdownDirectory(absoluteDir, relativePrefix, type, domain, result
1394
1413
  }
1395
1414
  for (const file of files) {
1396
1415
  try {
1397
- const content = readFileSync9(join8(absoluteDir, file), "utf8");
1416
+ const content = readFileSync9(join9(absoluteDir, file), "utf8");
1398
1417
  const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
1399
1418
  let title = file.replace(/\.md$/, "");
1400
1419
  if (fmMatch) {
@@ -1625,7 +1644,7 @@ function isSkippedEntry(raw) {
1625
1644
 
1626
1645
  // src/consolidate/writeKnowledge.ts
1627
1646
  import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
1628
- import { dirname as dirname4 } from "path";
1647
+ import { dirname as dirname3 } from "path";
1629
1648
  var KNOWLEDGE_LINK_PREFIXES = [
1630
1649
  "rules/",
1631
1650
  "domains/",
@@ -1642,7 +1661,7 @@ function writeKnowledgeFiles(repoRoot, files) {
1642
1661
  for (const kf of files) {
1643
1662
  try {
1644
1663
  const absolutePath = memoryPath(repoRoot, kf.targetPath);
1645
- const dir = dirname4(absolutePath);
1664
+ const dir = dirname3(absolutePath);
1646
1665
  mkdirSync5(dir, { recursive: true });
1647
1666
  const content = serializeKnowledgeFile(kf.frontmatter, kf.body);
1648
1667
  const alreadyExists = existsSync7(absolutePath);
@@ -1770,7 +1789,7 @@ ${endMarker}` + result.slice(endIdx + endMarker.length);
1770
1789
 
1771
1790
  // src/consolidate/archive.ts
1772
1791
  import { mkdirSync as mkdirSync6, renameSync as renameSync2 } from "fs";
1773
- import { join as join10 } from "path";
1792
+ import { join as join11 } from "path";
1774
1793
  function archiveDoneSessions(repoRoot, sessions, autoArchiveDays = 30) {
1775
1794
  const archivedDir = memoryPath(repoRoot, "captures", "archived");
1776
1795
  const cutoffMs = Date.now() - autoArchiveDays * 24 * 60 * 60 * 1e3;
@@ -1783,7 +1802,7 @@ function archiveDoneSessions(repoRoot, sessions, autoArchiveDays = 30) {
1783
1802
  if (consolidatedTime > cutoffMs) continue;
1784
1803
  try {
1785
1804
  mkdirSync6(archivedDir, { recursive: true });
1786
- renameSync2(s.absolutePath, join10(archivedDir, s.filename));
1805
+ renameSync2(s.absolutePath, join11(archivedDir, s.filename));
1787
1806
  archivedCount++;
1788
1807
  } catch {
1789
1808
  }
@@ -1965,7 +1984,7 @@ var CONSOLIDATE_LOCK_TTL_MS = 30 * 60 * 1e3;
1965
1984
 
1966
1985
  // src/consolidate/scheduleConsolidate.ts
1967
1986
  function cliPath2() {
1968
- return join11(dirname5(fileURLToPath2(import.meta.url)), "..", "cli.js");
1987
+ return join12(dirname4(fileURLToPath2(import.meta.url)), "..", "cli.js");
1969
1988
  }
1970
1989
  async function runFlushCommand(opts) {
1971
1990
  const ctx = loadRepoContext(opts.cwd);
@@ -2150,7 +2169,7 @@ async function commitCapture(opts) {
2150
2169
  // src/capture/claude-code/resolveSession.ts
2151
2170
  import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync } from "fs";
2152
2171
  import { homedir } from "os";
2153
- import { basename as basename2, join as join12, resolve as resolve3 } from "path";
2172
+ import { basename as basename2, join as join13, resolve as resolve3 } from "path";
2154
2173
  function encodeClaudeProjectDir(absPath) {
2155
2174
  return resolve3(absPath).replace(/\//g, "-");
2156
2175
  }
@@ -2164,20 +2183,20 @@ function resolveSessionJsonlPath(repoRoot, options = {}) {
2164
2183
  return resolve3(fromHook);
2165
2184
  }
2166
2185
  const sessionId = process.env.CLAUDE_SESSION_ID ?? process.env.CLAUDE_CODE_SESSION_ID ?? process.env.SESSION_ID;
2167
- const claudeHome = process.env.CLAUDE_CONFIG_DIR ? resolve3(process.env.CLAUDE_CONFIG_DIR) : join12(homedir(), ".claude");
2168
- const projectsRoot = join12(claudeHome, "projects");
2186
+ const claudeHome = process.env.CLAUDE_CONFIG_DIR ? resolve3(process.env.CLAUDE_CONFIG_DIR) : join13(homedir(), ".claude");
2187
+ const projectsRoot = join13(claudeHome, "projects");
2169
2188
  if (!existsSync9(projectsRoot)) {
2170
2189
  return null;
2171
2190
  }
2172
2191
  const cwd = resolve3(options.cwd ?? repoRoot);
2173
2192
  const preferredProjectDir = encodeClaudeProjectDir(cwd);
2174
- const preferredPath = join12(projectsRoot, preferredProjectDir);
2193
+ const preferredPath = join13(projectsRoot, preferredProjectDir);
2175
2194
  if (existsSync9(preferredPath)) {
2176
2195
  const hit = pickNewestJsonl(preferredPath, sessionId);
2177
2196
  if (hit) {
2178
2197
  return hit;
2179
2198
  }
2180
- const legacySessions = join12(preferredPath, "sessions");
2199
+ const legacySessions = join13(preferredPath, "sessions");
2181
2200
  if (existsSync9(legacySessions)) {
2182
2201
  const legacyHit = pickNewestJsonl(legacySessions, sessionId);
2183
2202
  if (legacyHit) {
@@ -2188,9 +2207,9 @@ function resolveSessionJsonlPath(repoRoot, options = {}) {
2188
2207
  const candidates = [];
2189
2208
  for (const projectDir of readdirSync4(projectsRoot, { withFileTypes: true })) {
2190
2209
  if (!projectDir.isDirectory()) continue;
2191
- const projectPath = join12(projectsRoot, projectDir.name);
2210
+ const projectPath = join13(projectsRoot, projectDir.name);
2192
2211
  collectJsonlCandidates(projectPath, sessionId, candidates);
2193
- const legacySessions = join12(projectPath, "sessions");
2212
+ const legacySessions = join13(projectPath, "sessions");
2194
2213
  if (existsSync9(legacySessions)) {
2195
2214
  collectJsonlCandidates(legacySessions, sessionId, candidates);
2196
2215
  }
@@ -2218,7 +2237,7 @@ function collectJsonlCandidates(dir, sessionId, out) {
2218
2237
  if (!entry.isFile() || !entry.name.endsWith(".jsonl")) {
2219
2238
  continue;
2220
2239
  }
2221
- const fullPath = join12(dir, entry.name);
2240
+ const fullPath = join13(dir, entry.name);
2222
2241
  if (sessionId && !entry.name.includes(sessionId) && basename2(entry.name, ".jsonl") !== sessionId) {
2223
2242
  continue;
2224
2243
  }
@@ -2253,7 +2272,7 @@ async function runClaudeCodeCapture(repoRoot, cwd, dryRun, options) {
2253
2272
  // src/capture/codebuddy/resolveSession.ts
2254
2273
  import { existsSync as existsSync10, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
2255
2274
  import { homedir as homedir2 } from "os";
2256
- import { basename as basename3, join as join13, resolve as resolve4 } from "path";
2275
+ import { basename as basename3, join as join14, resolve as resolve4 } from "path";
2257
2276
  function encodeCodebuddyProjectDir(absPath) {
2258
2277
  return resolve4(absPath).replace(/^\//, "").replace(/\//g, "-");
2259
2278
  }
@@ -2267,14 +2286,14 @@ function resolveCodebuddySessionJsonl(options) {
2267
2286
  return resolve4(fromHook);
2268
2287
  }
2269
2288
  const sessionId = process.env.CODEBUDDY_SESSION_ID ?? process.env.SESSION_ID;
2270
- const codebuddyHome = process.env.CODEBUDDY_CONFIG_DIR ? resolve4(process.env.CODEBUDDY_CONFIG_DIR) : join13(homedir2(), ".codebuddy");
2271
- const projectsRoot = join13(codebuddyHome, "projects");
2289
+ const codebuddyHome = process.env.CODEBUDDY_CONFIG_DIR ? resolve4(process.env.CODEBUDDY_CONFIG_DIR) : join14(homedir2(), ".codebuddy");
2290
+ const projectsRoot = join14(codebuddyHome, "projects");
2272
2291
  if (!existsSync10(projectsRoot)) {
2273
2292
  return null;
2274
2293
  }
2275
2294
  const cwd = resolve4(options.cwd ?? options.repoRoot);
2276
2295
  const preferredProjectDir = encodeCodebuddyProjectDir(cwd);
2277
- const preferredPath = join13(projectsRoot, preferredProjectDir);
2296
+ const preferredPath = join14(projectsRoot, preferredProjectDir);
2278
2297
  if (existsSync10(preferredPath)) {
2279
2298
  const hit = pickNewestJsonlRecursive(preferredPath, sessionId);
2280
2299
  if (hit) {
@@ -2286,7 +2305,7 @@ function resolveCodebuddySessionJsonl(options) {
2286
2305
  if (!projectDir.isDirectory()) {
2287
2306
  continue;
2288
2307
  }
2289
- collectJsonlRecursive(join13(projectsRoot, projectDir.name), sessionId, candidates);
2308
+ collectJsonlRecursive(join14(projectsRoot, projectDir.name), sessionId, candidates);
2290
2309
  }
2291
2310
  if (candidates.length === 0) {
2292
2311
  return null;
@@ -2308,7 +2327,7 @@ function collectJsonlRecursive(dir, sessionId, out) {
2308
2327
  return;
2309
2328
  }
2310
2329
  for (const entry of readdirSync5(dir, { withFileTypes: true })) {
2311
- const full = join13(dir, entry.name);
2330
+ const full = join14(dir, entry.name);
2312
2331
  if (entry.isDirectory()) {
2313
2332
  collectJsonlRecursive(full, sessionId, out);
2314
2333
  continue;
@@ -2358,7 +2377,7 @@ async function runCodebuddyCapture(repoRoot, cwd, dryRun, options) {
2358
2377
  // src/capture/cursor/resolveSession.ts
2359
2378
  import { existsSync as existsSync11, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
2360
2379
  import { homedir as homedir3 } from "os";
2361
- import { join as join14, resolve as resolve5 } from "path";
2380
+ import { join as join15, resolve as resolve5 } from "path";
2362
2381
  function encodeCursorProjectDir(absPath) {
2363
2382
  return resolve5(absPath).replace(/^\//, "").replace(/\//g, "-");
2364
2383
  }
@@ -2367,25 +2386,25 @@ function resolveCursorSessionJsonl(options) {
2367
2386
  if (override && existsSync11(override)) {
2368
2387
  return resolve5(override);
2369
2388
  }
2370
- const cursorHome = process.env.CURSOR_CONFIG_DIR ? resolve5(process.env.CURSOR_CONFIG_DIR) : join14(homedir3(), ".cursor");
2371
- const projectsRoot = join14(cursorHome, "projects");
2389
+ const cursorHome = process.env.CURSOR_CONFIG_DIR ? resolve5(process.env.CURSOR_CONFIG_DIR) : join15(homedir3(), ".cursor");
2390
+ const projectsRoot = join15(cursorHome, "projects");
2372
2391
  if (!existsSync11(projectsRoot)) {
2373
2392
  return null;
2374
2393
  }
2375
2394
  const sessionId = options.hookInput?.sessionId ?? options.hookInput?.conversationId ?? process.env.CURSOR_SESSION_ID ?? process.env.CURSOR_AGENT_SESSION_ID;
2376
2395
  const workspace = options.hookInput?.workspaceRoots?.[0] ?? (options.cwd ? resolve5(options.cwd) : resolve5(options.repoRoot));
2377
2396
  const encoded = encodeCursorProjectDir(workspace);
2378
- const projectDir = join14(projectsRoot, encoded);
2379
- const transcriptsRoot = join14(projectDir, "agent-transcripts");
2397
+ const projectDir = join15(projectsRoot, encoded);
2398
+ const transcriptsRoot = join15(projectDir, "agent-transcripts");
2380
2399
  if (!existsSync11(transcriptsRoot)) {
2381
2400
  return pickNewestCursorJsonl(projectsRoot);
2382
2401
  }
2383
2402
  if (sessionId) {
2384
- const direct = join14(transcriptsRoot, sessionId, `${sessionId}.jsonl`);
2403
+ const direct = join15(transcriptsRoot, sessionId, `${sessionId}.jsonl`);
2385
2404
  if (existsSync11(direct)) {
2386
2405
  return direct;
2387
2406
  }
2388
- const nested = findJsonlUnderDir(join14(transcriptsRoot, sessionId), sessionId);
2407
+ const nested = findJsonlUnderDir(join15(transcriptsRoot, sessionId), sessionId);
2389
2408
  if (nested) {
2390
2409
  return nested;
2391
2410
  }
@@ -2396,16 +2415,16 @@ function findJsonlUnderDir(dir, sessionId) {
2396
2415
  if (!existsSync11(dir)) {
2397
2416
  return null;
2398
2417
  }
2399
- const direct = join14(dir, `${sessionId}.jsonl`);
2418
+ const direct = join15(dir, `${sessionId}.jsonl`);
2400
2419
  if (existsSync11(direct)) {
2401
2420
  return direct;
2402
2421
  }
2403
2422
  for (const entry of readdirSync6(dir, { withFileTypes: true })) {
2404
2423
  if (entry.isFile() && entry.name.endsWith(".jsonl")) {
2405
- return join14(dir, entry.name);
2424
+ return join15(dir, entry.name);
2406
2425
  }
2407
2426
  if (entry.isDirectory()) {
2408
- const found = findJsonlUnderDir(join14(dir, entry.name), sessionId);
2427
+ const found = findJsonlUnderDir(join15(dir, entry.name), sessionId);
2409
2428
  if (found) {
2410
2429
  return found;
2411
2430
  }
@@ -2427,7 +2446,7 @@ function collectJsonlRecursive2(dir, out) {
2427
2446
  return;
2428
2447
  }
2429
2448
  for (const entry of readdirSync6(dir, { withFileTypes: true })) {
2430
- const full = join14(dir, entry.name);
2449
+ const full = join15(dir, entry.name);
2431
2450
  if (entry.isDirectory()) {
2432
2451
  collectJsonlRecursive2(full, out);
2433
2452
  continue;
@@ -2671,7 +2690,7 @@ async function runFlushCommandCli(opts) {
2671
2690
 
2672
2691
  // src/inject/runInject.ts
2673
2692
  import { existsSync as existsSync12, readdirSync as readdirSync7, readFileSync as readFileSync13 } from "fs";
2674
- import { join as join15 } from "path";
2693
+ import { join as join16 } from "path";
2675
2694
 
2676
2695
  // src/inject/constants.ts
2677
2696
  var INJECT_MAX_CHARS = 8e3;
@@ -2751,7 +2770,7 @@ function readAllRules(repoRoot) {
2751
2770
  const parts = [];
2752
2771
  for (const file of files) {
2753
2772
  try {
2754
- const filePath = join15(rulesDir, file);
2773
+ const filePath = join16(rulesDir, file);
2755
2774
  const content = readFileSync13(filePath, "utf8").trim();
2756
2775
  if (!content) continue;
2757
2776
  parts.push(`### ${file}`, "", content, "");
@@ -2779,46 +2798,46 @@ import { resolve as resolve7 } from "path";
2779
2798
 
2780
2799
  // src/init/assistants/claude-code.ts
2781
2800
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
2782
- import { join as join19 } from "path";
2801
+ import { join as join20 } from "path";
2783
2802
 
2784
2803
  // src/init/mergeClaudeSettings.ts
2785
2804
  import { existsSync as existsSync14, readFileSync as readFileSync16 } from "fs";
2786
- import { join as join18 } from "path";
2805
+ import { join as join19 } from "path";
2787
2806
 
2788
2807
  // src/init/templateDir.ts
2789
2808
  import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
2790
- import { dirname as dirname7, join as join17 } from "path";
2809
+ import { dirname as dirname6, join as join18 } from "path";
2791
2810
  import { fileURLToPath as fileURLToPath4 } from "url";
2792
2811
 
2793
2812
  // src/index.ts
2794
2813
  import { readFileSync as readFileSync14 } from "fs";
2795
- import { dirname as dirname6, join as join16 } from "path";
2814
+ import { dirname as dirname5, join as join17 } from "path";
2796
2815
  import { fileURLToPath as fileURLToPath3 } from "url";
2797
2816
  var PACKAGE_NAME = "@riconext/hermes-repo";
2798
- var __dirname = dirname6(fileURLToPath3(import.meta.url));
2817
+ var __dirname = dirname5(fileURLToPath3(import.meta.url));
2799
2818
  function readPkgVersion() {
2800
- const pkgPath = join16(__dirname, "..", "package.json");
2819
+ const pkgPath = join17(__dirname, "..", "package.json");
2801
2820
  const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
2802
2821
  return pkg.version;
2803
2822
  }
2804
2823
 
2805
2824
  // src/init/templateDir.ts
2806
2825
  function resolveTemplateDir() {
2807
- const here = dirname7(fileURLToPath4(import.meta.url));
2826
+ const here = dirname6(fileURLToPath4(import.meta.url));
2808
2827
  const candidates = [
2809
- join17(here, "templates"),
2810
- join17(here, "..", "..", "templates")
2828
+ join18(here, "templates"),
2829
+ join18(here, "..", "..", "templates")
2811
2830
  ];
2812
2831
  for (const dir of candidates) {
2813
2832
  if (existsSync13(dir)) {
2814
2833
  return dir;
2815
2834
  }
2816
2835
  }
2817
- return join17(here, "templates");
2836
+ return join18(here, "templates");
2818
2837
  }
2819
2838
  var templateDir = resolveTemplateDir();
2820
2839
  function resolveTemplatePath(name) {
2821
- return join17(templateDir, name);
2840
+ return join18(templateDir, name);
2822
2841
  }
2823
2842
  function readTemplate(name) {
2824
2843
  return readFileSync15(resolveTemplatePath(name), "utf8");
@@ -2831,7 +2850,7 @@ function renderTemplate(name) {
2831
2850
  // src/init/mergeClaudeSettings.ts
2832
2851
  var CLAUDE_SETTINGS_LOCAL_REL = ".claude/settings.local.json";
2833
2852
  function claudeSettingsLocalPath(repoRoot) {
2834
- return join18(repoRoot, ".claude", "settings.local.json");
2853
+ return join19(repoRoot, ".claude", "settings.local.json");
2835
2854
  }
2836
2855
  function mergeClaudeLocalSettings(repoRoot) {
2837
2856
  const settingsPath = claudeSettingsLocalPath(repoRoot);
@@ -2868,7 +2887,7 @@ var claudeCodeAdapter = {
2868
2887
  available: true,
2869
2888
  scaffoldPaths: [CLAUDE_SETTINGS_LOCAL_REL],
2870
2889
  write(ctx) {
2871
- mkdirSync7(join19(ctx.repoRoot, ".claude"), { recursive: true });
2890
+ mkdirSync7(join20(ctx.repoRoot, ".claude"), { recursive: true });
2872
2891
  const { content, action } = mergeClaudeLocalSettings(ctx.repoRoot);
2873
2892
  writeFileSync6(claudeSettingsLocalPath(ctx.repoRoot), content, "utf8");
2874
2893
  ctx.report.files.push({ path: CLAUDE_SETTINGS_LOCAL_REL, action });
@@ -2877,11 +2896,11 @@ var claudeCodeAdapter = {
2877
2896
 
2878
2897
  // src/init/assistants/codex.ts
2879
2898
  import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7 } from "fs";
2880
- import { join as join21 } from "path";
2899
+ import { join as join22 } from "path";
2881
2900
 
2882
2901
  // src/init/mergeCodexConfig.ts
2883
2902
  import { existsSync as existsSync15, readFileSync as readFileSync17 } from "fs";
2884
- import { join as join20 } from "path";
2903
+ import { join as join21 } from "path";
2885
2904
  var CODEX_CONFIG_REL = ".codex/config.toml";
2886
2905
  var CODEX_HERMES_START_MARKER = "# >>> hermes-repo codex (do not edit this block manually)";
2887
2906
  var CODEX_HERMES_END_MARKER = "# <<< hermes-repo codex";
@@ -2895,7 +2914,7 @@ function buildCodexHermesBlock() {
2895
2914
  ].join("\n");
2896
2915
  }
2897
2916
  function codexConfigPath(repoRoot) {
2898
- return join20(repoRoot, ".codex", "config.toml");
2917
+ return join21(repoRoot, ".codex", "config.toml");
2899
2918
  }
2900
2919
  function spliceHermesBlock(existing, block) {
2901
2920
  const startIdx = existing.indexOf(CODEX_HERMES_START_MARKER);
@@ -2942,7 +2961,7 @@ var codexAdapter = {
2942
2961
  available: true,
2943
2962
  scaffoldPaths: [CODEX_CONFIG_REL],
2944
2963
  write(ctx) {
2945
- mkdirSync8(join21(ctx.repoRoot, ".codex"), { recursive: true });
2964
+ mkdirSync8(join22(ctx.repoRoot, ".codex"), { recursive: true });
2946
2965
  const { content, action } = mergeCodexConfig(ctx.repoRoot);
2947
2966
  writeFileSync7(codexConfigPath(ctx.repoRoot), content, "utf8");
2948
2967
  ctx.report.files.push({ path: CODEX_CONFIG_REL, action });
@@ -2951,14 +2970,14 @@ var codexAdapter = {
2951
2970
 
2952
2971
  // src/init/assistants/codebuddy.ts
2953
2972
  import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "fs";
2954
- import { join as join23 } from "path";
2973
+ import { join as join24 } from "path";
2955
2974
 
2956
2975
  // src/init/mergeCodebuddySettings.ts
2957
2976
  import { existsSync as existsSync16, readFileSync as readFileSync18 } from "fs";
2958
- import { join as join22 } from "path";
2977
+ import { join as join23 } from "path";
2959
2978
  var CODEBUDDY_SETTINGS_LOCAL_REL = ".codebuddy/settings.local.json";
2960
2979
  function codebuddySettingsLocalPath(repoRoot) {
2961
- return join22(repoRoot, ".codebuddy", "settings.local.json");
2980
+ return join23(repoRoot, ".codebuddy", "settings.local.json");
2962
2981
  }
2963
2982
  function mergeCodebuddyLocalSettings(repoRoot) {
2964
2983
  const settingsPath = codebuddySettingsLocalPath(repoRoot);
@@ -2997,7 +3016,7 @@ var codebuddyAdapter = {
2997
3016
  available: true,
2998
3017
  scaffoldPaths: [CODEBUDDY_SETTINGS_LOCAL_REL],
2999
3018
  write(ctx) {
3000
- mkdirSync9(join23(ctx.repoRoot, ".codebuddy"), { recursive: true });
3019
+ mkdirSync9(join24(ctx.repoRoot, ".codebuddy"), { recursive: true });
3001
3020
  const { content, action } = mergeCodebuddyLocalSettings(ctx.repoRoot);
3002
3021
  writeFileSync8(codebuddySettingsLocalPath(ctx.repoRoot), content, "utf8");
3003
3022
  ctx.report.files.push({ path: CODEBUDDY_SETTINGS_LOCAL_REL, action });
@@ -3006,14 +3025,14 @@ var codebuddyAdapter = {
3006
3025
 
3007
3026
  // src/init/assistants/cursor.ts
3008
3027
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
3009
- import { join as join25 } from "path";
3028
+ import { join as join26 } from "path";
3010
3029
 
3011
3030
  // src/init/mergeCursorHooks.ts
3012
3031
  import { existsSync as existsSync17, readFileSync as readFileSync19 } from "fs";
3013
- import { join as join24 } from "path";
3032
+ import { join as join25 } from "path";
3014
3033
  var CURSOR_HOOKS_REL = ".cursor/hooks.json";
3015
3034
  function cursorHooksPath(repoRoot) {
3016
- return join24(repoRoot, ".cursor", "hooks.json");
3035
+ return join25(repoRoot, ".cursor", "hooks.json");
3017
3036
  }
3018
3037
  function mergeCursorHooks(repoRoot) {
3019
3038
  const hooksPath = cursorHooksPath(repoRoot);
@@ -3051,7 +3070,7 @@ var cursorAdapter = {
3051
3070
  available: true,
3052
3071
  scaffoldPaths: [CURSOR_HOOKS_REL],
3053
3072
  write(ctx) {
3054
- mkdirSync10(join25(ctx.repoRoot, ".cursor"), { recursive: true });
3073
+ mkdirSync10(join26(ctx.repoRoot, ".cursor"), { recursive: true });
3055
3074
  const { content, action } = mergeCursorHooks(ctx.repoRoot);
3056
3075
  writeFileSync9(cursorHooksPath(ctx.repoRoot), content, "utf8");
3057
3076
  ctx.report.files.push({ path: CURSOR_HOOKS_REL, action });
@@ -3114,16 +3133,16 @@ function validateAssistantSelection(ids) {
3114
3133
 
3115
3134
  // src/init/ensureDirs.ts
3116
3135
  import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
3117
- import { join as join26 } from "path";
3136
+ import { join as join27 } from "path";
3118
3137
  function ensureMemoryTree(repoRoot) {
3119
- const memoryRoot = join26(repoRoot, MEMORY_DIR);
3138
+ const memoryRoot = join27(repoRoot, MEMORY_DIR);
3120
3139
  mkdirSync11(memoryRoot, { recursive: true });
3121
3140
  for (const sub of MEMORY_SUBDIRS) {
3122
- mkdirSync11(join26(memoryRoot, sub), { recursive: true });
3141
+ mkdirSync11(join27(memoryRoot, sub), { recursive: true });
3123
3142
  }
3124
- mkdirSync11(join26(repoRoot, ".claude"), { recursive: true });
3143
+ mkdirSync11(join27(repoRoot, ".claude"), { recursive: true });
3125
3144
  for (const sub of GITKEEP_DIRS) {
3126
- const keepPath = join26(memoryRoot, sub, ".gitkeep");
3145
+ const keepPath = join27(memoryRoot, sub, ".gitkeep");
3127
3146
  writeFileSync10(keepPath, "", { flag: "a" });
3128
3147
  }
3129
3148
  }
@@ -3152,12 +3171,12 @@ function mergeAssistants(repoRoot, selected) {
3152
3171
 
3153
3172
  // src/init/mergeGitignore.ts
3154
3173
  import { existsSync as existsSync19, readFileSync as readFileSync21, writeFileSync as writeFileSync11 } from "fs";
3155
- import { join as join27 } from "path";
3174
+ import { join as join28 } from "path";
3156
3175
  var START_MARKER = "# >>> hermes-repo memory (do not edit this block manually)";
3157
3176
  var END_MARKER = "# <<< hermes-repo memory";
3158
3177
  function mergeHermesGitignore(repoRoot) {
3159
3178
  const block = readTemplate("gitignore-block.txt").trimEnd() + "\n";
3160
- const gitignorePath = join27(repoRoot, ".gitignore");
3179
+ const gitignorePath = join28(repoRoot, ".gitignore");
3161
3180
  const contentBefore = existsSync19(gitignorePath) ? readFileSync21(gitignorePath, "utf8") : "";
3162
3181
  const warnBroadMemoryIgnore = contentBefore.length > 0 && !contentBefore.includes(START_MARKER) && /(^|\n)\.memory\/\s*$/m.test(contentBefore);
3163
3182
  if (!existsSync19(gitignorePath)) {
@@ -3255,7 +3274,7 @@ function mergeConfigForInit(repoRoot, assistants) {
3255
3274
 
3256
3275
  // src/init/mergeAgentsMd.ts
3257
3276
  import { existsSync as existsSync21, readFileSync as readFileSync23, writeFileSync as writeFileSync12 } from "fs";
3258
- import { join as join28 } from "path";
3277
+ import { join as join29 } from "path";
3259
3278
  var HERMES_AGENTS_START_MARKER = "<!-- >>> hermes-repo agents (do not edit this block manually) -->";
3260
3279
  var HERMES_AGENTS_END_MARKER = "<!-- <<< hermes-repo agents -->";
3261
3280
  function buildHermesAgentsBlockBody() {
@@ -3311,7 +3330,7 @@ function spliceHermesBlock2(existing, block) {
3311
3330
  `;
3312
3331
  }
3313
3332
  function mergeAgentsMd(repoRoot, force) {
3314
- const agentsPath = join28(repoRoot, "AGENTS.md");
3333
+ const agentsPath = join29(repoRoot, "AGENTS.md");
3315
3334
  const block = buildHermesAgentsMarkedBlock();
3316
3335
  if (!existsSync21(agentsPath)) {
3317
3336
  writeFileSync12(agentsPath, buildNewAgentsMd(), "utf8");