@rely-ai/caliber 1.29.5 → 1.29.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.js +95 -65
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -181,7 +181,7 @@ __export(resolve_caliber_exports, {
181
181
  resolveCaliber: () => resolveCaliber
182
182
  });
183
183
  import fs20 from "fs";
184
- import { execSync as execSync6 } from "child_process";
184
+ import { execSync as execSync7 } from "child_process";
185
185
  function resolveCaliber() {
186
186
  if (_resolved) return _resolved;
187
187
  const isNpx = process.argv[1]?.includes("_npx") || process.env.npm_execpath?.includes("npx");
@@ -191,14 +191,12 @@ function resolveCaliber() {
191
191
  }
192
192
  try {
193
193
  const whichCmd = process.platform === "win32" ? "where caliber" : "which caliber";
194
- const found = execSync6(whichCmd, {
194
+ execSync7(whichCmd, {
195
195
  encoding: "utf-8",
196
196
  stdio: ["pipe", "pipe", "pipe"]
197
- }).trim();
198
- if (found) {
199
- _resolved = found;
200
- return _resolved;
201
- }
197
+ });
198
+ _resolved = "caliber";
199
+ return _resolved;
202
200
  } catch {
203
201
  }
204
202
  const binPath = process.argv[1];
@@ -225,7 +223,7 @@ var init_resolve_caliber = __esm({
225
223
  });
226
224
 
227
225
  // src/utils/editor.ts
228
- import { execSync as execSync12, spawn as spawn3 } from "child_process";
226
+ import { execSync as execSync13, spawn as spawn3 } from "child_process";
229
227
  import fs26 from "fs";
230
228
  import path22 from "path";
231
229
  import os6 from "os";
@@ -238,7 +236,7 @@ function getEmptyFilePath(proposedPath) {
238
236
  function commandExists(cmd) {
239
237
  try {
240
238
  const check = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
241
- execSync12(check, { stdio: "ignore" });
239
+ execSync13(check, { stdio: "ignore" });
242
240
  return true;
243
241
  } catch {
244
242
  return false;
@@ -664,11 +662,26 @@ import path3 from "path";
664
662
  // src/constants.ts
665
663
  import path2 from "path";
666
664
  import os from "os";
665
+ import { execSync as execSync2 } from "child_process";
667
666
  var AUTH_DIR = path2.join(os.homedir(), ".caliber");
668
667
  var CALIBER_DIR = ".caliber";
669
668
  var MANIFEST_FILE = path2.join(CALIBER_DIR, "manifest.json");
670
669
  var BACKUPS_DIR = path2.join(CALIBER_DIR, "backups");
671
- var LEARNING_DIR = path2.join(CALIBER_DIR, "learning");
670
+ var _learningDirCache = null;
671
+ function getLearningDir() {
672
+ if (_learningDirCache) return _learningDirCache;
673
+ try {
674
+ const gitCommonDir = execSync2("git rev-parse --git-common-dir", {
675
+ encoding: "utf-8",
676
+ stdio: ["pipe", "pipe", "pipe"]
677
+ }).trim();
678
+ const mainRoot = path2.dirname(path2.resolve(gitCommonDir));
679
+ _learningDirCache = path2.join(mainRoot, CALIBER_DIR, "learning");
680
+ } catch {
681
+ _learningDirCache = path2.join(CALIBER_DIR, "learning");
682
+ }
683
+ return _learningDirCache;
684
+ }
672
685
  var LEARNING_SESSION_FILE = "current-session.jsonl";
673
686
  var LEARNING_STATE_FILE = "state.json";
674
687
  var LEARNING_MAX_EVENTS = 500;
@@ -781,7 +794,7 @@ function readExistingConfigs(dir) {
781
794
  // src/fingerprint/code-analysis.ts
782
795
  import fs3 from "fs";
783
796
  import path4 from "path";
784
- import { execSync as execSync2 } from "child_process";
797
+ import { execSync as execSync3 } from "child_process";
785
798
  var IGNORE_DIRS2 = /* @__PURE__ */ new Set([
786
799
  "node_modules",
787
800
  ".git",
@@ -1128,7 +1141,7 @@ function buildImportCounts(files) {
1128
1141
  function getGitFrequency(dir) {
1129
1142
  const freq = /* @__PURE__ */ new Map();
1130
1143
  try {
1131
- const output = execSync2(
1144
+ const output = execSync3(
1132
1145
  'git log --since="6 months ago" --format="" --name-only --diff-filter=ACMR 2>/dev/null | head -10000',
1133
1146
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }
1134
1147
  );
@@ -1577,7 +1590,7 @@ var OpenAICompatProvider = class {
1577
1590
  };
1578
1591
 
1579
1592
  // src/llm/cursor-acp.ts
1580
- import { spawn, execSync as execSync3 } from "child_process";
1593
+ import { spawn, execSync as execSync4 } from "child_process";
1581
1594
  import os3 from "os";
1582
1595
 
1583
1596
  // src/llm/seat-based-errors.ts
@@ -1853,7 +1866,7 @@ var CursorAcpProvider = class {
1853
1866
  function isCursorAgentAvailable() {
1854
1867
  try {
1855
1868
  const cmd = IS_WINDOWS ? `where ${AGENT_BIN}` : `which ${AGENT_BIN}`;
1856
- execSync3(cmd, { stdio: "ignore" });
1869
+ execSync4(cmd, { stdio: "ignore" });
1857
1870
  return true;
1858
1871
  } catch {
1859
1872
  return false;
@@ -1861,7 +1874,7 @@ function isCursorAgentAvailable() {
1861
1874
  }
1862
1875
  function isCursorLoggedIn() {
1863
1876
  try {
1864
- const result = execSync3(`${AGENT_BIN} status`, { stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 });
1877
+ const result = execSync4(`${AGENT_BIN} status`, { stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 });
1865
1878
  return !result.toString().includes("not logged in");
1866
1879
  } catch {
1867
1880
  return false;
@@ -1869,7 +1882,7 @@ function isCursorLoggedIn() {
1869
1882
  }
1870
1883
 
1871
1884
  // src/llm/claude-cli.ts
1872
- import { spawn as spawn2, execSync as execSync4 } from "child_process";
1885
+ import { spawn as spawn2, execSync as execSync5 } from "child_process";
1873
1886
  var CLAUDE_CLI_BIN = "claude";
1874
1887
  var DEFAULT_TIMEOUT_MS2 = 10 * 60 * 1e3;
1875
1888
  var IS_WINDOWS2 = process.platform === "win32";
@@ -2004,7 +2017,7 @@ var ClaudeCliProvider = class {
2004
2017
  function isClaudeCliAvailable() {
2005
2018
  try {
2006
2019
  const cmd = process.platform === "win32" ? `where ${CLAUDE_CLI_BIN}` : `which ${CLAUDE_CLI_BIN}`;
2007
- execSync4(cmd, { stdio: "ignore" });
2020
+ execSync5(cmd, { stdio: "ignore" });
2008
2021
  return true;
2009
2022
  } catch {
2010
2023
  return false;
@@ -2744,7 +2757,7 @@ init_config();
2744
2757
  import fs6 from "fs";
2745
2758
  import path6 from "path";
2746
2759
  import crypto from "crypto";
2747
- import { execSync as execSync5 } from "child_process";
2760
+ import { execSync as execSync6 } from "child_process";
2748
2761
  var CACHE_VERSION = 1;
2749
2762
  var CACHE_DIR = ".caliber/cache";
2750
2763
  var CACHE_FILE = "fingerprint.json";
@@ -2753,7 +2766,7 @@ function getCachePath(dir) {
2753
2766
  }
2754
2767
  function getGitHead(dir) {
2755
2768
  try {
2756
- return execSync5("git rev-parse HEAD", {
2769
+ return execSync6("git rev-parse HEAD", {
2757
2770
  cwd: dir,
2758
2771
  encoding: "utf-8",
2759
2772
  stdio: ["pipe", "pipe", "pipe"],
@@ -2765,7 +2778,7 @@ function getGitHead(dir) {
2765
2778
  }
2766
2779
  function getDirtySignature(dir) {
2767
2780
  try {
2768
- const output = execSync5("git diff --name-only HEAD", {
2781
+ const output = execSync6("git diff --name-only HEAD", {
2769
2782
  cwd: dir,
2770
2783
  encoding: "utf-8",
2771
2784
  stdio: ["pipe", "pipe", "pipe"],
@@ -4991,7 +5004,7 @@ function removeLearningHooks() {
4991
5004
  // src/lib/state.ts
4992
5005
  import fs22 from "fs";
4993
5006
  import path18 from "path";
4994
- import { execSync as execSync7 } from "child_process";
5007
+ import { execSync as execSync8 } from "child_process";
4995
5008
  var STATE_FILE = path18.join(CALIBER_DIR, ".caliber-state.json");
4996
5009
  function normalizeTargetAgent(value) {
4997
5010
  if (Array.isArray(value)) return value;
@@ -5019,7 +5032,7 @@ function writeState(state) {
5019
5032
  }
5020
5033
  function getCurrentHeadSha() {
5021
5034
  try {
5022
- return execSync7("git rev-parse HEAD", {
5035
+ return execSync8("git rev-parse HEAD", {
5023
5036
  encoding: "utf-8",
5024
5037
  stdio: ["pipe", "pipe", "pipe"]
5025
5038
  }).trim();
@@ -5632,7 +5645,7 @@ function checkGrounding(dir) {
5632
5645
 
5633
5646
  // src/scoring/checks/accuracy.ts
5634
5647
  import { existsSync as existsSync4, statSync as statSync2 } from "fs";
5635
- import { execSync as execSync8 } from "child_process";
5648
+ import { execSync as execSync9 } from "child_process";
5636
5649
  import { join as join5 } from "path";
5637
5650
  function validateReferences(dir) {
5638
5651
  const configContent = collectPrimaryConfigContent(dir);
@@ -5641,13 +5654,13 @@ function validateReferences(dir) {
5641
5654
  }
5642
5655
  function detectGitDrift(dir) {
5643
5656
  try {
5644
- execSync8("git rev-parse --git-dir", { cwd: dir, stdio: ["pipe", "pipe", "pipe"] });
5657
+ execSync9("git rev-parse --git-dir", { cwd: dir, stdio: ["pipe", "pipe", "pipe"] });
5645
5658
  } catch {
5646
5659
  return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: false };
5647
5660
  }
5648
5661
  const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules", ".cursor/rules"];
5649
5662
  try {
5650
- const headTimestamp = execSync8(
5663
+ const headTimestamp = execSync9(
5651
5664
  "git log -1 --format=%ct HEAD",
5652
5665
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5653
5666
  ).trim();
@@ -5668,7 +5681,7 @@ function detectGitDrift(dir) {
5668
5681
  let latestConfigCommitHash = null;
5669
5682
  for (const file of configFiles) {
5670
5683
  try {
5671
- const hash = execSync8(
5684
+ const hash = execSync9(
5672
5685
  `git log -1 --format=%H -- "${file}"`,
5673
5686
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5674
5687
  ).trim();
@@ -5677,7 +5690,7 @@ function detectGitDrift(dir) {
5677
5690
  latestConfigCommitHash = hash;
5678
5691
  } else {
5679
5692
  try {
5680
- execSync8(
5693
+ execSync9(
5681
5694
  `git merge-base --is-ancestor ${latestConfigCommitHash} ${hash}`,
5682
5695
  { cwd: dir, stdio: ["pipe", "pipe", "pipe"] }
5683
5696
  );
@@ -5692,12 +5705,12 @@ function detectGitDrift(dir) {
5692
5705
  return { commitsSinceConfigUpdate: 0, lastConfigCommit: null, isGitRepo: true };
5693
5706
  }
5694
5707
  try {
5695
- const countStr = execSync8(
5708
+ const countStr = execSync9(
5696
5709
  `git rev-list --count ${latestConfigCommitHash}..HEAD`,
5697
5710
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5698
5711
  ).trim();
5699
5712
  const commitsSince = parseInt(countStr, 10) || 0;
5700
- const lastDate = execSync8(
5713
+ const lastDate = execSync9(
5701
5714
  `git log -1 --format=%ci ${latestConfigCommitHash}`,
5702
5715
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5703
5716
  ).trim();
@@ -5769,12 +5782,12 @@ function checkAccuracy(dir) {
5769
5782
 
5770
5783
  // src/scoring/checks/freshness.ts
5771
5784
  import { existsSync as existsSync5, statSync as statSync3 } from "fs";
5772
- import { execSync as execSync9 } from "child_process";
5785
+ import { execSync as execSync10 } from "child_process";
5773
5786
  import { join as join6 } from "path";
5774
5787
  function getCommitsSinceConfigUpdate(dir) {
5775
5788
  const configFiles = ["CLAUDE.md", "AGENTS.md", ".cursorrules"];
5776
5789
  try {
5777
- const headTimestamp = execSync9(
5790
+ const headTimestamp = execSync10(
5778
5791
  "git log -1 --format=%ct HEAD",
5779
5792
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5780
5793
  ).trim();
@@ -5794,12 +5807,12 @@ function getCommitsSinceConfigUpdate(dir) {
5794
5807
  }
5795
5808
  for (const file of configFiles) {
5796
5809
  try {
5797
- const hash = execSync9(
5810
+ const hash = execSync10(
5798
5811
  `git log -1 --format=%H -- "${file}"`,
5799
5812
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5800
5813
  ).trim();
5801
5814
  if (hash) {
5802
- const countStr = execSync9(
5815
+ const countStr = execSync10(
5803
5816
  `git rev-list --count ${hash}..HEAD`,
5804
5817
  { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
5805
5818
  ).trim();
@@ -5917,11 +5930,11 @@ function checkFreshness(dir) {
5917
5930
 
5918
5931
  // src/scoring/checks/bonus.ts
5919
5932
  import { existsSync as existsSync6, readdirSync as readdirSync3 } from "fs";
5920
- import { execSync as execSync10 } from "child_process";
5933
+ import { execSync as execSync11 } from "child_process";
5921
5934
  import { join as join7 } from "path";
5922
5935
  function hasPreCommitHook(dir) {
5923
5936
  try {
5924
- const gitDir = execSync10("git rev-parse --git-dir", { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
5937
+ const gitDir = execSync11("git rev-parse --git-dir", { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
5925
5938
  const hookPath = join7(gitDir, "hooks", "pre-commit");
5926
5939
  const content = readFileOrNull(hookPath);
5927
5940
  return content ? content.includes("caliber") : false;
@@ -6350,7 +6363,7 @@ import fs24 from "fs";
6350
6363
  import path20 from "path";
6351
6364
  import os5 from "os";
6352
6365
  import crypto4 from "crypto";
6353
- import { execSync as execSync11 } from "child_process";
6366
+ import { execSync as execSync12 } from "child_process";
6354
6367
  var CONFIG_DIR2 = path20.join(os5.homedir(), ".caliber");
6355
6368
  var CONFIG_FILE2 = path20.join(CONFIG_DIR2, "config.json");
6356
6369
  var runtimeDisabled = false;
@@ -6377,7 +6390,7 @@ function getMachineId() {
6377
6390
  }
6378
6391
  function getGitEmailHash() {
6379
6392
  try {
6380
- const email = execSync11("git config user.email", { encoding: "utf-8" }).trim();
6393
+ const email = execSync12("git config user.email", { encoding: "utf-8" }).trim();
6381
6394
  if (!email) return void 0;
6382
6395
  return crypto4.createHash("sha256").update(email).digest("hex");
6383
6396
  } catch {
@@ -9471,7 +9484,7 @@ import chalk19 from "chalk";
9471
9484
  import ora6 from "ora";
9472
9485
 
9473
9486
  // src/lib/git-diff.ts
9474
- import { execSync as execSync13 } from "child_process";
9487
+ import { execSync as execSync14 } from "child_process";
9475
9488
  var MAX_DIFF_BYTES = 1e5;
9476
9489
  var DOC_PATTERNS = [
9477
9490
  "CLAUDE.md",
@@ -9486,7 +9499,7 @@ function excludeArgs() {
9486
9499
  }
9487
9500
  function safeExec(cmd) {
9488
9501
  try {
9489
- return execSync13(cmd, {
9502
+ return execSync14(cmd, {
9490
9503
  encoding: "utf-8",
9491
9504
  stdio: ["pipe", "pipe", "pipe"],
9492
9505
  maxBuffer: 10 * 1024 * 1024
@@ -10007,7 +10020,7 @@ import fs39 from "fs";
10007
10020
  init_resolve_caliber();
10008
10021
  import fs38 from "fs";
10009
10022
  import path30 from "path";
10010
- import { execSync as execSync14 } from "child_process";
10023
+ import { execSync as execSync15 } from "child_process";
10011
10024
  var SETTINGS_PATH2 = path30.join(".claude", "settings.json");
10012
10025
  var REFRESH_TAIL = "refresh --quiet";
10013
10026
  var HOOK_DESCRIPTION = "Caliber: auto-refreshing docs based on code changes";
@@ -10087,7 +10100,7 @@ ${PRECOMMIT_END}`;
10087
10100
  }
10088
10101
  function getGitHooksDir() {
10089
10102
  try {
10090
- const gitDir = execSync14("git rev-parse --git-dir", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10103
+ const gitDir = execSync15("git rev-parse --git-dir", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10091
10104
  return path30.join(gitDir, "hooks");
10092
10105
  } catch {
10093
10106
  return null;
@@ -10400,15 +10413,15 @@ var DEFAULT_STATE = {
10400
10413
  lastAnalysisEventCount: 0
10401
10414
  };
10402
10415
  function ensureLearningDir() {
10403
- if (!fs40.existsSync(LEARNING_DIR)) {
10404
- fs40.mkdirSync(LEARNING_DIR, { recursive: true });
10416
+ if (!fs40.existsSync(getLearningDir())) {
10417
+ fs40.mkdirSync(getLearningDir(), { recursive: true });
10405
10418
  }
10406
10419
  }
10407
10420
  function sessionFilePath() {
10408
- return path31.join(LEARNING_DIR, LEARNING_SESSION_FILE);
10421
+ return path31.join(getLearningDir(), LEARNING_SESSION_FILE);
10409
10422
  }
10410
10423
  function stateFilePath() {
10411
- return path31.join(LEARNING_DIR, LEARNING_STATE_FILE);
10424
+ return path31.join(getLearningDir(), LEARNING_STATE_FILE);
10412
10425
  }
10413
10426
  function truncateResponse(response) {
10414
10427
  const str = JSON.stringify(response);
@@ -10480,7 +10493,7 @@ function resetState() {
10480
10493
  var LOCK_FILE2 = "finalize.lock";
10481
10494
  var LOCK_STALE_MS = 5 * 60 * 1e3;
10482
10495
  function lockFilePath() {
10483
- return path31.join(LEARNING_DIR, LOCK_FILE2);
10496
+ return path31.join(getLearningDir(), LOCK_FILE2);
10484
10497
  }
10485
10498
  function acquireFinalizeLock() {
10486
10499
  ensureLearningDir();
@@ -10567,19 +10580,21 @@ function sanitizeSecrets(text) {
10567
10580
  import fs41 from "fs";
10568
10581
  import path32 from "path";
10569
10582
  import chalk22 from "chalk";
10570
- var NOTIFICATION_FILE = path32.join(LEARNING_DIR, "last-finalize-summary.json");
10583
+ function notificationFilePath() {
10584
+ return path32.join(getLearningDir(), "last-finalize-summary.json");
10585
+ }
10571
10586
  function writeFinalizeSummary(summary) {
10572
10587
  try {
10573
10588
  ensureLearningDir();
10574
- fs41.writeFileSync(NOTIFICATION_FILE, JSON.stringify(summary, null, 2));
10589
+ fs41.writeFileSync(notificationFilePath(), JSON.stringify(summary, null, 2));
10575
10590
  } catch {
10576
10591
  }
10577
10592
  }
10578
10593
  function checkPendingNotifications() {
10579
10594
  try {
10580
- if (!fs41.existsSync(NOTIFICATION_FILE)) return;
10581
- const raw = fs41.readFileSync(NOTIFICATION_FILE, "utf-8");
10582
- fs41.unlinkSync(NOTIFICATION_FILE);
10595
+ if (!fs41.existsSync(notificationFilePath())) return;
10596
+ const raw = fs41.readFileSync(notificationFilePath(), "utf-8");
10597
+ fs41.unlinkSync(notificationFilePath());
10583
10598
  const summary = JSON.parse(raw);
10584
10599
  if (!summary.newItemCount || summary.newItemCount === 0) return;
10585
10600
  const wasteLabel = summary.wasteTokens > 0 ? ` (~${summary.wasteTokens.toLocaleString()} wasted tokens captured)` : "";
@@ -10595,7 +10610,7 @@ function checkPendingNotifications() {
10595
10610
  console.log("");
10596
10611
  } catch {
10597
10612
  try {
10598
- fs41.unlinkSync(NOTIFICATION_FILE);
10613
+ fs41.unlinkSync(notificationFilePath());
10599
10614
  } catch {
10600
10615
  }
10601
10616
  }
@@ -10634,10 +10649,25 @@ function trimEventsToFit(events, maxTokens) {
10634
10649
  if (estimateTokens(formatted) <= maxTokens) return kept;
10635
10650
  return kept.slice(-50);
10636
10651
  }
10652
+ function normalizeAnalysisResult(parsed) {
10653
+ let section = parsed.claudeMdLearnedSection ?? null;
10654
+ if (Array.isArray(section)) {
10655
+ section = section.join("\n");
10656
+ }
10657
+ if (section !== null && typeof section !== "string") {
10658
+ section = String(section);
10659
+ }
10660
+ return {
10661
+ ...parsed,
10662
+ claudeMdLearnedSection: section,
10663
+ skills: parsed.skills ?? null,
10664
+ explanations: parsed.explanations ?? []
10665
+ };
10666
+ }
10637
10667
  function parseAnalysisResponse(raw) {
10638
10668
  const cleaned = stripMarkdownFences(raw);
10639
10669
  try {
10640
- return JSON.parse(cleaned);
10670
+ return normalizeAnalysisResult(JSON.parse(cleaned));
10641
10671
  } catch {
10642
10672
  }
10643
10673
  const json = extractJson(cleaned);
@@ -10645,7 +10675,7 @@ function parseAnalysisResponse(raw) {
10645
10675
  return { claudeMdLearnedSection: null, skills: null, explanations: ["LLM response could not be parsed."] };
10646
10676
  }
10647
10677
  try {
10648
- return JSON.parse(json);
10678
+ return normalizeAnalysisResult(JSON.parse(json));
10649
10679
  } catch {
10650
10680
  return { claudeMdLearnedSection: null, skills: null, explanations: ["LLM response contained invalid JSON."] };
10651
10681
  }
@@ -10747,7 +10777,7 @@ var DEFAULT_TOTALS = {
10747
10777
  lastSessionTimestamp: ""
10748
10778
  };
10749
10779
  function roiFilePath() {
10750
- return path33.join(LEARNING_DIR, LEARNING_ROI_FILE);
10780
+ return path33.join(getLearningDir(), LEARNING_ROI_FILE);
10751
10781
  }
10752
10782
  function readROIStats() {
10753
10783
  const filePath = roiFilePath();
@@ -10974,8 +11004,8 @@ var AUTO_SETTLE_MS = 200;
10974
11004
  var INCREMENTAL_INTERVAL = 50;
10975
11005
  function writeFinalizeError(message) {
10976
11006
  try {
10977
- const errorPath = path34.join(LEARNING_DIR, LEARNING_LAST_ERROR_FILE);
10978
- if (!fs43.existsSync(LEARNING_DIR)) fs43.mkdirSync(LEARNING_DIR, { recursive: true });
11007
+ const errorPath = path34.join(getLearningDir(), LEARNING_LAST_ERROR_FILE);
11008
+ if (!fs43.existsSync(getLearningDir())) fs43.mkdirSync(getLearningDir(), { recursive: true });
10979
11009
  fs43.writeFileSync(errorPath, JSON.stringify({
10980
11010
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10981
11011
  error: message,
@@ -10986,7 +11016,7 @@ function writeFinalizeError(message) {
10986
11016
  }
10987
11017
  function readFinalizeError() {
10988
11018
  try {
10989
- const errorPath = path34.join(LEARNING_DIR, LEARNING_LAST_ERROR_FILE);
11019
+ const errorPath = path34.join(getLearningDir(), LEARNING_LAST_ERROR_FILE);
10990
11020
  if (!fs43.existsSync(errorPath)) return null;
10991
11021
  return JSON.parse(fs43.readFileSync(errorPath, "utf-8"));
10992
11022
  } catch {
@@ -11035,8 +11065,8 @@ async function learnObserveCommand(options) {
11035
11065
  const { resolveCaliber: resolveCaliber2 } = await Promise.resolve().then(() => (init_resolve_caliber(), resolve_caliber_exports));
11036
11066
  const bin = resolveCaliber2();
11037
11067
  const { spawn: spawn4 } = await import("child_process");
11038
- const logPath = path34.join(LEARNING_DIR, LEARNING_FINALIZE_LOG);
11039
- if (!fs43.existsSync(LEARNING_DIR)) fs43.mkdirSync(LEARNING_DIR, { recursive: true });
11068
+ const logPath = path34.join(getLearningDir(), LEARNING_FINALIZE_LOG);
11069
+ if (!fs43.existsSync(getLearningDir())) fs43.mkdirSync(getLearningDir(), { recursive: true });
11040
11070
  const logFd = fs43.openSync(logPath, "a");
11041
11071
  spawn4(bin, ["learn", "finalize", "--auto", "--incremental"], {
11042
11072
  detached: true,
@@ -11325,7 +11355,7 @@ async function learnStatusCommand() {
11325
11355
  if (lastError) {
11326
11356
  console.log(`Last error: ${chalk23.red(lastError.error)}`);
11327
11357
  console.log(chalk23.dim(` at ${lastError.timestamp}`));
11328
- const logPath = path34.join(LEARNING_DIR, LEARNING_FINALIZE_LOG);
11358
+ const logPath = path34.join(getLearningDir(), LEARNING_FINALIZE_LOG);
11329
11359
  if (fs43.existsSync(logPath)) {
11330
11360
  console.log(chalk23.dim(` Full log: ${logPath}`));
11331
11361
  }
@@ -11847,7 +11877,7 @@ learn.command("add <content>").description("Add a learning directly (used by age
11847
11877
  import fs47 from "fs";
11848
11878
  import path38 from "path";
11849
11879
  import { fileURLToPath as fileURLToPath2 } from "url";
11850
- import { execSync as execSync15 } from "child_process";
11880
+ import { execSync as execSync16 } from "child_process";
11851
11881
  import chalk27 from "chalk";
11852
11882
  import ora8 from "ora";
11853
11883
  import confirm2 from "@inquirer/confirm";
@@ -11877,7 +11907,7 @@ function isNewer(registry, current) {
11877
11907
  }
11878
11908
  function getInstalledVersion() {
11879
11909
  try {
11880
- const globalRoot = execSync15("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
11910
+ const globalRoot = execSync16("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
11881
11911
  const pkgPath = path38.join(globalRoot, "@rely-ai", "caliber", "package.json");
11882
11912
  return JSON.parse(fs47.readFileSync(pkgPath, "utf-8")).version;
11883
11913
  } catch {
@@ -11925,7 +11955,7 @@ Update available: ${current} -> ${latest}`)
11925
11955
  const tag = channel === "latest" ? latest : channel;
11926
11956
  const spinner = ora8("Updating caliber...").start();
11927
11957
  try {
11928
- execSync15(`npm install -g @rely-ai/caliber@${tag}`, {
11958
+ execSync16(`npm install -g @rely-ai/caliber@${tag}`, {
11929
11959
  stdio: "pipe",
11930
11960
  timeout: 12e4,
11931
11961
  env: { ...process.env, npm_config_fund: "false", npm_config_audit: "false" }
@@ -11942,7 +11972,7 @@ Update available: ${current} -> ${latest}`)
11942
11972
  console.log(chalk27.dim(`
11943
11973
  Restarting: caliber ${args.join(" ")}
11944
11974
  `));
11945
- execSync15(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
11975
+ execSync16(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
11946
11976
  stdio: "inherit",
11947
11977
  env: { ...process.env, CALIBER_SKIP_UPDATE_CHECK: "1" }
11948
11978
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rely-ai/caliber",
3
- "version": "1.29.5",
3
+ "version": "1.29.7",
4
4
  "description": "Analyze your codebase and generate optimized AI agent configs (CLAUDE.md, .cursorrules, skills) — no API key needed",
5
5
  "type": "module",
6
6
  "bin": {