nairon-bench 0.3.14 → 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 +459 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15226,21 +15226,28 @@ function aggregateRecommendations(frustrations) {
|
|
|
15226
15226
|
for (const f3 of frustrations) {
|
|
15227
15227
|
const key = f3.recommendedFix.tool;
|
|
15228
15228
|
if (!byTool[key]) {
|
|
15229
|
-
byTool[key] = { count: 0, timeSaved: 0, costSaved: 0, fix: f3.recommendedFix };
|
|
15229
|
+
byTool[key] = { count: 0, timeSaved: 0, costSaved: 0, fix: f3.recommendedFix, frustrations: [] };
|
|
15230
15230
|
}
|
|
15231
15231
|
byTool[key].count++;
|
|
15232
15232
|
byTool[key].timeSaved += f3.estimatedTimeWastedMinutes * (f3.recommendedFix.estimatedImprovementPercent / 100);
|
|
15233
15233
|
byTool[key].costSaved += f3.estimatedCostWasted * (f3.recommendedFix.estimatedImprovementPercent / 100);
|
|
15234
|
+
byTool[key].frustrations.push(f3);
|
|
15234
15235
|
}
|
|
15235
15236
|
const recommendations = [];
|
|
15236
15237
|
for (const [tool, data] of Object.entries(byTool)) {
|
|
15238
|
+
const preventedFrustrations = data.frustrations.sort((a2, b2) => b2.estimatedTimeWastedMinutes - a2.estimatedTimeWastedMinutes).slice(0, 3).map((f3) => ({
|
|
15239
|
+
patternType: f3.patternDescription,
|
|
15240
|
+
promptSnippet: f3.exactPrompt.slice(0, 80) + (f3.exactPrompt.length > 80 ? "..." : ""),
|
|
15241
|
+
timeWasted: f3.estimatedTimeWastedMinutes
|
|
15242
|
+
}));
|
|
15237
15243
|
recommendations.push({
|
|
15238
15244
|
tool,
|
|
15239
15245
|
description: data.fix.description,
|
|
15240
15246
|
installCommand: data.fix.installCommand,
|
|
15241
15247
|
wouldHavePreventedCount: data.count,
|
|
15242
15248
|
estimatedTimeSavedMinutes: Math.round(data.timeSaved),
|
|
15243
|
-
estimatedCostSaved: Math.round(data.costSaved * 100) / 100
|
|
15249
|
+
estimatedCostSaved: Math.round(data.costSaved * 100) / 100,
|
|
15250
|
+
preventedFrustrations
|
|
15244
15251
|
});
|
|
15245
15252
|
}
|
|
15246
15253
|
recommendations.sort((a2, b2) => b2.estimatedTimeSavedMinutes - a2.estimatedTimeSavedMinutes);
|
|
@@ -15280,13 +15287,24 @@ function formatFrustrationSummary(summary) {
|
|
|
15280
15287
|
}
|
|
15281
15288
|
}
|
|
15282
15289
|
if (summary.recommendations.length > 0) {
|
|
15283
|
-
lines.push(` ${colors2.bold(colors2.primary("
|
|
15290
|
+
lines.push(` ${colors2.bold(colors2.primary("Contextual Recommendations:"))}`);
|
|
15291
|
+
lines.push("");
|
|
15292
|
+
const totalTimeSavings = summary.recommendations.reduce((a2, r3) => a2 + r3.estimatedTimeSavedMinutes, 0);
|
|
15293
|
+
const totalCostSavings = summary.recommendations.reduce((a2, r3) => a2 + r3.estimatedCostSaved, 0);
|
|
15294
|
+
lines.push(` ${colors2.dim("Total potential savings:")} ${colors2.success(`~${totalTimeSavings} min`)} | ${colors2.success(`$${totalCostSavings.toFixed(2)}`)}`);
|
|
15284
15295
|
lines.push("");
|
|
15285
|
-
for (
|
|
15286
|
-
|
|
15287
|
-
lines.push(`
|
|
15288
|
-
lines.push(`
|
|
15289
|
-
lines.push(`
|
|
15296
|
+
for (let i3 = 0;i3 < Math.min(3, summary.recommendations.length); i3++) {
|
|
15297
|
+
const rec = summary.recommendations[i3];
|
|
15298
|
+
lines.push(` ${colors2.success(`${i3 + 1}.`)} ${colors2.bold(rec.tool)}`);
|
|
15299
|
+
lines.push(` ${rec.description}`);
|
|
15300
|
+
lines.push(` ${colors2.dim("Prevented:")} ${rec.wouldHavePreventedCount} issue${rec.wouldHavePreventedCount > 1 ? "s" : ""} ${colors2.dim("|")} ${colors2.success(`~${rec.estimatedTimeSavedMinutes} min saved`)}`);
|
|
15301
|
+
if (rec.preventedFrustrations.length > 0) {
|
|
15302
|
+
lines.push(` ${colors2.dim("Would have fixed:")}`);
|
|
15303
|
+
for (const pf of rec.preventedFrustrations.slice(0, 2)) {
|
|
15304
|
+
lines.push(` ${colors2.dim("•")} ${pf.patternType} ${colors2.dim(`(${pf.timeWasted} min)`)}`);
|
|
15305
|
+
}
|
|
15306
|
+
}
|
|
15307
|
+
lines.push(` ${colors2.dim("Install:")} ${colors2.primary(rec.installCommand)}`);
|
|
15290
15308
|
lines.push("");
|
|
15291
15309
|
}
|
|
15292
15310
|
}
|
|
@@ -15346,6 +15364,362 @@ function wrapText(text, width) {
|
|
|
15346
15364
|
return lines;
|
|
15347
15365
|
}
|
|
15348
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
|
+
|
|
15349
15723
|
// src/lib/optimization-installer.ts
|
|
15350
15724
|
import { execSync as execSync2, spawnSync } from "node:child_process";
|
|
15351
15725
|
import { existsSync as existsSync8, writeFileSync as writeFileSync3, readFileSync as readFileSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync4 } from "node:fs";
|
|
@@ -15983,6 +16357,13 @@ var scanCommand = defineCommand2({
|
|
|
15983
16357
|
const reportPath = generateReport(reportDir, score, git, agents, tests, args.since, sdlcAnalysis, scanCost, analysis);
|
|
15984
16358
|
console.log(` ${icons.success} Report saved: ${colors2.dim(reportPath)}`);
|
|
15985
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
|
+
}
|
|
15986
16367
|
if (agents && agents.sessions.length > 0 && !args.brief) {
|
|
15987
16368
|
const frustrationSummary = detectFrustrations(agents.sessions);
|
|
15988
16369
|
if (frustrationSummary.totalFrustrations > 0) {
|
|
@@ -19005,7 +19386,7 @@ function renderTimelineASCII(timeline) {
|
|
|
19005
19386
|
if (timeline.milestones.length > 0) {
|
|
19006
19387
|
lines.push(" Key Milestones:");
|
|
19007
19388
|
for (const milestone of timeline.milestones.slice(-5)) {
|
|
19008
|
-
const time =
|
|
19389
|
+
const time = formatTime2(milestone.timestamp);
|
|
19009
19390
|
const icon = getMilestoneIcon(milestone.type);
|
|
19010
19391
|
lines.push(` ${time} ${icon} ${truncate(milestone.title, 40)}`);
|
|
19011
19392
|
}
|
|
@@ -19014,7 +19395,7 @@ function renderTimelineASCII(timeline) {
|
|
|
19014
19395
|
if (timeline.strugglePoints.length > 0) {
|
|
19015
19396
|
lines.push(" Struggle Points:");
|
|
19016
19397
|
for (const struggle of timeline.strugglePoints.slice(-3)) {
|
|
19017
|
-
const time =
|
|
19398
|
+
const time = formatTime2(struggle.timestamp);
|
|
19018
19399
|
const icon = getSeverityIcon(struggle.severity);
|
|
19019
19400
|
lines.push(` ${time} ${icon} ${truncate(struggle.description, 40)}`);
|
|
19020
19401
|
}
|
|
@@ -19082,7 +19463,7 @@ function truncate(str, len2) {
|
|
|
19082
19463
|
function cleanCommitMessage(message) {
|
|
19083
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();
|
|
19084
19465
|
}
|
|
19085
|
-
function
|
|
19466
|
+
function formatTime2(date) {
|
|
19086
19467
|
return date.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" });
|
|
19087
19468
|
}
|
|
19088
19469
|
function formatDate(date) {
|
|
@@ -21411,9 +21792,18 @@ var reportCommand = defineCommand2({
|
|
|
21411
21792
|
type: "string",
|
|
21412
21793
|
description: "Output format: terminal, md, json, or text (legacy)",
|
|
21413
21794
|
default: "terminal"
|
|
21795
|
+
},
|
|
21796
|
+
leadership: {
|
|
21797
|
+
type: "boolean",
|
|
21798
|
+
description: "Generate leadership report with effort breakdown and hidden work visibility",
|
|
21799
|
+
default: false
|
|
21414
21800
|
}
|
|
21415
21801
|
},
|
|
21416
21802
|
async run({ args }) {
|
|
21803
|
+
if (args.leadership) {
|
|
21804
|
+
await runLeadershipReport(args);
|
|
21805
|
+
return;
|
|
21806
|
+
}
|
|
21417
21807
|
if (args.hackathon || args.since) {
|
|
21418
21808
|
await runHackathonReport(args);
|
|
21419
21809
|
return;
|
|
@@ -21706,6 +22096,41 @@ async function publishReport(report) {
|
|
|
21706
22096
|
consola.info("Try `nb report --hackathon --format md` for local markdown instead.");
|
|
21707
22097
|
}
|
|
21708
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
|
+
}
|
|
21709
22134
|
function parseSince2(since) {
|
|
21710
22135
|
const match = since.match(/^(\d+)(h|d|w|m)$/);
|
|
21711
22136
|
if (match) {
|
|
@@ -23142,6 +23567,27 @@ var BOLD = "\x1B[1m";
|
|
|
23142
23567
|
var RESET = "\x1B[0m";
|
|
23143
23568
|
var MAGENTA = "\x1B[35m";
|
|
23144
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
|
+
},
|
|
23581
|
+
{
|
|
23582
|
+
version: "0.3.15",
|
|
23583
|
+
date: "2026-02-14",
|
|
23584
|
+
title: "Contextual Recommendations",
|
|
23585
|
+
highlights: [
|
|
23586
|
+
"Recommendations now linked to specific frustrations they prevent",
|
|
23587
|
+
"Total time and cost savings summary",
|
|
23588
|
+
"See exactly which issues each tool would have fixed"
|
|
23589
|
+
]
|
|
23590
|
+
},
|
|
23145
23591
|
{
|
|
23146
23592
|
version: "0.3.14",
|
|
23147
23593
|
date: "2026-02-14",
|
|
@@ -23560,7 +24006,7 @@ function showFullChangelog() {
|
|
|
23560
24006
|
// package.json
|
|
23561
24007
|
var package_default = {
|
|
23562
24008
|
name: "nairon-bench",
|
|
23563
|
-
version: "0.
|
|
24009
|
+
version: "0.4.0",
|
|
23564
24010
|
description: "AI workflow benchmarking CLI",
|
|
23565
24011
|
type: "module",
|
|
23566
24012
|
bin: {
|
|
@@ -26085,7 +26531,7 @@ function formatBytes(bytes) {
|
|
|
26085
26531
|
// package.json
|
|
26086
26532
|
var package_default2 = {
|
|
26087
26533
|
name: "nairon-bench",
|
|
26088
|
-
version: "0.
|
|
26534
|
+
version: "0.4.0",
|
|
26089
26535
|
description: "AI workflow benchmarking CLI",
|
|
26090
26536
|
type: "module",
|
|
26091
26537
|
bin: {
|