nairon-bench 0.5.2 → 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.
- package/dist/index.js +218 -98
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3661,10 +3661,10 @@ class ConvexHttpClient {
|
|
|
3661
3661
|
}
|
|
3662
3662
|
this.isProcessingQueue = true;
|
|
3663
3663
|
while (this.mutationQueue.length > 0) {
|
|
3664
|
-
const { mutation, args, resolve, reject } = this.mutationQueue.shift();
|
|
3664
|
+
const { mutation, args, resolve: resolve2, reject } = this.mutationQueue.shift();
|
|
3665
3665
|
try {
|
|
3666
3666
|
const result = await this.mutationInner(mutation, args);
|
|
3667
|
-
|
|
3667
|
+
resolve2(result);
|
|
3668
3668
|
} catch (error) {
|
|
3669
3669
|
reject(error);
|
|
3670
3670
|
}
|
|
@@ -3672,8 +3672,8 @@ class ConvexHttpClient {
|
|
|
3672
3672
|
this.isProcessingQueue = false;
|
|
3673
3673
|
}
|
|
3674
3674
|
enqueueMutation(mutation, args) {
|
|
3675
|
-
return new Promise((
|
|
3676
|
-
this.mutationQueue.push({ mutation, args, resolve, reject });
|
|
3675
|
+
return new Promise((resolve2, reject) => {
|
|
3676
|
+
this.mutationQueue.push({ mutation, args, resolve: resolve2, reject });
|
|
3677
3677
|
this.processMutationQueue();
|
|
3678
3678
|
});
|
|
3679
3679
|
}
|
|
@@ -8518,7 +8518,7 @@ async function collectGit(projectDir, since) {
|
|
|
8518
8518
|
// src/collectors/agents.ts
|
|
8519
8519
|
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
8520
8520
|
import { homedir as homedir2 } from "node:os";
|
|
8521
|
-
import { join as join2, basename } from "node:path";
|
|
8521
|
+
import { join as join2, basename, resolve } from "node:path";
|
|
8522
8522
|
// ../shared/src/constants.ts
|
|
8523
8523
|
var PHASE_WEIGHTS = {
|
|
8524
8524
|
requirements: 0.2,
|
|
@@ -8921,17 +8921,18 @@ function getCacheInfo() {
|
|
|
8921
8921
|
|
|
8922
8922
|
// src/collectors/agents.ts
|
|
8923
8923
|
var sessionCache = null;
|
|
8924
|
-
async function collectAgentSessions(since, useCache = true) {
|
|
8924
|
+
async function collectAgentSessions(since, useCache = true, projectDir) {
|
|
8925
8925
|
sessionCache = useCache ? new SessionCache : null;
|
|
8926
|
+
const targetProjectDir = projectDir ? resolve(projectDir) : process.cwd();
|
|
8926
8927
|
const sessions = [];
|
|
8927
8928
|
const claudeProjectsDir = join2(homedir2(), ".claude", "projects");
|
|
8928
8929
|
if (existsSync2(claudeProjectsDir)) {
|
|
8929
|
-
const claudeSessions = collectClaudeSessions(claudeProjectsDir, since);
|
|
8930
|
+
const claudeSessions = collectClaudeSessions(claudeProjectsDir, since, targetProjectDir);
|
|
8930
8931
|
sessions.push(...claudeSessions);
|
|
8931
8932
|
}
|
|
8932
8933
|
const openCodeDir = join2(homedir2(), ".local", "share", "opencode");
|
|
8933
8934
|
if (existsSync2(openCodeDir)) {
|
|
8934
|
-
const openCodeSessions = collectOpenCodeSessions(openCodeDir, since);
|
|
8935
|
+
const openCodeSessions = collectOpenCodeSessions(openCodeDir, since, targetProjectDir);
|
|
8935
8936
|
sessions.push(...openCodeSessions);
|
|
8936
8937
|
}
|
|
8937
8938
|
const cursorDirs = [
|
|
@@ -9011,11 +9012,29 @@ async function collectAgentSessions(since, useCache = true) {
|
|
|
9011
9012
|
costByModel
|
|
9012
9013
|
};
|
|
9013
9014
|
}
|
|
9014
|
-
function collectClaudeSessions(projectsDir, since) {
|
|
9015
|
+
function collectClaudeSessions(projectsDir, since, targetProjectDir) {
|
|
9015
9016
|
const sessions = [];
|
|
9016
9017
|
try {
|
|
9017
9018
|
const projectDirs = readdirSync(projectsDir, { withFileTypes: true }).filter((d2) => d2.isDirectory()).map((d2) => join2(projectsDir, d2.name));
|
|
9019
|
+
let matchingProjectDir = null;
|
|
9018
9020
|
for (const projectDir of projectDirs) {
|
|
9021
|
+
const projectMetaFile = join2(projectDir, ".project.json");
|
|
9022
|
+
if (existsSync2(projectMetaFile)) {
|
|
9023
|
+
try {
|
|
9024
|
+
const meta = JSON.parse(readFileSync2(projectMetaFile, "utf-8"));
|
|
9025
|
+
if (meta.directory) {
|
|
9026
|
+
const metaDir = resolve(meta.directory);
|
|
9027
|
+
const isMatch = metaDir === targetProjectDir || targetProjectDir.startsWith(metaDir + "/") || metaDir.startsWith(targetProjectDir + "/");
|
|
9028
|
+
if (isMatch) {
|
|
9029
|
+
matchingProjectDir = projectDir;
|
|
9030
|
+
break;
|
|
9031
|
+
}
|
|
9032
|
+
}
|
|
9033
|
+
} catch {}
|
|
9034
|
+
}
|
|
9035
|
+
}
|
|
9036
|
+
const dirsToScan = matchingProjectDir ? [matchingProjectDir] : projectDirs;
|
|
9037
|
+
for (const projectDir of dirsToScan) {
|
|
9019
9038
|
const files = readdirSync(projectDir).filter((f3) => f3.endsWith(".jsonl")).map((f3) => join2(projectDir, f3));
|
|
9020
9039
|
for (const file of files) {
|
|
9021
9040
|
const session = parseClaudeSessionFile(file, since);
|
|
@@ -9289,7 +9308,7 @@ function similarity(a2, b2) {
|
|
|
9289
9308
|
const union = new Set([...wordsA, ...wordsB]);
|
|
9290
9309
|
return union.size > 0 ? intersection.size / union.size : 0;
|
|
9291
9310
|
}
|
|
9292
|
-
function collectOpenCodeSessions(baseDir, since) {
|
|
9311
|
+
function collectOpenCodeSessions(baseDir, since, targetProjectDir) {
|
|
9293
9312
|
const sessions = [];
|
|
9294
9313
|
const sessionStorageDir = join2(baseDir, "storage", "session");
|
|
9295
9314
|
const messageStorageDir = join2(baseDir, "storage", "message");
|
|
@@ -9301,7 +9320,7 @@ function collectOpenCodeSessions(baseDir, since) {
|
|
|
9301
9320
|
for (const projectDir of projectDirs) {
|
|
9302
9321
|
const sessionFiles = readdirSync(projectDir).filter((f3) => f3.startsWith("ses_") && f3.endsWith(".json")).map((f3) => join2(projectDir, f3));
|
|
9303
9322
|
for (const sessionFile of sessionFiles) {
|
|
9304
|
-
const session = parseOpenCodeSession(sessionFile, messageStorageDir, partStorageDir, since);
|
|
9323
|
+
const session = parseOpenCodeSession(sessionFile, messageStorageDir, partStorageDir, since, targetProjectDir);
|
|
9305
9324
|
if (session) {
|
|
9306
9325
|
sessions.push(session);
|
|
9307
9326
|
}
|
|
@@ -9310,7 +9329,7 @@ function collectOpenCodeSessions(baseDir, since) {
|
|
|
9310
9329
|
} catch {}
|
|
9311
9330
|
return sessions;
|
|
9312
9331
|
}
|
|
9313
|
-
function parseOpenCodeSession(sessionFile, messageStorageDir, partStorageDir, since) {
|
|
9332
|
+
function parseOpenCodeSession(sessionFile, messageStorageDir, partStorageDir, since, targetProjectDir) {
|
|
9314
9333
|
try {
|
|
9315
9334
|
const cached = sessionCache?.get(sessionFile);
|
|
9316
9335
|
if (cached) {
|
|
@@ -9322,6 +9341,13 @@ function parseOpenCodeSession(sessionFile, messageStorageDir, partStorageDir, si
|
|
|
9322
9341
|
}
|
|
9323
9342
|
const sessionContent = readFileSync2(sessionFile, "utf-8");
|
|
9324
9343
|
const session = JSON.parse(sessionContent);
|
|
9344
|
+
if (session.directory) {
|
|
9345
|
+
const sessionDir = resolve(session.directory);
|
|
9346
|
+
const isMatch = sessionDir === targetProjectDir || targetProjectDir.startsWith(sessionDir + "/") || sessionDir.startsWith(targetProjectDir + "/");
|
|
9347
|
+
if (!isMatch) {
|
|
9348
|
+
return null;
|
|
9349
|
+
}
|
|
9350
|
+
}
|
|
9325
9351
|
const sessionStart = new Date(session.time.created);
|
|
9326
9352
|
const sessionEnd = session.time.updated ? new Date(session.time.updated) : sessionStart;
|
|
9327
9353
|
if (sessionEnd < since)
|
|
@@ -11388,7 +11414,7 @@ function generateOverallSummary(requirements, planning, implementation, review,
|
|
|
11388
11414
|
}
|
|
11389
11415
|
return parts.join(" ") || "Balanced across all phases.";
|
|
11390
11416
|
}
|
|
11391
|
-
function
|
|
11417
|
+
function formatSDLCPhaseForTerminal(phase, overall) {
|
|
11392
11418
|
const lines = [];
|
|
11393
11419
|
const width = 50;
|
|
11394
11420
|
const CYAN = "\x1B[36m";
|
|
@@ -11415,48 +11441,55 @@ function formatSDLCForTerminal(analysis) {
|
|
|
11415
11441
|
}
|
|
11416
11442
|
};
|
|
11417
11443
|
lines.push("");
|
|
11418
|
-
lines.push(`${BOLD}${CYAN} SDLC
|
|
11444
|
+
lines.push(`${BOLD}${CYAN} SDLC OPTIMIZATION${RESET}`);
|
|
11419
11445
|
lines.push(`${DIM} ${"─".repeat(width)}${RESET}`);
|
|
11420
11446
|
lines.push("");
|
|
11421
|
-
const overall = analysis.overall;
|
|
11422
11447
|
lines.push(` ${BOLD}Overall:${RESET} ${gradeColor(overall.grade)}${overall.grade}${RESET} (${overall.score}/100)`);
|
|
11423
11448
|
lines.push(` ${DIM}${overall.summary}${RESET}`);
|
|
11424
11449
|
lines.push("");
|
|
11425
|
-
const
|
|
11426
|
-
|
|
11427
|
-
|
|
11428
|
-
|
|
11429
|
-
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
const
|
|
11433
|
-
|
|
11434
|
-
|
|
11435
|
-
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11439
|
-
|
|
11440
|
-
|
|
11441
|
-
}
|
|
11442
|
-
}
|
|
11443
|
-
|
|
11444
|
-
|
|
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) {
|
|
11445
11482
|
const impactColor = rec.impact === "high" ? RED : rec.impact === "medium" ? YELLOW : DIM;
|
|
11446
|
-
lines.push(`
|
|
11483
|
+
lines.push(` ${impactColor}!${RESET} ${rec.title}`);
|
|
11484
|
+
lines.push(` ${DIM}${rec.description}${RESET}`);
|
|
11447
11485
|
if (rec.installCommand) {
|
|
11448
|
-
lines.push(`
|
|
11486
|
+
lines.push(` ${DIM}${rec.installCommand}${RESET}`);
|
|
11449
11487
|
}
|
|
11450
11488
|
}
|
|
11451
|
-
lines.push("");
|
|
11452
11489
|
}
|
|
11490
|
+
lines.push("");
|
|
11453
11491
|
return lines;
|
|
11454
11492
|
}
|
|
11455
|
-
function renderBar(value, width) {
|
|
11456
|
-
const filled = Math.round(value / 100 * width);
|
|
11457
|
-
const empty = width - filled;
|
|
11458
|
-
return "█".repeat(filled) + "░".repeat(empty);
|
|
11459
|
-
}
|
|
11460
11493
|
|
|
11461
11494
|
// src/lib/frustration-detector.ts
|
|
11462
11495
|
import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as fsReaddirSync } from "node:fs";
|
|
@@ -14763,7 +14796,7 @@ var icons = {
|
|
|
14763
14796
|
brain: "\uD83E\uDDE0",
|
|
14764
14797
|
target: "\uD83C\uDFAF"
|
|
14765
14798
|
};
|
|
14766
|
-
var sleep = (ms) => new Promise((
|
|
14799
|
+
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
14767
14800
|
function clearLine2() {
|
|
14768
14801
|
readline.clearLine(process.stdout, 0);
|
|
14769
14802
|
readline.cursorTo(process.stdout, 0);
|
|
@@ -15110,8 +15143,12 @@ function extractFrustrationPrompts(sessionPath, patterns) {
|
|
|
15110
15143
|
}
|
|
15111
15144
|
}
|
|
15112
15145
|
} else if (sessionPath.endsWith(".json")) {
|
|
15113
|
-
|
|
15114
|
-
|
|
15146
|
+
const sessionData = JSON.parse(content);
|
|
15147
|
+
const sessionId = sessionData.id;
|
|
15148
|
+
const userPrompts = extractOpenCodePrompts(sessionId);
|
|
15149
|
+
for (const pattern of patterns) {
|
|
15150
|
+
const frustrationMsg = findFrustrationMessage(userPrompts);
|
|
15151
|
+
prompts.push(frustrationMsg || userPrompts[0] || "");
|
|
15115
15152
|
}
|
|
15116
15153
|
}
|
|
15117
15154
|
return prompts;
|
|
@@ -15119,6 +15156,45 @@ function extractFrustrationPrompts(sessionPath, patterns) {
|
|
|
15119
15156
|
return [];
|
|
15120
15157
|
}
|
|
15121
15158
|
}
|
|
15159
|
+
function extractOpenCodePrompts(sessionId) {
|
|
15160
|
+
const home = homedir6();
|
|
15161
|
+
const messageDir = join7(home, ".local", "share", "opencode", "storage", "message", sessionId);
|
|
15162
|
+
const partBaseDir = join7(home, ".local", "share", "opencode", "storage", "part");
|
|
15163
|
+
if (!existsSync7(messageDir))
|
|
15164
|
+
return [];
|
|
15165
|
+
const prompts = [];
|
|
15166
|
+
try {
|
|
15167
|
+
const messageFiles = fsReaddirSync(messageDir).filter((f3) => f3.endsWith(".json")).sort();
|
|
15168
|
+
for (const msgFile of messageFiles) {
|
|
15169
|
+
try {
|
|
15170
|
+
const msgPath = join7(messageDir, msgFile);
|
|
15171
|
+
const msgData = JSON.parse(readFileSync7(msgPath, "utf-8"));
|
|
15172
|
+
if (msgData.role !== "user")
|
|
15173
|
+
continue;
|
|
15174
|
+
const messageId = msgData.id;
|
|
15175
|
+
const timestamp = msgData.time?.created;
|
|
15176
|
+
const partDir = join7(partBaseDir, messageId);
|
|
15177
|
+
if (!existsSync7(partDir))
|
|
15178
|
+
continue;
|
|
15179
|
+
const partFiles = fsReaddirSync(partDir).filter((f3) => f3.endsWith(".json"));
|
|
15180
|
+
let messageText = "";
|
|
15181
|
+
for (const partFile of partFiles) {
|
|
15182
|
+
try {
|
|
15183
|
+
const partData = JSON.parse(readFileSync7(join7(partDir, partFile), "utf-8"));
|
|
15184
|
+
if (partData.type === "text" && partData.text) {
|
|
15185
|
+
messageText += partData.text + " ";
|
|
15186
|
+
}
|
|
15187
|
+
} catch {}
|
|
15188
|
+
}
|
|
15189
|
+
if (messageText.trim()) {
|
|
15190
|
+
const timeStr = timestamp ? new Date(timestamp).toLocaleTimeString() : "";
|
|
15191
|
+
prompts.push(`[${timeStr}] ${messageText.trim()}`);
|
|
15192
|
+
}
|
|
15193
|
+
} catch {}
|
|
15194
|
+
}
|
|
15195
|
+
} catch {}
|
|
15196
|
+
return prompts;
|
|
15197
|
+
}
|
|
15122
15198
|
function extractMessageText(msg) {
|
|
15123
15199
|
if (typeof msg.content === "string")
|
|
15124
15200
|
return msg.content;
|
|
@@ -15313,25 +15389,40 @@ function formatFrustrationSummary(summary) {
|
|
|
15313
15389
|
}
|
|
15314
15390
|
function formatFrustrationEvent(f3, index) {
|
|
15315
15391
|
const lines = [];
|
|
15316
|
-
lines.push(` ${colors2.
|
|
15317
|
-
lines.push(` ${colors2.dim("Session:")} ${f3.sessionId.slice(0,
|
|
15318
|
-
|
|
15319
|
-
|
|
15392
|
+
lines.push(` ${colors2.error(`${index}.`)} ${formatCauseLabel(f3.rootCause.category)}`);
|
|
15393
|
+
lines.push(` ${colors2.dim("Session:")} ${f3.sessionId.slice(0, 16)}... ${colors2.dim(`(${f3.agent})`)}`);
|
|
15394
|
+
if (f3.timestamp) {
|
|
15395
|
+
const date = new Date(f3.timestamp);
|
|
15396
|
+
lines.push(` ${colors2.dim("When:")} ${date.toLocaleDateString()} ${date.toLocaleTimeString()}`);
|
|
15397
|
+
}
|
|
15398
|
+
lines.push(` ${colors2.dim("Time wasted:")} ${colors2.warning(`~${f3.estimatedTimeWastedMinutes} min`)}`);
|
|
15320
15399
|
if (f3.exactPrompt && f3.exactPrompt.length > 0 && !f3.exactPrompt.startsWith("(Unable")) {
|
|
15321
15400
|
lines.push("");
|
|
15322
|
-
lines.push(` ${colors2.
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15401
|
+
lines.push(` ${colors2.bold("Your prompt:")}`);
|
|
15402
|
+
lines.push(` ${colors2.dim("┌" + "─".repeat(50))}`);
|
|
15403
|
+
let promptText = f3.exactPrompt;
|
|
15404
|
+
if (promptText.startsWith("[")) {
|
|
15405
|
+
const closeBracket = promptText.indexOf("]");
|
|
15406
|
+
if (closeBracket > 0 && closeBracket < 15) {
|
|
15407
|
+
promptText = promptText.slice(closeBracket + 2);
|
|
15408
|
+
}
|
|
15326
15409
|
}
|
|
15327
|
-
|
|
15328
|
-
|
|
15410
|
+
const promptLines = wrapText(promptText, 48);
|
|
15411
|
+
for (const line of promptLines.slice(0, 6)) {
|
|
15412
|
+
lines.push(` ${colors2.dim("│")} ${colors2.primary(line)}`);
|
|
15329
15413
|
}
|
|
15330
|
-
|
|
15414
|
+
if (promptLines.length > 6) {
|
|
15415
|
+
lines.push(` ${colors2.dim("│")} ${colors2.dim(`... (${promptLines.length - 6} more lines)`)}`);
|
|
15416
|
+
}
|
|
15417
|
+
lines.push(` ${colors2.dim("└" + "─".repeat(50))}`);
|
|
15418
|
+
} else {
|
|
15419
|
+
lines.push("");
|
|
15420
|
+
lines.push(` ${colors2.dim("(Prompt not captured - " + f3.patternDescription + ")")}`);
|
|
15331
15421
|
}
|
|
15332
15422
|
lines.push("");
|
|
15333
|
-
lines.push(` ${colors2.success("Fix:")} ${f3.recommendedFix.tool}`);
|
|
15334
|
-
lines.push(`
|
|
15423
|
+
lines.push(` ${colors2.success("→ Fix with:")} ${colors2.bold(f3.recommendedFix.tool)}`);
|
|
15424
|
+
lines.push(` ${colors2.dim(f3.recommendedFix.description)}`);
|
|
15425
|
+
lines.push(` ${colors2.dim("$")} ${colors2.primary(f3.recommendedFix.installCommand)}`);
|
|
15335
15426
|
return lines;
|
|
15336
15427
|
}
|
|
15337
15428
|
function formatCauseLabel(cause) {
|
|
@@ -16376,7 +16467,7 @@ var scanCommand = defineCommand2({
|
|
|
16376
16467
|
const timestamp = new Date().toLocaleTimeString();
|
|
16377
16468
|
try {
|
|
16378
16469
|
const git2 = await collectGit(projectDir, since);
|
|
16379
|
-
const agents2 = await collectAgentSessions(since, useCache);
|
|
16470
|
+
const agents2 = await collectAgentSessions(since, useCache, projectDir);
|
|
16380
16471
|
const tests2 = await collectTestResults(projectDir);
|
|
16381
16472
|
const score2 = computeNaironScore(git2 ?? undefined, agents2 ?? undefined, tests2 ?? undefined);
|
|
16382
16473
|
const delta = scanCount > 1 ? score2.overall - lastScore : 0;
|
|
@@ -16421,7 +16512,7 @@ var scanCommand = defineCommand2({
|
|
|
16421
16512
|
}
|
|
16422
16513
|
if (!silent)
|
|
16423
16514
|
await thinkingStep("Scanning AI session logs...", 600);
|
|
16424
|
-
const agents = await collectAgentSessions(since, useCache);
|
|
16515
|
+
const agents = await collectAgentSessions(since, useCache, projectDir);
|
|
16425
16516
|
if (agents && !silent) {
|
|
16426
16517
|
await revealDiscovery(icons.success, `Sessions: ${colors2.primary(agents.totalSessions.toString())} sessions loaded`, 200);
|
|
16427
16518
|
}
|
|
@@ -16550,29 +16641,37 @@ var scanCommand = defineCommand2({
|
|
|
16550
16641
|
} else if (sdlc.overall.summary.includes("optimizations available")) {
|
|
16551
16642
|
sdlc.overall.summary = sdlc.overall.summary.replace(/\d+ optimizations available\./, "All recommended tools installed.");
|
|
16552
16643
|
}
|
|
16553
|
-
const
|
|
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);
|
|
16554
16655
|
for (const line of sdlcLines) {
|
|
16555
16656
|
console.log(line);
|
|
16556
16657
|
}
|
|
16557
|
-
let
|
|
16558
|
-
for (const
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
allRecs.push(phaseRecToInstallable(rec));
|
|
16562
|
-
}
|
|
16658
|
+
let phaseRecs = [];
|
|
16659
|
+
for (const rec of selectedPhase.recommendations) {
|
|
16660
|
+
if (rec.installCommand) {
|
|
16661
|
+
phaseRecs.push(phaseRecToInstallable(rec));
|
|
16563
16662
|
}
|
|
16564
16663
|
}
|
|
16565
|
-
|
|
16566
|
-
if (
|
|
16664
|
+
phaseRecs = filterAlreadyInstalled(phaseRecs, installedStatus);
|
|
16665
|
+
if (phaseRecs.length > 0) {
|
|
16567
16666
|
console.log();
|
|
16568
|
-
const optionLabels =
|
|
16569
|
-
const selected = await consola.prompt(`${
|
|
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):`, {
|
|
16570
16669
|
type: "multiselect",
|
|
16571
16670
|
options: optionLabels,
|
|
16572
16671
|
required: false
|
|
16573
16672
|
});
|
|
16574
16673
|
if (selected && typeof selected !== "symbol" && Array.isArray(selected) && selected.length > 0) {
|
|
16575
|
-
const toInstall =
|
|
16674
|
+
const toInstall = phaseRecs.filter((rec) => selected.some((s2) => s2.startsWith(rec.name))).map((r3) => ({ ...r3, selected: true }));
|
|
16576
16675
|
if (toInstall.length > 0) {
|
|
16577
16676
|
console.log();
|
|
16578
16677
|
console.log(` ${colors2.bold("Installing...")}${colors2.dim("")}`);
|
|
@@ -20474,10 +20573,10 @@ function renderCoverageSummary(report) {
|
|
|
20474
20573
|
lines.push(` Format: ${report.format}`);
|
|
20475
20574
|
lines.push(` Overall: ${report.summary.overall}%`);
|
|
20476
20575
|
lines.push("");
|
|
20477
|
-
lines.push(` Lines: ${
|
|
20478
|
-
lines.push(` Statements: ${
|
|
20479
|
-
lines.push(` Functions: ${
|
|
20480
|
-
lines.push(` Branches: ${
|
|
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}%`);
|
|
20481
20580
|
if (report.uncoveredFiles.length > 0) {
|
|
20482
20581
|
lines.push("");
|
|
20483
20582
|
lines.push(` Uncovered files: ${report.uncoveredFiles.length}`);
|
|
@@ -20523,7 +20622,7 @@ function renderCoverageMarkdown(report) {
|
|
|
20523
20622
|
}
|
|
20524
20623
|
return lines;
|
|
20525
20624
|
}
|
|
20526
|
-
function
|
|
20625
|
+
function renderBar(percentage, width = 15) {
|
|
20527
20626
|
const filled = Math.round(percentage / 100 * width);
|
|
20528
20627
|
const empty = width - filled;
|
|
20529
20628
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
@@ -21706,10 +21805,10 @@ function formatReportAsTerminal(report) {
|
|
|
21706
21805
|
lines.push(` ${report.gradeDescription}`);
|
|
21707
21806
|
lines.push("");
|
|
21708
21807
|
lines.push(" Score Breakdown:");
|
|
21709
|
-
lines.push(` SDLC Coverage: ${
|
|
21710
|
-
lines.push(` Prompt Quality: ${
|
|
21711
|
-
lines.push(` Tool Utilization: ${
|
|
21712
|
-
lines.push(` 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}`);
|
|
21713
21812
|
lines.push("");
|
|
21714
21813
|
lines.push(" Quick Stats:");
|
|
21715
21814
|
lines.push(` Sessions: ${report.summary.totalSessions} | Prompts: ${report.summary.totalPrompts} | Commits: ${report.summary.totalCommits}`);
|
|
@@ -21796,7 +21895,7 @@ function formatReportAsTerminal(report) {
|
|
|
21796
21895
|
return lines.join(`
|
|
21797
21896
|
`);
|
|
21798
21897
|
}
|
|
21799
|
-
function
|
|
21898
|
+
function renderBar2(value, width = 20) {
|
|
21800
21899
|
const filled = Math.round(value / 100 * width);
|
|
21801
21900
|
const empty = width - filled;
|
|
21802
21901
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
@@ -21888,7 +21987,7 @@ function formatReportAsJSON(report) {
|
|
|
21888
21987
|
|
|
21889
21988
|
// src/commands/report.ts
|
|
21890
21989
|
import { writeFileSync as writeFileSync6 } from "node:fs";
|
|
21891
|
-
import { resolve } from "node:path";
|
|
21990
|
+
import { resolve as resolve2 } from "node:path";
|
|
21892
21991
|
var reportCommand = defineCommand2({
|
|
21893
21992
|
meta: {
|
|
21894
21993
|
name: "report",
|
|
@@ -22098,7 +22197,7 @@ async function runHackathonReport(args) {
|
|
|
22098
22197
|
break;
|
|
22099
22198
|
}
|
|
22100
22199
|
if (args.output) {
|
|
22101
|
-
const filepath =
|
|
22200
|
+
const filepath = resolve2(projectDir, args.output);
|
|
22102
22201
|
writeFileSync6(filepath, output);
|
|
22103
22202
|
consola.success(`Report saved to ${filepath}`);
|
|
22104
22203
|
}
|
|
@@ -22250,7 +22349,7 @@ async function runLeadershipReport(args) {
|
|
|
22250
22349
|
const since = parseSince2(args.since || "7d");
|
|
22251
22350
|
const periodLabel = args.since === "30d" ? "Last 30 days" : args.since === "48h" ? "Last 48 hours" : "Last 7 days";
|
|
22252
22351
|
consola.start(`Generating leadership report (${periodLabel})...`);
|
|
22253
|
-
const agents = await collectAgentSessions(since);
|
|
22352
|
+
const agents = await collectAgentSessions(since, true, projectDir);
|
|
22254
22353
|
if (!agents || agents.sessions.length === 0) {
|
|
22255
22354
|
consola.warn("No AI sessions found in the specified time range.");
|
|
22256
22355
|
consola.info("Try running with --since 30d for a longer time range.");
|
|
@@ -22267,7 +22366,7 @@ async function runLeadershipReport(args) {
|
|
|
22267
22366
|
`);
|
|
22268
22367
|
}
|
|
22269
22368
|
if (args.output) {
|
|
22270
|
-
const filepath =
|
|
22369
|
+
const filepath = resolve2(projectDir, args.output);
|
|
22271
22370
|
writeFileSync6(filepath, output);
|
|
22272
22371
|
consola.success(`Report saved to ${filepath}`);
|
|
22273
22372
|
}
|
|
@@ -22350,7 +22449,7 @@ async function showHistory(client, clerkId, limit, format2) {
|
|
|
22350
22449
|
const recent = trend.slice(-limit);
|
|
22351
22450
|
for (const entry of recent) {
|
|
22352
22451
|
const date = new Date(entry.date).toLocaleDateString();
|
|
22353
|
-
const bar =
|
|
22452
|
+
const bar = renderBar3(entry.overall, 30);
|
|
22354
22453
|
const eff = `${entry.tokenEfficiency}x`;
|
|
22355
22454
|
consola.log(` ${date.padEnd(12)} ${String(entry.overall).padStart(3)}/100 ${bar} eff: ${eff}`);
|
|
22356
22455
|
}
|
|
@@ -22405,7 +22504,7 @@ function renderScanReport(scan, phaseFilter) {
|
|
|
22405
22504
|
const phases = phaseFilter ? scan.phases.filter((p) => p.phase === phaseFilter) : scan.phases;
|
|
22406
22505
|
lines.push("Phase Scores:");
|
|
22407
22506
|
for (const phase of phases) {
|
|
22408
|
-
const bar =
|
|
22507
|
+
const bar = renderBar3(phase.score, 20);
|
|
22409
22508
|
const delta = phase.delta !== undefined && phase.delta !== null ? ` (${phase.delta > 0 ? "+" : ""}${phase.delta})` : "";
|
|
22410
22509
|
lines.push(` ${phase.phase.padEnd(16)} ${String(phase.score).padStart(3)}/100 ${bar}${delta}`);
|
|
22411
22510
|
}
|
|
@@ -22423,7 +22522,7 @@ function renderScanReport(scan, phaseFilter) {
|
|
|
22423
22522
|
return lines.join(`
|
|
22424
22523
|
`);
|
|
22425
22524
|
}
|
|
22426
|
-
function
|
|
22525
|
+
function renderBar3(value, width) {
|
|
22427
22526
|
const filled = Math.round(value / 100 * width);
|
|
22428
22527
|
const empty = width - filled;
|
|
22429
22528
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
@@ -23272,10 +23371,10 @@ async function prompt2(question) {
|
|
|
23272
23371
|
input: process.stdin,
|
|
23273
23372
|
output: process.stdout
|
|
23274
23373
|
});
|
|
23275
|
-
return new Promise((
|
|
23374
|
+
return new Promise((resolve3) => {
|
|
23276
23375
|
rl.question(question, (answer) => {
|
|
23277
23376
|
rl.close();
|
|
23278
|
-
|
|
23377
|
+
resolve3(answer.trim());
|
|
23279
23378
|
});
|
|
23280
23379
|
});
|
|
23281
23380
|
}
|
|
@@ -23720,6 +23819,27 @@ var BOLD = "\x1B[1m";
|
|
|
23720
23819
|
var RESET = "\x1B[0m";
|
|
23721
23820
|
var MAGENTA = "\x1B[35m";
|
|
23722
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
|
+
},
|
|
23832
|
+
{
|
|
23833
|
+
version: "0.5.3",
|
|
23834
|
+
date: "2026-02-14",
|
|
23835
|
+
title: "Project-Scoped Analysis",
|
|
23836
|
+
highlights: [
|
|
23837
|
+
"CRITICAL FIX: Sessions now filtered to current project only",
|
|
23838
|
+
"No more mixing data from different projects in reports",
|
|
23839
|
+
"Improved frustration display with exact prompts and timestamps",
|
|
23840
|
+
"Better OpenCode prompt extraction for frustration analysis"
|
|
23841
|
+
]
|
|
23842
|
+
},
|
|
23723
23843
|
{
|
|
23724
23844
|
version: "0.5.2",
|
|
23725
23845
|
date: "2026-02-14",
|
|
@@ -24191,7 +24311,7 @@ function showFullChangelog() {
|
|
|
24191
24311
|
// package.json
|
|
24192
24312
|
var package_default = {
|
|
24193
24313
|
name: "nairon-bench",
|
|
24194
|
-
version: "0.
|
|
24314
|
+
version: "0.6.0",
|
|
24195
24315
|
description: "AI workflow benchmarking CLI",
|
|
24196
24316
|
type: "module",
|
|
24197
24317
|
bin: {
|
|
@@ -24380,7 +24500,7 @@ async function fetchGitHubUser(accessToken) {
|
|
|
24380
24500
|
return await response.json();
|
|
24381
24501
|
}
|
|
24382
24502
|
function sleep2(ms) {
|
|
24383
|
-
return new Promise((
|
|
24503
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
24384
24504
|
}
|
|
24385
24505
|
|
|
24386
24506
|
// src/commands/init.ts
|
|
@@ -25169,7 +25289,7 @@ var safeJSON = (text) => {
|
|
|
25169
25289
|
};
|
|
25170
25290
|
|
|
25171
25291
|
// ../../node_modules/supermemory/internal/utils/sleep.mjs
|
|
25172
|
-
var sleep3 = (ms) => new Promise((
|
|
25292
|
+
var sleep3 = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
25173
25293
|
|
|
25174
25294
|
// ../../node_modules/supermemory/version.mjs
|
|
25175
25295
|
var VERSION = "4.11.1";
|
|
@@ -25811,8 +25931,8 @@ var _APIPromise_client;
|
|
|
25811
25931
|
|
|
25812
25932
|
class APIPromise extends Promise {
|
|
25813
25933
|
constructor(client, responsePromise, parseResponse = defaultParseResponse) {
|
|
25814
|
-
super((
|
|
25815
|
-
|
|
25934
|
+
super((resolve3) => {
|
|
25935
|
+
resolve3(null);
|
|
25816
25936
|
});
|
|
25817
25937
|
this.responsePromise = responsePromise;
|
|
25818
25938
|
this.parseResponse = parseResponse;
|
|
@@ -26718,7 +26838,7 @@ function formatBytes(bytes) {
|
|
|
26718
26838
|
// package.json
|
|
26719
26839
|
var package_default2 = {
|
|
26720
26840
|
name: "nairon-bench",
|
|
26721
|
-
version: "0.
|
|
26841
|
+
version: "0.6.0",
|
|
26722
26842
|
description: "AI workflow benchmarking CLI",
|
|
26723
26843
|
type: "module",
|
|
26724
26844
|
bin: {
|