@kevinrabun/judges 3.53.0 → 3.55.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 +24 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/approve-chain.d.ts +8 -0
- package/dist/commands/approve-chain.d.ts.map +1 -0
- package/dist/commands/approve-chain.js +235 -0
- package/dist/commands/approve-chain.js.map +1 -0
- package/dist/commands/build-optimize.d.ts +7 -0
- package/dist/commands/build-optimize.d.ts.map +1 -0
- package/dist/commands/build-optimize.js +257 -0
- package/dist/commands/build-optimize.js.map +1 -0
- package/dist/commands/coach-mode.d.ts +8 -0
- package/dist/commands/coach-mode.d.ts.map +1 -0
- package/dist/commands/coach-mode.js +230 -0
- package/dist/commands/coach-mode.js.map +1 -0
- package/dist/commands/commit-hygiene.d.ts +6 -0
- package/dist/commands/commit-hygiene.d.ts.map +1 -0
- package/dist/commands/commit-hygiene.js +176 -0
- package/dist/commands/commit-hygiene.js.map +1 -0
- package/dist/commands/context-inject.d.ts +9 -0
- package/dist/commands/context-inject.d.ts.map +1 -0
- package/dist/commands/context-inject.js +212 -0
- package/dist/commands/context-inject.js.map +1 -0
- package/dist/commands/deploy-readiness.d.ts +6 -0
- package/dist/commands/deploy-readiness.d.ts.map +1 -0
- package/dist/commands/deploy-readiness.js +212 -0
- package/dist/commands/deploy-readiness.js.map +1 -0
- package/dist/commands/finding-contest.d.ts +8 -0
- package/dist/commands/finding-contest.d.ts.map +1 -0
- package/dist/commands/finding-contest.js +193 -0
- package/dist/commands/finding-contest.js.map +1 -0
- package/dist/commands/habit-tracker.d.ts +8 -0
- package/dist/commands/habit-tracker.d.ts.map +1 -0
- package/dist/commands/habit-tracker.js +195 -0
- package/dist/commands/habit-tracker.js.map +1 -0
- package/dist/commands/migration-safety.d.ts +6 -0
- package/dist/commands/migration-safety.d.ts.map +1 -0
- package/dist/commands/migration-safety.js +257 -0
- package/dist/commands/migration-safety.js.map +1 -0
- package/dist/commands/observability-gap.d.ts +6 -0
- package/dist/commands/observability-gap.d.ts.map +1 -0
- package/dist/commands/observability-gap.js +212 -0
- package/dist/commands/observability-gap.js.map +1 -0
- package/dist/commands/prompt-replay.d.ts +8 -0
- package/dist/commands/prompt-replay.d.ts.map +1 -0
- package/dist/commands/prompt-replay.js +177 -0
- package/dist/commands/prompt-replay.js.map +1 -0
- package/dist/commands/review-replay.d.ts +9 -0
- package/dist/commands/review-replay.d.ts.map +1 -0
- package/dist/commands/review-replay.js +265 -0
- package/dist/commands/review-replay.js.map +1 -0
- package/dist/commands/rollback-safety.d.ts +5 -0
- package/dist/commands/rollback-safety.d.ts.map +1 -0
- package/dist/commands/rollback-safety.js +192 -0
- package/dist/commands/rollback-safety.js.map +1 -0
- package/dist/commands/secret-age.d.ts +6 -0
- package/dist/commands/secret-age.d.ts.map +1 -0
- package/dist/commands/secret-age.js +215 -0
- package/dist/commands/secret-age.js.map +1 -0
- package/dist/commands/snippet-eval.d.ts +8 -0
- package/dist/commands/snippet-eval.d.ts.map +1 -0
- package/dist/commands/snippet-eval.js +224 -0
- package/dist/commands/snippet-eval.js.map +1 -0
- package/dist/commands/test-quality.d.ts +6 -0
- package/dist/commands/test-quality.d.ts.map +1 -0
- package/dist/commands/test-quality.js +161 -0
- package/dist/commands/test-quality.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coach mode — interactive teaching mode that explains why each
|
|
3
|
+
* finding matters with real-world examples and secure alternatives.
|
|
4
|
+
*
|
|
5
|
+
* Wraps evaluations with educational context for each finding category.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, existsSync } from "fs";
|
|
8
|
+
// ─── Knowledge Base ─────────────────────────────────────────────────────────
|
|
9
|
+
const LESSONS = [
|
|
10
|
+
{
|
|
11
|
+
category: "sql-injection",
|
|
12
|
+
explanation: "SQL injection occurs when user input is concatenated directly into SQL queries, allowing attackers to manipulate the query logic, extract data, or modify the database.",
|
|
13
|
+
realWorldExample: "Heartland Payment Systems (2008): SQL injection led to theft of 130 million credit card numbers. Equifax breach (2017): An unpatched vulnerability allowed SQL injection affecting 147 million people.",
|
|
14
|
+
secureAlternative: "BEFORE: `db.query('SELECT * FROM users WHERE id=' + userId)`\nAFTER: `db.query('SELECT * FROM users WHERE id=$1', [userId])`\n\nAlways use parameterized queries or prepared statements.",
|
|
15
|
+
resources: ["OWASP SQL Injection Prevention", "CWE-89: SQL Injection"],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
category: "xss",
|
|
19
|
+
explanation: "Cross-Site Scripting (XSS) lets attackers inject malicious scripts into web pages viewed by other users, stealing session cookies, redirecting users, or defacing content.",
|
|
20
|
+
realWorldExample: "British Airways (2018): XSS-style attack on payment page stole 380,000 credit card details. TweetDeck XSS worm (2014) auto-retweeted itself across thousands of accounts.",
|
|
21
|
+
secureAlternative: "BEFORE: `element.innerHTML = userInput`\nAFTER: `element.textContent = userInput`\n OR: `element.innerHTML = DOMPurify.sanitize(userInput)`\n\nAlways sanitize before DOM insertion.",
|
|
22
|
+
resources: ["OWASP XSS Prevention Cheat Sheet", "CWE-79: Cross-site Scripting"],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
category: "hardcoded-secret",
|
|
26
|
+
explanation: "Hardcoded secrets (API keys, passwords, tokens) in source code are exposed to anyone with repo access and persist in git history even if 'deleted'. Automated scrapers on GitHub find them within seconds.",
|
|
27
|
+
realWorldExample: "Uber (2016): AWS keys hardcoded in a GitHub repo led to breach of 57 million records. Multiple cryptocurrency thefts traced to API keys pushed to public repos.",
|
|
28
|
+
secureAlternative: "BEFORE: `const apiKey = 'sk-1234567890abcdef'`\nAFTER: `const apiKey = process.env.API_KEY`\n\nUse environment variables, .env files (gitignored), or a secrets manager (AWS SSM, HashiCorp Vault).",
|
|
29
|
+
resources: ["OWASP Secrets Management", "CWE-798: Hard-coded Credentials"],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
category: "eval",
|
|
33
|
+
explanation: "eval() and new Function() execute arbitrary code strings, enabling code injection attacks where attacker-controlled input becomes executable code.",
|
|
34
|
+
realWorldExample: "Multiple Node.js package supply chain attacks used eval() to execute obfuscated malicious payloads. The event-stream incident (2018) used eval-like patterns to steal cryptocurrency.",
|
|
35
|
+
secureAlternative: "BEFORE: `eval('obj.' + propName)`\nAFTER: `obj[propName]` (property access)\n OR: Use a safe parser like expr-eval for math expressions.\n\nNever pass user input to eval().",
|
|
36
|
+
resources: ["CWE-95: Eval Injection", "MDN: Never use eval()"],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
category: "empty-catch",
|
|
40
|
+
explanation: "Empty catch blocks silently swallow exceptions, hiding bugs, security issues, and data corruption. The application continues in an undefined state without any indication of failure.",
|
|
41
|
+
realWorldExample: "Knight Capital (2012): Silent error handling in trading software caused $440 million loss in 45 minutes. Empty catches masked the deployment error that triggered the catastrophe.",
|
|
42
|
+
secureAlternative: "BEFORE: `try { op() } catch (e) {}`\nAFTER: `try { op() } catch (e) { logger.error('Operation failed', { error: e }); throw e; }`\n\nAlways log, report, or re-throw caught exceptions.",
|
|
43
|
+
resources: ["CWE-390: Detection of Error Without Action", "Error Handling Best Practices"],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
category: "insecure-http",
|
|
47
|
+
explanation: "Plain HTTP transmits data unencrypted, allowing man-in-the-middle attacks to intercept passwords, API keys, and sensitive data in transit.",
|
|
48
|
+
realWorldExample: "FireSheep (2010): Tool demonstrated mass session hijacking on HTTP networks at coffee shops. Multiple ISPs caught injecting ads and tracking scripts into HTTP traffic.",
|
|
49
|
+
secureAlternative: "BEFORE: `fetch('http://api.example.com/data')`\nAFTER: `fetch('https://api.example.com/data')`\n\nAlways use HTTPS. Enable HSTS headers. Reject HTTP in production.",
|
|
50
|
+
resources: ["OWASP Transport Layer Protection", "CWE-319: Cleartext Transmission"],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
category: "weak-crypto",
|
|
54
|
+
explanation: "Math.random() is predictable and not cryptographically secure. MD5 and SHA1 are broken for security purposes — collisions can be generated practically.",
|
|
55
|
+
realWorldExample: "Flame malware (2012): Exploited MD5 collision to forge Microsoft certificates. Multiple password breaches accelerated by MD5 hash cracking (orders of magnitude faster than bcrypt).",
|
|
56
|
+
secureAlternative: "BEFORE: `const token = Math.random().toString(36)`\nAFTER: `const token = crypto.randomUUID()`\n\nBEFORE: `crypto.createHash('md5')`\nAFTER: `crypto.createHash('sha256')` or bcrypt for passwords.",
|
|
57
|
+
resources: ["OWASP Cryptographic Failures", "CWE-338: Weak PRNG"],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
category: "command-injection",
|
|
61
|
+
explanation: "Passing user input to shell commands (exec, spawn with string) allows attackers to inject additional commands using ; && || etc.",
|
|
62
|
+
realWorldExample: "ImageTragick (2016): Image processing library passed filenames to shell commands, enabling remote code execution on thousands of servers. Multiple CI/CD pipeline compromises via command injection in build scripts.",
|
|
63
|
+
secureAlternative: "BEFORE: `execSync('convert ' + filename)`\nAFTER: `spawn('convert', [filename])`\n\nUse array-based APIs. Validate inputs against allowlists. Never pass user input to exec().",
|
|
64
|
+
resources: ["OWASP OS Command Injection", "CWE-78: OS Command Injection"],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
category: "cors",
|
|
68
|
+
explanation: "Permissive CORS (Access-Control-Allow-Origin: *) allows any website to make authenticated requests to your API, enabling cross-origin data theft.",
|
|
69
|
+
realWorldExample: "Multiple cryptocurrency exchanges had funds stolen via CORS misconfiguration, where malicious sites could read authenticated API responses including account balances and trade capabilities.",
|
|
70
|
+
secureAlternative: "BEFORE: `app.use(cors())` // allows all origins\nAFTER: `app.use(cors({ origin: ['https://myapp.com'], credentials: true }))`\n\nSpecify allowed origins. Never use * with credentials.",
|
|
71
|
+
resources: ["OWASP CORS Misconfiguration", "MDN: CORS"],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
category: "missing-auth",
|
|
75
|
+
explanation: "API endpoints without authentication middleware are accessible to anyone, including automated scanners. Every endpoint processing or returning data must verify the caller's identity.",
|
|
76
|
+
realWorldExample: "Parler data scrape (2021): Unauthenticated API endpoints allowed bulk download of millions of posts including deleted content. T-Mobile (2021): Unauthenticated API exposed 40 million records.",
|
|
77
|
+
secureAlternative: "BEFORE: `app.get('/users', handler)`\nAFTER: `app.get('/users', authMiddleware, roleCheck('admin'), handler)`\n\nApply authentication to all non-public routes. Add authorization for sensitive operations.",
|
|
78
|
+
resources: ["OWASP Broken Access Control", "CWE-306: Missing Authentication"],
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
function findLesson(text) {
|
|
82
|
+
const lower = text.toLowerCase();
|
|
83
|
+
for (const lesson of LESSONS) {
|
|
84
|
+
if (lower.includes(lesson.category) || lower.includes(lesson.category.replace(/-/g, " "))) {
|
|
85
|
+
return lesson;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Fuzzy match
|
|
89
|
+
const keywords = {
|
|
90
|
+
sql: "sql-injection",
|
|
91
|
+
inject: "sql-injection",
|
|
92
|
+
xss: "xss",
|
|
93
|
+
"cross-site": "xss",
|
|
94
|
+
innerhtml: "xss",
|
|
95
|
+
secret: "hardcoded-secret",
|
|
96
|
+
password: "hardcoded-secret",
|
|
97
|
+
hardcode: "hardcoded-secret",
|
|
98
|
+
eval: "eval",
|
|
99
|
+
"new function": "eval",
|
|
100
|
+
"empty catch": "empty-catch",
|
|
101
|
+
"catch {}": "empty-catch",
|
|
102
|
+
http: "insecure-http",
|
|
103
|
+
"math.random": "weak-crypto",
|
|
104
|
+
md5: "weak-crypto",
|
|
105
|
+
crypto: "weak-crypto",
|
|
106
|
+
exec: "command-injection",
|
|
107
|
+
spawn: "command-injection",
|
|
108
|
+
command: "command-injection",
|
|
109
|
+
cors: "cors",
|
|
110
|
+
auth: "missing-auth",
|
|
111
|
+
middleware: "missing-auth",
|
|
112
|
+
};
|
|
113
|
+
for (const [kw, cat] of Object.entries(keywords)) {
|
|
114
|
+
if (lower.includes(kw)) {
|
|
115
|
+
return LESSONS.find((l) => l.category === cat) || null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
121
|
+
export function runCoachMode(argv) {
|
|
122
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
123
|
+
console.log(`
|
|
124
|
+
judges coach-mode — Educational security coaching
|
|
125
|
+
|
|
126
|
+
Usage:
|
|
127
|
+
judges coach-mode --topic sql-injection
|
|
128
|
+
judges coach-mode --topic xss
|
|
129
|
+
judges coach-mode --all
|
|
130
|
+
judges coach-mode --scan <file>
|
|
131
|
+
|
|
132
|
+
Options:
|
|
133
|
+
--topic <name> Learn about a specific finding category
|
|
134
|
+
--all Show all available lessons
|
|
135
|
+
--scan <file> Scan a file and show coaching for each finding
|
|
136
|
+
--format json JSON output
|
|
137
|
+
--help, -h Show this help
|
|
138
|
+
|
|
139
|
+
Topics: sql-injection, xss, hardcoded-secret, eval, empty-catch,
|
|
140
|
+
insecure-http, weak-crypto, command-injection, cors, missing-auth
|
|
141
|
+
`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
145
|
+
const topic = argv.find((_a, i) => argv[i - 1] === "--topic") || "";
|
|
146
|
+
const isAll = argv.includes("--all");
|
|
147
|
+
const scanFile = argv.find((_a, i) => argv[i - 1] === "--scan") || "";
|
|
148
|
+
if (isAll) {
|
|
149
|
+
if (format === "json") {
|
|
150
|
+
console.log(JSON.stringify({ lessons: LESSONS, total: LESSONS.length }, null, 2));
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
console.log(`\n Coach Mode — ${LESSONS.length} lessons available\n ──────────────────────────`);
|
|
154
|
+
for (const lesson of LESSONS) {
|
|
155
|
+
console.log(`\n 📚 ${lesson.category}`);
|
|
156
|
+
console.log(` ${lesson.explanation.substring(0, 80)}...`);
|
|
157
|
+
}
|
|
158
|
+
console.log("\n Use --topic <name> for full lesson details.\n");
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (topic) {
|
|
163
|
+
const lesson = findLesson(topic);
|
|
164
|
+
if (!lesson) {
|
|
165
|
+
console.error(` Unknown topic: ${topic}. Use --all to see available topics.`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (format === "json") {
|
|
169
|
+
console.log(JSON.stringify(lesson, null, 2));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.log(`\n 📚 ${lesson.category.toUpperCase()}`);
|
|
173
|
+
console.log(` ──────────────────────────\n`);
|
|
174
|
+
console.log(` WHY IT MATTERS:`);
|
|
175
|
+
console.log(` ${lesson.explanation}\n`);
|
|
176
|
+
console.log(` REAL-WORLD EXAMPLES:`);
|
|
177
|
+
console.log(` ${lesson.realWorldExample}\n`);
|
|
178
|
+
console.log(` SECURE ALTERNATIVE:`);
|
|
179
|
+
for (const line of lesson.secureAlternative.split("\n")) {
|
|
180
|
+
console.log(` ${line}`);
|
|
181
|
+
}
|
|
182
|
+
console.log(`\n RESOURCES:`);
|
|
183
|
+
for (const r of lesson.resources) {
|
|
184
|
+
console.log(` 📖 ${r}`);
|
|
185
|
+
}
|
|
186
|
+
console.log("");
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (scanFile) {
|
|
191
|
+
if (!existsSync(scanFile)) {
|
|
192
|
+
console.error(` File not found: ${scanFile}`);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const content = readFileSync(scanFile, "utf-8");
|
|
196
|
+
const lines = content.split("\n");
|
|
197
|
+
const found = [];
|
|
198
|
+
for (let i = 0; i < lines.length; i++) {
|
|
199
|
+
const lesson = findLesson(lines[i]);
|
|
200
|
+
if (lesson && !found.some((f) => f.lesson.category === lesson.category)) {
|
|
201
|
+
found.push({ line: i + 1, lesson });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (format === "json") {
|
|
205
|
+
console.log(JSON.stringify({
|
|
206
|
+
file: scanFile,
|
|
207
|
+
findings: found.map((f) => ({ line: f.line, ...f.lesson })),
|
|
208
|
+
timestamp: new Date().toISOString(),
|
|
209
|
+
}, null, 2));
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
console.log(`\n Coach Mode — ${scanFile} (${found.length} teaching moment(s))\n ──────────────────────────`);
|
|
213
|
+
if (found.length === 0) {
|
|
214
|
+
console.log(" ✅ No common anti-patterns detected to coach on.");
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
for (const f of found) {
|
|
218
|
+
console.log(`\n 📚 Line ${f.line}: ${f.lesson.category}`);
|
|
219
|
+
console.log(` ${f.lesson.explanation}`);
|
|
220
|
+
console.log(` 🔴 Example breach: ${f.lesson.realWorldExample.split(".")[0]}`);
|
|
221
|
+
console.log(` 💡 ${f.lesson.secureAlternative.split("\n")[f.lesson.secureAlternative.includes("AFTER") ? 1 : 0]}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
console.log("");
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
console.log(" Use --topic <name>, --all, or --scan <file>. See --help for details.");
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=coach-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coach-mode.js","sourceRoot":"","sources":["../../src/commands/coach-mode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit-hygiene.d.ts","sourceRoot":"","sources":["../../src/commands/commit-hygiene.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyJH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAyDrD"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Commit hygiene — audit commit messages and diff structure for
|
|
3
|
+
* AI-generated code submission quality.
|
|
4
|
+
*/
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
// ─── Patterns ───────────────────────────────────────────────────────────────
|
|
7
|
+
const VAGUE_MESSAGES = [
|
|
8
|
+
/^update(d)?\s*(code|files?|stuff)?$/i,
|
|
9
|
+
/^fix(ed)?\s*(it|bug|stuff|things?)?$/i,
|
|
10
|
+
/^changes?$/i,
|
|
11
|
+
/^wip$/i,
|
|
12
|
+
/^misc$/i,
|
|
13
|
+
/^\.+$/,
|
|
14
|
+
/^temp$/i,
|
|
15
|
+
/^asdf/i,
|
|
16
|
+
/^test$/i,
|
|
17
|
+
];
|
|
18
|
+
const CONVENTIONAL_REGEX = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?:\s/;
|
|
19
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
20
|
+
function getCommits(count) {
|
|
21
|
+
try {
|
|
22
|
+
const log = execSync(`git log --oneline -${count} --format="%H|%s"`, { encoding: "utf-8", timeout: 10000 });
|
|
23
|
+
const commits = [];
|
|
24
|
+
for (const line of log.trim().split("\n")) {
|
|
25
|
+
if (!line)
|
|
26
|
+
continue;
|
|
27
|
+
const [hash, ...msgParts] = line.split("|");
|
|
28
|
+
const message = msgParts.join("|");
|
|
29
|
+
let files = 0, insertions = 0, deletions = 0;
|
|
30
|
+
try {
|
|
31
|
+
const stat = execSync(`git diff --shortstat ${hash}^ ${hash}`, { encoding: "utf-8", timeout: 5000 });
|
|
32
|
+
const fm = stat.match(/(\d+)\s+files?\s+changed/);
|
|
33
|
+
const im = stat.match(/(\d+)\s+insertions?/);
|
|
34
|
+
const dm = stat.match(/(\d+)\s+deletions?/);
|
|
35
|
+
if (fm)
|
|
36
|
+
files = parseInt(fm[1]);
|
|
37
|
+
if (im)
|
|
38
|
+
insertions = parseInt(im[1]);
|
|
39
|
+
if (dm)
|
|
40
|
+
deletions = parseInt(dm[1]);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
/* first commit or error */
|
|
44
|
+
}
|
|
45
|
+
commits.push({ hash: hash.substring(0, 8), message, files, insertions, deletions });
|
|
46
|
+
}
|
|
47
|
+
return commits;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function analyzeCommits(commits, requireConventional) {
|
|
54
|
+
const issues = [];
|
|
55
|
+
for (const c of commits) {
|
|
56
|
+
// Vague message check
|
|
57
|
+
if (VAGUE_MESSAGES.some((r) => r.test(c.message.trim()))) {
|
|
58
|
+
issues.push({
|
|
59
|
+
hash: c.hash,
|
|
60
|
+
message: c.message,
|
|
61
|
+
kind: "vague-message",
|
|
62
|
+
detail: "Commit message is too vague — describe what and why",
|
|
63
|
+
severity: "medium",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Conventional commit check
|
|
67
|
+
if (requireConventional && !CONVENTIONAL_REGEX.test(c.message)) {
|
|
68
|
+
issues.push({
|
|
69
|
+
hash: c.hash,
|
|
70
|
+
message: c.message,
|
|
71
|
+
kind: "non-conventional",
|
|
72
|
+
detail: "Missing conventional commit prefix (feat:, fix:, etc.)",
|
|
73
|
+
severity: "low",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Message length
|
|
77
|
+
if (c.message.length < 10) {
|
|
78
|
+
issues.push({
|
|
79
|
+
hash: c.hash,
|
|
80
|
+
message: c.message,
|
|
81
|
+
kind: "short-message",
|
|
82
|
+
detail: `Message only ${c.message.length} chars — too short to be descriptive`,
|
|
83
|
+
severity: "low",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (c.message.length > 100) {
|
|
87
|
+
issues.push({
|
|
88
|
+
hash: c.hash,
|
|
89
|
+
message: c.message,
|
|
90
|
+
kind: "long-subject",
|
|
91
|
+
detail: `Subject line is ${c.message.length} chars — keep under 72`,
|
|
92
|
+
severity: "low",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Oversized diff
|
|
96
|
+
if (c.files > 20) {
|
|
97
|
+
issues.push({
|
|
98
|
+
hash: c.hash,
|
|
99
|
+
message: c.message,
|
|
100
|
+
kind: "oversized-diff",
|
|
101
|
+
detail: `${c.files} files changed — consider splitting into atomic commits`,
|
|
102
|
+
severity: "high",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (c.insertions + c.deletions > 1000) {
|
|
106
|
+
issues.push({
|
|
107
|
+
hash: c.hash,
|
|
108
|
+
message: c.message,
|
|
109
|
+
kind: "massive-change",
|
|
110
|
+
detail: `${c.insertions}+ / ${c.deletions}- lines — too large for effective review`,
|
|
111
|
+
severity: "high",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// Merge commit detection (simple)
|
|
115
|
+
if (/^Merge\s+(branch|pull)/i.test(c.message)) {
|
|
116
|
+
// Not an issue per se, but track for stats
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return issues.sort((a, b) => {
|
|
120
|
+
const sev = { high: 3, medium: 2, low: 1 };
|
|
121
|
+
return sev[b.severity] - sev[a.severity];
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
125
|
+
export function runCommitHygiene(argv) {
|
|
126
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
127
|
+
console.log(`
|
|
128
|
+
judges commit-hygiene — Audit commit message and diff quality
|
|
129
|
+
|
|
130
|
+
Usage:
|
|
131
|
+
judges commit-hygiene
|
|
132
|
+
judges commit-hygiene --count 50
|
|
133
|
+
judges commit-hygiene --conventional
|
|
134
|
+
judges commit-hygiene --format json
|
|
135
|
+
|
|
136
|
+
Options:
|
|
137
|
+
--count <n> Number of recent commits to analyze (default: 20)
|
|
138
|
+
--conventional Require conventional commit format
|
|
139
|
+
--format json JSON output
|
|
140
|
+
--help, -h Show this help
|
|
141
|
+
`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
145
|
+
const count = parseInt(argv.find((_a, i) => argv[i - 1] === "--count") || "20");
|
|
146
|
+
const requireConventional = argv.includes("--conventional");
|
|
147
|
+
const commits = getCommits(count);
|
|
148
|
+
if (commits.length === 0) {
|
|
149
|
+
console.log(" No commits found. Ensure you're in a git repository.");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const issues = analyzeCommits(commits, requireConventional);
|
|
153
|
+
if (format === "json") {
|
|
154
|
+
console.log(JSON.stringify({ commits: commits.length, issues, timestamp: new Date().toISOString() }, null, 2));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.log(`\n Commit Hygiene — ${commits.length} commits analyzed, ${issues.length} issue(s)\n ──────────────────────────`);
|
|
158
|
+
if (issues.length === 0) {
|
|
159
|
+
console.log(" ✅ All commits look clean");
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
for (const issue of issues.slice(0, 30)) {
|
|
163
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "⚪";
|
|
164
|
+
console.log(` ${icon} ${issue.hash} "${issue.message.substring(0, 50)}"`);
|
|
165
|
+
console.log(` ${issue.detail}`);
|
|
166
|
+
}
|
|
167
|
+
if (issues.length > 30)
|
|
168
|
+
console.log(`\n ... and ${issues.length - 30} more`);
|
|
169
|
+
}
|
|
170
|
+
// Summary stats
|
|
171
|
+
const avgSize = commits.reduce((s, c) => s + c.insertions + c.deletions, 0) / commits.length;
|
|
172
|
+
console.log(`\n Avg change size: ${Math.round(avgSize)} lines/commit`);
|
|
173
|
+
console.log(` Issues: ${issues.filter((i) => i.severity === "high").length} high, ${issues.filter((i) => i.severity === "medium").length} medium, ${issues.filter((i) => i.severity === "low").length} low\n`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=commit-hygiene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit-hygiene.js","sourceRoot":"","sources":["../../src/commands/commit-hygiene.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context inject — feed project-specific context (architecture docs,
|
|
3
|
+
* API contracts, coding standards) into evaluation for higher-precision
|
|
4
|
+
* findings.
|
|
5
|
+
*
|
|
6
|
+
* Parses context files and maintains a local context cache for judges.
|
|
7
|
+
*/
|
|
8
|
+
export declare function runContextInject(argv: string[]): void;
|
|
9
|
+
//# sourceMappingURL=context-inject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-inject.d.ts","sourceRoot":"","sources":["../../src/commands/context-inject.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwFH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA2JrD"}
|