nairon-bench 0.5.3 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +83 -58
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11414,7 +11414,7 @@ function generateOverallSummary(requirements, planning, implementation, review,
11414
11414
  }
11415
11415
  return parts.join(" ") || "Balanced across all phases.";
11416
11416
  }
11417
- function formatSDLCForTerminal(analysis) {
11417
+ function formatSDLCPhaseForTerminal(phase, overall) {
11418
11418
  const lines = [];
11419
11419
  const width = 50;
11420
11420
  const CYAN = "\x1B[36m";
@@ -11441,48 +11441,55 @@ function formatSDLCForTerminal(analysis) {
11441
11441
  }
11442
11442
  };
11443
11443
  lines.push("");
11444
- lines.push(`${BOLD}${CYAN} SDLC PHASE BREAKDOWN${RESET}`);
11444
+ lines.push(`${BOLD}${CYAN} SDLC OPTIMIZATION${RESET}`);
11445
11445
  lines.push(`${DIM} ${"─".repeat(width)}${RESET}`);
11446
11446
  lines.push("");
11447
- const overall = analysis.overall;
11448
11447
  lines.push(` ${BOLD}Overall:${RESET} ${gradeColor(overall.grade)}${overall.grade}${RESET} (${overall.score}/100)`);
11449
11448
  lines.push(` ${DIM}${overall.summary}${RESET}`);
11450
11449
  lines.push("");
11451
- const phases = [
11452
- { emoji: "1", ...analysis.requirements },
11453
- { emoji: "2", ...analysis.planning },
11454
- { emoji: "3", ...analysis.implementation },
11455
- { emoji: "4", ...analysis.review }
11456
- ];
11457
- for (const phase of phases) {
11458
- const color = gradeColor(phase.grade);
11459
- const bar = renderBar(phase.score, 15);
11460
- lines.push(` ${BOLD}${phase.emoji}. ${phase.name}${RESET}`);
11461
- lines.push(` ${bar} ${color}${phase.grade}${RESET} ${DIM}(${phase.score}/100)${RESET}`);
11462
- if (phase.metrics.length > 0) {
11463
- const topMetrics = phase.metrics.slice(0, 2);
11464
- for (const m2 of topMetrics) {
11465
- const statusIcon = m2.status === "good" ? GREEN + "+" : m2.status === "warning" ? YELLOW + "~" : RED + "-";
11466
- lines.push(` ${statusIcon}${RESET} ${m2.name}: ${m2.value}${m2.target ? ` ${DIM}(target: ${m2.target})${RESET}` : ""}`);
11467
- }
11468
- }
11469
- if (phase.recommendations.length > 0) {
11470
- const rec = phase.recommendations[0];
11450
+ const phaseColor = gradeColor(phase.grade);
11451
+ lines.push(` ${BOLD}Focus:${RESET} ${phase.name}`);
11452
+ lines.push(` ${phaseColor}${phase.grade}${RESET} ${DIM}(${phase.score}/100)${RESET}`);
11453
+ lines.push("");
11454
+ if (phase.metrics.length > 0) {
11455
+ lines.push(` ${BOLD}Signals:${RESET}`);
11456
+ const topMetrics = phase.metrics.slice(0, 4);
11457
+ for (const m2 of topMetrics) {
11458
+ const statusIcon = m2.status === "good" ? GREEN + "+" : m2.status === "warning" ? YELLOW + "~" : RED + "-";
11459
+ lines.push(` ${statusIcon}${RESET} ${m2.name}: ${m2.value}${m2.target ? ` ${DIM}(target: ${m2.target})${RESET}` : ""}`);
11460
+ }
11461
+ lines.push("");
11462
+ }
11463
+ if (phase.strengths.length > 0) {
11464
+ lines.push(` ${BOLD}Strengths:${RESET}`);
11465
+ for (const item of phase.strengths.slice(0, 3)) {
11466
+ lines.push(` ${GREEN}+${RESET} ${item}`);
11467
+ }
11468
+ lines.push("");
11469
+ }
11470
+ if (phase.weaknesses.length > 0) {
11471
+ lines.push(` ${BOLD}Weak Spots:${RESET}`);
11472
+ for (const item of phase.weaknesses.slice(0, 3)) {
11473
+ lines.push(` ${RED}!${RESET} ${item}`);
11474
+ }
11475
+ lines.push("");
11476
+ }
11477
+ lines.push(` ${BOLD}Optimizations:${RESET}`);
11478
+ if (phase.recommendations.length === 0) {
11479
+ lines.push(` ${DIM}No optimizations available for this phase.${RESET}`);
11480
+ } else {
11481
+ for (const rec of phase.recommendations) {
11471
11482
  const impactColor = rec.impact === "high" ? RED : rec.impact === "medium" ? YELLOW : DIM;
11472
- lines.push(` ${impactColor}!${RESET} ${rec.title}`);
11483
+ lines.push(` ${impactColor}!${RESET} ${rec.title}`);
11484
+ lines.push(` ${DIM}${rec.description}${RESET}`);
11473
11485
  if (rec.installCommand) {
11474
- lines.push(` ${DIM}${rec.installCommand}${RESET}`);
11486
+ lines.push(` ${DIM}${rec.installCommand}${RESET}`);
11475
11487
  }
11476
11488
  }
11477
- lines.push("");
11478
11489
  }
11490
+ lines.push("");
11479
11491
  return lines;
11480
11492
  }
11481
- function renderBar(value, width) {
11482
- const filled = Math.round(value / 100 * width);
11483
- const empty = width - filled;
11484
- return "█".repeat(filled) + "░".repeat(empty);
11485
- }
11486
11493
 
11487
11494
  // src/lib/frustration-detector.ts
11488
11495
  import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as fsReaddirSync } from "node:fs";
@@ -16634,29 +16641,37 @@ var scanCommand = defineCommand2({
16634
16641
  } else if (sdlc.overall.summary.includes("optimizations available")) {
16635
16642
  sdlc.overall.summary = sdlc.overall.summary.replace(/\d+ optimizations available\./, "All recommended tools installed.");
16636
16643
  }
16637
- const sdlcLines = formatSDLCForTerminal(sdlc);
16644
+ const phaseChoice = await consola.prompt("Which SDLC phase do you want to optimize?", {
16645
+ type: "select",
16646
+ options: [
16647
+ { value: "requirements", label: "Requirements & Context" },
16648
+ { value: "planning", label: "Planning & Design" },
16649
+ { value: "implementation", label: "Implementation" },
16650
+ { value: "review", label: "Review & Testing" }
16651
+ ]
16652
+ });
16653
+ const selectedPhase = phaseChoice === "planning" ? sdlc.planning : phaseChoice === "implementation" ? sdlc.implementation : phaseChoice === "review" ? sdlc.review : sdlc.requirements;
16654
+ const sdlcLines = formatSDLCPhaseForTerminal(selectedPhase, sdlc.overall);
16638
16655
  for (const line of sdlcLines) {
16639
16656
  console.log(line);
16640
16657
  }
16641
- let allRecs = [];
16642
- for (const phase of [sdlc.requirements, sdlc.planning, sdlc.implementation, sdlc.review]) {
16643
- for (const rec of phase.recommendations) {
16644
- if (rec.installCommand) {
16645
- allRecs.push(phaseRecToInstallable(rec));
16646
- }
16658
+ let phaseRecs = [];
16659
+ for (const rec of selectedPhase.recommendations) {
16660
+ if (rec.installCommand) {
16661
+ phaseRecs.push(phaseRecToInstallable(rec));
16647
16662
  }
16648
16663
  }
16649
- allRecs = filterAlreadyInstalled(allRecs, installedStatus);
16650
- if (allRecs.length > 0) {
16664
+ phaseRecs = filterAlreadyInstalled(phaseRecs, installedStatus);
16665
+ if (phaseRecs.length > 0) {
16651
16666
  console.log();
16652
- const optionLabels = allRecs.map((rec) => `${rec.name} - ${rec.description}`);
16653
- const selected = await consola.prompt(`${allRecs.length} optimizations available. Select to install (space to select, enter to confirm):`, {
16667
+ const optionLabels = phaseRecs.map((rec) => `${rec.name} - ${rec.description}`);
16668
+ const selected = await consola.prompt(`${phaseRecs.length} optimizations available for ${selectedPhase.name}. Select to install (space to select, enter to confirm):`, {
16654
16669
  type: "multiselect",
16655
16670
  options: optionLabels,
16656
16671
  required: false
16657
16672
  });
16658
16673
  if (selected && typeof selected !== "symbol" && Array.isArray(selected) && selected.length > 0) {
16659
- const toInstall = allRecs.filter((rec) => selected.some((s2) => s2.startsWith(rec.name))).map((r3) => ({ ...r3, selected: true }));
16674
+ const toInstall = phaseRecs.filter((rec) => selected.some((s2) => s2.startsWith(rec.name))).map((r3) => ({ ...r3, selected: true }));
16660
16675
  if (toInstall.length > 0) {
16661
16676
  console.log();
16662
16677
  console.log(` ${colors2.bold("Installing...")}${colors2.dim("")}`);
@@ -20558,10 +20573,10 @@ function renderCoverageSummary(report) {
20558
20573
  lines.push(` Format: ${report.format}`);
20559
20574
  lines.push(` Overall: ${report.summary.overall}%`);
20560
20575
  lines.push("");
20561
- lines.push(` Lines: ${renderBar2(report.summary.lines.percentage)} ${report.summary.lines.percentage}%`);
20562
- lines.push(` Statements: ${renderBar2(report.summary.statements.percentage)} ${report.summary.statements.percentage}%`);
20563
- lines.push(` Functions: ${renderBar2(report.summary.functions.percentage)} ${report.summary.functions.percentage}%`);
20564
- lines.push(` Branches: ${renderBar2(report.summary.branches.percentage)} ${report.summary.branches.percentage}%`);
20576
+ lines.push(` Lines: ${renderBar(report.summary.lines.percentage)} ${report.summary.lines.percentage}%`);
20577
+ lines.push(` Statements: ${renderBar(report.summary.statements.percentage)} ${report.summary.statements.percentage}%`);
20578
+ lines.push(` Functions: ${renderBar(report.summary.functions.percentage)} ${report.summary.functions.percentage}%`);
20579
+ lines.push(` Branches: ${renderBar(report.summary.branches.percentage)} ${report.summary.branches.percentage}%`);
20565
20580
  if (report.uncoveredFiles.length > 0) {
20566
20581
  lines.push("");
20567
20582
  lines.push(` Uncovered files: ${report.uncoveredFiles.length}`);
@@ -20607,7 +20622,7 @@ function renderCoverageMarkdown(report) {
20607
20622
  }
20608
20623
  return lines;
20609
20624
  }
20610
- function renderBar2(percentage, width = 15) {
20625
+ function renderBar(percentage, width = 15) {
20611
20626
  const filled = Math.round(percentage / 100 * width);
20612
20627
  const empty = width - filled;
20613
20628
  return "█".repeat(filled) + "░".repeat(empty);
@@ -21790,10 +21805,10 @@ function formatReportAsTerminal(report) {
21790
21805
  lines.push(` ${report.gradeDescription}`);
21791
21806
  lines.push("");
21792
21807
  lines.push(" Score Breakdown:");
21793
- lines.push(` SDLC Coverage: ${renderBar3(report.scores.sdlcCoverage)} ${report.scores.sdlcCoverage}`);
21794
- lines.push(` Prompt Quality: ${renderBar3(report.scores.promptQuality)} ${report.scores.promptQuality}`);
21795
- lines.push(` Tool Utilization: ${renderBar3(report.scores.toolUtilization)} ${report.scores.toolUtilization}`);
21796
- lines.push(` Efficiency: ${renderBar3(report.scores.efficiency)} ${report.scores.efficiency}`);
21808
+ lines.push(` SDLC Coverage: ${renderBar2(report.scores.sdlcCoverage)} ${report.scores.sdlcCoverage}`);
21809
+ lines.push(` Prompt Quality: ${renderBar2(report.scores.promptQuality)} ${report.scores.promptQuality}`);
21810
+ lines.push(` Tool Utilization: ${renderBar2(report.scores.toolUtilization)} ${report.scores.toolUtilization}`);
21811
+ lines.push(` Efficiency: ${renderBar2(report.scores.efficiency)} ${report.scores.efficiency}`);
21797
21812
  lines.push("");
21798
21813
  lines.push(" Quick Stats:");
21799
21814
  lines.push(` Sessions: ${report.summary.totalSessions} | Prompts: ${report.summary.totalPrompts} | Commits: ${report.summary.totalCommits}`);
@@ -21880,7 +21895,7 @@ function formatReportAsTerminal(report) {
21880
21895
  return lines.join(`
21881
21896
  `);
21882
21897
  }
21883
- function renderBar3(value, width = 20) {
21898
+ function renderBar2(value, width = 20) {
21884
21899
  const filled = Math.round(value / 100 * width);
21885
21900
  const empty = width - filled;
21886
21901
  return "█".repeat(filled) + "░".repeat(empty);
@@ -22434,7 +22449,7 @@ async function showHistory(client, clerkId, limit, format2) {
22434
22449
  const recent = trend.slice(-limit);
22435
22450
  for (const entry of recent) {
22436
22451
  const date = new Date(entry.date).toLocaleDateString();
22437
- const bar = renderBar4(entry.overall, 30);
22452
+ const bar = renderBar3(entry.overall, 30);
22438
22453
  const eff = `${entry.tokenEfficiency}x`;
22439
22454
  consola.log(` ${date.padEnd(12)} ${String(entry.overall).padStart(3)}/100 ${bar} eff: ${eff}`);
22440
22455
  }
@@ -22489,7 +22504,7 @@ function renderScanReport(scan, phaseFilter) {
22489
22504
  const phases = phaseFilter ? scan.phases.filter((p) => p.phase === phaseFilter) : scan.phases;
22490
22505
  lines.push("Phase Scores:");
22491
22506
  for (const phase of phases) {
22492
- const bar = renderBar4(phase.score, 20);
22507
+ const bar = renderBar3(phase.score, 20);
22493
22508
  const delta = phase.delta !== undefined && phase.delta !== null ? ` (${phase.delta > 0 ? "+" : ""}${phase.delta})` : "";
22494
22509
  lines.push(` ${phase.phase.padEnd(16)} ${String(phase.score).padStart(3)}/100 ${bar}${delta}`);
22495
22510
  }
@@ -22507,7 +22522,7 @@ function renderScanReport(scan, phaseFilter) {
22507
22522
  return lines.join(`
22508
22523
  `);
22509
22524
  }
22510
- function renderBar4(value, width) {
22525
+ function renderBar3(value, width) {
22511
22526
  const filled = Math.round(value / 100 * width);
22512
22527
  const empty = width - filled;
22513
22528
  return "█".repeat(filled) + "░".repeat(empty);
@@ -23804,6 +23819,16 @@ var BOLD = "\x1B[1m";
23804
23819
  var RESET = "\x1B[0m";
23805
23820
  var MAGENTA = "\x1B[35m";
23806
23821
  var CHANGELOG = [
23822
+ {
23823
+ version: "0.6.0",
23824
+ date: "2026-02-15",
23825
+ title: "Phase-Focused Optimizations",
23826
+ highlights: [
23827
+ "nb scan now asks which SDLC phase to optimize",
23828
+ "Phase-specific optimization breakdown and installs",
23829
+ "New SDLC optimization formatter and coverage test"
23830
+ ]
23831
+ },
23807
23832
  {
23808
23833
  version: "0.5.3",
23809
23834
  date: "2026-02-14",
@@ -24286,7 +24311,7 @@ function showFullChangelog() {
24286
24311
  // package.json
24287
24312
  var package_default = {
24288
24313
  name: "nairon-bench",
24289
- version: "0.5.3",
24314
+ version: "0.6.0",
24290
24315
  description: "AI workflow benchmarking CLI",
24291
24316
  type: "module",
24292
24317
  bin: {
@@ -26813,7 +26838,7 @@ function formatBytes(bytes) {
26813
26838
  // package.json
26814
26839
  var package_default2 = {
26815
26840
  name: "nairon-bench",
26816
- version: "0.5.3",
26841
+ version: "0.6.0",
26817
26842
  description: "AI workflow benchmarking CLI",
26818
26843
  type: "module",
26819
26844
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nairon-bench",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "AI workflow benchmarking CLI",
5
5
  "type": "module",
6
6
  "bin": {