@rely-ai/caliber 1.20.0-dev.1773691540 → 1.20.0-dev.1773694290

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 +254 -67
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -228,7 +228,7 @@ import { fileURLToPath } from "url";
228
228
  // src/commands/init.ts
229
229
  import path20 from "path";
230
230
  import chalk11 from "chalk";
231
- import ora2 from "ora";
231
+ import ora3 from "ora";
232
232
  import select5 from "@inquirer/select";
233
233
  import checkbox from "@inquirer/checkbox";
234
234
  import fs25 from "fs";
@@ -4362,7 +4362,7 @@ function checkExistence(dir) {
4362
4362
  import { join as join4 } from "path";
4363
4363
 
4364
4364
  // src/scoring/utils.ts
4365
- import { readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
4365
+ import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
4366
4366
  import { join as join3, relative } from "path";
4367
4367
  function readFileOrNull2(filePath) {
4368
4368
  try {
@@ -4545,6 +4545,58 @@ function extractReferences(content) {
4545
4545
  }
4546
4546
  return Array.from(refs);
4547
4547
  }
4548
+ function validateFileReferences(content, dir, checkExists = existsSync3) {
4549
+ const refs = extractReferences(content);
4550
+ const valid = [];
4551
+ const invalid = [];
4552
+ for (const ref of refs) {
4553
+ if (/^https?:\/\//.test(ref)) continue;
4554
+ if (/^\d+\.\d+/.test(ref)) continue;
4555
+ if (ref.startsWith("#") || ref.startsWith("@")) continue;
4556
+ if (ref.includes("*") || ref.includes("..")) continue;
4557
+ if (!ref.includes("/") && !ref.includes(".")) continue;
4558
+ const fullPath = join3(dir, ref);
4559
+ if (checkExists(fullPath)) {
4560
+ valid.push(ref);
4561
+ } else {
4562
+ const withoutTrailing = ref.replace(/\/+$/, "");
4563
+ if (withoutTrailing !== ref && checkExists(join3(dir, withoutTrailing))) {
4564
+ valid.push(ref);
4565
+ } else {
4566
+ invalid.push(ref);
4567
+ }
4568
+ }
4569
+ }
4570
+ return { valid, invalid, total: valid.length + invalid.length };
4571
+ }
4572
+ function countConcreteness(content) {
4573
+ let concrete = 0;
4574
+ let abstract = 0;
4575
+ let inCodeBlock = false;
4576
+ for (const line of content.split("\n")) {
4577
+ if (line.trim().startsWith("```")) {
4578
+ inCodeBlock = !inCodeBlock;
4579
+ continue;
4580
+ }
4581
+ const classification = classifyLine(line, inCodeBlock);
4582
+ if (classification === "concrete") concrete++;
4583
+ else if (classification === "abstract") abstract++;
4584
+ }
4585
+ return { concrete, abstract };
4586
+ }
4587
+ function countTreeLines(content) {
4588
+ const treeLinePattern = /[├└│─┬]/;
4589
+ let count = 0;
4590
+ let inCodeBlock = false;
4591
+ for (const line of content.split("\n")) {
4592
+ if (line.trim().startsWith("```")) {
4593
+ inCodeBlock = !inCodeBlock;
4594
+ continue;
4595
+ }
4596
+ if (inCodeBlock && treeLinePattern.test(line)) count++;
4597
+ }
4598
+ return count;
4599
+ }
4548
4600
  function classifyLine(line, inCodeBlock) {
4549
4601
  if (inCodeBlock) return "concrete";
4550
4602
  const trimmed = line.trim();
@@ -4604,25 +4656,17 @@ function checkQuality(dir) {
4604
4656
  instruction: `Reduce total config from ~${totalTokens} tokens to under 5000.`
4605
4657
  } : void 0
4606
4658
  });
4607
- let concreteCount = 0;
4608
- let abstractCount = 0;
4659
+ const { concrete: concreteCount, abstract: abstractCount } = primaryInstructions ? countConcreteness(primaryInstructions) : { concrete: 0, abstract: 0 };
4609
4660
  const abstractExamples = [];
4610
- if (primaryInstructions) {
4611
- let inCodeBlock2 = false;
4661
+ if (primaryInstructions && abstractCount > 0) {
4662
+ let inCb = false;
4612
4663
  for (const line of primaryInstructions.split("\n")) {
4613
4664
  if (line.trim().startsWith("```")) {
4614
- inCodeBlock2 = !inCodeBlock2;
4665
+ inCb = !inCb;
4615
4666
  continue;
4616
4667
  }
4617
- const classification = classifyLine(line, inCodeBlock2);
4618
- if (classification === "neutral") continue;
4619
- if (classification === "concrete") {
4620
- concreteCount++;
4621
- } else {
4622
- abstractCount++;
4623
- if (abstractExamples.length < 3) {
4624
- abstractExamples.push(line.trim().slice(0, 80));
4625
- }
4668
+ if (!inCb && classifyLine(line, false) === "abstract" && abstractExamples.length < 3) {
4669
+ abstractExamples.push(line.trim().slice(0, 80));
4626
4670
  }
4627
4671
  }
4628
4672
  }
@@ -4645,20 +4689,7 @@ function checkQuality(dir) {
4645
4689
  instruction: `Replace generic prose with specific references. Examples of vague lines: ${abstractExamples.join("; ")}`
4646
4690
  } : void 0
4647
4691
  });
4648
- const treeLinePattern = /[├└│─┬]/;
4649
- let treeLineCount = 0;
4650
- let inCodeBlock = false;
4651
- if (combinedContent) {
4652
- for (const line of combinedContent.split("\n")) {
4653
- if (line.trim().startsWith("```")) {
4654
- inCodeBlock = !inCodeBlock;
4655
- continue;
4656
- }
4657
- if (inCodeBlock && treeLinePattern.test(line)) {
4658
- treeLineCount++;
4659
- }
4660
- }
4661
- }
4692
+ const treeLineCount = combinedContent ? countTreeLines(combinedContent) : 0;
4662
4693
  const hasLargeTree = treeLineCount > 10;
4663
4694
  checks.push({
4664
4695
  id: "no_directory_tree",
@@ -4823,30 +4854,7 @@ import { join as join5 } from "path";
4823
4854
  function validateReferences(dir) {
4824
4855
  const configContent = collectPrimaryConfigContent(dir);
4825
4856
  if (!configContent) return { valid: [], invalid: [], total: 0 };
4826
- const refs = extractReferences(configContent);
4827
- const valid = [];
4828
- const invalid = [];
4829
- for (const ref of refs) {
4830
- if (/^https?:\/\//.test(ref)) continue;
4831
- if (/^\d+\.\d+/.test(ref)) continue;
4832
- if (ref.startsWith("#")) continue;
4833
- if (ref.startsWith("@")) continue;
4834
- if (ref.includes("*")) continue;
4835
- if (ref.includes("..")) continue;
4836
- if (!ref.includes("/") && !ref.includes(".")) continue;
4837
- const fullPath = join5(dir, ref);
4838
- if (existsSync4(fullPath)) {
4839
- valid.push(ref);
4840
- } else {
4841
- const withoutTrailing = ref.replace(/\/+$/, "");
4842
- if (withoutTrailing !== ref && existsSync4(join5(dir, withoutTrailing))) {
4843
- valid.push(ref);
4844
- } else {
4845
- invalid.push(ref);
4846
- }
4847
- }
4848
- }
4849
- return { valid, invalid, total: valid.length + invalid.length };
4857
+ return validateFileReferences(configContent, dir);
4850
4858
  }
4851
4859
  function detectGitDrift(dir) {
4852
4860
  try {
@@ -6428,6 +6436,184 @@ function printSkills(recs) {
6428
6436
  console.log("");
6429
6437
  }
6430
6438
 
6439
+ // src/ai/score-refine.ts
6440
+ import { existsSync as existsSync9 } from "fs";
6441
+ import ora2 from "ora";
6442
+ var MAX_REFINE_ITERATIONS = 2;
6443
+ function extractConfigContent(setup) {
6444
+ const claude = setup.claude;
6445
+ const codex = setup.codex;
6446
+ return {
6447
+ claudeMd: claude?.claudeMd ?? null,
6448
+ agentsMd: codex?.agentsMd ?? null
6449
+ };
6450
+ }
6451
+ function validateSetup(setup, dir, checkExists = existsSync9) {
6452
+ const issues = [];
6453
+ const { claudeMd, agentsMd } = extractConfigContent(setup);
6454
+ const primaryContent = [claudeMd, agentsMd].filter(Boolean).join("\n");
6455
+ if (!primaryContent) return issues;
6456
+ const refs = validateFileReferences(primaryContent, dir, checkExists);
6457
+ if (refs.invalid.length > 0 && refs.total > 0) {
6458
+ const ratio = refs.valid.length / refs.total;
6459
+ const earnedPoints = Math.round(ratio * POINTS_REFERENCES_VALID);
6460
+ const lost = POINTS_REFERENCES_VALID - earnedPoints;
6461
+ if (lost > 0) {
6462
+ issues.push({
6463
+ check: "References valid",
6464
+ detail: `${refs.valid.length}/${refs.total} references verified, ${refs.invalid.length} invalid`,
6465
+ fixInstruction: `Remove these non-existent paths from the config: ${refs.invalid.map((r) => `\`${r}\``).join(", ")}. Do NOT guess replacements \u2014 just delete them.`,
6466
+ pointsLost: lost
6467
+ });
6468
+ }
6469
+ }
6470
+ const totalTokens = estimateTokens2(primaryContent);
6471
+ const tokenThreshold = TOKEN_BUDGET_THRESHOLDS.find((t) => totalTokens <= t.maxTokens);
6472
+ const tokenPoints = tokenThreshold?.points ?? 0;
6473
+ const maxTokenPoints = TOKEN_BUDGET_THRESHOLDS[0].points;
6474
+ if (tokenPoints < maxTokenPoints) {
6475
+ issues.push({
6476
+ check: "Token budget",
6477
+ detail: `~${totalTokens} tokens (target: \u2264${TOKEN_BUDGET_THRESHOLDS[0].maxTokens} for full points)`,
6478
+ fixInstruction: `Config is ~${totalTokens} tokens. Remove the least important lines to get under ${TOKEN_BUDGET_THRESHOLDS[0].maxTokens} tokens. Prioritize removing verbose prose over code blocks or path references.`,
6479
+ pointsLost: maxTokenPoints - tokenPoints
6480
+ });
6481
+ }
6482
+ const content = claudeMd ?? agentsMd ?? "";
6483
+ if (content) {
6484
+ const structure = analyzeMarkdownStructure(content);
6485
+ const blockThreshold = CODE_BLOCK_THRESHOLDS.find((t) => structure.codeBlockCount >= t.minBlocks);
6486
+ const blockPoints = blockThreshold?.points ?? 0;
6487
+ const maxBlockPoints = CODE_BLOCK_THRESHOLDS[0].points;
6488
+ if (blockPoints < maxBlockPoints && structure.codeBlockCount < CODE_BLOCK_THRESHOLDS[0].minBlocks) {
6489
+ issues.push({
6490
+ check: "Executable content",
6491
+ detail: `${structure.codeBlockCount} code block${structure.codeBlockCount === 1 ? "" : "s"} (need \u2265${CODE_BLOCK_THRESHOLDS[0].minBlocks} for full points)`,
6492
+ fixInstruction: `Add ${CODE_BLOCK_THRESHOLDS[0].minBlocks - structure.codeBlockCount} more code blocks with actual project commands (build, test, lint, deploy).`,
6493
+ pointsLost: maxBlockPoints - blockPoints
6494
+ });
6495
+ }
6496
+ const { concrete: concreteCount, abstract: abstractCount } = countConcreteness(content);
6497
+ const totalMeaningful = concreteCount + abstractCount;
6498
+ const concreteRatio = totalMeaningful > 0 ? concreteCount / totalMeaningful : 1;
6499
+ const concThreshold = CONCRETENESS_THRESHOLDS.find((t) => concreteRatio >= t.minRatio);
6500
+ const concPoints = totalMeaningful === 0 ? 0 : concThreshold?.points ?? 0;
6501
+ const maxConcPoints = CONCRETENESS_THRESHOLDS[0].points;
6502
+ if (concPoints < maxConcPoints && totalMeaningful > 0 && concreteRatio < CONCRETENESS_THRESHOLDS[0].minRatio) {
6503
+ issues.push({
6504
+ check: "Concrete instructions",
6505
+ detail: `${Math.round(concreteRatio * 100)}% concrete (need \u2265${Math.round(CONCRETENESS_THRESHOLDS[0].minRatio * 100)}%)`,
6506
+ fixInstruction: `${abstractCount} lines are generic prose. Replace vague instructions with specific ones that reference project files, paths, or commands in backticks.`,
6507
+ pointsLost: maxConcPoints - concPoints
6508
+ });
6509
+ }
6510
+ const treeLineCount = countTreeLines(content);
6511
+ if (treeLineCount > 10) {
6512
+ issues.push({
6513
+ check: "No directory tree listings",
6514
+ detail: `${treeLineCount}-line directory tree found in code blocks`,
6515
+ fixInstruction: "Remove directory tree listings from code blocks. Reference key directories inline with backticks instead.",
6516
+ pointsLost: POINTS_NO_DIR_TREE
6517
+ });
6518
+ }
6519
+ if (structure.h2Count < 3 || structure.listItemCount < 3) {
6520
+ const parts = [];
6521
+ if (structure.h2Count < 3) parts.push(`add ${3 - structure.h2Count} more ## sections`);
6522
+ if (structure.listItemCount < 3) parts.push("use bullet lists for multi-item instructions");
6523
+ issues.push({
6524
+ check: "Structured with headings",
6525
+ detail: `${structure.h2Count} sections, ${structure.listItemCount} list items`,
6526
+ fixInstruction: `Improve structure: ${parts.join(" and ")}.`,
6527
+ pointsLost: POINTS_HAS_STRUCTURE - ((structure.h2Count >= 3 ? 1 : 0) + (structure.listItemCount >= 3 ? 1 : 0))
6528
+ });
6529
+ }
6530
+ }
6531
+ return issues.sort((a, b) => b.pointsLost - a.pointsLost);
6532
+ }
6533
+ function buildFeedbackMessage(issues) {
6534
+ const lines = [
6535
+ "Your generated config has these scoring issues. Fix ONLY these \u2014 do not rewrite, restructure, or make cosmetic changes to anything else:\n"
6536
+ ];
6537
+ for (let i = 0; i < issues.length; i++) {
6538
+ const issue = issues[i];
6539
+ lines.push(`${i + 1}. ${issue.check.toUpperCase()} (-${issue.pointsLost} pts): ${issue.detail}`);
6540
+ lines.push(` Action: ${issue.fixInstruction}
6541
+ `);
6542
+ }
6543
+ lines.push("Return the complete updated AgentSetup JSON with only these fixes applied.");
6544
+ return lines.join("\n");
6545
+ }
6546
+ function countIssuePoints(issues) {
6547
+ return issues.reduce((sum, i) => sum + i.pointsLost, 0);
6548
+ }
6549
+ async function scoreAndRefine(setup, dir, sessionHistory, callbacks) {
6550
+ const existsCache = /* @__PURE__ */ new Map();
6551
+ const cachedExists = (path29) => {
6552
+ const cached = existsCache.get(path29);
6553
+ if (cached !== void 0) return cached;
6554
+ const result = existsSync9(path29);
6555
+ existsCache.set(path29, result);
6556
+ return result;
6557
+ };
6558
+ let currentSetup = setup;
6559
+ let bestSetup = setup;
6560
+ let bestLostPoints = Infinity;
6561
+ for (let iteration = 0; iteration < MAX_REFINE_ITERATIONS; iteration++) {
6562
+ const issues = validateSetup(currentSetup, dir, cachedExists);
6563
+ const lostPoints = countIssuePoints(issues);
6564
+ if (lostPoints < bestLostPoints) {
6565
+ bestSetup = currentSetup;
6566
+ bestLostPoints = lostPoints;
6567
+ }
6568
+ if (issues.length === 0) {
6569
+ if (callbacks?.onStatus) callbacks.onStatus("Setup passes all scoring checks");
6570
+ return bestSetup;
6571
+ }
6572
+ if (callbacks?.onStatus) {
6573
+ const issueNames = issues.map((i) => i.check).join(", ");
6574
+ callbacks.onStatus(`Fixing ${issues.length} scoring issue${issues.length === 1 ? "" : "s"}: ${issueNames}...`);
6575
+ }
6576
+ const feedbackMessage = buildFeedbackMessage(issues);
6577
+ const refined = await refineSetup(currentSetup, feedbackMessage, sessionHistory);
6578
+ if (!refined) {
6579
+ if (callbacks?.onStatus) callbacks.onStatus("Refinement failed, keeping current setup");
6580
+ return bestSetup;
6581
+ }
6582
+ sessionHistory.push({ role: "user", content: feedbackMessage });
6583
+ sessionHistory.push({
6584
+ role: "assistant",
6585
+ content: `Applied scoring fixes for: ${issues.map((i) => i.check).join(", ")}`
6586
+ });
6587
+ currentSetup = refined;
6588
+ }
6589
+ const finalIssues = validateSetup(currentSetup, dir, cachedExists);
6590
+ const finalLostPoints = countIssuePoints(finalIssues);
6591
+ if (finalLostPoints < bestLostPoints) {
6592
+ bestSetup = currentSetup;
6593
+ }
6594
+ return bestSetup;
6595
+ }
6596
+ async function runScoreRefineWithSpinner(setup, dir, sessionHistory) {
6597
+ const spinner = ora2("Validating setup against scoring criteria...").start();
6598
+ try {
6599
+ const refined = await scoreAndRefine(setup, dir, sessionHistory, {
6600
+ onStatus: (msg) => {
6601
+ spinner.text = msg;
6602
+ }
6603
+ });
6604
+ if (refined !== setup) {
6605
+ spinner.succeed("Setup refined based on scoring feedback");
6606
+ } else {
6607
+ spinner.succeed("Setup passes scoring validation");
6608
+ }
6609
+ return refined;
6610
+ } catch (err) {
6611
+ const msg = err instanceof Error ? err.message : "unknown error";
6612
+ spinner.warn(`Scoring validation skipped: ${msg}`);
6613
+ return setup;
6614
+ }
6615
+ }
6616
+
6431
6617
  // src/lib/debug-report.ts
6432
6618
  import fs24 from "fs";
6433
6619
  import path19 from "path";
@@ -7074,12 +7260,12 @@ async function initCommand(options) {
7074
7260
  report.addJson("Generation: Parsed Setup", generatedSetup);
7075
7261
  }
7076
7262
  log(options.verbose, `Generation completed: ${elapsedMs}ms, stopReason: ${genStopReason || "end_turn"}`);
7077
- printSetupSummary(generatedSetup);
7078
7263
  const sessionHistory = [];
7079
7264
  sessionHistory.push({
7080
7265
  role: "assistant",
7081
7266
  content: summarizeSetup("Initial generation", generatedSetup)
7082
7267
  });
7268
+ generatedSetup = await runScoreRefineWithSpinner(generatedSetup, process.cwd(), sessionHistory);
7083
7269
  console.log(title.bold(" Step 3/4 \u2014 Review\n"));
7084
7270
  const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
7085
7271
  const staged = stageFiles(setupFiles, process.cwd());
@@ -7149,7 +7335,7 @@ async function initCommand(options) {
7149
7335
  console.log(JSON.stringify(generatedSetup, null, 2));
7150
7336
  return;
7151
7337
  }
7152
- const writeSpinner = ora2("Writing config files...").start();
7338
+ const writeSpinner = ora3("Writing config files...").start();
7153
7339
  try {
7154
7340
  if (targetAgent.includes("codex") && !fs25.existsSync("AGENTS.md") && !generatedSetup.codex) {
7155
7341
  const claude = generatedSetup.claude;
@@ -7314,7 +7500,7 @@ async function refineLoop(currentSetup, _targetAgent, sessionHistory) {
7314
7500
  console.log(chalk11.dim(' Type "done" to accept the current setup.\n'));
7315
7501
  continue;
7316
7502
  }
7317
- const refineSpinner = ora2("Refining setup...").start();
7503
+ const refineSpinner = ora3("Refining setup...").start();
7318
7504
  const refineMessages = new SpinnerMessages(refineSpinner, REFINE_MESSAGES);
7319
7505
  refineMessages.start();
7320
7506
  const refined = await refineSetup(
@@ -7640,9 +7826,9 @@ function writeErrorLog(config, rawOutput, error, stopReason) {
7640
7826
 
7641
7827
  // src/commands/undo.ts
7642
7828
  import chalk12 from "chalk";
7643
- import ora3 from "ora";
7829
+ import ora4 from "ora";
7644
7830
  function undoCommand() {
7645
- const spinner = ora3("Reverting setup...").start();
7831
+ const spinner = ora4("Reverting setup...").start();
7646
7832
  try {
7647
7833
  const { restored, removed } = undoSetup();
7648
7834
  if (restored.length === 0 && removed.length === 0) {
@@ -7708,7 +7894,7 @@ async function statusCommand(options) {
7708
7894
 
7709
7895
  // src/commands/regenerate.ts
7710
7896
  import chalk14 from "chalk";
7711
- import ora4 from "ora";
7897
+ import ora5 from "ora";
7712
7898
  import select6 from "@inquirer/select";
7713
7899
  init_config();
7714
7900
  async function regenerateCommand(options) {
@@ -7724,7 +7910,7 @@ async function regenerateCommand(options) {
7724
7910
  }
7725
7911
  const targetAgent = readState()?.targetAgent ?? ["claude", "cursor"];
7726
7912
  await validateModel({ fast: true });
7727
- const spinner = ora4("Analyzing project...").start();
7913
+ const spinner = ora5("Analyzing project...").start();
7728
7914
  const fingerprint = await collectFingerprint(process.cwd());
7729
7915
  spinner.succeed("Project analyzed");
7730
7916
  const baselineScore = computeLocalScore(process.cwd(), targetAgent);
@@ -7733,7 +7919,7 @@ async function regenerateCommand(options) {
7733
7919
  console.log(chalk14.green(" Your setup is already at 100/100 \u2014 nothing to regenerate.\n"));
7734
7920
  return;
7735
7921
  }
7736
- const genSpinner = ora4("Regenerating setup...").start();
7922
+ const genSpinner = ora5("Regenerating setup...").start();
7737
7923
  const genMessages = new SpinnerMessages(genSpinner, GENERATION_MESSAGES, { showElapsedTime: true });
7738
7924
  genMessages.start();
7739
7925
  let generatedSetup = null;
@@ -7768,6 +7954,7 @@ async function regenerateCommand(options) {
7768
7954
  throw new Error("__exit__");
7769
7955
  }
7770
7956
  genSpinner.succeed("Setup regenerated");
7957
+ generatedSetup = await runScoreRefineWithSpinner(generatedSetup, process.cwd(), []);
7771
7958
  const setupFiles = collectSetupFiles(generatedSetup, targetAgent);
7772
7959
  const staged = stageFiles(setupFiles, process.cwd());
7773
7960
  const totalChanges = staged.newFiles + staged.modifiedFiles;
@@ -7804,7 +7991,7 @@ async function regenerateCommand(options) {
7804
7991
  console.log(chalk14.dim("Regeneration cancelled. No files were modified."));
7805
7992
  return;
7806
7993
  }
7807
- const writeSpinner = ora4("Writing config files...").start();
7994
+ const writeSpinner = ora5("Writing config files...").start();
7808
7995
  try {
7809
7996
  const result = writeSetup(generatedSetup);
7810
7997
  writeSpinner.succeed("Config files written");
@@ -7883,7 +8070,7 @@ async function scoreCommand(options) {
7883
8070
  import fs30 from "fs";
7884
8071
  import path24 from "path";
7885
8072
  import chalk16 from "chalk";
7886
- import ora5 from "ora";
8073
+ import ora6 from "ora";
7887
8074
 
7888
8075
  // src/lib/git-diff.ts
7889
8076
  import { execSync as execSync13 } from "child_process";
@@ -8237,7 +8424,7 @@ async function refreshSingleRepo(repoDir, options) {
8237
8424
  log2(quiet, chalk16.dim(`${prefix}No changes since last refresh.`));
8238
8425
  return;
8239
8426
  }
8240
- const spinner = quiet ? null : ora5(`${prefix}Analyzing changes...`).start();
8427
+ const spinner = quiet ? null : ora6(`${prefix}Analyzing changes...`).start();
8241
8428
  const existingDocs = readExistingConfigs(repoDir);
8242
8429
  const learnedSection = readLearnedSection();
8243
8430
  const fingerprint = await collectFingerprint(repoDir);
@@ -9269,7 +9456,7 @@ import path28 from "path";
9269
9456
  import { fileURLToPath as fileURLToPath2 } from "url";
9270
9457
  import { execSync as execSync14 } from "child_process";
9271
9458
  import chalk20 from "chalk";
9272
- import ora6 from "ora";
9459
+ import ora7 from "ora";
9273
9460
  import confirm2 from "@inquirer/confirm";
9274
9461
  var __dirname_vc = path28.dirname(fileURLToPath2(import.meta.url));
9275
9462
  var pkg2 = JSON.parse(
@@ -9343,7 +9530,7 @@ Update available: ${current} -> ${latest}`)
9343
9530
  return;
9344
9531
  }
9345
9532
  const tag = channel === "latest" ? latest : channel;
9346
- const spinner = ora6("Updating caliber...").start();
9533
+ const spinner = ora7("Updating caliber...").start();
9347
9534
  try {
9348
9535
  execSync14(`npm install -g @rely-ai/caliber@${tag}`, {
9349
9536
  stdio: "pipe",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rely-ai/caliber",
3
- "version": "1.20.0-dev.1773691540",
3
+ "version": "1.20.0-dev.1773694290",
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": {