@kevinrabun/judges 3.55.0 → 3.56.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 +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/api-versioning-audit.d.ts +6 -0
- package/dist/commands/api-versioning-audit.d.ts.map +1 -0
- package/dist/commands/api-versioning-audit.js +234 -0
- package/dist/commands/api-versioning-audit.js.map +1 -0
- package/dist/commands/boundary-enforce.d.ts +6 -0
- package/dist/commands/boundary-enforce.d.ts.map +1 -0
- package/dist/commands/boundary-enforce.js +256 -0
- package/dist/commands/boundary-enforce.js.map +1 -0
- package/dist/commands/error-taxonomy.d.ts +6 -0
- package/dist/commands/error-taxonomy.d.ts.map +1 -0
- package/dist/commands/error-taxonomy.js +227 -0
- package/dist/commands/error-taxonomy.js.map +1 -0
- package/dist/commands/log-quality.d.ts +6 -0
- package/dist/commands/log-quality.d.ts.map +1 -0
- package/dist/commands/log-quality.js +212 -0
- package/dist/commands/log-quality.js.map +1 -0
- package/dist/commands/null-safety-audit.d.ts +6 -0
- package/dist/commands/null-safety-audit.d.ts.map +1 -0
- package/dist/commands/null-safety-audit.js +222 -0
- package/dist/commands/null-safety-audit.js.map +1 -0
- package/dist/commands/ownership-map.d.ts +6 -0
- package/dist/commands/ownership-map.d.ts.map +1 -0
- package/dist/commands/ownership-map.js +229 -0
- package/dist/commands/ownership-map.js.map +1 -0
- package/dist/commands/retry-pattern-audit.d.ts +6 -0
- package/dist/commands/retry-pattern-audit.d.ts.map +1 -0
- package/dist/commands/retry-pattern-audit.js +216 -0
- package/dist/commands/retry-pattern-audit.js.map +1 -0
- package/dist/commands/test-isolation.d.ts +6 -0
- package/dist/commands/test-isolation.d.ts.map +1 -0
- package/dist/commands/test-isolation.js +235 -0
- package/dist/commands/test-isolation.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Null safety audit — identify null/undefined dereference risks, missing
|
|
3
|
+
* guards, and inconsistent nullability patterns.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
6
|
+
import { join, extname } from "path";
|
|
7
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
8
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go"]);
|
|
9
|
+
function collectFiles(dir, max = 300) {
|
|
10
|
+
const files = [];
|
|
11
|
+
function walk(d) {
|
|
12
|
+
if (files.length >= max)
|
|
13
|
+
return;
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = readdirSync(d);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const e of entries) {
|
|
22
|
+
if (files.length >= max)
|
|
23
|
+
return;
|
|
24
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
25
|
+
continue;
|
|
26
|
+
const full = join(d, e);
|
|
27
|
+
try {
|
|
28
|
+
if (statSync(full).isDirectory())
|
|
29
|
+
walk(full);
|
|
30
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
31
|
+
files.push(full);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* skip */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
walk(dir);
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
42
|
+
function analyzeFile(filepath) {
|
|
43
|
+
const risks = [];
|
|
44
|
+
let content;
|
|
45
|
+
try {
|
|
46
|
+
content = readFileSync(filepath, "utf-8");
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return risks;
|
|
50
|
+
}
|
|
51
|
+
const lines = content.split("\n");
|
|
52
|
+
const ext = extname(filepath);
|
|
53
|
+
for (let i = 0; i < lines.length; i++) {
|
|
54
|
+
const line = lines[i];
|
|
55
|
+
// Non-null assertion operator (TypeScript !)
|
|
56
|
+
if ((ext === ".ts" || ext === ".tsx") && /\w+!\.\w+/.test(line) && !/\/\//.test(line.split("!.")[0])) {
|
|
57
|
+
risks.push({
|
|
58
|
+
file: filepath,
|
|
59
|
+
line: i + 1,
|
|
60
|
+
risk: "Non-null assertion operator (!.)",
|
|
61
|
+
severity: "medium",
|
|
62
|
+
suggestion: "Replace with optional chaining (?.) or null check",
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// Chained property access without optional chaining
|
|
66
|
+
if (/\w+\.\w+\.\w+\.\w+/.test(line) && !/\?\./.test(line) && !/import|from|require|\/\/|console/.test(line)) {
|
|
67
|
+
// Check if any intermediate could be null
|
|
68
|
+
if (/(?:result|response|data|item|user|config|options|params|body|payload)\.\w+\.\w+/.test(line)) {
|
|
69
|
+
risks.push({
|
|
70
|
+
file: filepath,
|
|
71
|
+
line: i + 1,
|
|
72
|
+
risk: "Deep property access without null check",
|
|
73
|
+
severity: "medium",
|
|
74
|
+
suggestion: "Use optional chaining (?.) for potentially null chains",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Array access without bounds check
|
|
79
|
+
if (/\w+\[\d+\]/.test(line) && !/length|\.at\(|slice|\/\//.test(line)) {
|
|
80
|
+
const block = lines.slice(Math.max(0, i - 3), i + 1).join("\n");
|
|
81
|
+
if (!/length|bounds|check|if\s*\(|\.at\(/i.test(block)) {
|
|
82
|
+
risks.push({
|
|
83
|
+
file: filepath,
|
|
84
|
+
line: i + 1,
|
|
85
|
+
risk: "Array index access without bounds check",
|
|
86
|
+
severity: "low",
|
|
87
|
+
suggestion: "Check array length or use .at() with null check",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Equality comparison with null using == instead of ===
|
|
92
|
+
if (/==\s*null\b/.test(line) && !/===\s*null/.test(line) && !/!==?\s*null/.test(line)) {
|
|
93
|
+
// == null catches both null and undefined in JS/TS, which is actually intentional in many cases
|
|
94
|
+
// Only flag if there's inconsistency
|
|
95
|
+
}
|
|
96
|
+
// Return type could be null but not documented (TypeScript)
|
|
97
|
+
if ((ext === ".ts" || ext === ".tsx") && /\):\s*\w+\s*\{/.test(line)) {
|
|
98
|
+
const funcBlock = lines.slice(i, Math.min(i + 20, lines.length)).join("\n");
|
|
99
|
+
if (/return\s+null\b|return\s+undefined\b/.test(funcBlock) &&
|
|
100
|
+
!/\|\s*null|\|\s*undefined|Maybe|Optional/.test(line)) {
|
|
101
|
+
risks.push({
|
|
102
|
+
file: filepath,
|
|
103
|
+
line: i + 1,
|
|
104
|
+
risk: "Function returns null but type doesn't declare it",
|
|
105
|
+
severity: "high",
|
|
106
|
+
suggestion: "Add | null or | undefined to return type",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Unsafe JSON.parse without try/catch
|
|
111
|
+
if (/JSON\.parse\s*\(/.test(line)) {
|
|
112
|
+
const block = lines.slice(Math.max(0, i - 5), Math.min(i + 5, lines.length)).join("\n");
|
|
113
|
+
if (!/try|catch|error/i.test(block)) {
|
|
114
|
+
risks.push({
|
|
115
|
+
file: filepath,
|
|
116
|
+
line: i + 1,
|
|
117
|
+
risk: "JSON.parse without error handling",
|
|
118
|
+
severity: "high",
|
|
119
|
+
suggestion: "Wrap in try/catch — malformed input causes runtime crash",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Destructuring without defaults
|
|
124
|
+
if (/const\s*\{[^}]+\}\s*=\s*\w+/.test(line) && !/=\s*\{/.test(line.split("=").slice(2).join("="))) {
|
|
125
|
+
const source = line.match(/=\s*(\w+)/)?.[1];
|
|
126
|
+
if (source && /result|response|data|args|params|options|config/i.test(source)) {
|
|
127
|
+
const block = lines.slice(Math.max(0, i - 3), i + 1).join("\n");
|
|
128
|
+
if (!/if\s*\(|&&|nullish|\?\?|optional/i.test(block)) {
|
|
129
|
+
risks.push({
|
|
130
|
+
file: filepath,
|
|
131
|
+
line: i + 1,
|
|
132
|
+
risk: "Destructuring potentially null value",
|
|
133
|
+
severity: "medium",
|
|
134
|
+
suggestion: "Add defaults or null check: const { x = default } = source ?? {}",
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// parseInt/parseFloat without NaN check
|
|
140
|
+
if (/(?:parseInt|parseFloat|Number)\s*\(/.test(line)) {
|
|
141
|
+
const block = lines.slice(i, Math.min(i + 3, lines.length)).join("\n");
|
|
142
|
+
if (!/isNaN|Number\.isFinite|Number\.isNaN|isFinite/i.test(block)) {
|
|
143
|
+
risks.push({
|
|
144
|
+
file: filepath,
|
|
145
|
+
line: i + 1,
|
|
146
|
+
risk: "Number parsing without NaN check",
|
|
147
|
+
severity: "low",
|
|
148
|
+
suggestion: "Check for NaN after parsing: if (Number.isNaN(result))",
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Python-specific: using dict[key] instead of dict.get(key)
|
|
153
|
+
if (ext === ".py" && /\w+\[\s*['"][^'"]+['"]\s*\]/.test(line)) {
|
|
154
|
+
if (!/get\(|in\s+\w+|try|KeyError/i.test(lines.slice(Math.max(0, i - 2), i + 1).join("\n"))) {
|
|
155
|
+
risks.push({
|
|
156
|
+
file: filepath,
|
|
157
|
+
line: i + 1,
|
|
158
|
+
risk: "Dict access without KeyError guard",
|
|
159
|
+
severity: "medium",
|
|
160
|
+
suggestion: "Use dict.get(key, default) or check with 'in'",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return risks;
|
|
166
|
+
}
|
|
167
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
168
|
+
export function runNullSafetyAudit(argv) {
|
|
169
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
170
|
+
console.log(`
|
|
171
|
+
judges null-safety-audit — Identify null/undefined dereference risks
|
|
172
|
+
|
|
173
|
+
Usage:
|
|
174
|
+
judges null-safety-audit [dir]
|
|
175
|
+
judges null-safety-audit src/ --format json
|
|
176
|
+
|
|
177
|
+
Options:
|
|
178
|
+
[dir] Directory to scan (default: .)
|
|
179
|
+
--format json JSON output
|
|
180
|
+
--help, -h Show this help
|
|
181
|
+
|
|
182
|
+
Checks: non-null assertions, deep property chains, array bounds, undocumented null returns,
|
|
183
|
+
JSON.parse without try/catch, destructuring null values, NaN checks.
|
|
184
|
+
`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
188
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
189
|
+
const files = collectFiles(dir);
|
|
190
|
+
const allRisks = [];
|
|
191
|
+
for (const f of files)
|
|
192
|
+
allRisks.push(...analyzeFile(f));
|
|
193
|
+
const highCount = allRisks.filter((r) => r.severity === "high").length;
|
|
194
|
+
const medCount = allRisks.filter((r) => r.severity === "medium").length;
|
|
195
|
+
const score = Math.max(0, 100 - highCount * 8 - medCount * 3);
|
|
196
|
+
if (format === "json") {
|
|
197
|
+
console.log(JSON.stringify({
|
|
198
|
+
risks: allRisks,
|
|
199
|
+
score,
|
|
200
|
+
summary: { high: highCount, medium: medCount, total: allRisks.length },
|
|
201
|
+
timestamp: new Date().toISOString(),
|
|
202
|
+
}, null, 2));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
const badge = score >= 80 ? "✅ SAFE" : score >= 50 ? "⚠️ RISKS" : "❌ UNSAFE";
|
|
206
|
+
console.log(`\n Null Safety: ${badge} (${score}/100)\n ──────────────────────────`);
|
|
207
|
+
if (allRisks.length === 0) {
|
|
208
|
+
console.log(" No null safety risks detected.\n");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
for (const r of allRisks.slice(0, 25)) {
|
|
212
|
+
const icon = r.severity === "high" ? "🔴" : r.severity === "medium" ? "🟡" : "🔵";
|
|
213
|
+
console.log(` ${icon} ${r.risk}`);
|
|
214
|
+
console.log(` ${r.file}:${r.line}`);
|
|
215
|
+
console.log(` → ${r.suggestion}`);
|
|
216
|
+
}
|
|
217
|
+
if (allRisks.length > 25)
|
|
218
|
+
console.log(` ... and ${allRisks.length - 25} more`);
|
|
219
|
+
console.log(`\n Total: ${allRisks.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=null-safety-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"null-safety-audit.js","sourceRoot":"","sources":["../../src/commands/null-safety-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership-map.d.ts","sourceRoot":"","sources":["../../src/commands/ownership-map.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgNH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmDpD"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ownership map — generate and validate code ownership coverage from
|
|
3
|
+
* CODEOWNERS, git history, and module boundaries.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync, statSync, existsSync } from "fs";
|
|
6
|
+
import { join, extname, relative } from "path";
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
// ─── CODEOWNERS Parsing ─────────────────────────────────────────────────────
|
|
9
|
+
function parseCodeowners(dir) {
|
|
10
|
+
const candidates = [join(dir, "CODEOWNERS"), join(dir, ".github", "CODEOWNERS"), join(dir, "docs", "CODEOWNERS")];
|
|
11
|
+
for (const path of candidates) {
|
|
12
|
+
if (existsSync(path)) {
|
|
13
|
+
const content = readFileSync(path, "utf-8");
|
|
14
|
+
const entries = [];
|
|
15
|
+
for (const line of content.split("\n")) {
|
|
16
|
+
const trimmed = line.trim();
|
|
17
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
18
|
+
continue;
|
|
19
|
+
const parts = trimmed.split(/\s+/);
|
|
20
|
+
if (parts.length >= 2) {
|
|
21
|
+
entries.push({ pattern: parts[0], owners: parts.slice(1) });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return entries;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
30
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs", ".cs", ".rb"]);
|
|
31
|
+
function collectSourceFiles(dir, max = 500) {
|
|
32
|
+
const files = [];
|
|
33
|
+
function walk(d) {
|
|
34
|
+
if (files.length >= max)
|
|
35
|
+
return;
|
|
36
|
+
let entries;
|
|
37
|
+
try {
|
|
38
|
+
entries = readdirSync(d);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const e of entries) {
|
|
44
|
+
if (files.length >= max)
|
|
45
|
+
return;
|
|
46
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
47
|
+
continue;
|
|
48
|
+
const full = join(d, e);
|
|
49
|
+
try {
|
|
50
|
+
if (statSync(full).isDirectory())
|
|
51
|
+
walk(full);
|
|
52
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
53
|
+
files.push(full);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
/* skip */
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
walk(dir);
|
|
61
|
+
return files;
|
|
62
|
+
}
|
|
63
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
64
|
+
function matchesPattern(filepath, pattern) {
|
|
65
|
+
if (pattern.endsWith("*")) {
|
|
66
|
+
return filepath.startsWith(pattern.slice(0, -1));
|
|
67
|
+
}
|
|
68
|
+
if (pattern.startsWith("*")) {
|
|
69
|
+
return filepath.endsWith(pattern.slice(1));
|
|
70
|
+
}
|
|
71
|
+
if (pattern.includes("*")) {
|
|
72
|
+
const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
|
|
73
|
+
return regex.test(filepath);
|
|
74
|
+
}
|
|
75
|
+
return filepath.startsWith(pattern) || filepath === pattern;
|
|
76
|
+
}
|
|
77
|
+
function getRecentAuthors(dir, filepath, months = 6) {
|
|
78
|
+
try {
|
|
79
|
+
const since = new Date();
|
|
80
|
+
since.setMonth(since.getMonth() - months);
|
|
81
|
+
const dateStr = since.toISOString().split("T")[0];
|
|
82
|
+
const output = execSync(`git log --since="${dateStr}" --format="%ae" -- "${filepath}"`, {
|
|
83
|
+
cwd: dir,
|
|
84
|
+
encoding: "utf-8",
|
|
85
|
+
timeout: 5000,
|
|
86
|
+
}).trim();
|
|
87
|
+
if (!output)
|
|
88
|
+
return [];
|
|
89
|
+
return [...new Set(output.split("\n"))];
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function analyze(dir) {
|
|
96
|
+
const gaps = [];
|
|
97
|
+
const entries = parseCodeowners(dir);
|
|
98
|
+
const files = collectSourceFiles(dir);
|
|
99
|
+
if (entries.length === 0) {
|
|
100
|
+
gaps.push({
|
|
101
|
+
path: "CODEOWNERS",
|
|
102
|
+
issue: "No CODEOWNERS file",
|
|
103
|
+
severity: "high",
|
|
104
|
+
detail: "Create a CODEOWNERS file to formalize code ownership",
|
|
105
|
+
});
|
|
106
|
+
return { gaps, stats: { total: files.length, owned: 0, orphaned: files.length, stale: 0 } };
|
|
107
|
+
}
|
|
108
|
+
let owned = 0;
|
|
109
|
+
let orphaned = 0;
|
|
110
|
+
let stale = 0;
|
|
111
|
+
// Check top-level directories for ownership
|
|
112
|
+
const dirs = new Set();
|
|
113
|
+
for (const f of files) {
|
|
114
|
+
const rel = relative(dir, f).replace(/\\/g, "/");
|
|
115
|
+
const topDir = rel.split("/")[0];
|
|
116
|
+
dirs.add(topDir);
|
|
117
|
+
// Check if file has an owner
|
|
118
|
+
const hasOwner = entries.some((e) => matchesPattern(rel, e.pattern));
|
|
119
|
+
if (hasOwner) {
|
|
120
|
+
owned++;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
orphaned++;
|
|
124
|
+
if (orphaned <= 15) {
|
|
125
|
+
gaps.push({
|
|
126
|
+
path: rel,
|
|
127
|
+
issue: "No code owner",
|
|
128
|
+
severity: "medium",
|
|
129
|
+
detail: "File has no matching CODEOWNERS entry",
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (orphaned > 15) {
|
|
135
|
+
gaps.push({
|
|
136
|
+
path: "(multiple)",
|
|
137
|
+
issue: `${orphaned - 15} more unowned files`,
|
|
138
|
+
severity: "medium",
|
|
139
|
+
detail: "Add broader patterns to CODEOWNERS",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// Check for stale owners (paths with owner but no recent commits)
|
|
143
|
+
for (const entry of entries) {
|
|
144
|
+
const matchingFiles = files.filter((f) => matchesPattern(relative(dir, f).replace(/\\/g, "/"), entry.pattern));
|
|
145
|
+
if (matchingFiles.length === 0) {
|
|
146
|
+
gaps.push({
|
|
147
|
+
path: entry.pattern,
|
|
148
|
+
issue: "CODEOWNERS pattern matches no files",
|
|
149
|
+
severity: "low",
|
|
150
|
+
detail: `Pattern "${entry.pattern}" → ${entry.owners.join(", ")} matches nothing`,
|
|
151
|
+
});
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
// Sample one file for recency
|
|
155
|
+
const sample = matchingFiles[0];
|
|
156
|
+
const authors = getRecentAuthors(dir, sample);
|
|
157
|
+
if (authors.length === 0) {
|
|
158
|
+
stale++;
|
|
159
|
+
gaps.push({
|
|
160
|
+
path: entry.pattern,
|
|
161
|
+
issue: "Stale ownership",
|
|
162
|
+
severity: "medium",
|
|
163
|
+
detail: `No commits in 6 months for "${entry.pattern}" (owners: ${entry.owners.join(", ")})`,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Check for overlapping patterns
|
|
168
|
+
for (let i = 0; i < entries.length; i++) {
|
|
169
|
+
for (let j = i + 1; j < entries.length; j++) {
|
|
170
|
+
const iFiles = files.filter((f) => matchesPattern(relative(dir, f).replace(/\\/g, "/"), entries[i].pattern));
|
|
171
|
+
const jFiles = files.filter((f) => matchesPattern(relative(dir, f).replace(/\\/g, "/"), entries[j].pattern));
|
|
172
|
+
const overlap = iFiles.filter((f) => jFiles.includes(f));
|
|
173
|
+
if (overlap.length > 0) {
|
|
174
|
+
gaps.push({
|
|
175
|
+
path: `${entries[i].pattern} ∩ ${entries[j].pattern}`,
|
|
176
|
+
issue: "Overlapping ownership patterns",
|
|
177
|
+
severity: "low",
|
|
178
|
+
detail: `${overlap.length} files match both patterns — later pattern takes precedence`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { gaps, stats: { total: files.length, owned, orphaned, stale } };
|
|
184
|
+
}
|
|
185
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
186
|
+
export function runOwnershipMap(argv) {
|
|
187
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
188
|
+
console.log(`
|
|
189
|
+
judges ownership-map — Generate and validate code ownership coverage
|
|
190
|
+
|
|
191
|
+
Usage:
|
|
192
|
+
judges ownership-map [dir]
|
|
193
|
+
judges ownership-map --format json
|
|
194
|
+
|
|
195
|
+
Options:
|
|
196
|
+
[dir] Directory to scan (default: .)
|
|
197
|
+
--format json JSON output
|
|
198
|
+
--help, -h Show this help
|
|
199
|
+
|
|
200
|
+
Checks: CODEOWNERS coverage, orphaned files, stale owners, overlapping patterns.
|
|
201
|
+
`);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
205
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
206
|
+
const { gaps, stats } = analyze(dir);
|
|
207
|
+
const coveragePct = stats.total > 0 ? Math.round((stats.owned / stats.total) * 100) : 100;
|
|
208
|
+
const score = Math.max(0, coveragePct - stats.stale * 5);
|
|
209
|
+
if (format === "json") {
|
|
210
|
+
console.log(JSON.stringify({ gaps, stats, coverage: coveragePct, score, timestamp: new Date().toISOString() }, null, 2));
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
const badge = coveragePct >= 90 ? "✅ GOOD" : coveragePct >= 60 ? "⚠️ PARTIAL" : "❌ LOW";
|
|
214
|
+
console.log(`\n Ownership Coverage: ${badge} (${coveragePct}%)\n ──────────────────────────────`);
|
|
215
|
+
console.log(` Total files: ${stats.total} | Owned: ${stats.owned} | Orphaned: ${stats.orphaned} | Stale: ${stats.stale}\n`);
|
|
216
|
+
if (gaps.length === 0) {
|
|
217
|
+
console.log(" No ownership issues detected.\n");
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
for (const g of gaps) {
|
|
221
|
+
const icon = g.severity === "high" ? "🔴" : g.severity === "medium" ? "🟡" : "🔵";
|
|
222
|
+
console.log(` ${icon} ${g.issue}`);
|
|
223
|
+
console.log(` ${g.path}`);
|
|
224
|
+
console.log(` ${g.detail}`);
|
|
225
|
+
}
|
|
226
|
+
console.log(`\n Score: ${score}/100\n`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=ownership-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership-map.js","sourceRoot":"","sources":["../../src/commands/ownership-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-pattern-audit.d.ts","sourceRoot":"","sources":["../../src/commands/retry-pattern-audit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2LH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiEzD"}
|