@kevinrabun/judges 3.106.0 → 3.107.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/CHANGELOG.md +13 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +63 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/finding-auto-fix-suggest.d.ts +2 -0
- package/dist/commands/finding-auto-fix-suggest.d.ts.map +1 -0
- package/dist/commands/finding-auto-fix-suggest.js +77 -0
- package/dist/commands/finding-auto-fix-suggest.js.map +1 -0
- package/dist/commands/finding-batch-triage.d.ts +2 -0
- package/dist/commands/finding-batch-triage.d.ts.map +1 -0
- package/dist/commands/finding-batch-triage.js +91 -0
- package/dist/commands/finding-batch-triage.js.map +1 -0
- package/dist/commands/finding-confidence-boost.d.ts +2 -0
- package/dist/commands/finding-confidence-boost.d.ts.map +1 -0
- package/dist/commands/finding-confidence-boost.js +89 -0
- package/dist/commands/finding-confidence-boost.js.map +1 -0
- package/dist/commands/finding-noise-reduce.d.ts +2 -0
- package/dist/commands/finding-noise-reduce.d.ts.map +1 -0
- package/dist/commands/finding-noise-reduce.js +82 -0
- package/dist/commands/finding-noise-reduce.js.map +1 -0
- package/dist/commands/finding-scope-filter.d.ts +2 -0
- package/dist/commands/finding-scope-filter.d.ts.map +1 -0
- package/dist/commands/finding-scope-filter.js +78 -0
- package/dist/commands/finding-scope-filter.js.map +1 -0
- package/dist/commands/review-code-ownership.d.ts +2 -0
- package/dist/commands/review-code-ownership.d.ts.map +1 -0
- package/dist/commands/review-code-ownership.js +89 -0
- package/dist/commands/review-code-ownership.js.map +1 -0
- package/dist/commands/review-pr-label-suggest.d.ts +2 -0
- package/dist/commands/review-pr-label-suggest.d.ts.map +1 -0
- package/dist/commands/review-pr-label-suggest.js +78 -0
- package/dist/commands/review-pr-label-suggest.js.map +1 -0
- package/dist/commands/review-release-gate.d.ts +2 -0
- package/dist/commands/review-release-gate.d.ts.map +1 -0
- package/dist/commands/review-release-gate.js +82 -0
- package/dist/commands/review-release-gate.js.map +1 -0
- package/dist/commands/review-review-cadence.d.ts +2 -0
- package/dist/commands/review-review-cadence.d.ts.map +1 -0
- package/dist/commands/review-review-cadence.js +86 -0
- package/dist/commands/review-review-cadence.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
function suggestLabels(data) {
|
|
4
|
+
const labels = [];
|
|
5
|
+
const findings = data.findings ?? [];
|
|
6
|
+
// Verdict-based labels
|
|
7
|
+
if (data.overallVerdict === "fail") {
|
|
8
|
+
labels.push({ label: "needs-fixes", reason: "Verdict is fail" });
|
|
9
|
+
}
|
|
10
|
+
else if (data.overallVerdict === "warning") {
|
|
11
|
+
labels.push({ label: "needs-review", reason: "Verdict is warning" });
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
labels.push({ label: "approved", reason: "Verdict is pass" });
|
|
15
|
+
}
|
|
16
|
+
// Severity-based labels
|
|
17
|
+
if (data.criticalCount > 0) {
|
|
18
|
+
labels.push({ label: "security-critical", reason: `${data.criticalCount} critical findings` });
|
|
19
|
+
}
|
|
20
|
+
if (data.highCount > 0) {
|
|
21
|
+
labels.push({ label: "high-priority", reason: `${data.highCount} high findings` });
|
|
22
|
+
}
|
|
23
|
+
// Domain-based labels
|
|
24
|
+
const domains = new Set();
|
|
25
|
+
for (const f of findings) {
|
|
26
|
+
const prefix = f.ruleId.split("-")[0].toUpperCase();
|
|
27
|
+
domains.add(prefix);
|
|
28
|
+
}
|
|
29
|
+
if (domains.has("SEC") || domains.has("AUTH") || domains.has("CRYPTO")) {
|
|
30
|
+
labels.push({ label: "security", reason: "Security-related findings" });
|
|
31
|
+
}
|
|
32
|
+
if (domains.has("PERF") || domains.has("OPT")) {
|
|
33
|
+
labels.push({ label: "performance", reason: "Performance-related findings" });
|
|
34
|
+
}
|
|
35
|
+
if (domains.has("COST")) {
|
|
36
|
+
labels.push({ label: "cost-impact", reason: "Cost-related findings" });
|
|
37
|
+
}
|
|
38
|
+
// Size-based label
|
|
39
|
+
if (findings.length > 10) {
|
|
40
|
+
labels.push({ label: "large-review", reason: `${findings.length} findings` });
|
|
41
|
+
}
|
|
42
|
+
return labels;
|
|
43
|
+
}
|
|
44
|
+
export function runReviewPrLabelSuggest(argv) {
|
|
45
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
46
|
+
console.log(`Usage: judges review-pr-label-suggest [options]
|
|
47
|
+
|
|
48
|
+
Suggest PR labels based on review findings.
|
|
49
|
+
|
|
50
|
+
Options:
|
|
51
|
+
--report <path> Path to verdict JSON file
|
|
52
|
+
--format <fmt> Output format: table (default) or json
|
|
53
|
+
-h, --help Show this help message`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const formatIdx = argv.indexOf("--format");
|
|
57
|
+
const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
|
|
58
|
+
const reportIdx = argv.indexOf("--report");
|
|
59
|
+
const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
|
|
60
|
+
? join(process.cwd(), argv[reportIdx + 1])
|
|
61
|
+
: join(process.cwd(), ".judges", "last-verdict.json");
|
|
62
|
+
if (!existsSync(reportPath)) {
|
|
63
|
+
console.log(`No report found at: ${reportPath}`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const data = JSON.parse(readFileSync(reportPath, "utf-8"));
|
|
67
|
+
const labels = suggestLabels(data);
|
|
68
|
+
if (format === "json") {
|
|
69
|
+
console.log(JSON.stringify(labels, null, 2));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
console.log("\n=== Suggested PR Labels ===\n");
|
|
73
|
+
for (const l of labels) {
|
|
74
|
+
console.log(` ${l.label} — ${l.reason}`);
|
|
75
|
+
}
|
|
76
|
+
console.log();
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=review-pr-label-suggest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-pr-label-suggest.js","sourceRoot":"","sources":["../../src/commands/review-pr-label-suggest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAa5B,SAAS,aAAa,CAAC,IAAqB;IAC1C,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAErC,uBAAuB;IACvB,IAAI,IAAI,CAAC,cAAc,KAAK,MAAM,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACnE,CAAC;SAAM,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,wBAAwB;IACxB,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,oBAAoB,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,sBAAsB;IACtB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,mBAAmB;IACnB,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAc;IACpD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;8CAO8B,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAEvF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,UAAU,GACd,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAE1D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;QACjD,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAoB,CAAC;IAC9E,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAEnC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-release-gate.d.ts","sourceRoot":"","sources":["../../src/commands/review-release-gate.ts"],"names":[],"mappings":"AAiEA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA0DzD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
function evaluateReleaseGate(data, config) {
|
|
4
|
+
const checks = [];
|
|
5
|
+
const critOk = data.criticalCount <= config.maxCritical;
|
|
6
|
+
checks.push({
|
|
7
|
+
check: `Critical findings ≤ ${config.maxCritical}`,
|
|
8
|
+
passed: critOk,
|
|
9
|
+
detail: `Found: ${data.criticalCount}`,
|
|
10
|
+
});
|
|
11
|
+
const highOk = data.highCount <= config.maxHigh;
|
|
12
|
+
checks.push({
|
|
13
|
+
check: `High findings ≤ ${config.maxHigh}`,
|
|
14
|
+
passed: highOk,
|
|
15
|
+
detail: `Found: ${data.highCount}`,
|
|
16
|
+
});
|
|
17
|
+
const scoreOk = data.overallScore >= config.minScore;
|
|
18
|
+
checks.push({
|
|
19
|
+
check: `Score ≥ ${config.minScore}`,
|
|
20
|
+
passed: scoreOk,
|
|
21
|
+
detail: `Score: ${data.overallScore}`,
|
|
22
|
+
});
|
|
23
|
+
if (config.requirePass) {
|
|
24
|
+
const verdictOk = data.overallVerdict === "pass";
|
|
25
|
+
checks.push({
|
|
26
|
+
check: "Verdict is pass",
|
|
27
|
+
passed: verdictOk,
|
|
28
|
+
detail: `Verdict: ${data.overallVerdict}`,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const releaseReady = checks.every((c) => c.passed);
|
|
32
|
+
return { releaseReady, checks };
|
|
33
|
+
}
|
|
34
|
+
export function runReviewReleaseGate(argv) {
|
|
35
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
36
|
+
console.log(`Usage: judges review-release-gate [options]
|
|
37
|
+
|
|
38
|
+
Evaluate release-level quality gate.
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
--report <path> Path to verdict JSON file
|
|
42
|
+
--config <path> Path to release gate config JSON
|
|
43
|
+
--format <fmt> Output format: table (default) or json
|
|
44
|
+
-h, --help Show this help message`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const formatIdx = argv.indexOf("--format");
|
|
48
|
+
const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
|
|
49
|
+
const reportIdx = argv.indexOf("--report");
|
|
50
|
+
const reportPath = reportIdx !== -1 && argv[reportIdx + 1]
|
|
51
|
+
? join(process.cwd(), argv[reportIdx + 1])
|
|
52
|
+
: join(process.cwd(), ".judges", "last-verdict.json");
|
|
53
|
+
const confIdx = argv.indexOf("--config");
|
|
54
|
+
const confPath = confIdx !== -1 && argv[confIdx + 1]
|
|
55
|
+
? join(process.cwd(), argv[confIdx + 1])
|
|
56
|
+
: join(process.cwd(), ".judges", "release-gate.json");
|
|
57
|
+
if (!existsSync(reportPath)) {
|
|
58
|
+
console.log(`No report found at: ${reportPath}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const data = JSON.parse(readFileSync(reportPath, "utf-8"));
|
|
62
|
+
let config;
|
|
63
|
+
if (existsSync(confPath)) {
|
|
64
|
+
config = JSON.parse(readFileSync(confPath, "utf-8"));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
config = { maxCritical: 0, maxHigh: 0, minScore: 80, requirePass: true };
|
|
68
|
+
}
|
|
69
|
+
const result = evaluateReleaseGate(data, config);
|
|
70
|
+
if (format === "json") {
|
|
71
|
+
console.log(JSON.stringify(result, null, 2));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const status = result.releaseReady ? "RELEASE READY" : "NOT RELEASE READY";
|
|
75
|
+
console.log(`\n=== ${status} ===\n`);
|
|
76
|
+
for (const c of result.checks) {
|
|
77
|
+
const icon = c.passed ? "PASS" : "FAIL";
|
|
78
|
+
console.log(` [${icon}] ${c.check} — ${c.detail}`);
|
|
79
|
+
}
|
|
80
|
+
console.log();
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=review-release-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-release-gate.js","sourceRoot":"","sources":["../../src/commands/review-release-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-review-cadence.d.ts","sourceRoot":"","sources":["../../src/commands/review-review-cadence.ts"],"names":[],"mappings":"AAqEA,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6C3D"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
function analyzeCadence(historyDir) {
|
|
4
|
+
const entries = [];
|
|
5
|
+
if (existsSync(historyDir)) {
|
|
6
|
+
const files = readdirSync(historyDir);
|
|
7
|
+
for (const file of files) {
|
|
8
|
+
if (typeof file === "string" && file.endsWith(".json")) {
|
|
9
|
+
const filePath = join(historyDir, file);
|
|
10
|
+
try {
|
|
11
|
+
const data = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
12
|
+
entries.push({
|
|
13
|
+
date: data.timestamp ?? file.replace(".json", ""),
|
|
14
|
+
score: data.overallScore,
|
|
15
|
+
findingCount: (data.findings ?? []).length,
|
|
16
|
+
verdict: data.overallVerdict,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Skip malformed files
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
entries.sort((a, b) => a.date.localeCompare(b.date));
|
|
26
|
+
const totalReviews = entries.length;
|
|
27
|
+
const avgScore = totalReviews > 0 ? Math.round(entries.reduce((s, e) => s + e.score, 0) / totalReviews) : 0;
|
|
28
|
+
const avgFindings = totalReviews > 0 ? Math.round(entries.reduce((s, e) => s + e.findingCount, 0) / totalReviews) : 0;
|
|
29
|
+
let cadenceAssessment;
|
|
30
|
+
if (totalReviews >= 20)
|
|
31
|
+
cadenceAssessment = "Excellent — frequent reviews";
|
|
32
|
+
else if (totalReviews >= 10)
|
|
33
|
+
cadenceAssessment = "Good — regular reviews";
|
|
34
|
+
else if (totalReviews >= 5)
|
|
35
|
+
cadenceAssessment = "Fair — increase review frequency";
|
|
36
|
+
else
|
|
37
|
+
cadenceAssessment = "Low — establish regular review cadence";
|
|
38
|
+
return {
|
|
39
|
+
totalReviews,
|
|
40
|
+
avgScore,
|
|
41
|
+
avgFindings,
|
|
42
|
+
recentEntries: entries.slice(-10),
|
|
43
|
+
cadenceAssessment,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function runReviewReviewCadence(argv) {
|
|
47
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
48
|
+
console.log(`Usage: judges review-review-cadence [options]
|
|
49
|
+
|
|
50
|
+
Analyze review cadence and trends.
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
--history <path> Path to history directory
|
|
54
|
+
--format <fmt> Output format: table (default) or json
|
|
55
|
+
-h, --help Show this help message`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const formatIdx = argv.indexOf("--format");
|
|
59
|
+
const format = formatIdx !== -1 && argv[formatIdx + 1] ? argv[formatIdx + 1] : "table";
|
|
60
|
+
const histIdx = argv.indexOf("--history");
|
|
61
|
+
const historyDir = histIdx !== -1 && argv[histIdx + 1]
|
|
62
|
+
? join(process.cwd(), argv[histIdx + 1])
|
|
63
|
+
: join(process.cwd(), ".judges", "history");
|
|
64
|
+
const report = analyzeCadence(historyDir);
|
|
65
|
+
if (format === "json") {
|
|
66
|
+
console.log(JSON.stringify(report, null, 2));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
console.log("\n=== Review Cadence ===\n");
|
|
70
|
+
console.log(`Total reviews: ${report.totalReviews}`);
|
|
71
|
+
console.log(`Average score: ${report.avgScore}`);
|
|
72
|
+
console.log(`Average findings: ${report.avgFindings}`);
|
|
73
|
+
console.log(`Assessment: ${report.cadenceAssessment}\n`);
|
|
74
|
+
if (report.recentEntries.length > 0) {
|
|
75
|
+
console.log("Recent reviews:");
|
|
76
|
+
for (const e of report.recentEntries) {
|
|
77
|
+
console.log(` ${e.date}: score=${e.score}, findings=${e.findingCount}, verdict=${e.verdict}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log("No review history found.");
|
|
82
|
+
console.log(`Store verdict JSON files in: ${historyDir}`);
|
|
83
|
+
}
|
|
84
|
+
console.log();
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=review-review-cadence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-review-cadence.js","sourceRoot":"","sources":["../../src/commands/review-review-cadence.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/kevinrabun/judges",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "3.
|
|
10
|
+
"version": "3.107.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@kevinrabun/judges",
|
|
15
|
-
"version": "3.
|
|
15
|
+
"version": "3.107.0",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|