nairon-bench 0.3.15 → 0.4.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 +423 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15364,6 +15364,362 @@ function wrapText(text, width) {
15364
15364
  return lines;
15365
15365
  }
15366
15366
 
15367
+ // src/lib/effort-analyzer.ts
15368
+ function analyzeEffort(sessions, git) {
15369
+ const sessionEfforts = [];
15370
+ let totalGeneration = 0;
15371
+ let totalReview = 0;
15372
+ let totalCorrection = 0;
15373
+ let totalIntegration = 0;
15374
+ let totalCorrectionLoops = 0;
15375
+ let totalContextChurn = 0;
15376
+ let totalRegenerations = 0;
15377
+ for (const session of sessions) {
15378
+ const effort = analyzeSessionEffort(session);
15379
+ sessionEfforts.push(effort);
15380
+ totalGeneration += effort.generationMinutes;
15381
+ totalReview += effort.reviewMinutes;
15382
+ totalCorrection += effort.correctionMinutes;
15383
+ totalIntegration += effort.integrationMinutes;
15384
+ for (const pattern of session.patterns) {
15385
+ if (pattern.type === "undo_loop") {
15386
+ totalCorrectionLoops += pattern.count;
15387
+ }
15388
+ if (pattern.type === "context_compaction" || pattern.type === "memory_loss") {
15389
+ totalContextChurn += pattern.count;
15390
+ }
15391
+ if (pattern.type === "repeated_rephrasing") {
15392
+ totalRegenerations += pattern.count;
15393
+ }
15394
+ }
15395
+ }
15396
+ const totalMinutes = totalGeneration + totalReview + totalCorrection + totalIntegration;
15397
+ const safeTotal = totalMinutes || 1;
15398
+ const generationPercent = Math.round(totalGeneration / safeTotal * 100);
15399
+ const reviewPercent = Math.round(totalReview / safeTotal * 100);
15400
+ const correctionPercent = Math.round(totalCorrection / safeTotal * 100);
15401
+ const integrationPercent = Math.round(totalIntegration / safeTotal * 100);
15402
+ const safeGeneration = totalGeneration || 1;
15403
+ const correctionRatio = totalCorrection / safeGeneration;
15404
+ const reviewOverhead = totalReview / safeGeneration;
15405
+ const trueEffortMultiplier = totalMinutes / safeGeneration;
15406
+ return {
15407
+ generationMinutes: totalGeneration,
15408
+ reviewMinutes: totalReview,
15409
+ correctionMinutes: totalCorrection,
15410
+ integrationMinutes: totalIntegration,
15411
+ totalMinutes,
15412
+ generationPercent,
15413
+ reviewPercent,
15414
+ correctionPercent,
15415
+ integrationPercent,
15416
+ totalSessions: sessions.length,
15417
+ correctionLoops: totalCorrectionLoops,
15418
+ contextChurnEvents: totalContextChurn,
15419
+ regenerationCycles: totalRegenerations,
15420
+ correctionRatio: Math.round(correctionRatio * 100) / 100,
15421
+ reviewOverhead: Math.round(reviewOverhead * 100) / 100,
15422
+ trueEffortMultiplier: Math.round(trueEffortMultiplier * 100) / 100,
15423
+ sessions: sessionEfforts
15424
+ };
15425
+ }
15426
+ function analyzeSessionEffort(session) {
15427
+ const totalMinutes = session.durationMinutes;
15428
+ let generationRatio = 0.4;
15429
+ let reviewRatio = 0.3;
15430
+ let correctionRatio = 0.2;
15431
+ let integrationRatio = 0.1;
15432
+ const patterns = [];
15433
+ let contextChurn = "low";
15434
+ let correctionIntensity = "low";
15435
+ for (const pattern of session.patterns) {
15436
+ patterns.push(pattern.type);
15437
+ if (pattern.type === "undo_loop") {
15438
+ const undoImpact = Math.min(pattern.count * 0.05, 0.25);
15439
+ correctionRatio += undoImpact;
15440
+ generationRatio -= undoImpact / 2;
15441
+ reviewRatio -= undoImpact / 2;
15442
+ correctionIntensity = pattern.count >= 5 ? "high" : pattern.count >= 2 ? "medium" : "low";
15443
+ }
15444
+ if (pattern.type === "memory_loss" || pattern.type === "context_compaction") {
15445
+ const contextImpact = Math.min(pattern.count * 0.08, 0.2);
15446
+ correctionRatio += contextImpact / 2;
15447
+ reviewRatio += contextImpact / 2;
15448
+ generationRatio -= contextImpact;
15449
+ contextChurn = pattern.count >= 3 ? "high" : pattern.count >= 1 ? "medium" : "low";
15450
+ }
15451
+ if (pattern.type === "repeated_rephrasing") {
15452
+ const rephrasingImpact = Math.min(pattern.count * 0.03, 0.15);
15453
+ generationRatio += rephrasingImpact;
15454
+ reviewRatio -= rephrasingImpact / 2;
15455
+ integrationRatio -= rephrasingImpact / 2;
15456
+ }
15457
+ if (pattern.type === "frustration_caps") {
15458
+ correctionRatio += 0.05;
15459
+ reviewRatio -= 0.05;
15460
+ }
15461
+ if (pattern.type === "smooth_flow") {
15462
+ generationRatio += 0.1;
15463
+ correctionRatio -= 0.1;
15464
+ }
15465
+ }
15466
+ const totalRatio = generationRatio + reviewRatio + correctionRatio + integrationRatio;
15467
+ generationRatio /= totalRatio;
15468
+ reviewRatio /= totalRatio;
15469
+ correctionRatio /= totalRatio;
15470
+ integrationRatio /= totalRatio;
15471
+ const generationMinutes = Math.round(totalMinutes * generationRatio);
15472
+ const reviewMinutes = Math.round(totalMinutes * reviewRatio);
15473
+ const correctionMinutes = Math.round(totalMinutes * correctionRatio);
15474
+ const integrationMinutes = totalMinutes - generationMinutes - reviewMinutes - correctionMinutes;
15475
+ return {
15476
+ sessionId: session.sessionId,
15477
+ agent: session.agent,
15478
+ startedAt: session.startedAt,
15479
+ generationMinutes,
15480
+ reviewMinutes,
15481
+ correctionMinutes,
15482
+ integrationMinutes,
15483
+ totalMinutes,
15484
+ patterns,
15485
+ contextChurn,
15486
+ correctionIntensity
15487
+ };
15488
+ }
15489
+ function generateLeadershipReport(effort, periodLabel = "Last 7 days") {
15490
+ const totalHours = effort.totalMinutes / 60;
15491
+ const generationHours = effort.generationMinutes / 60;
15492
+ const reviewHours = effort.reviewMinutes / 60;
15493
+ const correctionHours = effort.correctionMinutes / 60;
15494
+ const integrationHours = effort.integrationMinutes / 60;
15495
+ const perceivedEffort = generationHours;
15496
+ const hiddenWork = totalHours - perceivedEffort;
15497
+ const hiddenWorkPercent = hiddenWork / totalHours * 100;
15498
+ const contextChurnRate = effort.contextChurnEvents / Math.max(effort.totalSessions, 1);
15499
+ const repeatedCorrectionRate = effort.correctionLoops / Math.max(effort.totalSessions, 1);
15500
+ let burnoutRisk = "low";
15501
+ if (effort.correctionRatio > 0.8 || hiddenWorkPercent > 60) {
15502
+ burnoutRisk = "high";
15503
+ } else if (effort.correctionRatio > 0.5 || hiddenWorkPercent > 40) {
15504
+ burnoutRisk = "medium";
15505
+ }
15506
+ const insights = [];
15507
+ if (hiddenWorkPercent > 50) {
15508
+ insights.push(`${Math.round(hiddenWorkPercent)}% of effort is invisible (review, correction, integration) - leadership may underestimate true workload`);
15509
+ }
15510
+ if (effort.correctionRatio > 0.5) {
15511
+ insights.push(`High correction ratio (${Math.round(effort.correctionRatio * 100)}%) - AI output requires significant human oversight`);
15512
+ }
15513
+ if (contextChurnRate > 0.5) {
15514
+ insights.push(`Frequent context loss (${Math.round(contextChurnRate * 100)}% of sessions) - engineers repeatedly re-explaining requirements`);
15515
+ }
15516
+ if (effort.trueEffortMultiplier > 2) {
15517
+ insights.push(`True effort is ${effort.trueEffortMultiplier.toFixed(1)}x perceived effort - AI accelerates generation but not total delivery`);
15518
+ }
15519
+ if (burnoutRisk === "high") {
15520
+ insights.push("High burnout risk: excessive correction cycles indicate AI output quality issues");
15521
+ }
15522
+ if (insights.length === 0) {
15523
+ insights.push("AI workflow appears efficient - correction overhead is within healthy limits");
15524
+ }
15525
+ return {
15526
+ period: periodLabel,
15527
+ aiAssistedTasksCount: effort.totalSessions,
15528
+ totalAIGenerationHours: Math.round(generationHours * 10) / 10,
15529
+ totalReviewHours: Math.round(reviewHours * 10) / 10,
15530
+ totalCorrectionHours: Math.round(correctionHours * 10) / 10,
15531
+ totalIntegrationHours: Math.round(integrationHours * 10) / 10,
15532
+ totalEffortHours: Math.round(totalHours * 10) / 10,
15533
+ averageCorrectionRatio: Math.round(effort.correctionRatio * 100) / 100,
15534
+ integrationOverheadPercent: effort.integrationPercent,
15535
+ contextChurnRate: Math.round(contextChurnRate * 100) / 100,
15536
+ perceivedEffortHours: Math.round(perceivedEffort * 10) / 10,
15537
+ trueEffortHours: Math.round(totalHours * 10) / 10,
15538
+ hiddenWorkHours: Math.round(hiddenWork * 10) / 10,
15539
+ hiddenWorkPercent: Math.round(hiddenWorkPercent),
15540
+ burnoutRisk,
15541
+ contextLossFrequency: effort.contextChurnEvents,
15542
+ repeatedCorrectionRate: Math.round(repeatedCorrectionRate * 100) / 100,
15543
+ insights
15544
+ };
15545
+ }
15546
+ function formatEffortBreakdown(effort) {
15547
+ const lines = [];
15548
+ lines.push("");
15549
+ lines.push(colors2.dim(" " + "═".repeat(50)));
15550
+ lines.push(` ${icons.chart} ${colors2.bold("Effort Breakdown")} ${colors2.dim("(AI Work Visibility)")}`);
15551
+ lines.push(colors2.dim(" " + "═".repeat(50)));
15552
+ lines.push("");
15553
+ const total = effort.totalMinutes || 1;
15554
+ const genBar = "█".repeat(Math.round(effort.generationPercent / 5));
15555
+ const revBar = "█".repeat(Math.round(effort.reviewPercent / 5));
15556
+ const corBar = "█".repeat(Math.round(effort.correctionPercent / 5));
15557
+ const intBar = "█".repeat(Math.round(effort.integrationPercent / 5));
15558
+ lines.push(` ${colors2.bold("Time Breakdown:")}`);
15559
+ lines.push(` ${colors2.success("Generation")} ${formatTime(effort.generationMinutes).padEnd(10)} ${colors2.success(genBar)} ${effort.generationPercent}%`);
15560
+ lines.push(` ${colors2.primary("Review")} ${formatTime(effort.reviewMinutes).padEnd(10)} ${colors2.primary(revBar)} ${effort.reviewPercent}%`);
15561
+ lines.push(` ${colors2.warning("Correction")} ${formatTime(effort.correctionMinutes).padEnd(10)} ${colors2.warning(corBar)} ${effort.correctionPercent}%`);
15562
+ lines.push(` ${colors2.dim("Integration")} ${formatTime(effort.integrationMinutes).padEnd(10)} ${colors2.dim(intBar)} ${effort.integrationPercent}%`);
15563
+ lines.push("");
15564
+ lines.push(` ${colors2.bold("Total Active Effort:")} ${formatTime(effort.totalMinutes)}`);
15565
+ lines.push("");
15566
+ const hiddenWork = effort.reviewMinutes + effort.correctionMinutes + effort.integrationMinutes;
15567
+ const hiddenPercent = Math.round(hiddenWork / total * 100);
15568
+ if (hiddenPercent > 30) {
15569
+ lines.push(` ${colors2.warning("!")} ${colors2.bold("Hidden Work Alert:")}`);
15570
+ lines.push(` ${hiddenPercent}% of effort is invisible (review + correction + integration)`);
15571
+ lines.push(` ${colors2.dim("This is work leadership may not see")}`);
15572
+ lines.push("");
15573
+ }
15574
+ lines.push(` ${colors2.bold("Key Metrics:")}`);
15575
+ lines.push(` Correction ratio: ${formatRatio(effort.correctionRatio)} ${getRatioIndicator(effort.correctionRatio)}`);
15576
+ lines.push(` Review overhead: ${formatRatio(effort.reviewOverhead)}`);
15577
+ lines.push(` True effort factor: ${effort.trueEffortMultiplier}x ${colors2.dim("(total / generation)")}`);
15578
+ lines.push("");
15579
+ if (effort.correctionLoops > 0 || effort.contextChurnEvents > 0) {
15580
+ lines.push(` ${colors2.bold("Detected Issues:")}`);
15581
+ if (effort.correctionLoops > 0) {
15582
+ lines.push(` ${colors2.warning("•")} ${effort.correctionLoops} correction loop${effort.correctionLoops > 1 ? "s" : ""}`);
15583
+ }
15584
+ if (effort.contextChurnEvents > 0) {
15585
+ lines.push(` ${colors2.warning("•")} ${effort.contextChurnEvents} context churn event${effort.contextChurnEvents > 1 ? "s" : ""}`);
15586
+ }
15587
+ if (effort.regenerationCycles > 0) {
15588
+ lines.push(` ${colors2.dim("•")} ${effort.regenerationCycles} regeneration cycle${effort.regenerationCycles > 1 ? "s" : ""}`);
15589
+ }
15590
+ lines.push("");
15591
+ }
15592
+ lines.push(colors2.dim(" " + "═".repeat(50)));
15593
+ return lines;
15594
+ }
15595
+ function formatLeadershipReport(report) {
15596
+ const lines = [];
15597
+ lines.push("");
15598
+ lines.push(colors2.dim(" " + "═".repeat(60)));
15599
+ lines.push(` ${icons.chart} ${colors2.bold("Leadership Report")} ${colors2.dim(`(${report.period})`)}`);
15600
+ lines.push(colors2.dim(" " + "═".repeat(60)));
15601
+ lines.push("");
15602
+ lines.push(` ${colors2.bold("Executive Summary")}`);
15603
+ lines.push(` ─────────────────────────────────────────────────────`);
15604
+ lines.push(` AI-Assisted Sessions: ${report.aiAssistedTasksCount}`);
15605
+ lines.push(` Total Effort: ${report.totalEffortHours} hours`);
15606
+ lines.push("");
15607
+ lines.push(` ${colors2.bold("Effort Visibility")}`);
15608
+ lines.push(` ─────────────────────────────────────────────────────`);
15609
+ lines.push(` ${colors2.success("AI Generation:")} ${report.totalAIGenerationHours}h ${colors2.dim("← What leadership sees")}`);
15610
+ lines.push(` ${colors2.primary("Review:")} ${report.totalReviewHours}h`);
15611
+ lines.push(` ${colors2.warning("Correction:")} ${report.totalCorrectionHours}h`);
15612
+ lines.push(` ${colors2.dim("Integration:")} ${report.totalIntegrationHours}h`);
15613
+ lines.push(` ─────────────────────────────────────────────────`);
15614
+ lines.push(` ${colors2.bold("True Total:")} ${report.trueEffortHours}h ${colors2.dim("← Actual effort")}`);
15615
+ lines.push("");
15616
+ if (report.hiddenWorkPercent > 20) {
15617
+ lines.push(` ${colors2.warning(icons.warning)} ${colors2.bold("Hidden Work:")}`);
15618
+ lines.push(` ${report.hiddenWorkHours}h (${report.hiddenWorkPercent}%) is invisible to leadership`);
15619
+ lines.push("");
15620
+ }
15621
+ lines.push(` ${colors2.bold("Risk Indicators")}`);
15622
+ lines.push(` ─────────────────────────────────────────────────────`);
15623
+ const burnoutColor = report.burnoutRisk === "high" ? colors2.error : report.burnoutRisk === "medium" ? colors2.warning : colors2.success;
15624
+ lines.push(` Burnout Risk: ${burnoutColor(report.burnoutRisk.toUpperCase())}`);
15625
+ lines.push(` Correction Ratio: ${report.averageCorrectionRatio} ${getRatioIndicator(report.averageCorrectionRatio)}`);
15626
+ lines.push(` Context Churn Rate: ${report.contextChurnRate}`);
15627
+ lines.push("");
15628
+ if (report.insights.length > 0) {
15629
+ lines.push(` ${colors2.bold("Key Insights")}`);
15630
+ lines.push(` ─────────────────────────────────────────────────────`);
15631
+ for (const insight of report.insights) {
15632
+ lines.push(` ${colors2.primary("→")} ${insight}`);
15633
+ }
15634
+ lines.push("");
15635
+ }
15636
+ lines.push(colors2.dim(" " + "═".repeat(60)));
15637
+ return lines;
15638
+ }
15639
+ function formatLeadershipReportMarkdown(report) {
15640
+ let md = `# AI Work Visibility Report
15641
+
15642
+ `;
15643
+ md += `**Period:** ${report.period}
15644
+
15645
+ `;
15646
+ md += `## Executive Summary
15647
+
15648
+ `;
15649
+ md += `| Metric | Value |
15650
+ `;
15651
+ md += `|--------|-------|
15652
+ `;
15653
+ md += `| AI-Assisted Sessions | ${report.aiAssistedTasksCount} |
15654
+ `;
15655
+ md += `| Total Effort | ${report.totalEffortHours} hours |
15656
+ `;
15657
+ md += `| Perceived Effort (AI Generation) | ${report.perceivedEffortHours} hours |
15658
+ `;
15659
+ md += `| Hidden Work | ${report.hiddenWorkHours} hours (${report.hiddenWorkPercent}%) |
15660
+
15661
+ `;
15662
+ md += `## Effort Breakdown
15663
+
15664
+ `;
15665
+ md += `| Phase | Hours | % of Total |
15666
+ `;
15667
+ md += `|-------|-------|------------|
15668
+ `;
15669
+ md += `| AI Generation | ${report.totalAIGenerationHours}h | ${Math.round(report.totalAIGenerationHours / report.totalEffortHours * 100)}% |
15670
+ `;
15671
+ md += `| Review | ${report.totalReviewHours}h | ${Math.round(report.totalReviewHours / report.totalEffortHours * 100)}% |
15672
+ `;
15673
+ md += `| Correction | ${report.totalCorrectionHours}h | ${Math.round(report.totalCorrectionHours / report.totalEffortHours * 100)}% |
15674
+ `;
15675
+ md += `| Integration | ${report.totalIntegrationHours}h | ${Math.round(report.totalIntegrationHours / report.totalEffortHours * 100)}% |
15676
+
15677
+ `;
15678
+ md += `## Risk Assessment
15679
+
15680
+ `;
15681
+ md += `- **Burnout Risk:** ${report.burnoutRisk.toUpperCase()}
15682
+ `;
15683
+ md += `- **Correction Ratio:** ${report.averageCorrectionRatio}
15684
+ `;
15685
+ md += `- **Context Churn Rate:** ${report.contextChurnRate}
15686
+
15687
+ `;
15688
+ md += `## Key Insights
15689
+
15690
+ `;
15691
+ for (const insight of report.insights) {
15692
+ md += `- ${insight}
15693
+ `;
15694
+ }
15695
+ md += `
15696
+ `;
15697
+ md += `---
15698
+
15699
+ `;
15700
+ md += `*Generated by nairon-bench - AI Workflow Benchmarking*
15701
+ `;
15702
+ return md;
15703
+ }
15704
+ function formatTime(minutes) {
15705
+ if (minutes < 60) {
15706
+ return `${minutes}m`;
15707
+ }
15708
+ const hours = Math.floor(minutes / 60);
15709
+ const mins = minutes % 60;
15710
+ return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
15711
+ }
15712
+ function formatRatio(ratio) {
15713
+ return `${Math.round(ratio * 100)}%`;
15714
+ }
15715
+ function getRatioIndicator(ratio) {
15716
+ if (ratio > 0.8)
15717
+ return colors2.error("(high - needs attention)");
15718
+ if (ratio > 0.5)
15719
+ return colors2.warning("(moderate)");
15720
+ return colors2.success("(healthy)");
15721
+ }
15722
+
15367
15723
  // src/lib/optimization-installer.ts
15368
15724
  import { execSync as execSync2, spawnSync } from "node:child_process";
15369
15725
  import { existsSync as existsSync8, writeFileSync as writeFileSync3, readFileSync as readFileSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
@@ -16001,6 +16357,13 @@ var scanCommand = defineCommand2({
16001
16357
  const reportPath = generateReport(reportDir, score, git, agents, tests, args.since, sdlcAnalysis, scanCost, analysis);
16002
16358
  console.log(` ${icons.success} Report saved: ${colors2.dim(reportPath)}`);
16003
16359
  }
16360
+ if (agents && agents.sessions.length > 0 && !args.brief) {
16361
+ const effortBreakdown = analyzeEffort(agents.sessions, git);
16362
+ const effortLines = formatEffortBreakdown(effortBreakdown);
16363
+ for (const line of effortLines) {
16364
+ console.log(line);
16365
+ }
16366
+ }
16004
16367
  if (agents && agents.sessions.length > 0 && !args.brief) {
16005
16368
  const frustrationSummary = detectFrustrations(agents.sessions);
16006
16369
  if (frustrationSummary.totalFrustrations > 0) {
@@ -19023,7 +19386,7 @@ function renderTimelineASCII(timeline) {
19023
19386
  if (timeline.milestones.length > 0) {
19024
19387
  lines.push(" Key Milestones:");
19025
19388
  for (const milestone of timeline.milestones.slice(-5)) {
19026
- const time = formatTime(milestone.timestamp);
19389
+ const time = formatTime2(milestone.timestamp);
19027
19390
  const icon = getMilestoneIcon(milestone.type);
19028
19391
  lines.push(` ${time} ${icon} ${truncate(milestone.title, 40)}`);
19029
19392
  }
@@ -19032,7 +19395,7 @@ function renderTimelineASCII(timeline) {
19032
19395
  if (timeline.strugglePoints.length > 0) {
19033
19396
  lines.push(" Struggle Points:");
19034
19397
  for (const struggle of timeline.strugglePoints.slice(-3)) {
19035
- const time = formatTime(struggle.timestamp);
19398
+ const time = formatTime2(struggle.timestamp);
19036
19399
  const icon = getSeverityIcon(struggle.severity);
19037
19400
  lines.push(` ${time} ${icon} ${truncate(struggle.description, 40)}`);
19038
19401
  }
@@ -19100,7 +19463,7 @@ function truncate(str, len2) {
19100
19463
  function cleanCommitMessage(message) {
19101
19464
  return message.replace(/^(feat|fix|refactor|docs|test|chore|style|perf|ci|build|revert)(\(.+?\))?:\s*/i, "").replace(/^(add|fix|update|remove|implement|refactor)\s+/i, "").trim();
19102
19465
  }
19103
- function formatTime(date) {
19466
+ function formatTime2(date) {
19104
19467
  return date.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" });
19105
19468
  }
19106
19469
  function formatDate(date) {
@@ -21429,9 +21792,18 @@ var reportCommand = defineCommand2({
21429
21792
  type: "string",
21430
21793
  description: "Output format: terminal, md, json, or text (legacy)",
21431
21794
  default: "terminal"
21795
+ },
21796
+ leadership: {
21797
+ type: "boolean",
21798
+ description: "Generate leadership report with effort breakdown and hidden work visibility",
21799
+ default: false
21432
21800
  }
21433
21801
  },
21434
21802
  async run({ args }) {
21803
+ if (args.leadership) {
21804
+ await runLeadershipReport(args);
21805
+ return;
21806
+ }
21435
21807
  if (args.hackathon || args.since) {
21436
21808
  await runHackathonReport(args);
21437
21809
  return;
@@ -21724,6 +22096,41 @@ async function publishReport(report) {
21724
22096
  consola.info("Try `nb report --hackathon --format md` for local markdown instead.");
21725
22097
  }
21726
22098
  }
22099
+ async function runLeadershipReport(args) {
22100
+ const projectDir = process.cwd();
22101
+ const since = parseSince2(args.since || "7d");
22102
+ const periodLabel = args.since === "30d" ? "Last 30 days" : args.since === "48h" ? "Last 48 hours" : "Last 7 days";
22103
+ consola.start(`Generating leadership report (${periodLabel})...`);
22104
+ const agents = await collectAgentSessions(since);
22105
+ if (!agents || agents.sessions.length === 0) {
22106
+ consola.warn("No AI sessions found in the specified time range.");
22107
+ consola.info("Try running with --since 30d for a longer time range.");
22108
+ return;
22109
+ }
22110
+ const effort = analyzeEffort(agents.sessions);
22111
+ const report = generateLeadershipReport(effort, periodLabel);
22112
+ const format2 = args.format || "terminal";
22113
+ let output;
22114
+ if (format2 === "md" || format2 === "markdown") {
22115
+ output = formatLeadershipReportMarkdown(report);
22116
+ } else {
22117
+ output = formatLeadershipReport(report).join(`
22118
+ `);
22119
+ }
22120
+ if (args.output) {
22121
+ const filepath = resolve(projectDir, args.output);
22122
+ writeFileSync5(filepath, output);
22123
+ consola.success(`Report saved to ${filepath}`);
22124
+ }
22125
+ console.log(output);
22126
+ consola.log("");
22127
+ consola.info(`Sessions analyzed: ${report.aiAssistedTasksCount}`);
22128
+ consola.info(`True effort: ${report.trueEffortHours}h (${report.hiddenWorkPercent}% invisible)`);
22129
+ consola.info(`Burnout risk: ${report.burnoutRisk.toUpperCase()}`);
22130
+ if (format2 === "terminal" || !format2) {
22131
+ consola.info("Run `nb report --leadership --format md` for exportable markdown");
22132
+ }
22133
+ }
21727
22134
  function parseSince2(since) {
21728
22135
  const match = since.match(/^(\d+)(h|d|w|m)$/);
21729
22136
  if (match) {
@@ -23160,6 +23567,17 @@ var BOLD = "\x1B[1m";
23160
23567
  var RESET = "\x1B[0m";
23161
23568
  var MAGENTA = "\x1B[35m";
23162
23569
  var CHANGELOG = [
23570
+ {
23571
+ version: "0.4.0",
23572
+ date: "2026-02-14",
23573
+ title: "AI Work Visibility",
23574
+ highlights: [
23575
+ "New: Effort breakdown shows generation/review/correction/integration time",
23576
+ "New: nb report --leadership for executive-ready reports",
23577
+ "See hidden work (61% invisible!) that leadership may miss",
23578
+ "Burnout risk detection and true effort multiplier"
23579
+ ]
23580
+ },
23163
23581
  {
23164
23582
  version: "0.3.15",
23165
23583
  date: "2026-02-14",
@@ -23588,7 +24006,7 @@ function showFullChangelog() {
23588
24006
  // package.json
23589
24007
  var package_default = {
23590
24008
  name: "nairon-bench",
23591
- version: "0.3.15",
24009
+ version: "0.4.0",
23592
24010
  description: "AI workflow benchmarking CLI",
23593
24011
  type: "module",
23594
24012
  bin: {
@@ -26113,7 +26531,7 @@ function formatBytes(bytes) {
26113
26531
  // package.json
26114
26532
  var package_default2 = {
26115
26533
  name: "nairon-bench",
26116
- version: "0.3.15",
26534
+ version: "0.4.0",
26117
26535
  description: "AI workflow benchmarking CLI",
26118
26536
  type: "module",
26119
26537
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nairon-bench",
3
- "version": "0.3.15",
3
+ "version": "0.4.0",
4
4
  "description": "AI workflow benchmarking CLI",
5
5
  "type": "module",
6
6
  "bin": {