nairon-bench 0.5.3 → 0.6.1
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 +328 -93
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8516,9 +8516,9 @@ async function collectGit(projectDir, since) {
|
|
|
8516
8516
|
}
|
|
8517
8517
|
|
|
8518
8518
|
// src/collectors/agents.ts
|
|
8519
|
-
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
8519
|
+
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
|
|
8520
8520
|
import { homedir as homedir2 } from "node:os";
|
|
8521
|
-
import { join as join2, basename, resolve } from "node:path";
|
|
8521
|
+
import { join as join2, basename, resolve, sep as sep2 } from "node:path";
|
|
8522
8522
|
// ../shared/src/constants.ts
|
|
8523
8523
|
var PHASE_WEIGHTS = {
|
|
8524
8524
|
requirements: 0.2,
|
|
@@ -8935,18 +8935,34 @@ async function collectAgentSessions(since, useCache = true, projectDir) {
|
|
|
8935
8935
|
const openCodeSessions = collectOpenCodeSessions(openCodeDir, since, targetProjectDir);
|
|
8936
8936
|
sessions.push(...openCodeSessions);
|
|
8937
8937
|
}
|
|
8938
|
-
const
|
|
8939
|
-
join2(homedir2(), ".cursor", "
|
|
8940
|
-
join2(homedir2(), "Library", "Application Support", "Cursor", "
|
|
8941
|
-
join2(homedir2(), ".config", "cursor", "
|
|
8938
|
+
const cursorProjectsDirs = [
|
|
8939
|
+
join2(homedir2(), ".cursor", "projects"),
|
|
8940
|
+
join2(homedir2(), "Library", "Application Support", "Cursor", "projects"),
|
|
8941
|
+
join2(homedir2(), ".config", "cursor", "projects")
|
|
8942
8942
|
];
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8943
|
+
let cursorSessions = [];
|
|
8944
|
+
for (const cursorProjectsDir of cursorProjectsDirs) {
|
|
8945
|
+
if (existsSync2(cursorProjectsDir)) {
|
|
8946
|
+
cursorSessions = collectCursorProjectSessions(cursorProjectsDir, since, targetProjectDir);
|
|
8947
|
+
if (cursorSessions.length > 0)
|
|
8948
|
+
break;
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8951
|
+
if (cursorSessions.length === 0) {
|
|
8952
|
+
const cursorDirs = [
|
|
8953
|
+
join2(homedir2(), ".cursor", "sessions"),
|
|
8954
|
+
join2(homedir2(), "Library", "Application Support", "Cursor", "sessions"),
|
|
8955
|
+
join2(homedir2(), ".config", "cursor", "sessions")
|
|
8956
|
+
];
|
|
8957
|
+
for (const cursorDir of cursorDirs) {
|
|
8958
|
+
if (existsSync2(cursorDir)) {
|
|
8959
|
+
cursorSessions = collectCursorSessions(cursorDir, since, targetProjectDir);
|
|
8960
|
+
if (cursorSessions.length > 0)
|
|
8961
|
+
break;
|
|
8962
|
+
}
|
|
8948
8963
|
}
|
|
8949
8964
|
}
|
|
8965
|
+
sessions.push(...cursorSessions);
|
|
8950
8966
|
const windsurfDirs = [
|
|
8951
8967
|
join2(homedir2(), ".codeium", "chat_history"),
|
|
8952
8968
|
join2(homedir2(), ".windsurf", "sessions"),
|
|
@@ -9549,7 +9565,7 @@ function detectOpenCodePatterns(messages, partStorageDir) {
|
|
|
9549
9565
|
}
|
|
9550
9566
|
return patterns;
|
|
9551
9567
|
}
|
|
9552
|
-
function collectCursorSessions(sessionsDir, since) {
|
|
9568
|
+
function collectCursorSessions(sessionsDir, since, targetProjectDir) {
|
|
9553
9569
|
const sessions = [];
|
|
9554
9570
|
try {
|
|
9555
9571
|
const files = readdirSync(sessionsDir).filter((f3) => f3.endsWith(".json") || f3.endsWith(".jsonl"));
|
|
@@ -9572,6 +9588,10 @@ function collectCursorSessions(sessionsDir, since) {
|
|
|
9572
9588
|
}
|
|
9573
9589
|
if (data.length === 0)
|
|
9574
9590
|
continue;
|
|
9591
|
+
const sessionProjectDir = getCursorSessionProjectDir(data);
|
|
9592
|
+
if (!sessionProjectDir || !isPathMatch(sessionProjectDir, targetProjectDir)) {
|
|
9593
|
+
continue;
|
|
9594
|
+
}
|
|
9575
9595
|
const firstEntry = data[0];
|
|
9576
9596
|
const lastEntry = data[data.length - 1];
|
|
9577
9597
|
const startTime = firstEntry?.timestamp ? new Date(firstEntry.timestamp) : new Date;
|
|
@@ -9613,6 +9633,152 @@ function collectCursorSessions(sessionsDir, since) {
|
|
|
9613
9633
|
} catch {}
|
|
9614
9634
|
return sessions;
|
|
9615
9635
|
}
|
|
9636
|
+
function collectCursorProjectSessions(projectsDir, since, targetProjectDir) {
|
|
9637
|
+
const sessions = [];
|
|
9638
|
+
try {
|
|
9639
|
+
const entries = readdirSync(projectsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
9640
|
+
const targetKey = normalizeCursorProjectKey(encodeCursorProjectKey(targetProjectDir));
|
|
9641
|
+
const matchingProjects = entries.filter((name) => {
|
|
9642
|
+
const normalized = normalizeCursorProjectKey(name);
|
|
9643
|
+
return normalized === targetKey || normalized.startsWith(targetKey + "-") || targetKey.startsWith(normalized + "-");
|
|
9644
|
+
});
|
|
9645
|
+
for (const projectName of matchingProjects) {
|
|
9646
|
+
const transcriptsDir = join2(projectsDir, projectName, "agent-transcripts");
|
|
9647
|
+
if (!existsSync2(transcriptsDir))
|
|
9648
|
+
continue;
|
|
9649
|
+
const files = readdirSync(transcriptsDir).filter((f3) => f3.endsWith(".json")).map((f3) => join2(transcriptsDir, f3));
|
|
9650
|
+
for (const filePath of files) {
|
|
9651
|
+
const session = parseCursorTranscript(filePath, since);
|
|
9652
|
+
if (session)
|
|
9653
|
+
sessions.push(session);
|
|
9654
|
+
}
|
|
9655
|
+
}
|
|
9656
|
+
} catch {}
|
|
9657
|
+
return sessions;
|
|
9658
|
+
}
|
|
9659
|
+
function parseCursorTranscript(filePath, since) {
|
|
9660
|
+
try {
|
|
9661
|
+
const cached = sessionCache?.get(filePath);
|
|
9662
|
+
if (cached) {
|
|
9663
|
+
const cachedEndedAt = cached.endedAt ? new Date(cached.endedAt) : null;
|
|
9664
|
+
if (cachedEndedAt && cachedEndedAt >= since) {
|
|
9665
|
+
return cached;
|
|
9666
|
+
}
|
|
9667
|
+
return null;
|
|
9668
|
+
}
|
|
9669
|
+
const stats = statSync2(filePath);
|
|
9670
|
+
const endedAt = new Date(stats.mtimeMs);
|
|
9671
|
+
if (endedAt < since)
|
|
9672
|
+
return null;
|
|
9673
|
+
const startedAt = stats.birthtimeMs && stats.birthtimeMs > 0 ? new Date(stats.birthtimeMs) : endedAt;
|
|
9674
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
9675
|
+
const data = JSON.parse(content);
|
|
9676
|
+
if (!Array.isArray(data) || data.length === 0)
|
|
9677
|
+
return null;
|
|
9678
|
+
let messageCount = 0;
|
|
9679
|
+
let toolCalls = 0;
|
|
9680
|
+
const toolNames = new Set;
|
|
9681
|
+
for (const entry of data) {
|
|
9682
|
+
if (entry?.role)
|
|
9683
|
+
messageCount += 1;
|
|
9684
|
+
if (Array.isArray(entry?.toolCalls)) {
|
|
9685
|
+
toolCalls += entry.toolCalls.length;
|
|
9686
|
+
for (const tool of entry.toolCalls) {
|
|
9687
|
+
if (tool?.toolName)
|
|
9688
|
+
toolNames.add(tool.toolName);
|
|
9689
|
+
}
|
|
9690
|
+
}
|
|
9691
|
+
if (entry?.toolResult?.toolName) {
|
|
9692
|
+
toolNames.add(entry.toolResult.toolName);
|
|
9693
|
+
}
|
|
9694
|
+
}
|
|
9695
|
+
const durationMinutes = Math.max(1, Math.round((endedAt.getTime() - startedAt.getTime()) / 60000));
|
|
9696
|
+
const session = {
|
|
9697
|
+
agent: "cursor",
|
|
9698
|
+
sessionId: basename(filePath, ".json").slice(0, 8),
|
|
9699
|
+
startedAt: startedAt.toISOString(),
|
|
9700
|
+
endedAt: endedAt.toISOString(),
|
|
9701
|
+
durationMinutes,
|
|
9702
|
+
inputTokens: 0,
|
|
9703
|
+
outputTokens: 0,
|
|
9704
|
+
cachedTokens: 0,
|
|
9705
|
+
totalTokens: 0,
|
|
9706
|
+
costUsd: 0,
|
|
9707
|
+
model: "cursor",
|
|
9708
|
+
toolCalls,
|
|
9709
|
+
messageCount,
|
|
9710
|
+
toolNames: Array.from(toolNames),
|
|
9711
|
+
patterns: [{ type: "smooth_flow", count: 1, estimatedWastedTokens: 0, messageIndices: [] }]
|
|
9712
|
+
};
|
|
9713
|
+
sessionCache?.set(filePath, session);
|
|
9714
|
+
return session;
|
|
9715
|
+
} catch {
|
|
9716
|
+
return null;
|
|
9717
|
+
}
|
|
9718
|
+
}
|
|
9719
|
+
function encodeCursorProjectKey(projectDir) {
|
|
9720
|
+
const normalized = resolve(projectDir);
|
|
9721
|
+
const trimmed2 = normalized.replace(/^[\\/]+/, "");
|
|
9722
|
+
return trimmed2.replace(/[:\\/]/g, "-");
|
|
9723
|
+
}
|
|
9724
|
+
function normalizeCursorProjectKey(projectKey) {
|
|
9725
|
+
return process.platform === "win32" ? projectKey.toLowerCase() : projectKey;
|
|
9726
|
+
}
|
|
9727
|
+
function isPathMatch(pathA, pathB) {
|
|
9728
|
+
const resolvedA = resolve(pathA);
|
|
9729
|
+
const resolvedB = resolve(pathB);
|
|
9730
|
+
return resolvedA === resolvedB || resolvedA.startsWith(resolvedB + sep2) || resolvedB.startsWith(resolvedA + sep2);
|
|
9731
|
+
}
|
|
9732
|
+
function getCursorSessionProjectDir(entries) {
|
|
9733
|
+
for (const entry of entries) {
|
|
9734
|
+
const pathCandidate = extractCursorProjectPath(entry);
|
|
9735
|
+
if (pathCandidate)
|
|
9736
|
+
return pathCandidate;
|
|
9737
|
+
}
|
|
9738
|
+
return null;
|
|
9739
|
+
}
|
|
9740
|
+
function extractCursorProjectPath(entry) {
|
|
9741
|
+
const candidates = [
|
|
9742
|
+
entry.cwd,
|
|
9743
|
+
entry.projectPath,
|
|
9744
|
+
entry.workspacePath,
|
|
9745
|
+
entry.workspaceRoot,
|
|
9746
|
+
entry.rootPath,
|
|
9747
|
+
entry.repositoryPath,
|
|
9748
|
+
entry.folder,
|
|
9749
|
+
entry.workspace
|
|
9750
|
+
];
|
|
9751
|
+
for (const candidate of candidates) {
|
|
9752
|
+
if (typeof candidate === "string") {
|
|
9753
|
+
const normalized = normalizeFileUri(candidate);
|
|
9754
|
+
if (normalized)
|
|
9755
|
+
return normalized;
|
|
9756
|
+
}
|
|
9757
|
+
if (candidate && typeof candidate === "object") {
|
|
9758
|
+
const record = candidate;
|
|
9759
|
+
const nestedCandidates = [record.path, record.uri, record.folder, record.workspace, record.root];
|
|
9760
|
+
for (const nested of nestedCandidates) {
|
|
9761
|
+
if (typeof nested === "string") {
|
|
9762
|
+
const normalized = normalizeFileUri(nested);
|
|
9763
|
+
if (normalized)
|
|
9764
|
+
return normalized;
|
|
9765
|
+
}
|
|
9766
|
+
}
|
|
9767
|
+
}
|
|
9768
|
+
}
|
|
9769
|
+
return null;
|
|
9770
|
+
}
|
|
9771
|
+
function normalizeFileUri(value) {
|
|
9772
|
+
if (!value)
|
|
9773
|
+
return null;
|
|
9774
|
+
if (!value.startsWith("file://"))
|
|
9775
|
+
return value;
|
|
9776
|
+
let decoded = decodeURIComponent(value.replace(/^file:\/\//, ""));
|
|
9777
|
+
if (/^\/[A-Za-z]:\//.test(decoded)) {
|
|
9778
|
+
decoded = decoded.slice(1);
|
|
9779
|
+
}
|
|
9780
|
+
return decoded;
|
|
9781
|
+
}
|
|
9616
9782
|
function collectWindsurfSessions(sessionsDir, since) {
|
|
9617
9783
|
const sessions = [];
|
|
9618
9784
|
try {
|
|
@@ -11414,7 +11580,7 @@ function generateOverallSummary(requirements, planning, implementation, review,
|
|
|
11414
11580
|
}
|
|
11415
11581
|
return parts.join(" ") || "Balanced across all phases.";
|
|
11416
11582
|
}
|
|
11417
|
-
function
|
|
11583
|
+
function formatSDLCPhaseForTerminal(phase, overall) {
|
|
11418
11584
|
const lines = [];
|
|
11419
11585
|
const width = 50;
|
|
11420
11586
|
const CYAN = "\x1B[36m";
|
|
@@ -11441,48 +11607,55 @@ function formatSDLCForTerminal(analysis) {
|
|
|
11441
11607
|
}
|
|
11442
11608
|
};
|
|
11443
11609
|
lines.push("");
|
|
11444
|
-
lines.push(`${BOLD}${CYAN} SDLC
|
|
11610
|
+
lines.push(`${BOLD}${CYAN} SDLC OPTIMIZATION${RESET}`);
|
|
11445
11611
|
lines.push(`${DIM} ${"─".repeat(width)}${RESET}`);
|
|
11446
11612
|
lines.push("");
|
|
11447
|
-
const overall = analysis.overall;
|
|
11448
11613
|
lines.push(` ${BOLD}Overall:${RESET} ${gradeColor(overall.grade)}${overall.grade}${RESET} (${overall.score}/100)`);
|
|
11449
11614
|
lines.push(` ${DIM}${overall.summary}${RESET}`);
|
|
11450
11615
|
lines.push("");
|
|
11451
|
-
const
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
const
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
}
|
|
11468
|
-
}
|
|
11469
|
-
|
|
11470
|
-
|
|
11616
|
+
const phaseColor = gradeColor(phase.grade);
|
|
11617
|
+
lines.push(` ${BOLD}Focus:${RESET} ${phase.name}`);
|
|
11618
|
+
lines.push(` ${phaseColor}${phase.grade}${RESET} ${DIM}(${phase.score}/100)${RESET}`);
|
|
11619
|
+
lines.push("");
|
|
11620
|
+
if (phase.metrics.length > 0) {
|
|
11621
|
+
lines.push(` ${BOLD}Signals:${RESET}`);
|
|
11622
|
+
const topMetrics = phase.metrics.slice(0, 4);
|
|
11623
|
+
for (const m2 of topMetrics) {
|
|
11624
|
+
const statusIcon = m2.status === "good" ? GREEN + "+" : m2.status === "warning" ? YELLOW + "~" : RED + "-";
|
|
11625
|
+
lines.push(` ${statusIcon}${RESET} ${m2.name}: ${m2.value}${m2.target ? ` ${DIM}(target: ${m2.target})${RESET}` : ""}`);
|
|
11626
|
+
}
|
|
11627
|
+
lines.push("");
|
|
11628
|
+
}
|
|
11629
|
+
if (phase.strengths.length > 0) {
|
|
11630
|
+
lines.push(` ${BOLD}Strengths:${RESET}`);
|
|
11631
|
+
for (const item of phase.strengths.slice(0, 3)) {
|
|
11632
|
+
lines.push(` ${GREEN}+${RESET} ${item}`);
|
|
11633
|
+
}
|
|
11634
|
+
lines.push("");
|
|
11635
|
+
}
|
|
11636
|
+
if (phase.weaknesses.length > 0) {
|
|
11637
|
+
lines.push(` ${BOLD}Weak Spots:${RESET}`);
|
|
11638
|
+
for (const item of phase.weaknesses.slice(0, 3)) {
|
|
11639
|
+
lines.push(` ${RED}!${RESET} ${item}`);
|
|
11640
|
+
}
|
|
11641
|
+
lines.push("");
|
|
11642
|
+
}
|
|
11643
|
+
lines.push(` ${BOLD}Optimizations:${RESET}`);
|
|
11644
|
+
if (phase.recommendations.length === 0) {
|
|
11645
|
+
lines.push(` ${DIM}No optimizations available for this phase.${RESET}`);
|
|
11646
|
+
} else {
|
|
11647
|
+
for (const rec of phase.recommendations) {
|
|
11471
11648
|
const impactColor = rec.impact === "high" ? RED : rec.impact === "medium" ? YELLOW : DIM;
|
|
11472
|
-
lines.push(`
|
|
11649
|
+
lines.push(` ${impactColor}!${RESET} ${rec.title}`);
|
|
11650
|
+
lines.push(` ${DIM}${rec.description}${RESET}`);
|
|
11473
11651
|
if (rec.installCommand) {
|
|
11474
|
-
lines.push(`
|
|
11652
|
+
lines.push(` ${DIM}${rec.installCommand}${RESET}`);
|
|
11475
11653
|
}
|
|
11476
11654
|
}
|
|
11477
|
-
lines.push("");
|
|
11478
11655
|
}
|
|
11656
|
+
lines.push("");
|
|
11479
11657
|
return lines;
|
|
11480
11658
|
}
|
|
11481
|
-
function renderBar(value, width) {
|
|
11482
|
-
const filled = Math.round(value / 100 * width);
|
|
11483
|
-
const empty = width - filled;
|
|
11484
|
-
return "█".repeat(filled) + "░".repeat(empty);
|
|
11485
|
-
}
|
|
11486
11659
|
|
|
11487
11660
|
// src/lib/frustration-detector.ts
|
|
11488
11661
|
import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as fsReaddirSync } from "node:fs";
|
|
@@ -16634,46 +16807,88 @@ var scanCommand = defineCommand2({
|
|
|
16634
16807
|
} else if (sdlc.overall.summary.includes("optimizations available")) {
|
|
16635
16808
|
sdlc.overall.summary = sdlc.overall.summary.replace(/\d+ optimizations available\./, "All recommended tools installed.");
|
|
16636
16809
|
}
|
|
16637
|
-
const
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
16643
|
-
|
|
16810
|
+
const phaseOptions = [
|
|
16811
|
+
{ value: "requirements", label: "Requirements & Context" },
|
|
16812
|
+
{ value: "planning", label: "Planning & Design" },
|
|
16813
|
+
{ value: "implementation", label: "Implementation" },
|
|
16814
|
+
{ value: "review", label: "Review & Testing" },
|
|
16815
|
+
{ value: "exit", label: "Exit" }
|
|
16816
|
+
];
|
|
16817
|
+
while (true) {
|
|
16818
|
+
const phaseChoice = await consola.prompt("Which SDLC phase do you want to optimize?", {
|
|
16819
|
+
type: "select",
|
|
16820
|
+
options: phaseOptions
|
|
16821
|
+
});
|
|
16822
|
+
if (typeof phaseChoice === "symbol" || phaseChoice === "exit") {
|
|
16823
|
+
break;
|
|
16824
|
+
}
|
|
16825
|
+
const selectedPhase = phaseChoice === "planning" ? sdlc.planning : phaseChoice === "implementation" ? sdlc.implementation : phaseChoice === "review" ? sdlc.review : sdlc.requirements;
|
|
16826
|
+
const sdlcLines = formatSDLCPhaseForTerminal(selectedPhase, sdlc.overall);
|
|
16827
|
+
for (const line of sdlcLines) {
|
|
16828
|
+
console.log(line);
|
|
16829
|
+
}
|
|
16830
|
+
let phaseRecs = [];
|
|
16831
|
+
for (const rec of selectedPhase.recommendations) {
|
|
16644
16832
|
if (rec.installCommand) {
|
|
16645
|
-
|
|
16833
|
+
phaseRecs.push(phaseRecToInstallable(rec));
|
|
16646
16834
|
}
|
|
16647
16835
|
}
|
|
16648
|
-
|
|
16649
|
-
|
|
16650
|
-
|
|
16651
|
-
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16836
|
+
phaseRecs = filterAlreadyInstalled(phaseRecs, installedStatus);
|
|
16837
|
+
const nextAction = await consola.prompt("What would you like to do next?", {
|
|
16838
|
+
type: "select",
|
|
16839
|
+
options: phaseRecs.length > 0 ? [
|
|
16840
|
+
{ value: "install", label: "Install optimizations" },
|
|
16841
|
+
{ value: "change", label: "Choose another phase" },
|
|
16842
|
+
{ value: "exit", label: "Exit" }
|
|
16843
|
+
] : [
|
|
16844
|
+
{ value: "change", label: "Choose another phase" },
|
|
16845
|
+
{ value: "exit", label: "Exit" }
|
|
16846
|
+
]
|
|
16657
16847
|
});
|
|
16658
|
-
if (
|
|
16659
|
-
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16848
|
+
if (typeof nextAction === "symbol" || nextAction === "exit") {
|
|
16849
|
+
break;
|
|
16850
|
+
}
|
|
16851
|
+
if (nextAction === "change") {
|
|
16852
|
+
continue;
|
|
16853
|
+
}
|
|
16854
|
+
if (phaseRecs.length > 0) {
|
|
16855
|
+
console.log();
|
|
16856
|
+
const optionLabels = phaseRecs.map((rec) => `${rec.name} - ${rec.description}`);
|
|
16857
|
+
const selected = await consola.prompt(`${phaseRecs.length} optimizations available for ${selectedPhase.name}. Select to install (space to select, enter to confirm):`, {
|
|
16858
|
+
type: "multiselect",
|
|
16859
|
+
options: optionLabels,
|
|
16860
|
+
required: false
|
|
16861
|
+
});
|
|
16862
|
+
if (selected && typeof selected !== "symbol" && Array.isArray(selected) && selected.length > 0) {
|
|
16863
|
+
const toInstall = phaseRecs.filter((rec) => selected.some((s2) => s2.startsWith(rec.name))).map((r3) => ({ ...r3, selected: true }));
|
|
16864
|
+
if (toInstall.length > 0) {
|
|
16865
|
+
console.log();
|
|
16866
|
+
console.log(` ${colors2.bold("Installing...")}${colors2.dim("")}`);
|
|
16867
|
+
console.log();
|
|
16868
|
+
const results = await installOptimizations(toInstall, projectDir, {});
|
|
16869
|
+
for (const result of results) {
|
|
16870
|
+
if (result.success) {
|
|
16871
|
+
console.log(` ${colors2.success("✓")} ${result.name}: ${result.message}`);
|
|
16872
|
+
} else {
|
|
16873
|
+
console.log(` ${colors2.error("✗")} ${result.name}: ${result.error || result.message}`);
|
|
16874
|
+
}
|
|
16670
16875
|
}
|
|
16876
|
+
console.log();
|
|
16671
16877
|
}
|
|
16878
|
+
} else {
|
|
16879
|
+
console.log(` ${colors2.dim("Skipped.")}`);
|
|
16672
16880
|
console.log();
|
|
16673
16881
|
}
|
|
16674
|
-
}
|
|
16675
|
-
|
|
16676
|
-
|
|
16882
|
+
}
|
|
16883
|
+
const continueChoice = await consola.prompt("Continue with another phase?", {
|
|
16884
|
+
type: "select",
|
|
16885
|
+
options: [
|
|
16886
|
+
{ value: "change", label: "Choose another phase" },
|
|
16887
|
+
{ value: "exit", label: "Exit" }
|
|
16888
|
+
]
|
|
16889
|
+
});
|
|
16890
|
+
if (typeof continueChoice === "symbol" || continueChoice === "exit") {
|
|
16891
|
+
break;
|
|
16677
16892
|
}
|
|
16678
16893
|
}
|
|
16679
16894
|
}
|
|
@@ -17070,7 +17285,7 @@ init_dist();
|
|
|
17070
17285
|
init_client();
|
|
17071
17286
|
|
|
17072
17287
|
// src/collectors/report-data.ts
|
|
17073
|
-
import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as
|
|
17288
|
+
import { existsSync as existsSync11, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
|
|
17074
17289
|
import { homedir as homedir9 } from "node:os";
|
|
17075
17290
|
import { join as join11, basename as basename3 } from "node:path";
|
|
17076
17291
|
async function collectReportData(projectDir, since, until = new Date, harness) {
|
|
@@ -17177,7 +17392,7 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
|
17177
17392
|
const transcriptFiles = readdirSync5(transcriptsDir).filter((f3) => f3.endsWith(".jsonl"));
|
|
17178
17393
|
for (const file of transcriptFiles) {
|
|
17179
17394
|
const filePath = join11(transcriptsDir, file);
|
|
17180
|
-
const stat =
|
|
17395
|
+
const stat = statSync3(filePath);
|
|
17181
17396
|
if (stat.mtime < since || stat.mtime > until)
|
|
17182
17397
|
continue;
|
|
17183
17398
|
try {
|
|
@@ -17193,7 +17408,7 @@ function collectClaudeCodeSessions(claudeDir, since, until, projectDir) {
|
|
|
17193
17408
|
const projectFiles = readdirSync5(projectSessionDir).filter((f3) => f3.endsWith(".jsonl"));
|
|
17194
17409
|
for (const file of projectFiles) {
|
|
17195
17410
|
const filePath = join11(projectSessionDir, file);
|
|
17196
|
-
const stat =
|
|
17411
|
+
const stat = statSync3(filePath);
|
|
17197
17412
|
if (stat.mtime < since || stat.mtime > until)
|
|
17198
17413
|
continue;
|
|
17199
17414
|
try {
|
|
@@ -20558,10 +20773,10 @@ function renderCoverageSummary(report) {
|
|
|
20558
20773
|
lines.push(` Format: ${report.format}`);
|
|
20559
20774
|
lines.push(` Overall: ${report.summary.overall}%`);
|
|
20560
20775
|
lines.push("");
|
|
20561
|
-
lines.push(` Lines: ${
|
|
20562
|
-
lines.push(` Statements: ${
|
|
20563
|
-
lines.push(` Functions: ${
|
|
20564
|
-
lines.push(` Branches: ${
|
|
20776
|
+
lines.push(` Lines: ${renderBar(report.summary.lines.percentage)} ${report.summary.lines.percentage}%`);
|
|
20777
|
+
lines.push(` Statements: ${renderBar(report.summary.statements.percentage)} ${report.summary.statements.percentage}%`);
|
|
20778
|
+
lines.push(` Functions: ${renderBar(report.summary.functions.percentage)} ${report.summary.functions.percentage}%`);
|
|
20779
|
+
lines.push(` Branches: ${renderBar(report.summary.branches.percentage)} ${report.summary.branches.percentage}%`);
|
|
20565
20780
|
if (report.uncoveredFiles.length > 0) {
|
|
20566
20781
|
lines.push("");
|
|
20567
20782
|
lines.push(` Uncovered files: ${report.uncoveredFiles.length}`);
|
|
@@ -20607,7 +20822,7 @@ function renderCoverageMarkdown(report) {
|
|
|
20607
20822
|
}
|
|
20608
20823
|
return lines;
|
|
20609
20824
|
}
|
|
20610
|
-
function
|
|
20825
|
+
function renderBar(percentage, width = 15) {
|
|
20611
20826
|
const filled = Math.round(percentage / 100 * width);
|
|
20612
20827
|
const empty = width - filled;
|
|
20613
20828
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
@@ -21790,10 +22005,10 @@ function formatReportAsTerminal(report) {
|
|
|
21790
22005
|
lines.push(` ${report.gradeDescription}`);
|
|
21791
22006
|
lines.push("");
|
|
21792
22007
|
lines.push(" Score Breakdown:");
|
|
21793
|
-
lines.push(` SDLC Coverage: ${
|
|
21794
|
-
lines.push(` Prompt Quality: ${
|
|
21795
|
-
lines.push(` Tool Utilization: ${
|
|
21796
|
-
lines.push(` Efficiency: ${
|
|
22008
|
+
lines.push(` SDLC Coverage: ${renderBar2(report.scores.sdlcCoverage)} ${report.scores.sdlcCoverage}`);
|
|
22009
|
+
lines.push(` Prompt Quality: ${renderBar2(report.scores.promptQuality)} ${report.scores.promptQuality}`);
|
|
22010
|
+
lines.push(` Tool Utilization: ${renderBar2(report.scores.toolUtilization)} ${report.scores.toolUtilization}`);
|
|
22011
|
+
lines.push(` Efficiency: ${renderBar2(report.scores.efficiency)} ${report.scores.efficiency}`);
|
|
21797
22012
|
lines.push("");
|
|
21798
22013
|
lines.push(" Quick Stats:");
|
|
21799
22014
|
lines.push(` Sessions: ${report.summary.totalSessions} | Prompts: ${report.summary.totalPrompts} | Commits: ${report.summary.totalCommits}`);
|
|
@@ -21880,7 +22095,7 @@ function formatReportAsTerminal(report) {
|
|
|
21880
22095
|
return lines.join(`
|
|
21881
22096
|
`);
|
|
21882
22097
|
}
|
|
21883
|
-
function
|
|
22098
|
+
function renderBar2(value, width = 20) {
|
|
21884
22099
|
const filled = Math.round(value / 100 * width);
|
|
21885
22100
|
const empty = width - filled;
|
|
21886
22101
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
@@ -22434,7 +22649,7 @@ async function showHistory(client, clerkId, limit, format2) {
|
|
|
22434
22649
|
const recent = trend.slice(-limit);
|
|
22435
22650
|
for (const entry of recent) {
|
|
22436
22651
|
const date = new Date(entry.date).toLocaleDateString();
|
|
22437
|
-
const bar =
|
|
22652
|
+
const bar = renderBar3(entry.overall, 30);
|
|
22438
22653
|
const eff = `${entry.tokenEfficiency}x`;
|
|
22439
22654
|
consola.log(` ${date.padEnd(12)} ${String(entry.overall).padStart(3)}/100 ${bar} eff: ${eff}`);
|
|
22440
22655
|
}
|
|
@@ -22489,7 +22704,7 @@ function renderScanReport(scan, phaseFilter) {
|
|
|
22489
22704
|
const phases = phaseFilter ? scan.phases.filter((p) => p.phase === phaseFilter) : scan.phases;
|
|
22490
22705
|
lines.push("Phase Scores:");
|
|
22491
22706
|
for (const phase of phases) {
|
|
22492
|
-
const bar =
|
|
22707
|
+
const bar = renderBar3(phase.score, 20);
|
|
22493
22708
|
const delta = phase.delta !== undefined && phase.delta !== null ? ` (${phase.delta > 0 ? "+" : ""}${phase.delta})` : "";
|
|
22494
22709
|
lines.push(` ${phase.phase.padEnd(16)} ${String(phase.score).padStart(3)}/100 ${bar}${delta}`);
|
|
22495
22710
|
}
|
|
@@ -22507,7 +22722,7 @@ function renderScanReport(scan, phaseFilter) {
|
|
|
22507
22722
|
return lines.join(`
|
|
22508
22723
|
`);
|
|
22509
22724
|
}
|
|
22510
|
-
function
|
|
22725
|
+
function renderBar3(value, width) {
|
|
22511
22726
|
const filled = Math.round(value / 100 * width);
|
|
22512
22727
|
const empty = width - filled;
|
|
22513
22728
|
return "█".repeat(filled) + "░".repeat(empty);
|
|
@@ -23804,6 +24019,26 @@ var BOLD = "\x1B[1m";
|
|
|
23804
24019
|
var RESET = "\x1B[0m";
|
|
23805
24020
|
var MAGENTA = "\x1B[35m";
|
|
23806
24021
|
var CHANGELOG = [
|
|
24022
|
+
{
|
|
24023
|
+
version: "0.6.1",
|
|
24024
|
+
date: "2026-02-16",
|
|
24025
|
+
title: "Phase Navigation",
|
|
24026
|
+
highlights: [
|
|
24027
|
+
"nb scan now lets you switch phases or exit anytime",
|
|
24028
|
+
"Clear next-step prompts for installs or switching",
|
|
24029
|
+
"Cleaner interactive flow for phase optimizations"
|
|
24030
|
+
]
|
|
24031
|
+
},
|
|
24032
|
+
{
|
|
24033
|
+
version: "0.6.0",
|
|
24034
|
+
date: "2026-02-15",
|
|
24035
|
+
title: "Phase-Focused Optimizations",
|
|
24036
|
+
highlights: [
|
|
24037
|
+
"nb scan now asks which SDLC phase to optimize",
|
|
24038
|
+
"Phase-specific optimization breakdown and installs",
|
|
24039
|
+
"New SDLC optimization formatter and coverage test"
|
|
24040
|
+
]
|
|
24041
|
+
},
|
|
23807
24042
|
{
|
|
23808
24043
|
version: "0.5.3",
|
|
23809
24044
|
date: "2026-02-14",
|
|
@@ -24286,7 +24521,7 @@ function showFullChangelog() {
|
|
|
24286
24521
|
// package.json
|
|
24287
24522
|
var package_default = {
|
|
24288
24523
|
name: "nairon-bench",
|
|
24289
|
-
version: "0.
|
|
24524
|
+
version: "0.6.1",
|
|
24290
24525
|
description: "AI workflow benchmarking CLI",
|
|
24291
24526
|
type: "module",
|
|
24292
24527
|
bin: {
|
|
@@ -26813,7 +27048,7 @@ function formatBytes(bytes) {
|
|
|
26813
27048
|
// package.json
|
|
26814
27049
|
var package_default2 = {
|
|
26815
27050
|
name: "nairon-bench",
|
|
26816
|
-
version: "0.
|
|
27051
|
+
version: "0.6.1",
|
|
26817
27052
|
description: "AI workflow benchmarking CLI",
|
|
26818
27053
|
type: "module",
|
|
26819
27054
|
bin: {
|