@rely-ai/caliber 1.23.0-dev.1773820608 → 1.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.js +214 -562
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -216,56 +216,6 @@ var init_constants = __esm({
216
216
  }
217
217
  });
218
218
 
219
- // src/lib/resolve-caliber.ts
220
- var resolve_caliber_exports = {};
221
- __export(resolve_caliber_exports, {
222
- isCaliberCommand: () => isCaliberCommand,
223
- resolveCaliber: () => resolveCaliber
224
- });
225
- import fs18 from "fs";
226
- import { execSync as execSync7 } from "child_process";
227
- function resolveCaliber() {
228
- if (_resolved) return _resolved;
229
- const isNpx = process.argv[1]?.includes("_npx") || process.env.npm_execpath?.includes("npx");
230
- if (isNpx) {
231
- _resolved = "npx --yes @rely-ai/caliber";
232
- return _resolved;
233
- }
234
- try {
235
- const whichCmd = process.platform === "win32" ? "where caliber" : "which caliber";
236
- const found = execSync7(whichCmd, {
237
- encoding: "utf-8",
238
- stdio: ["pipe", "pipe", "pipe"]
239
- }).trim();
240
- if (found) {
241
- _resolved = found;
242
- return _resolved;
243
- }
244
- } catch {
245
- }
246
- const binPath = process.argv[1];
247
- if (binPath && fs18.existsSync(binPath)) {
248
- _resolved = binPath;
249
- return _resolved;
250
- }
251
- _resolved = "caliber";
252
- return _resolved;
253
- }
254
- function isCaliberCommand(command, subcommandTail) {
255
- if (command === `caliber ${subcommandTail}`) return true;
256
- if (command.endsWith(`/caliber ${subcommandTail}`)) return true;
257
- if (command === `npx --yes @rely-ai/caliber ${subcommandTail}`) return true;
258
- if (command === `npx @rely-ai/caliber ${subcommandTail}`) return true;
259
- return false;
260
- }
261
- var _resolved;
262
- var init_resolve_caliber = __esm({
263
- "src/lib/resolve-caliber.ts"() {
264
- "use strict";
265
- _resolved = null;
266
- }
267
- });
268
-
269
219
  // src/lib/lock.ts
270
220
  var lock_exports = {};
271
221
  __export(lock_exports, {
@@ -273,13 +223,13 @@ __export(lock_exports, {
273
223
  isCaliberRunning: () => isCaliberRunning,
274
224
  releaseLock: () => releaseLock
275
225
  });
276
- import fs31 from "fs";
277
- import path25 from "path";
278
- import os7 from "os";
226
+ import fs30 from "fs";
227
+ import path24 from "path";
228
+ import os6 from "os";
279
229
  function isCaliberRunning() {
280
230
  try {
281
- if (!fs31.existsSync(LOCK_FILE)) return false;
282
- const raw = fs31.readFileSync(LOCK_FILE, "utf-8").trim();
231
+ if (!fs30.existsSync(LOCK_FILE)) return false;
232
+ const raw = fs30.readFileSync(LOCK_FILE, "utf-8").trim();
283
233
  const { pid, ts } = JSON.parse(raw);
284
234
  if (Date.now() - ts > STALE_MS) return false;
285
235
  try {
@@ -294,13 +244,13 @@ function isCaliberRunning() {
294
244
  }
295
245
  function acquireLock() {
296
246
  try {
297
- fs31.writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid, ts: Date.now() }));
247
+ fs30.writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid, ts: Date.now() }));
298
248
  } catch {
299
249
  }
300
250
  }
301
251
  function releaseLock() {
302
252
  try {
303
- if (fs31.existsSync(LOCK_FILE)) fs31.unlinkSync(LOCK_FILE);
253
+ if (fs30.existsSync(LOCK_FILE)) fs30.unlinkSync(LOCK_FILE);
304
254
  } catch {
305
255
  }
306
256
  }
@@ -308,15 +258,15 @@ var LOCK_FILE, STALE_MS;
308
258
  var init_lock = __esm({
309
259
  "src/lib/lock.ts"() {
310
260
  "use strict";
311
- LOCK_FILE = path25.join(os7.tmpdir(), ".caliber.lock");
261
+ LOCK_FILE = path24.join(os6.tmpdir(), ".caliber.lock");
312
262
  STALE_MS = 10 * 60 * 1e3;
313
263
  }
314
264
  });
315
265
 
316
266
  // src/cli.ts
317
267
  import { Command } from "commander";
318
- import fs38 from "fs";
319
- import path30 from "path";
268
+ import fs35 from "fs";
269
+ import path28 from "path";
320
270
  import { fileURLToPath } from "url";
321
271
 
322
272
  // src/commands/init.ts
@@ -2618,15 +2568,15 @@ init_config();
2618
2568
  // src/utils/dependencies.ts
2619
2569
  import { readFileSync } from "fs";
2620
2570
  import { join } from "path";
2621
- function readFileOrNull(path32) {
2571
+ function readFileOrNull(path30) {
2622
2572
  try {
2623
- return readFileSync(path32, "utf-8");
2573
+ return readFileSync(path30, "utf-8");
2624
2574
  } catch {
2625
2575
  return null;
2626
2576
  }
2627
2577
  }
2628
- function readJsonOrNull(path32) {
2629
- const content = readFileOrNull(path32);
2578
+ function readJsonOrNull(path30) {
2579
+ const content = readFileOrNull(path30);
2630
2580
  if (!content) return null;
2631
2581
  try {
2632
2582
  return JSON.parse(content);
@@ -3893,10 +3843,50 @@ ${agentRefs.join(" ")}
3893
3843
  }
3894
3844
 
3895
3845
  // src/lib/hooks.ts
3896
- init_resolve_caliber();
3897
3846
  import fs19 from "fs";
3898
3847
  import path14 from "path";
3899
3848
  import { execSync as execSync8 } from "child_process";
3849
+
3850
+ // src/lib/resolve-caliber.ts
3851
+ import fs18 from "fs";
3852
+ import { execSync as execSync7 } from "child_process";
3853
+ var _resolved = null;
3854
+ function resolveCaliber() {
3855
+ if (_resolved) return _resolved;
3856
+ const isNpx = process.argv[1]?.includes("_npx") || process.env.npm_execpath?.includes("npx");
3857
+ if (isNpx) {
3858
+ _resolved = "npx --yes @rely-ai/caliber";
3859
+ return _resolved;
3860
+ }
3861
+ try {
3862
+ const whichCmd = process.platform === "win32" ? "where caliber" : "which caliber";
3863
+ const found = execSync7(whichCmd, {
3864
+ encoding: "utf-8",
3865
+ stdio: ["pipe", "pipe", "pipe"]
3866
+ }).trim();
3867
+ if (found) {
3868
+ _resolved = found;
3869
+ return _resolved;
3870
+ }
3871
+ } catch {
3872
+ }
3873
+ const binPath = process.argv[1];
3874
+ if (binPath && fs18.existsSync(binPath)) {
3875
+ _resolved = binPath;
3876
+ return _resolved;
3877
+ }
3878
+ _resolved = "caliber";
3879
+ return _resolved;
3880
+ }
3881
+ function isCaliberCommand(command, subcommandTail) {
3882
+ if (command === `caliber ${subcommandTail}`) return true;
3883
+ if (command.endsWith(`/caliber ${subcommandTail}`)) return true;
3884
+ if (command === `npx --yes @rely-ai/caliber ${subcommandTail}`) return true;
3885
+ if (command === `npx @rely-ai/caliber ${subcommandTail}`) return true;
3886
+ return false;
3887
+ }
3888
+
3889
+ // src/lib/hooks.ts
3900
3890
  var SETTINGS_PATH = path14.join(".claude", "settings.json");
3901
3891
  var REFRESH_TAIL = "refresh --quiet";
3902
3892
  var HOOK_DESCRIPTION = "Caliber: auto-refreshing docs based on code changes";
@@ -4032,7 +4022,6 @@ function removePreCommitHook() {
4032
4022
  }
4033
4023
 
4034
4024
  // src/lib/learning-hooks.ts
4035
- init_resolve_caliber();
4036
4025
  import fs20 from "fs";
4037
4026
  import path15 from "path";
4038
4027
  var SETTINGS_PATH2 = path15.join(".claude", "settings.json");
@@ -4040,7 +4029,7 @@ var HOOK_TAILS = [
4040
4029
  { event: "PostToolUse", tail: "learn observe", description: "Caliber: recording tool usage for session learning" },
4041
4030
  { event: "PostToolUseFailure", tail: "learn observe --failure", description: "Caliber: recording tool failure for session learning" },
4042
4031
  { event: "UserPromptSubmit", tail: "learn observe --prompt", description: "Caliber: recording user prompt for correction detection" },
4043
- { event: "SessionEnd", tail: "learn finalize --auto", description: "Caliber: finalizing session learnings" }
4032
+ { event: "SessionEnd", tail: "learn finalize", description: "Caliber: finalizing session learnings" }
4044
4033
  ];
4045
4034
  function getHookConfigs() {
4046
4035
  const bin = resolveCaliber();
@@ -4101,7 +4090,7 @@ var CURSOR_HOOK_EVENTS = [
4101
4090
  { event: "postToolUse", tail: "learn observe" },
4102
4091
  { event: "postToolUseFailure", tail: "learn observe --failure" },
4103
4092
  { event: "userPromptSubmit", tail: "learn observe --prompt" },
4104
- { event: "sessionEnd", tail: "learn finalize --auto" }
4093
+ { event: "sessionEnd", tail: "learn finalize" }
4105
4094
  ];
4106
4095
  function readCursorHooks() {
4107
4096
  if (!fs20.existsSync(CURSOR_HOOKS_PATH)) return { version: 1, hooks: {} };
@@ -6165,9 +6154,6 @@ function trackLearnNewLearning(props) {
6165
6154
  source_event_count: props.sourceEventCount
6166
6155
  });
6167
6156
  }
6168
- function trackInsightsViewed(totalSessions, learningCount) {
6169
- trackEvent("insights_viewed", { total_sessions: totalSessions, learning_count: learningCount });
6170
- }
6171
6157
 
6172
6158
  // src/commands/recommend.ts
6173
6159
  function detectLocalPlatforms() {
@@ -6955,11 +6941,11 @@ function countIssuePoints(issues) {
6955
6941
  }
6956
6942
  async function scoreAndRefine(setup, dir, sessionHistory, callbacks) {
6957
6943
  const existsCache = /* @__PURE__ */ new Map();
6958
- const cachedExists = (path32) => {
6959
- const cached = existsCache.get(path32);
6944
+ const cachedExists = (path30) => {
6945
+ const cached = existsCache.get(path30);
6960
6946
  if (cached !== void 0) return cached;
6961
- const result = existsSync9(path32);
6962
- existsCache.set(path32, result);
6947
+ const result = existsSync9(path30);
6948
+ existsCache.set(path30, result);
6963
6949
  return result;
6964
6950
  };
6965
6951
  const projectStructure = collectProjectStructure(dir);
@@ -8140,7 +8126,7 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
8140
8126
  }
8141
8127
  function summarizeSetup(action, setup) {
8142
8128
  const descriptions = setup.fileDescriptions;
8143
- const files = descriptions ? Object.entries(descriptions).map(([path32, desc]) => ` ${path32}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
8129
+ const files = descriptions ? Object.entries(descriptions).map(([path30, desc]) => ` ${path30}: ${desc}`).join("\n") : Object.keys(setup).filter((k) => k !== "targetAgent" && k !== "fileDescriptions").join(", ");
8144
8130
  return `${action}. Files:
8145
8131
  ${files}`;
8146
8132
  }
@@ -8245,7 +8231,6 @@ async function promptLearnInstall(targetAgent) {
8245
8231
  `));
8246
8232
  return select5({
8247
8233
  message: "Enable session learning?",
8248
- default: true,
8249
8234
  choices: [
8250
8235
  { name: "Enable session learning (recommended)", value: true },
8251
8236
  { name: "Skip for now", value: false }
@@ -8672,79 +8657,12 @@ async function regenerateCommand(options) {
8672
8657
  }
8673
8658
 
8674
8659
  // src/commands/score.ts
8675
- import fs28 from "fs";
8676
- import os6 from "os";
8677
- import path22 from "path";
8678
- import { execFileSync } from "child_process";
8679
8660
  import chalk15 from "chalk";
8680
- var CONFIG_FILES = ["CLAUDE.md", "AGENTS.md", ".cursorrules", "CALIBER_LEARNINGS.md"];
8681
- var CONFIG_DIRS = [".claude", ".cursor"];
8682
- function scoreBaseRef(ref, target) {
8683
- if (!/^[\w.\-\/~^@{}]+$/.test(ref)) return null;
8684
- const tmpDir = fs28.mkdtempSync(path22.join(os6.tmpdir(), "caliber-compare-"));
8685
- try {
8686
- for (const file of CONFIG_FILES) {
8687
- try {
8688
- const content = execFileSync("git", ["show", `${ref}:${file}`], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
8689
- fs28.writeFileSync(path22.join(tmpDir, file), content);
8690
- } catch {
8691
- }
8692
- }
8693
- for (const dir of CONFIG_DIRS) {
8694
- try {
8695
- const files = execFileSync("git", ["ls-tree", "-r", "--name-only", ref, `${dir}/`], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n").filter(Boolean);
8696
- for (const file of files) {
8697
- const filePath = path22.join(tmpDir, file);
8698
- fs28.mkdirSync(path22.dirname(filePath), { recursive: true });
8699
- const content = execFileSync("git", ["show", `${ref}:${file}`], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
8700
- fs28.writeFileSync(filePath, content);
8701
- }
8702
- } catch {
8703
- }
8704
- }
8705
- const result = computeLocalScore(tmpDir, target);
8706
- return { score: result.score, grade: result.grade };
8707
- } catch {
8708
- return null;
8709
- } finally {
8710
- fs28.rmSync(tmpDir, { recursive: true, force: true });
8711
- }
8712
- }
8713
8661
  async function scoreCommand(options) {
8714
8662
  const dir = process.cwd();
8715
8663
  const target = options.agent ?? readState()?.targetAgent;
8716
8664
  const result = computeLocalScore(dir, target);
8717
8665
  trackScoreComputed(result.score, target);
8718
- if (options.compare) {
8719
- const baseResult = scoreBaseRef(options.compare, target);
8720
- if (!baseResult) {
8721
- console.error(chalk15.red(`Could not score ref "${options.compare}" \u2014 branch or ref not found.`));
8722
- process.exitCode = 1;
8723
- return;
8724
- }
8725
- const delta = result.score - baseResult.score;
8726
- if (options.json) {
8727
- console.log(JSON.stringify({ current: result, base: { score: baseResult.score, grade: baseResult.grade, ref: options.compare }, delta }, null, 2));
8728
- return;
8729
- }
8730
- if (options.quiet) {
8731
- const sign = delta > 0 ? "+" : "";
8732
- console.log(`${result.score}/100 (${result.grade}) ${sign}${delta} from ${options.compare}`);
8733
- return;
8734
- }
8735
- displayScore(result);
8736
- const separator2 = chalk15.gray(" " + "\u2500".repeat(53));
8737
- console.log(separator2);
8738
- if (delta > 0) {
8739
- console.log(chalk15.green(` +${delta}`) + chalk15.gray(` from ${options.compare} (${baseResult.score}/100)`));
8740
- } else if (delta < 0) {
8741
- console.log(chalk15.red(` ${delta}`) + chalk15.gray(` from ${options.compare} (${baseResult.score}/100)`));
8742
- } else {
8743
- console.log(chalk15.gray(` No change from ${options.compare} (${baseResult.score}/100)`));
8744
- }
8745
- console.log("");
8746
- return;
8747
- }
8748
8666
  if (options.json) {
8749
8667
  console.log(JSON.stringify(result, null, 2));
8750
8668
  return;
@@ -8767,8 +8685,8 @@ async function scoreCommand(options) {
8767
8685
  }
8768
8686
 
8769
8687
  // src/commands/refresh.ts
8770
- import fs32 from "fs";
8771
- import path26 from "path";
8688
+ import fs31 from "fs";
8689
+ import path25 from "path";
8772
8690
  import chalk16 from "chalk";
8773
8691
  import ora6 from "ora";
8774
8692
 
@@ -8846,37 +8764,37 @@ function collectDiff(lastSha) {
8846
8764
  }
8847
8765
 
8848
8766
  // src/writers/refresh.ts
8849
- import fs29 from "fs";
8850
- import path23 from "path";
8767
+ import fs28 from "fs";
8768
+ import path22 from "path";
8851
8769
  function writeRefreshDocs(docs) {
8852
8770
  const written = [];
8853
8771
  if (docs.claudeMd) {
8854
- fs29.writeFileSync("CLAUDE.md", docs.claudeMd);
8772
+ fs28.writeFileSync("CLAUDE.md", docs.claudeMd);
8855
8773
  written.push("CLAUDE.md");
8856
8774
  }
8857
8775
  if (docs.readmeMd) {
8858
- fs29.writeFileSync("README.md", docs.readmeMd);
8776
+ fs28.writeFileSync("README.md", docs.readmeMd);
8859
8777
  written.push("README.md");
8860
8778
  }
8861
8779
  if (docs.cursorrules) {
8862
- fs29.writeFileSync(".cursorrules", docs.cursorrules);
8780
+ fs28.writeFileSync(".cursorrules", docs.cursorrules);
8863
8781
  written.push(".cursorrules");
8864
8782
  }
8865
8783
  if (docs.cursorRules) {
8866
- const rulesDir = path23.join(".cursor", "rules");
8867
- if (!fs29.existsSync(rulesDir)) fs29.mkdirSync(rulesDir, { recursive: true });
8784
+ const rulesDir = path22.join(".cursor", "rules");
8785
+ if (!fs28.existsSync(rulesDir)) fs28.mkdirSync(rulesDir, { recursive: true });
8868
8786
  for (const rule of docs.cursorRules) {
8869
- const filePath = path23.join(rulesDir, rule.filename);
8870
- fs29.writeFileSync(filePath, rule.content);
8787
+ const filePath = path22.join(rulesDir, rule.filename);
8788
+ fs28.writeFileSync(filePath, rule.content);
8871
8789
  written.push(filePath);
8872
8790
  }
8873
8791
  }
8874
8792
  if (docs.claudeSkills) {
8875
- const skillsDir = path23.join(".claude", "skills");
8876
- if (!fs29.existsSync(skillsDir)) fs29.mkdirSync(skillsDir, { recursive: true });
8793
+ const skillsDir = path22.join(".claude", "skills");
8794
+ if (!fs28.existsSync(skillsDir)) fs28.mkdirSync(skillsDir, { recursive: true });
8877
8795
  for (const skill of docs.claudeSkills) {
8878
- const filePath = path23.join(skillsDir, skill.filename);
8879
- fs29.writeFileSync(filePath, skill.content);
8796
+ const filePath = path22.join(skillsDir, skill.filename);
8797
+ fs28.writeFileSync(filePath, skill.content);
8880
8798
  written.push(filePath);
8881
8799
  }
8882
8800
  }
@@ -8953,29 +8871,8 @@ Changed files: ${diff.changedFiles.join(", ")}`);
8953
8871
  }
8954
8872
 
8955
8873
  // src/learner/writer.ts
8956
- import fs30 from "fs";
8957
- import path24 from "path";
8958
-
8959
- // src/learner/utils.ts
8960
- var TYPE_PREFIX_RE = /^\*\*\[[^\]]+\]\*\*\s*/;
8961
- function normalizeBullet(bullet) {
8962
- return bullet.replace(/^- /, "").replace(TYPE_PREFIX_RE, "").replace(/`[^`]*`/g, "").replace(/\s+/g, " ").toLowerCase().trim();
8963
- }
8964
- function hasTypePrefix(bullet) {
8965
- return TYPE_PREFIX_RE.test(bullet.replace(/^- /, ""));
8966
- }
8967
- var SIMILARITY_THRESHOLD = 0.7;
8968
- function isSimilarLearning(a, b) {
8969
- const normA = normalizeBullet(a);
8970
- const normB = normalizeBullet(b);
8971
- if (!normA || !normB) return false;
8972
- const shorter = Math.min(normA.length, normB.length);
8973
- const longer = Math.max(normA.length, normB.length);
8974
- if (!(normA.includes(normB) || normB.includes(normA))) return false;
8975
- return shorter / longer > SIMILARITY_THRESHOLD;
8976
- }
8977
-
8978
- // src/learner/writer.ts
8874
+ import fs29 from "fs";
8875
+ import path23 from "path";
8979
8876
  var LEARNINGS_FILE = "CALIBER_LEARNINGS.md";
8980
8877
  var LEARNINGS_HEADER = `# Caliber Learnings
8981
8878
 
@@ -9022,6 +8919,13 @@ function parseBullets(content) {
9022
8919
  if (current) bullets.push(current);
9023
8920
  return bullets;
9024
8921
  }
8922
+ var TYPE_PREFIX_RE = /^\*\*\[[^\]]+\]\*\*\s*/;
8923
+ function normalizeBullet(bullet) {
8924
+ return bullet.replace(/^- /, "").replace(TYPE_PREFIX_RE, "").replace(/`[^`]*`/g, "").replace(/\s+/g, " ").toLowerCase().trim();
8925
+ }
8926
+ function hasTypePrefix(bullet) {
8927
+ return TYPE_PREFIX_RE.test(bullet.replace(/^- /, ""));
8928
+ }
9025
8929
  function deduplicateLearnedItems(existing, incoming) {
9026
8930
  const existingBullets = existing ? parseBullets(existing) : [];
9027
8931
  const incomingBullets = parseBullets(incoming);
@@ -9030,7 +8934,13 @@ function deduplicateLearnedItems(existing, incoming) {
9030
8934
  for (const bullet of incomingBullets) {
9031
8935
  const norm = normalizeBullet(bullet);
9032
8936
  if (!norm) continue;
9033
- const dupIdx = merged.findIndex((e) => isSimilarLearning(bullet, e));
8937
+ const dupIdx = merged.findIndex((e) => {
8938
+ const eNorm = normalizeBullet(e);
8939
+ const shorter = Math.min(norm.length, eNorm.length);
8940
+ const longer = Math.max(norm.length, eNorm.length);
8941
+ if (!(eNorm.includes(norm) || norm.includes(eNorm))) return false;
8942
+ return shorter / longer > 0.7;
8943
+ });
9034
8944
  if (dupIdx !== -1) {
9035
8945
  if (hasTypePrefix(bullet) && !hasTypePrefix(merged[dupIdx])) {
9036
8946
  merged[dupIdx] = bullet;
@@ -9046,16 +8956,16 @@ function deduplicateLearnedItems(existing, incoming) {
9046
8956
  function writeLearnedSection(content) {
9047
8957
  const existingSection = readLearnedSection();
9048
8958
  const { merged, newCount, newItems } = deduplicateLearnedItems(existingSection, content);
9049
- fs30.writeFileSync(LEARNINGS_FILE, LEARNINGS_HEADER + merged + "\n");
8959
+ fs29.writeFileSync(LEARNINGS_FILE, LEARNINGS_HEADER + merged + "\n");
9050
8960
  return { newCount, newItems };
9051
8961
  }
9052
8962
  function writeLearnedSkill(skill) {
9053
- const skillDir = path24.join(".claude", "skills", skill.name);
9054
- if (!fs30.existsSync(skillDir)) fs30.mkdirSync(skillDir, { recursive: true });
9055
- const skillPath = path24.join(skillDir, "SKILL.md");
9056
- if (!skill.isNew && fs30.existsSync(skillPath)) {
9057
- const existing = fs30.readFileSync(skillPath, "utf-8");
9058
- fs30.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
8963
+ const skillDir = path23.join(".claude", "skills", skill.name);
8964
+ if (!fs29.existsSync(skillDir)) fs29.mkdirSync(skillDir, { recursive: true });
8965
+ const skillPath = path23.join(skillDir, "SKILL.md");
8966
+ if (!skill.isNew && fs29.existsSync(skillPath)) {
8967
+ const existing = fs29.readFileSync(skillPath, "utf-8");
8968
+ fs29.writeFileSync(skillPath, existing.trimEnd() + "\n\n" + skill.content);
9059
8969
  } else {
9060
8970
  const frontmatter = [
9061
8971
  "---",
@@ -9064,37 +8974,37 @@ function writeLearnedSkill(skill) {
9064
8974
  "---",
9065
8975
  ""
9066
8976
  ].join("\n");
9067
- fs30.writeFileSync(skillPath, frontmatter + skill.content);
8977
+ fs29.writeFileSync(skillPath, frontmatter + skill.content);
9068
8978
  }
9069
8979
  return skillPath;
9070
8980
  }
9071
8981
  function readLearnedSection() {
9072
- if (fs30.existsSync(LEARNINGS_FILE)) {
9073
- const content2 = fs30.readFileSync(LEARNINGS_FILE, "utf-8");
8982
+ if (fs29.existsSync(LEARNINGS_FILE)) {
8983
+ const content2 = fs29.readFileSync(LEARNINGS_FILE, "utf-8");
9074
8984
  const bullets = content2.split("\n").filter((l) => l.startsWith("- ")).join("\n");
9075
8985
  return bullets || null;
9076
8986
  }
9077
8987
  const claudeMdPath = "CLAUDE.md";
9078
- if (!fs30.existsSync(claudeMdPath)) return null;
9079
- const content = fs30.readFileSync(claudeMdPath, "utf-8");
8988
+ if (!fs29.existsSync(claudeMdPath)) return null;
8989
+ const content = fs29.readFileSync(claudeMdPath, "utf-8");
9080
8990
  const startIdx = content.indexOf(LEARNED_START);
9081
8991
  const endIdx = content.indexOf(LEARNED_END);
9082
8992
  if (startIdx === -1 || endIdx === -1) return null;
9083
8993
  return content.slice(startIdx + LEARNED_START.length, endIdx).trim() || null;
9084
8994
  }
9085
8995
  function migrateInlineLearnings() {
9086
- if (fs30.existsSync(LEARNINGS_FILE)) return false;
8996
+ if (fs29.existsSync(LEARNINGS_FILE)) return false;
9087
8997
  const claudeMdPath = "CLAUDE.md";
9088
- if (!fs30.existsSync(claudeMdPath)) return false;
9089
- const content = fs30.readFileSync(claudeMdPath, "utf-8");
8998
+ if (!fs29.existsSync(claudeMdPath)) return false;
8999
+ const content = fs29.readFileSync(claudeMdPath, "utf-8");
9090
9000
  const startIdx = content.indexOf(LEARNED_START);
9091
9001
  const endIdx = content.indexOf(LEARNED_END);
9092
9002
  if (startIdx === -1 || endIdx === -1) return false;
9093
9003
  const section = content.slice(startIdx + LEARNED_START.length, endIdx).trim();
9094
9004
  if (!section) return false;
9095
- fs30.writeFileSync(LEARNINGS_FILE, LEARNINGS_HEADER + section + "\n");
9005
+ fs29.writeFileSync(LEARNINGS_FILE, LEARNINGS_HEADER + section + "\n");
9096
9006
  const cleaned = content.slice(0, startIdx) + content.slice(endIdx + LEARNED_END.length);
9097
- fs30.writeFileSync(claudeMdPath, cleaned.replace(/\n{3,}/g, "\n\n").trim() + "\n");
9007
+ fs29.writeFileSync(claudeMdPath, cleaned.replace(/\n{3,}/g, "\n\n").trim() + "\n");
9098
9008
  return true;
9099
9009
  }
9100
9010
 
@@ -9106,11 +9016,11 @@ function log2(quiet, ...args) {
9106
9016
  function discoverGitRepos(parentDir) {
9107
9017
  const repos = [];
9108
9018
  try {
9109
- const entries = fs32.readdirSync(parentDir, { withFileTypes: true });
9019
+ const entries = fs31.readdirSync(parentDir, { withFileTypes: true });
9110
9020
  for (const entry of entries) {
9111
9021
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
9112
- const childPath = path26.join(parentDir, entry.name);
9113
- if (fs32.existsSync(path26.join(childPath, ".git"))) {
9022
+ const childPath = path25.join(parentDir, entry.name);
9023
+ if (fs31.existsSync(path25.join(childPath, ".git"))) {
9114
9024
  repos.push(childPath);
9115
9025
  }
9116
9026
  }
@@ -9213,7 +9123,7 @@ async function refreshCommand(options) {
9213
9123
  `));
9214
9124
  const originalDir = process.cwd();
9215
9125
  for (const repo of repos) {
9216
- const repoName = path26.basename(repo);
9126
+ const repoName = path25.basename(repo);
9217
9127
  try {
9218
9128
  process.chdir(repo);
9219
9129
  await refreshSingleRepo(repo, { ...options, label: repoName });
@@ -9234,7 +9144,6 @@ async function refreshCommand(options) {
9234
9144
 
9235
9145
  // src/commands/hooks.ts
9236
9146
  import chalk17 from "chalk";
9237
- import fs33 from "fs";
9238
9147
  var HOOKS = [
9239
9148
  {
9240
9149
  id: "session-end",
@@ -9274,14 +9183,6 @@ async function hooksCommand(options) {
9274
9183
  console.log(chalk17.green(" \u2713") + ` ${hook.label} enabled`);
9275
9184
  }
9276
9185
  }
9277
- if (fs33.existsSync(".claude")) {
9278
- const r = installLearningHooks();
9279
- if (r.installed) console.log(chalk17.green(" \u2713") + " Claude Code learning hooks enabled");
9280
- }
9281
- if (fs33.existsSync(".cursor")) {
9282
- const r = installCursorLearningHooks();
9283
- if (r.installed) console.log(chalk17.green(" \u2713") + " Cursor learning hooks enabled");
9284
- }
9285
9186
  return;
9286
9187
  }
9287
9188
  if (options.remove) {
@@ -9446,8 +9347,8 @@ async function configCommand() {
9446
9347
  }
9447
9348
 
9448
9349
  // src/commands/learn.ts
9449
- import fs37 from "fs";
9450
- import chalk20 from "chalk";
9350
+ import fs34 from "fs";
9351
+ import chalk19 from "chalk";
9451
9352
 
9452
9353
  // src/learner/stdin.ts
9453
9354
  var STDIN_TIMEOUT_MS = 5e3;
@@ -9478,25 +9379,24 @@ function readStdin() {
9478
9379
 
9479
9380
  // src/learner/storage.ts
9480
9381
  init_constants();
9481
- import fs34 from "fs";
9482
- import path27 from "path";
9382
+ import fs32 from "fs";
9383
+ import path26 from "path";
9483
9384
  var MAX_RESPONSE_LENGTH = 2e3;
9484
9385
  var DEFAULT_STATE = {
9485
9386
  sessionId: null,
9486
9387
  eventCount: 0,
9487
- lastAnalysisTimestamp: null,
9488
- lastAnalysisEventCount: 0
9388
+ lastAnalysisTimestamp: null
9489
9389
  };
9490
9390
  function ensureLearningDir() {
9491
- if (!fs34.existsSync(LEARNING_DIR)) {
9492
- fs34.mkdirSync(LEARNING_DIR, { recursive: true });
9391
+ if (!fs32.existsSync(LEARNING_DIR)) {
9392
+ fs32.mkdirSync(LEARNING_DIR, { recursive: true });
9493
9393
  }
9494
9394
  }
9495
9395
  function sessionFilePath() {
9496
- return path27.join(LEARNING_DIR, LEARNING_SESSION_FILE);
9396
+ return path26.join(LEARNING_DIR, LEARNING_SESSION_FILE);
9497
9397
  }
9498
9398
  function stateFilePath() {
9499
- return path27.join(LEARNING_DIR, LEARNING_STATE_FILE);
9399
+ return path26.join(LEARNING_DIR, LEARNING_STATE_FILE);
9500
9400
  }
9501
9401
  function truncateResponse(response) {
9502
9402
  const str = JSON.stringify(response);
@@ -9507,29 +9407,29 @@ function appendEvent(event) {
9507
9407
  ensureLearningDir();
9508
9408
  const truncated = { ...event, tool_response: truncateResponse(event.tool_response) };
9509
9409
  const filePath = sessionFilePath();
9510
- fs34.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
9410
+ fs32.appendFileSync(filePath, JSON.stringify(truncated) + "\n");
9511
9411
  const count = getEventCount();
9512
9412
  if (count > LEARNING_MAX_EVENTS) {
9513
- const lines = fs34.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
9413
+ const lines = fs32.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
9514
9414
  const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
9515
- fs34.writeFileSync(filePath, kept.join("\n") + "\n");
9415
+ fs32.writeFileSync(filePath, kept.join("\n") + "\n");
9516
9416
  }
9517
9417
  }
9518
9418
  function appendPromptEvent(event) {
9519
9419
  ensureLearningDir();
9520
9420
  const filePath = sessionFilePath();
9521
- fs34.appendFileSync(filePath, JSON.stringify(event) + "\n");
9421
+ fs32.appendFileSync(filePath, JSON.stringify(event) + "\n");
9522
9422
  const count = getEventCount();
9523
9423
  if (count > LEARNING_MAX_EVENTS) {
9524
- const lines = fs34.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
9424
+ const lines = fs32.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
9525
9425
  const kept = lines.slice(lines.length - LEARNING_MAX_EVENTS);
9526
- fs34.writeFileSync(filePath, kept.join("\n") + "\n");
9426
+ fs32.writeFileSync(filePath, kept.join("\n") + "\n");
9527
9427
  }
9528
9428
  }
9529
9429
  function readAllEvents() {
9530
9430
  const filePath = sessionFilePath();
9531
- if (!fs34.existsSync(filePath)) return [];
9532
- const lines = fs34.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
9431
+ if (!fs32.existsSync(filePath)) return [];
9432
+ const lines = fs32.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
9533
9433
  const events = [];
9534
9434
  for (const line of lines) {
9535
9435
  try {
@@ -9541,26 +9441,26 @@ function readAllEvents() {
9541
9441
  }
9542
9442
  function getEventCount() {
9543
9443
  const filePath = sessionFilePath();
9544
- if (!fs34.existsSync(filePath)) return 0;
9545
- const content = fs34.readFileSync(filePath, "utf-8");
9444
+ if (!fs32.existsSync(filePath)) return 0;
9445
+ const content = fs32.readFileSync(filePath, "utf-8");
9546
9446
  return content.split("\n").filter(Boolean).length;
9547
9447
  }
9548
9448
  function clearSession() {
9549
9449
  const filePath = sessionFilePath();
9550
- if (fs34.existsSync(filePath)) fs34.unlinkSync(filePath);
9450
+ if (fs32.existsSync(filePath)) fs32.unlinkSync(filePath);
9551
9451
  }
9552
9452
  function readState2() {
9553
9453
  const filePath = stateFilePath();
9554
- if (!fs34.existsSync(filePath)) return { ...DEFAULT_STATE };
9454
+ if (!fs32.existsSync(filePath)) return { ...DEFAULT_STATE };
9555
9455
  try {
9556
- return JSON.parse(fs34.readFileSync(filePath, "utf-8"));
9456
+ return JSON.parse(fs32.readFileSync(filePath, "utf-8"));
9557
9457
  } catch {
9558
9458
  return { ...DEFAULT_STATE };
9559
9459
  }
9560
9460
  }
9561
9461
  function writeState2(state) {
9562
9462
  ensureLearningDir();
9563
- fs34.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
9463
+ fs32.writeFileSync(stateFilePath(), JSON.stringify(state, null, 2));
9564
9464
  }
9565
9465
  function resetState() {
9566
9466
  writeState2({ ...DEFAULT_STATE });
@@ -9568,14 +9468,14 @@ function resetState() {
9568
9468
  var LOCK_FILE2 = "finalize.lock";
9569
9469
  var LOCK_STALE_MS = 5 * 60 * 1e3;
9570
9470
  function lockFilePath() {
9571
- return path27.join(LEARNING_DIR, LOCK_FILE2);
9471
+ return path26.join(LEARNING_DIR, LOCK_FILE2);
9572
9472
  }
9573
9473
  function acquireFinalizeLock() {
9574
9474
  ensureLearningDir();
9575
9475
  const lockPath = lockFilePath();
9576
- if (fs34.existsSync(lockPath)) {
9476
+ if (fs32.existsSync(lockPath)) {
9577
9477
  try {
9578
- const stat = fs34.statSync(lockPath);
9478
+ const stat = fs32.statSync(lockPath);
9579
9479
  if (Date.now() - stat.mtimeMs < LOCK_STALE_MS) {
9580
9480
  return false;
9581
9481
  }
@@ -9583,7 +9483,7 @@ function acquireFinalizeLock() {
9583
9483
  }
9584
9484
  }
9585
9485
  try {
9586
- fs34.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
9486
+ fs32.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
9587
9487
  return true;
9588
9488
  } catch {
9589
9489
  return false;
@@ -9592,7 +9492,7 @@ function acquireFinalizeLock() {
9592
9492
  function releaseFinalizeLock() {
9593
9493
  const lockPath = lockFilePath();
9594
9494
  try {
9595
- if (fs34.existsSync(lockPath)) fs34.unlinkSync(lockPath);
9495
+ if (fs32.existsSync(lockPath)) fs32.unlinkSync(lockPath);
9596
9496
  } catch {
9597
9497
  }
9598
9498
  }
@@ -9636,45 +9536,6 @@ function sanitizeSecrets(text) {
9636
9536
  return result;
9637
9537
  }
9638
9538
 
9639
- // src/lib/notifications.ts
9640
- init_constants();
9641
- import fs35 from "fs";
9642
- import path28 from "path";
9643
- import chalk19 from "chalk";
9644
- var NOTIFICATION_FILE = path28.join(LEARNING_DIR, "last-finalize-summary.json");
9645
- function writeFinalizeSummary(summary) {
9646
- try {
9647
- ensureLearningDir();
9648
- fs35.writeFileSync(NOTIFICATION_FILE, JSON.stringify(summary, null, 2));
9649
- } catch {
9650
- }
9651
- }
9652
- function checkPendingNotifications() {
9653
- try {
9654
- if (!fs35.existsSync(NOTIFICATION_FILE)) return;
9655
- const raw = fs35.readFileSync(NOTIFICATION_FILE, "utf-8");
9656
- fs35.unlinkSync(NOTIFICATION_FILE);
9657
- const summary = JSON.parse(raw);
9658
- if (!summary.newItemCount || summary.newItemCount === 0) return;
9659
- const wasteLabel = summary.wasteTokens > 0 ? ` (~${summary.wasteTokens.toLocaleString()} wasted tokens captured)` : "";
9660
- console.log(
9661
- chalk19.dim(`caliber: learned ${summary.newItemCount} new pattern${summary.newItemCount === 1 ? "" : "s"} from your last session${wasteLabel}`)
9662
- );
9663
- for (const item of summary.newItems.slice(0, 3)) {
9664
- console.log(chalk19.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
9665
- }
9666
- if (summary.newItems.length > 3) {
9667
- console.log(chalk19.dim(` ... and ${summary.newItems.length - 3} more`));
9668
- }
9669
- console.log("");
9670
- } catch {
9671
- try {
9672
- fs35.unlinkSync(NOTIFICATION_FILE);
9673
- } catch {
9674
- }
9675
- }
9676
- }
9677
-
9678
9539
  // src/ai/learn.ts
9679
9540
  init_config();
9680
9541
  var MAX_PROMPT_TOKENS = 1e5;
@@ -9744,29 +9605,14 @@ ${existingLearnedSection}`);
9744
9605
 
9745
9606
  ${skillsSummary}`);
9746
9607
  }
9747
- contextParts.push(`## Task Segmentation & Attribution Instructions
9748
-
9749
- Analyze the event timeline and identify logical tasks (a task = one user intent, from their prompt through the agent's work until the next user prompt or session end).
9750
-
9751
- For each task, determine:
9752
- - "summary": what the user was trying to accomplish (1 sentence)
9753
- - "outcome": "success" (completed without issues), "corrected" (user had to redirect the agent), or "failed" (task was abandoned or produced errors)
9754
- - "startEventIdx" and "endEventIdx": 0-based indices in the event list
9755
- - "attribution": if the task was corrected or failed, identify which section of CLAUDE.md (by ## heading) SHOULD have contained guidance that would have prevented the issue. Include "configSection" (the heading text) and "relevance" (0-1).
9756
-
9757
- Include the "tasks" array in your JSON response alongside "claudeMdLearnedSection", "skills", and "explanations".`);
9758
- const prompt = `${contextParts.join("\n\n---\n\n")}
9759
-
9760
- ---
9761
-
9762
- ## Tool Events from Session (${fittedEvents.length} events)
9608
+ const prompt = `${contextParts.length ? contextParts.join("\n\n---\n\n") + "\n\n---\n\n" : ""}## Tool Events from Session (${fittedEvents.length} events)
9763
9609
 
9764
9610
  ${eventsText}`;
9765
9611
  const fastModel = getFastModel();
9766
9612
  const raw = await llmCall({
9767
9613
  system: LEARN_SYSTEM_PROMPT,
9768
9614
  prompt,
9769
- maxTokens: 8192,
9615
+ maxTokens: 4096,
9770
9616
  ...fastModel ? { model: fastModel } : {}
9771
9617
  });
9772
9618
  return parseAnalysisResponse(raw);
@@ -9802,8 +9648,8 @@ init_config();
9802
9648
 
9803
9649
  // src/learner/roi.ts
9804
9650
  init_constants();
9805
- import fs36 from "fs";
9806
- import path29 from "path";
9651
+ import fs33 from "fs";
9652
+ import path27 from "path";
9807
9653
  var DEFAULT_TOTALS = {
9808
9654
  totalWasteTokens: 0,
9809
9655
  totalWasteSeconds: 0,
@@ -9817,22 +9663,22 @@ var DEFAULT_TOTALS = {
9817
9663
  lastSessionTimestamp: ""
9818
9664
  };
9819
9665
  function roiFilePath() {
9820
- return path29.join(LEARNING_DIR, LEARNING_ROI_FILE);
9666
+ return path27.join(LEARNING_DIR, LEARNING_ROI_FILE);
9821
9667
  }
9822
9668
  function readROIStats() {
9823
9669
  const filePath = roiFilePath();
9824
- if (!fs36.existsSync(filePath)) {
9670
+ if (!fs33.existsSync(filePath)) {
9825
9671
  return { learnings: [], sessions: [], totals: { ...DEFAULT_TOTALS } };
9826
9672
  }
9827
9673
  try {
9828
- return JSON.parse(fs36.readFileSync(filePath, "utf-8"));
9674
+ return JSON.parse(fs33.readFileSync(filePath, "utf-8"));
9829
9675
  } catch {
9830
9676
  return { learnings: [], sessions: [], totals: { ...DEFAULT_TOTALS } };
9831
9677
  }
9832
9678
  }
9833
9679
  function writeROIStats(stats) {
9834
9680
  ensureLearningDir();
9835
- fs36.writeFileSync(roiFilePath(), JSON.stringify(stats, null, 2));
9681
+ fs33.writeFileSync(roiFilePath(), JSON.stringify(stats, null, 2));
9836
9682
  }
9837
9683
  function recalculateTotals(stats) {
9838
9684
  const totals = stats.totals;
@@ -9865,16 +9711,7 @@ function recordSession(summary, learnings) {
9865
9711
  const stats = readROIStats();
9866
9712
  stats.sessions.push(summary);
9867
9713
  if (learnings?.length) {
9868
- for (const entry of learnings) {
9869
- const existingIdx = stats.learnings.findIndex((e) => isSimilarLearning(e.summary, entry.summary));
9870
- if (existingIdx !== -1) {
9871
- stats.learnings[existingIdx].occurrences = (stats.learnings[existingIdx].occurrences || 1) + 1;
9872
- stats.learnings[existingIdx].timestamp = entry.timestamp;
9873
- } else {
9874
- entry.occurrences = 1;
9875
- stats.learnings.push(entry);
9876
- }
9877
- }
9714
+ stats.learnings.push(...learnings);
9878
9715
  }
9879
9716
  if (stats.sessions.length > MAX_SESSIONS) {
9880
9717
  stats.sessions = stats.sessions.slice(-MAX_SESSIONS);
@@ -9923,9 +9760,6 @@ function formatROISummary(stats) {
9923
9760
 
9924
9761
  // src/commands/learn.ts
9925
9762
  var MIN_EVENTS_FOR_ANALYSIS = 25;
9926
- var MIN_EVENTS_AUTO = 10;
9927
- var AUTO_SETTLE_MS = 200;
9928
- var INCREMENTAL_INTERVAL = 50;
9929
9763
  async function learnObserveCommand(options) {
9930
9764
  try {
9931
9765
  const raw = await readStdin();
@@ -9962,53 +9796,33 @@ async function learnObserveCommand(options) {
9962
9796
  state.eventCount++;
9963
9797
  if (!state.sessionId) state.sessionId = sessionId;
9964
9798
  writeState2(state);
9965
- const eventsSinceLastAnalysis = state.eventCount - (state.lastAnalysisEventCount || 0);
9966
- if (eventsSinceLastAnalysis >= INCREMENTAL_INTERVAL) {
9967
- try {
9968
- const { resolveCaliber: resolveCaliber2 } = await Promise.resolve().then(() => (init_resolve_caliber(), resolve_caliber_exports));
9969
- const bin = resolveCaliber2();
9970
- const { spawn: spawn4 } = await import("child_process");
9971
- spawn4(bin, ["learn", "finalize", "--auto", "--incremental"], {
9972
- detached: true,
9973
- stdio: "ignore"
9974
- }).unref();
9975
- } catch {
9976
- }
9977
- }
9978
9799
  } catch {
9979
9800
  }
9980
9801
  }
9981
9802
  async function learnFinalizeCommand(options) {
9982
- const isAuto = options?.auto === true;
9983
- const isIncremental = options?.incremental === true;
9984
- if (!options?.force && !isAuto) {
9803
+ if (!options?.force) {
9985
9804
  const { isCaliberRunning: isCaliberRunning2 } = await Promise.resolve().then(() => (init_lock(), lock_exports));
9986
9805
  if (isCaliberRunning2()) {
9987
- if (!isAuto) console.log(chalk20.dim("caliber: skipping finalize \u2014 another caliber process is running"));
9806
+ console.log(chalk19.dim("caliber: skipping finalize \u2014 another caliber process is running"));
9988
9807
  return;
9989
9808
  }
9990
9809
  }
9991
- if (isAuto) {
9992
- await new Promise((r) => setTimeout(r, AUTO_SETTLE_MS));
9993
- }
9994
9810
  if (!acquireFinalizeLock()) {
9995
- if (!isAuto) console.log(chalk20.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
9811
+ console.log(chalk19.dim("caliber: skipping finalize \u2014 another finalize is in progress"));
9996
9812
  return;
9997
9813
  }
9998
9814
  let analyzed = false;
9999
9815
  try {
10000
9816
  const config = loadConfig();
10001
9817
  if (!config) {
10002
- if (isAuto) return;
10003
- console.log(chalk20.yellow("caliber: no LLM provider configured \u2014 run `caliber config` first"));
9818
+ console.log(chalk19.yellow("caliber: no LLM provider configured \u2014 run `caliber config` first"));
10004
9819
  clearSession();
10005
9820
  resetState();
10006
9821
  return;
10007
9822
  }
10008
9823
  const events = readAllEvents();
10009
- const threshold = isAuto ? MIN_EVENTS_AUTO : MIN_EVENTS_FOR_ANALYSIS;
10010
- if (events.length < threshold) {
10011
- if (!isAuto) console.log(chalk20.dim(`caliber: ${events.length}/${threshold} events recorded \u2014 need more before analysis`));
9824
+ if (events.length < MIN_EVENTS_FOR_ANALYSIS) {
9825
+ console.log(chalk19.dim(`caliber: ${events.length}/${MIN_EVENTS_FOR_ANALYSIS} events recorded \u2014 need more before analysis`));
10012
9826
  return;
10013
9827
  }
10014
9828
  await validateModel({ fast: true });
@@ -10035,19 +9849,10 @@ async function learnFinalizeCommand(options) {
10035
9849
  });
10036
9850
  newLearningsProduced = result.newItemCount;
10037
9851
  if (result.newItemCount > 0) {
10038
- if (isAuto) {
10039
- writeFinalizeSummary({
10040
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10041
- newItemCount: result.newItemCount,
10042
- newItems: result.newItems,
10043
- wasteTokens: waste.totalWasteTokens
10044
- });
10045
- } else {
10046
- const wasteLabel = waste.totalWasteTokens > 0 ? ` (~${waste.totalWasteTokens.toLocaleString()} wasted tokens captured)` : "";
10047
- console.log(chalk20.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}${wasteLabel}`));
10048
- for (const item of result.newItems) {
10049
- console.log(chalk20.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
10050
- }
9852
+ const wasteLabel = waste.totalWasteTokens > 0 ? ` (~${waste.totalWasteTokens.toLocaleString()} wasted tokens captured)` : "";
9853
+ console.log(chalk19.dim(`caliber: learned ${result.newItemCount} new pattern${result.newItemCount === 1 ? "" : "s"}${wasteLabel}`));
9854
+ for (const item of result.newItems) {
9855
+ console.log(chalk19.dim(` + ${item.replace(/^- /, "").slice(0, 80)}`));
10051
9856
  }
10052
9857
  const wastePerLearning = Math.round(waste.totalWasteTokens / result.newItemCount);
10053
9858
  const TYPE_RE = /^\*\*\[([^\]]+)\]\*\*/;
@@ -10072,15 +9877,6 @@ async function learnFinalizeCommand(options) {
10072
9877
  roiLearningEntries = learningEntries;
10073
9878
  }
10074
9879
  }
10075
- const tasks = response.tasks || [];
10076
- let taskSuccessCount = 0;
10077
- let taskCorrectionCount = 0;
10078
- let taskFailureCount = 0;
10079
- for (const t2 of tasks) {
10080
- if (t2.outcome === "success") taskSuccessCount++;
10081
- else if (t2.outcome === "corrected") taskCorrectionCount++;
10082
- else if (t2.outcome === "failed") taskFailureCount++;
10083
- }
10084
9880
  const sessionSummary = {
10085
9881
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10086
9882
  sessionId: readState2().sessionId || "unknown",
@@ -10090,11 +9886,7 @@ async function learnFinalizeCommand(options) {
10090
9886
  wasteSeconds: Math.round(waste.totalWasteSeconds),
10091
9887
  hadLearningsAvailable: hadLearnings,
10092
9888
  learningsCount: existingLearnedItems,
10093
- newLearningsProduced,
10094
- taskCount: tasks.length > 0 ? tasks.length : void 0,
10095
- taskSuccessCount: tasks.length > 0 ? taskSuccessCount : void 0,
10096
- taskCorrectionCount: tasks.length > 0 ? taskCorrectionCount : void 0,
10097
- taskFailureCount: tasks.length > 0 ? taskFailureCount : void 0
9889
+ newLearningsProduced
10098
9890
  };
10099
9891
  const roiStats = recordSession(sessionSummary, roiLearningEntries);
10100
9892
  trackLearnSessionAnalyzed({
@@ -10121,73 +9913,66 @@ async function learnFinalizeCommand(options) {
10121
9913
  estimatedSavingsSeconds: t.estimatedSavingsSeconds,
10122
9914
  learningCount: roiStats.learnings.length
10123
9915
  });
10124
- if (!isAuto && t.estimatedSavingsTokens > 0) {
9916
+ if (t.estimatedSavingsTokens > 0) {
10125
9917
  const totalLearnings = existingLearnedItems + newLearningsProduced;
10126
- console.log(chalk20.dim(`caliber: ${totalLearnings} learnings active \u2014 est. ~${t.estimatedSavingsTokens.toLocaleString()} tokens saved across ${t.totalSessionsWithLearnings} sessions`));
9918
+ console.log(chalk19.dim(`caliber: ${totalLearnings} learnings active \u2014 est. ~${t.estimatedSavingsTokens.toLocaleString()} tokens saved across ${t.totalSessionsWithLearnings} sessions`));
10127
9919
  }
10128
9920
  } catch (err) {
10129
- if (options?.force && !isAuto) {
10130
- console.error(chalk20.red("caliber: finalize failed \u2014"), err instanceof Error ? err.message : err);
9921
+ if (options?.force) {
9922
+ console.error(chalk19.red("caliber: finalize failed \u2014"), err instanceof Error ? err.message : err);
10131
9923
  }
10132
9924
  } finally {
10133
9925
  if (analyzed) {
10134
- if (isIncremental) {
10135
- const state = readState2();
10136
- state.lastAnalysisEventCount = state.eventCount;
10137
- state.lastAnalysisTimestamp = (/* @__PURE__ */ new Date()).toISOString();
10138
- writeState2(state);
10139
- } else {
10140
- clearSession();
10141
- resetState();
10142
- }
9926
+ clearSession();
9927
+ resetState();
10143
9928
  }
10144
9929
  releaseFinalizeLock();
10145
9930
  }
10146
9931
  }
10147
9932
  async function learnInstallCommand() {
10148
9933
  let anyInstalled = false;
10149
- if (fs37.existsSync(".claude")) {
9934
+ if (fs34.existsSync(".claude")) {
10150
9935
  const r = installLearningHooks();
10151
9936
  if (r.installed) {
10152
- console.log(chalk20.green("\u2713") + " Claude Code learning hooks installed");
9937
+ console.log(chalk19.green("\u2713") + " Claude Code learning hooks installed");
10153
9938
  anyInstalled = true;
10154
9939
  } else if (r.alreadyInstalled) {
10155
- console.log(chalk20.dim(" Claude Code hooks already installed"));
9940
+ console.log(chalk19.dim(" Claude Code hooks already installed"));
10156
9941
  }
10157
9942
  }
10158
- if (fs37.existsSync(".cursor")) {
9943
+ if (fs34.existsSync(".cursor")) {
10159
9944
  const r = installCursorLearningHooks();
10160
9945
  if (r.installed) {
10161
- console.log(chalk20.green("\u2713") + " Cursor learning hooks installed");
9946
+ console.log(chalk19.green("\u2713") + " Cursor learning hooks installed");
10162
9947
  anyInstalled = true;
10163
9948
  } else if (r.alreadyInstalled) {
10164
- console.log(chalk20.dim(" Cursor hooks already installed"));
9949
+ console.log(chalk19.dim(" Cursor hooks already installed"));
10165
9950
  }
10166
9951
  }
10167
- if (!fs37.existsSync(".claude") && !fs37.existsSync(".cursor")) {
10168
- console.log(chalk20.yellow("No .claude/ or .cursor/ directory found."));
10169
- console.log(chalk20.dim(" Run `caliber init` first, or create the directory manually."));
9952
+ if (!fs34.existsSync(".claude") && !fs34.existsSync(".cursor")) {
9953
+ console.log(chalk19.yellow("No .claude/ or .cursor/ directory found."));
9954
+ console.log(chalk19.dim(" Run `caliber init` first, or create the directory manually."));
10170
9955
  return;
10171
9956
  }
10172
9957
  if (anyInstalled) {
10173
- console.log(chalk20.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
10174
- console.log(chalk20.dim(" Learnings written to CALIBER_LEARNINGS.md."));
9958
+ console.log(chalk19.dim(` Tool usage will be recorded and learnings extracted after \u2265${MIN_EVENTS_FOR_ANALYSIS} events.`));
9959
+ console.log(chalk19.dim(" Learnings written to CALIBER_LEARNINGS.md."));
10175
9960
  }
10176
9961
  }
10177
9962
  async function learnRemoveCommand() {
10178
9963
  let anyRemoved = false;
10179
9964
  const r1 = removeLearningHooks();
10180
9965
  if (r1.removed) {
10181
- console.log(chalk20.green("\u2713") + " Claude Code learning hooks removed");
9966
+ console.log(chalk19.green("\u2713") + " Claude Code learning hooks removed");
10182
9967
  anyRemoved = true;
10183
9968
  }
10184
9969
  const r2 = removeCursorLearningHooks();
10185
9970
  if (r2.removed) {
10186
- console.log(chalk20.green("\u2713") + " Cursor learning hooks removed");
9971
+ console.log(chalk19.green("\u2713") + " Cursor learning hooks removed");
10187
9972
  anyRemoved = true;
10188
9973
  }
10189
9974
  if (!anyRemoved) {
10190
- console.log(chalk20.dim("No learning hooks found."));
9975
+ console.log(chalk19.dim("No learning hooks found."));
10191
9976
  }
10192
9977
  }
10193
9978
  async function learnStatusCommand() {
@@ -10195,178 +9980,50 @@ async function learnStatusCommand() {
10195
9980
  const cursorInstalled = areCursorLearningHooksInstalled();
10196
9981
  const state = readState2();
10197
9982
  const eventCount = getEventCount();
10198
- console.log(chalk20.bold("Session Learning Status"));
9983
+ console.log(chalk19.bold("Session Learning Status"));
10199
9984
  console.log();
10200
9985
  if (claudeInstalled) {
10201
- console.log(chalk20.green("\u2713") + " Claude Code hooks " + chalk20.green("installed"));
9986
+ console.log(chalk19.green("\u2713") + " Claude Code hooks " + chalk19.green("installed"));
10202
9987
  } else {
10203
- console.log(chalk20.dim("\u2717") + " Claude Code hooks " + chalk20.dim("not installed"));
9988
+ console.log(chalk19.dim("\u2717") + " Claude Code hooks " + chalk19.dim("not installed"));
10204
9989
  }
10205
9990
  if (cursorInstalled) {
10206
- console.log(chalk20.green("\u2713") + " Cursor hooks " + chalk20.green("installed"));
9991
+ console.log(chalk19.green("\u2713") + " Cursor hooks " + chalk19.green("installed"));
10207
9992
  } else {
10208
- console.log(chalk20.dim("\u2717") + " Cursor hooks " + chalk20.dim("not installed"));
9993
+ console.log(chalk19.dim("\u2717") + " Cursor hooks " + chalk19.dim("not installed"));
10209
9994
  }
10210
9995
  if (!claudeInstalled && !cursorInstalled) {
10211
- console.log(chalk20.dim(" Run `caliber learn install` to enable session learning."));
9996
+ console.log(chalk19.dim(" Run `caliber learn install` to enable session learning."));
10212
9997
  }
10213
9998
  console.log();
10214
- console.log(`Events recorded: ${chalk20.cyan(String(eventCount))}`);
10215
- console.log(`Threshold for analysis: ${chalk20.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
9999
+ console.log(`Events recorded: ${chalk19.cyan(String(eventCount))}`);
10000
+ console.log(`Threshold for analysis: ${chalk19.cyan(String(MIN_EVENTS_FOR_ANALYSIS))}`);
10216
10001
  if (state.lastAnalysisTimestamp) {
10217
- console.log(`Last analysis: ${chalk20.cyan(state.lastAnalysisTimestamp)}`);
10002
+ console.log(`Last analysis: ${chalk19.cyan(state.lastAnalysisTimestamp)}`);
10218
10003
  } else {
10219
- console.log(`Last analysis: ${chalk20.dim("none")}`);
10004
+ console.log(`Last analysis: ${chalk19.dim("none")}`);
10220
10005
  }
10221
10006
  const learnedSection = readLearnedSection();
10222
10007
  if (learnedSection) {
10223
10008
  const lineCount = learnedSection.split("\n").filter(Boolean).length;
10224
10009
  console.log(`
10225
- Learned items in CALIBER_LEARNINGS.md: ${chalk20.cyan(String(lineCount))}`);
10010
+ Learned items in CALIBER_LEARNINGS.md: ${chalk19.cyan(String(lineCount))}`);
10226
10011
  }
10227
10012
  const roiStats = readROIStats();
10228
10013
  const roiSummary = formatROISummary(roiStats);
10229
10014
  if (roiSummary) {
10230
10015
  console.log();
10231
- console.log(chalk20.bold(roiSummary.split("\n")[0]));
10016
+ console.log(chalk19.bold(roiSummary.split("\n")[0]));
10232
10017
  for (const line of roiSummary.split("\n").slice(1)) {
10233
10018
  console.log(line);
10234
10019
  }
10235
10020
  }
10236
10021
  }
10237
10022
 
10238
- // src/commands/insights.ts
10239
- import chalk21 from "chalk";
10240
- var MIN_SESSIONS_FULL = 20;
10241
- function buildInsightsData(stats) {
10242
- const t = stats.totals;
10243
- const totalSessions = t.totalSessionsWithLearnings + t.totalSessionsWithoutLearnings;
10244
- const failureRateWith = t.totalSessionsWithLearnings > 0 ? t.totalFailuresWithLearnings / t.totalSessionsWithLearnings : null;
10245
- const failureRateWithout = t.totalSessionsWithoutLearnings > 0 ? t.totalFailuresWithoutLearnings / t.totalSessionsWithoutLearnings : null;
10246
- const failureRateImprovement = failureRateWith !== null && failureRateWithout !== null && failureRateWithout > 0 ? Math.round((1 - failureRateWith / failureRateWithout) * 100) : null;
10247
- let taskCount = 0;
10248
- let taskSuccessCount = 0;
10249
- let taskCorrectionCount = 0;
10250
- let taskFailureCount = 0;
10251
- for (const s of stats.sessions) {
10252
- if (s.taskCount) {
10253
- taskCount += s.taskCount;
10254
- taskSuccessCount += s.taskSuccessCount || 0;
10255
- taskCorrectionCount += s.taskCorrectionCount || 0;
10256
- taskFailureCount += s.taskFailureCount || 0;
10257
- }
10258
- }
10259
- const taskSuccessRate = taskCount > 0 ? Math.round(taskSuccessCount / taskCount * 100) : null;
10260
- return {
10261
- totalSessions,
10262
- learningCount: stats.learnings.length,
10263
- failureRateWith,
10264
- failureRateWithout,
10265
- failureRateImprovement,
10266
- taskCount,
10267
- taskSuccessCount,
10268
- taskCorrectionCount,
10269
- taskFailureCount,
10270
- taskSuccessRate,
10271
- totalWasteTokens: t.totalWasteTokens,
10272
- totalWasteSeconds: t.totalWasteSeconds,
10273
- estimatedSavingsTokens: t.estimatedSavingsTokens,
10274
- estimatedSavingsSeconds: t.estimatedSavingsSeconds
10275
- };
10276
- }
10277
- function displayColdStart(score) {
10278
- console.log(chalk21.bold("\n Agent Insights\n"));
10279
- const hooksInstalled = areLearningHooksInstalled() || areCursorLearningHooksInstalled();
10280
- if (!hooksInstalled) {
10281
- console.log(chalk21.yellow(" No learning hooks installed."));
10282
- console.log(chalk21.dim(" Run ") + chalk21.cyan("caliber learn install") + chalk21.dim(" to start tracking agent performance."));
10283
- } else {
10284
- console.log(chalk21.dim(" No session data yet. Use your AI agent and insights will appear here."));
10285
- console.log(chalk21.dim(" Learnings are extracted automatically at the end of each session."));
10286
- }
10287
- console.log(chalk21.dim(`
10288
- Config score: ${score.score}/100 (${score.grade})`));
10289
- console.log("");
10290
- }
10291
- function displayEarlyData(data, score) {
10292
- console.log(chalk21.bold("\n Agent Insights") + chalk21.yellow(" (early data)\n"));
10293
- console.log(chalk21.dim(" Still collecting data. Insights become more reliable after 20+ sessions.\n"));
10294
- console.log(` Sessions tracked: ${chalk21.cyan(String(data.totalSessions))}`);
10295
- console.log(` Learnings accumulated: ${chalk21.cyan(String(data.learningCount))}`);
10296
- if (data.totalWasteTokens > 0) {
10297
- console.log(` Waste captured: ${chalk21.cyan(data.totalWasteTokens.toLocaleString())} tokens`);
10298
- }
10299
- if (data.failureRateImprovement !== null && data.failureRateImprovement > 0) {
10300
- console.log(` Failure rate trend: ${chalk21.green(`${data.failureRateImprovement}% fewer`)} failures with learnings ${chalk21.dim("(early signal)")}`);
10301
- }
10302
- if (data.taskSuccessRate !== null) {
10303
- console.log(` Task success rate: ${chalk21.cyan(`${data.taskSuccessRate}%`)} ${chalk21.dim(`(${data.taskCount} tasks)`)}`);
10304
- }
10305
- console.log(` Config score: ${chalk21.cyan(`${score.score}/100`)} (${score.grade})`);
10306
- console.log("");
10307
- }
10308
- function displayFullInsights(data, score) {
10309
- console.log(chalk21.bold("\n Agent Insights\n"));
10310
- console.log(chalk21.bold(" Agent Health"));
10311
- if (data.taskSuccessRate !== null) {
10312
- const color = data.taskSuccessRate >= 80 ? chalk21.green : data.taskSuccessRate >= 60 ? chalk21.yellow : chalk21.red;
10313
- console.log(` Task success rate: ${color(`${data.taskSuccessRate}%`)} across ${data.taskCount} tasks`);
10314
- if (data.taskCorrectionCount > 0) {
10315
- console.log(` Corrections needed: ${chalk21.yellow(String(data.taskCorrectionCount))} tasks required user correction`);
10316
- }
10317
- }
10318
- console.log(` Sessions tracked: ${chalk21.cyan(String(data.totalSessions))}`);
10319
- console.log(chalk21.bold("\n Learning Impact"));
10320
- console.log(` Learnings active: ${chalk21.cyan(String(data.learningCount))}`);
10321
- if (data.failureRateWith !== null && data.failureRateWithout !== null) {
10322
- console.log(` Failure rate: ${chalk21.red(data.failureRateWithout.toFixed(1))}/session ${chalk21.dim("\u2192")} ${chalk21.green(data.failureRateWith.toFixed(1))}/session with learnings`);
10323
- if (data.failureRateImprovement !== null && data.failureRateImprovement > 0) {
10324
- console.log(` Improvement: ${chalk21.green(`${data.failureRateImprovement}%`)} fewer failures`);
10325
- }
10326
- }
10327
- if (data.totalWasteTokens > 0 || data.estimatedSavingsTokens > 0) {
10328
- console.log(chalk21.bold("\n Efficiency"));
10329
- if (data.totalWasteTokens > 0) {
10330
- console.log(` Waste captured: ${chalk21.cyan(data.totalWasteTokens.toLocaleString())} tokens`);
10331
- }
10332
- if (data.estimatedSavingsTokens > 0) {
10333
- console.log(` Estimated savings: ~${chalk21.green(data.estimatedSavingsTokens.toLocaleString())} tokens`);
10334
- }
10335
- if (data.estimatedSavingsSeconds > 0) {
10336
- console.log(` Time saved: ~${chalk21.green(formatDuration(data.estimatedSavingsSeconds))}`);
10337
- }
10338
- }
10339
- console.log(chalk21.bold("\n Config Quality"));
10340
- console.log(` Score: ${chalk21.cyan(`${score.score}/100`)} (${score.grade})`);
10341
- console.log("");
10342
- }
10343
- async function insightsCommand(options) {
10344
- const stats = readROIStats();
10345
- const data = buildInsightsData(stats);
10346
- const score = computeLocalScore(process.cwd(), readState()?.targetAgent);
10347
- trackInsightsViewed(data.totalSessions, data.learningCount);
10348
- if (options.json) {
10349
- console.log(JSON.stringify({
10350
- ...data,
10351
- tier: data.totalSessions === 0 ? "cold-start" : data.totalSessions < MIN_SESSIONS_FULL ? "early" : "full",
10352
- configScore: score.score,
10353
- configGrade: score.grade
10354
- }, null, 2));
10355
- return;
10356
- }
10357
- if (data.totalSessions === 0) {
10358
- displayColdStart(score);
10359
- } else if (data.totalSessions < MIN_SESSIONS_FULL) {
10360
- displayEarlyData(data, score);
10361
- } else {
10362
- displayFullInsights(data, score);
10363
- }
10364
- }
10365
-
10366
10023
  // src/cli.ts
10367
- var __dirname = path30.dirname(fileURLToPath(import.meta.url));
10024
+ var __dirname = path28.dirname(fileURLToPath(import.meta.url));
10368
10025
  var pkg = JSON.parse(
10369
- fs38.readFileSync(path30.resolve(__dirname, "..", "package.json"), "utf-8")
10026
+ fs35.readFileSync(path28.resolve(__dirname, "..", "package.json"), "utf-8")
10370
10027
  );
10371
10028
  var program = new Command();
10372
10029
  var displayVersion = process.env.CALIBER_LOCAL ? `${pkg.version}-local` : pkg.version;
@@ -10411,10 +10068,6 @@ program.hook("preAction", (thisCommand) => {
10411
10068
  setTelemetryDisabled(true);
10412
10069
  }
10413
10070
  initTelemetry();
10414
- const cmdName = thisCommand.name();
10415
- if (cmdName !== "learn" && cmdName !== "observe" && cmdName !== "finalize") {
10416
- checkPendingNotifications();
10417
- }
10418
10071
  });
10419
10072
  function parseAgentOption(value) {
10420
10073
  if (value === "both") return ["claude", "cursor"];
@@ -10433,28 +10086,27 @@ program.command("status").description("Show current Caliber setup status").optio
10433
10086
  program.command("regenerate").alias("regen").alias("re").description("Re-analyze project and regenerate setup").option("--dry-run", "Preview changes without writing files").action(tracked("regenerate", regenerateCommand));
10434
10087
  program.command("config").description("Configure LLM provider, API key, and model").action(tracked("config", configCommand));
10435
10088
  program.command("skills").description("Discover and install community skills for your project").action(tracked("skills", recommendCommand));
10436
- program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).option("--compare <ref>", "Compare score against a git ref (branch, tag, or SHA)").action(tracked("score", scoreCommand));
10089
+ program.command("score").description("Score your current agent config setup (deterministic, no network)").option("--json", "Output as JSON").option("--quiet", "One-line output for scripts/hooks").option("--agent <type>", "Target agents (comma-separated): claude, cursor, codex", parseAgentOption).action(tracked("score", scoreCommand));
10437
10090
  program.command("refresh").description("Update docs based on recent code changes").option("--quiet", "Suppress output (for use in hooks)").option("--dry-run", "Preview changes without writing files").action(tracked("refresh", refreshCommand));
10438
10091
  program.command("hooks").description("Manage auto-refresh hooks (toggle interactively)").option("--install", "Enable all hooks non-interactively").option("--remove", "Disable all hooks non-interactively").action(tracked("hooks", hooksCommand));
10439
- program.command("insights").description("Show agent performance insights and learning impact").option("--json", "Output as JSON").action(tracked("insights", insightsCommand));
10440
10092
  var learn = program.command("learn", { hidden: true }).description("[dev] Session learning \u2014 observe tool usage and extract reusable instructions");
10441
10093
  learn.command("observe").description("Record a tool event from stdin (called by hooks)").option("--failure", "Mark event as a tool failure").option("--prompt", "Record a user prompt event").action(tracked("learn:observe", learnObserveCommand));
10442
- learn.command("finalize").description("Analyze session events and update CALIBER_LEARNINGS.md (called on SessionEnd)").option("--force", "Skip the running-process check (for manual invocation)").option("--auto", "Silent mode for hooks (lower threshold, no interactive output)").option("--incremental", "Extract learnings mid-session without clearing events").action(tracked("learn:finalize", (opts) => learnFinalizeCommand(opts)));
10094
+ learn.command("finalize").description("Analyze session events and update CALIBER_LEARNINGS.md (called on SessionEnd)").option("--force", "Skip the running-process check (for manual invocation)").action(tracked("learn:finalize", (opts) => learnFinalizeCommand(opts)));
10443
10095
  learn.command("install").description("Install learning hooks into .claude/settings.json").action(tracked("learn:install", learnInstallCommand));
10444
10096
  learn.command("remove").description("Remove learning hooks from .claude/settings.json").action(tracked("learn:remove", learnRemoveCommand));
10445
10097
  learn.command("status").description("Show learning system status").action(tracked("learn:status", learnStatusCommand));
10446
10098
 
10447
10099
  // src/utils/version-check.ts
10448
- import fs39 from "fs";
10449
- import path31 from "path";
10100
+ import fs36 from "fs";
10101
+ import path29 from "path";
10450
10102
  import { fileURLToPath as fileURLToPath2 } from "url";
10451
10103
  import { execSync as execSync15 } from "child_process";
10452
- import chalk22 from "chalk";
10104
+ import chalk20 from "chalk";
10453
10105
  import ora7 from "ora";
10454
10106
  import confirm2 from "@inquirer/confirm";
10455
- var __dirname_vc = path31.dirname(fileURLToPath2(import.meta.url));
10107
+ var __dirname_vc = path29.dirname(fileURLToPath2(import.meta.url));
10456
10108
  var pkg2 = JSON.parse(
10457
- fs39.readFileSync(path31.resolve(__dirname_vc, "..", "package.json"), "utf-8")
10109
+ fs36.readFileSync(path29.resolve(__dirname_vc, "..", "package.json"), "utf-8")
10458
10110
  );
10459
10111
  function getChannel(version) {
10460
10112
  const match = version.match(/-(dev|next)\./);
@@ -10479,8 +10131,8 @@ function isNewer(registry, current) {
10479
10131
  function getInstalledVersion() {
10480
10132
  try {
10481
10133
  const globalRoot = execSync15("npm root -g", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10482
- const pkgPath = path31.join(globalRoot, "@rely-ai", "caliber", "package.json");
10483
- return JSON.parse(fs39.readFileSync(pkgPath, "utf-8")).version;
10134
+ const pkgPath = path29.join(globalRoot, "@rely-ai", "caliber", "package.json");
10135
+ return JSON.parse(fs36.readFileSync(pkgPath, "utf-8")).version;
10484
10136
  } catch {
10485
10137
  return null;
10486
10138
  }
@@ -10505,17 +10157,17 @@ async function checkForUpdates() {
10505
10157
  if (!isInteractive) {
10506
10158
  const installTag = channel === "latest" ? "" : `@${channel}`;
10507
10159
  console.log(
10508
- chalk22.yellow(
10160
+ chalk20.yellow(
10509
10161
  `
10510
10162
  Update available: ${current} -> ${latest}
10511
- Run ${chalk22.bold(`npm install -g @rely-ai/caliber${installTag}`)} to upgrade.
10163
+ Run ${chalk20.bold(`npm install -g @rely-ai/caliber${installTag}`)} to upgrade.
10512
10164
  `
10513
10165
  )
10514
10166
  );
10515
10167
  return;
10516
10168
  }
10517
10169
  console.log(
10518
- chalk22.yellow(`
10170
+ chalk20.yellow(`
10519
10171
  Update available: ${current} -> ${latest}`)
10520
10172
  );
10521
10173
  const shouldUpdate = await confirm2({ message: "Would you like to update now? (Y/n)", default: true });
@@ -10534,13 +10186,13 @@ Update available: ${current} -> ${latest}`)
10534
10186
  const installed = getInstalledVersion();
10535
10187
  if (installed !== latest) {
10536
10188
  spinner.fail(`Update incomplete \u2014 got ${installed ?? "unknown"}, expected ${latest}`);
10537
- console.log(chalk22.yellow(`Run ${chalk22.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually.
10189
+ console.log(chalk20.yellow(`Run ${chalk20.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually.
10538
10190
  `));
10539
10191
  return;
10540
10192
  }
10541
- spinner.succeed(chalk22.green(`Updated to ${latest}`));
10193
+ spinner.succeed(chalk20.green(`Updated to ${latest}`));
10542
10194
  const args = process.argv.slice(2);
10543
- console.log(chalk22.dim(`
10195
+ console.log(chalk20.dim(`
10544
10196
  Restarting: caliber ${args.join(" ")}
10545
10197
  `));
10546
10198
  execSync15(`caliber ${args.map((a) => JSON.stringify(a)).join(" ")}`, {
@@ -10553,11 +10205,11 @@ Restarting: caliber ${args.join(" ")}
10553
10205
  if (err instanceof Error) {
10554
10206
  const stderr = err.stderr;
10555
10207
  const errMsg = stderr ? String(stderr).trim().split("\n").pop() : err.message.split("\n")[0];
10556
- if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk22.dim(` ${errMsg}`));
10208
+ if (errMsg && !errMsg.includes("SIGTERM")) console.log(chalk20.dim(` ${errMsg}`));
10557
10209
  }
10558
10210
  console.log(
10559
- chalk22.yellow(
10560
- `Run ${chalk22.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually to upgrade.
10211
+ chalk20.yellow(
10212
+ `Run ${chalk20.bold(`npm install -g @rely-ai/caliber@${tag}`)} manually to upgrade.
10561
10213
  `
10562
10214
  )
10563
10215
  );