📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
* Reads and writes .brooks-lint-history.json in the project root.
|
||||
* Each record: { date, mode, score, findings: { critical, warning, suggestion }, scope }
|
||||
*
|
||||
* Run: node scripts/history.mjs [projectRoot]
|
||||
* Prints the history for projectRoot (default: cwd).
|
||||
* Run: node scripts/history.mjs [projectRoot] # readable trend view
|
||||
* node scripts/history.mjs [projectRoot] --json # raw JSON for tooling
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
@@ -14,6 +14,27 @@ import path from "node:path";
|
||||
|
||||
const HISTORY_FILE = ".brooks-lint-history.json";
|
||||
|
||||
// Map the human-facing mode names the report template uses (common.md) onto the
|
||||
// canonical CLI mode names. History records are written by the model and may use
|
||||
// either form ("PR Review" vs "review"); ci-review.mjs queries with the canonical
|
||||
// name. Normalizing both sides keeps getTrend from silently missing every record.
|
||||
const MODE_ALIASES = {
|
||||
"pr review": "review",
|
||||
"architecture audit": "audit",
|
||||
"tech debt": "debt",
|
||||
"tech debt assessment": "debt",
|
||||
"test quality": "test",
|
||||
"test quality review": "test",
|
||||
"health dashboard": "health",
|
||||
"full sweep": "sweep",
|
||||
};
|
||||
|
||||
export function normalizeMode(mode) {
|
||||
if (typeof mode !== "string") return mode;
|
||||
const key = mode.trim().toLowerCase();
|
||||
return MODE_ALIASES[key] ?? key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read history from .brooks-lint-history.json.
|
||||
* Returns empty array if the file does not exist or contains invalid JSON.
|
||||
@@ -40,11 +61,14 @@ export function appendHistory(projectRoot, record) {
|
||||
|
||||
/**
|
||||
* Get trend info for a mode from a history array (not including the current run).
|
||||
* Mode matching is alias-tolerant (see normalizeMode), so a canonical query like
|
||||
* "review" still matches records stored as "PR Review".
|
||||
* Returns null if no prior records exist for the mode.
|
||||
* Returns { lastScore, runCount } where lastScore is the most recent prior score.
|
||||
*/
|
||||
export function getTrend(history, mode) {
|
||||
const modeHistory = history.filter(r => r.mode === mode);
|
||||
const target = normalizeMode(mode);
|
||||
const modeHistory = history.filter(r => normalizeMode(r.mode) === target);
|
||||
if (modeHistory.length === 0) return null;
|
||||
return {
|
||||
lastScore: modeHistory[modeHistory.length - 1].score,
|
||||
@@ -52,12 +76,50 @@ export function getTrend(history, mode) {
|
||||
};
|
||||
}
|
||||
|
||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||
const projectRoot = process.argv[2] ?? process.cwd();
|
||||
const history = readHistory(projectRoot);
|
||||
if (history.length === 0) {
|
||||
console.log("No history found.");
|
||||
} else {
|
||||
console.log(JSON.stringify(history, null, 2));
|
||||
}
|
||||
/**
|
||||
* Render a sequence of 0–100 scores as a unicode sparkline.
|
||||
*/
|
||||
export function sparkline(scores) {
|
||||
const bars = "▁▂▃▄▅▆▇█";
|
||||
return scores
|
||||
.map(s => {
|
||||
const clamped = Math.max(0, Math.min(100, s));
|
||||
return bars[Math.round((clamped / 100) * (bars.length - 1))];
|
||||
})
|
||||
.join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the whole history as a per-mode trend summary (one line per mode).
|
||||
*/
|
||||
export function renderHistory(history) {
|
||||
if (history.length === 0) return "No history found.";
|
||||
|
||||
const byMode = new Map();
|
||||
for (const r of history) {
|
||||
const m = normalizeMode(r.mode);
|
||||
if (!byMode.has(m)) byMode.set(m, []);
|
||||
byMode.get(m).push(r);
|
||||
}
|
||||
|
||||
const lines = [`Brooks-Lint Health History — ${history.length} record(s)`, ""];
|
||||
for (const [mode, records] of byMode) {
|
||||
const scores = records.map(r => r.score).filter(s => typeof s === "number");
|
||||
if (scores.length === 0) continue;
|
||||
const latest = scores[scores.length - 1];
|
||||
const delta = latest - scores[0];
|
||||
const trend = scores.length > 1
|
||||
? `${delta >= 0 ? "+" : ""}${delta} over ${scores.length} runs`
|
||||
: "1 run";
|
||||
lines.push(`${mode.padEnd(8)} ${sparkline(scores)} latest ${latest}/100 (${trend})`);
|
||||
}
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||
const cliArgs = process.argv.slice(2);
|
||||
const asJson = cliArgs.includes("--json");
|
||||
const projectRoot = cliArgs.find(a => !a.startsWith("--")) ?? process.cwd();
|
||||
const history = readHistory(projectRoot);
|
||||
console.log(asJson ? JSON.stringify(history, null, 2) : renderHistory(history));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user