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.
- package/dist/index.js +423 -5
- 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 =
|
|
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 =
|
|
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
|
|
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.
|
|
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.
|
|
26534
|
+
version: "0.4.0",
|
|
26117
26535
|
description: "AI workflow benchmarking CLI",
|
|
26118
26536
|
type: "module",
|
|
26119
26537
|
bin: {
|