@kevinrabun/judges 3.47.0 → 3.48.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +56 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/audit-trail.d.ts +18 -0
  6. package/dist/commands/audit-trail.d.ts.map +1 -0
  7. package/dist/commands/audit-trail.js +155 -0
  8. package/dist/commands/audit-trail.js.map +1 -0
  9. package/dist/commands/auto-fix.d.ts +18 -0
  10. package/dist/commands/auto-fix.d.ts.map +1 -0
  11. package/dist/commands/auto-fix.js +241 -0
  12. package/dist/commands/auto-fix.js.map +1 -0
  13. package/dist/commands/dep-correlate.d.ts +9 -0
  14. package/dist/commands/dep-correlate.d.ts.map +1 -0
  15. package/dist/commands/dep-correlate.js +208 -0
  16. package/dist/commands/dep-correlate.js.map +1 -0
  17. package/dist/commands/doc-gen.d.ts +8 -0
  18. package/dist/commands/doc-gen.d.ts.map +1 -0
  19. package/dist/commands/doc-gen.js +209 -0
  20. package/dist/commands/doc-gen.js.map +1 -0
  21. package/dist/commands/judge-author.d.ts +8 -0
  22. package/dist/commands/judge-author.d.ts.map +1 -0
  23. package/dist/commands/judge-author.js +261 -0
  24. package/dist/commands/judge-author.js.map +1 -0
  25. package/dist/commands/pattern-registry.d.ts +23 -0
  26. package/dist/commands/pattern-registry.d.ts.map +1 -0
  27. package/dist/commands/pattern-registry.js +227 -0
  28. package/dist/commands/pattern-registry.js.map +1 -0
  29. package/dist/commands/perf-hotspot.d.ts +8 -0
  30. package/dist/commands/perf-hotspot.d.ts.map +1 -0
  31. package/dist/commands/perf-hotspot.js +274 -0
  32. package/dist/commands/perf-hotspot.js.map +1 -0
  33. package/dist/commands/security-maturity.d.ts +8 -0
  34. package/dist/commands/security-maturity.d.ts.map +1 -0
  35. package/dist/commands/security-maturity.js +313 -0
  36. package/dist/commands/security-maturity.js.map +1 -0
  37. package/package.json +1 -1
  38. package/server.json +2 -2
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Documentation generation — generates security documentation
3
+ * from Judges findings history and configuration.
4
+ *
5
+ * All output is local markdown files.
6
+ */
7
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
8
+ import { join } from "path";
9
+ // ─── Helpers ────────────────────────────────────────────────────────────────
10
+ function loadJsonSafe(path, fallback) {
11
+ if (!existsSync(path))
12
+ return fallback;
13
+ try {
14
+ return JSON.parse(readFileSync(path, "utf-8"));
15
+ }
16
+ catch {
17
+ return fallback;
18
+ }
19
+ }
20
+ function generatePolicyDoc() {
21
+ const sections = [];
22
+ // Header
23
+ sections.push({
24
+ title: "Security Review Policy",
25
+ content: `# Security Review Policy\n\n_Generated by Judges on ${new Date().toISOString().split("T")[0]}_\n\n## Overview\n\nThis document outlines the security review policy enforced by the Judges automated code review system.\n`,
26
+ });
27
+ // Configuration
28
+ const configPath = ".judgesrc";
29
+ if (existsSync(configPath)) {
30
+ try {
31
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
32
+ let content = `## Configuration\n\n`;
33
+ if (config.preset)
34
+ content += `- **Preset:** ${config.preset}\n`;
35
+ if (config.minSeverity)
36
+ content += `- **Minimum Severity:** ${config.minSeverity}\n`;
37
+ if (config.disabledJudges?.length)
38
+ content += `- **Disabled Judges:** ${config.disabledJudges.join(", ")}\n`;
39
+ if (config.disabledRules?.length)
40
+ content += `- **Disabled Rules:** ${config.disabledRules.join(", ")}\n`;
41
+ content += `\n`;
42
+ sections.push({ title: "Configuration", content });
43
+ }
44
+ catch {
45
+ // skip
46
+ }
47
+ }
48
+ // Suppressions
49
+ const supps = loadJsonSafe(".judges-suppressions.json", { suppressions: [] });
50
+ if (supps.suppressions && supps.suppressions.length > 0) {
51
+ let content = `## Approved Suppressions\n\n| Rule | Reason | Approved By |\n|------|--------|-------------|\n`;
52
+ for (const s of supps.suppressions) {
53
+ content += `| ${s.ruleId || "—"} | ${s.reason || "—"} | ${s.approvedBy || "—"} |\n`;
54
+ }
55
+ content += `\n`;
56
+ sections.push({ title: "Suppressions", content });
57
+ }
58
+ // Quality gates
59
+ const gate = loadJsonSafe(join(".judges-quality-gate", "policy.json"), {});
60
+ if (Object.keys(gate).length > 0) {
61
+ let content = `## Quality Gate Policy\n\n`;
62
+ for (const [key, val] of Object.entries(gate)) {
63
+ content += `- **${key}:** ${JSON.stringify(val)}\n`;
64
+ }
65
+ content += `\n`;
66
+ sections.push({ title: "Quality Gate", content });
67
+ }
68
+ return sections;
69
+ }
70
+ function generateRemediationGuide() {
71
+ const sections = [];
72
+ sections.push({
73
+ title: "Remediation Guide",
74
+ content: `# Security Remediation Guide\n\n_Generated by Judges on ${new Date().toISOString().split("T")[0]}_\n\nThis guide covers common security findings and how to fix them.\n\n`,
75
+ });
76
+ const guides = [
77
+ {
78
+ rule: "SQL Injection",
79
+ fix: "Use parameterized queries or prepared statements. Never concatenate user input into SQL strings.",
80
+ example: "db.query('SELECT * FROM users WHERE id = ?', [userId])",
81
+ },
82
+ {
83
+ rule: "Cross-Site Scripting (XSS)",
84
+ fix: "Sanitize and encode all user-provided output. Use framework-provided escaping (e.g., React auto-escapes).",
85
+ example: "const safe = DOMPurify.sanitize(userInput)",
86
+ },
87
+ {
88
+ rule: "Command Injection",
89
+ fix: "Use parameterized APIs or allowlists instead of shell execution with user input.",
90
+ example: "execFile('git', ['log', '--oneline'], callback)",
91
+ },
92
+ {
93
+ rule: "Hardcoded Secrets",
94
+ fix: "Move secrets to environment variables or a secrets manager. Never commit credentials.",
95
+ example: "const apiKey = process.env.API_KEY",
96
+ },
97
+ {
98
+ rule: "Insecure Cryptography",
99
+ fix: "Use strong algorithms (AES-256-GCM, SHA-256+). Avoid MD5, SHA-1, DES, RC4.",
100
+ example: "crypto.createCipheriv('aes-256-gcm', key, iv)",
101
+ },
102
+ {
103
+ rule: "Path Traversal",
104
+ fix: "Validate and normalize file paths. Use allowlists for permitted directories.",
105
+ example: "const safePath = path.resolve(baseDir, path.basename(userInput))",
106
+ },
107
+ {
108
+ rule: "SSRF",
109
+ fix: "Validate and allowlist URLs. Block internal IP ranges. Use URL parsing.",
110
+ example: "const url = new URL(userInput); if (!ALLOWED_HOSTS.has(url.hostname)) throw new Error()",
111
+ },
112
+ {
113
+ rule: "Missing Authentication",
114
+ fix: "Require authentication on all sensitive endpoints. Use middleware for consistent enforcement.",
115
+ example: "app.use('/api', authMiddleware)",
116
+ },
117
+ ];
118
+ let content = "";
119
+ for (const g of guides) {
120
+ content += `## ${g.rule}\n\n**Fix:** ${g.fix}\n\n\`\`\`\n${g.example}\n\`\`\`\n\n---\n\n`;
121
+ }
122
+ sections.push({ title: "Remediation Details", content });
123
+ return sections;
124
+ }
125
+ function generateTeamPlaybook() {
126
+ const sections = [];
127
+ sections.push({
128
+ title: "Team Security Playbook",
129
+ content: `# Team Security Playbook\n\n_Generated by Judges on ${new Date().toISOString().split("T")[0]}_\n\n## Workflow\n\n1. **Pre-commit**: Run \`judges review\` locally before pushing code\n2. **CI Pipeline**: Configure \`judges ci-template\` for automated PR checks\n3. **Triage**: Use \`judges auto-triage\` to prioritize critical findings\n4. **Review**: Assign findings using \`judges assign-findings\`\n5. **Track**: Monitor progress with \`judges burndown\`\n6. **Report**: Generate digests with \`judges digest\`\n\n`,
130
+ });
131
+ sections.push({
132
+ title: "Escalation Procedures",
133
+ content: `## Escalation Procedures\n\n| Severity | SLA | Action |\n|----------|-----|--------|\n| Critical | 4 hours | Notify security lead, create incident ticket |\n| High | 24 hours | Assign to code owner, block PR merge |\n| Medium | 1 week | Assign to team backlog |\n| Low | 1 sprint | Track in burndown |\n\n`,
134
+ });
135
+ sections.push({
136
+ title: "Metrics",
137
+ content: `## Key Metrics\n\n- **Mean Time to Remediate (MTTR)**: Track via \`judges sla-track\`\n- **False Positive Rate**: Tune via \`judges noise-advisor\`\n- **Coverage**: Monitor via \`judges coverage-map\`\n- **Team Score**: View via \`judges team-leaderboard\`\n- **Security Maturity**: Assess via \`judges security-maturity\`\n\n`,
138
+ });
139
+ return sections;
140
+ }
141
+ // ─── CLI ────────────────────────────────────────────────────────────────────
142
+ const STORE = ".judges-docs";
143
+ export function runDocGen(argv) {
144
+ if (argv.includes("--help") || argv.includes("-h")) {
145
+ console.log(`
146
+ judges doc-gen — Generate security documentation
147
+
148
+ Usage:
149
+ judges doc-gen --policy
150
+ judges doc-gen --remediation
151
+ judges doc-gen --playbook
152
+ judges doc-gen --all
153
+
154
+ Options:
155
+ --policy Generate security review policy document
156
+ --remediation Generate remediation guide
157
+ --playbook Generate team security playbook
158
+ --all Generate all documents
159
+ --output <dir> Output directory (default: .judges-docs)
160
+ --format json JSON output
161
+ --help, -h Show this help
162
+ `);
163
+ return;
164
+ }
165
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
166
+ const outputDir = argv.find((_a, i) => argv[i - 1] === "--output") || STORE;
167
+ const genPolicy = argv.includes("--policy") || argv.includes("--all");
168
+ const genRemediation = argv.includes("--remediation") || argv.includes("--all");
169
+ const genPlaybook = argv.includes("--playbook") || argv.includes("--all");
170
+ if (!genPolicy && !genRemediation && !genPlaybook) {
171
+ console.log(" Specify --policy, --remediation, --playbook, or --all. Use --help for details.");
172
+ return;
173
+ }
174
+ if (!existsSync(outputDir))
175
+ mkdirSync(outputDir, { recursive: true });
176
+ const generated = [];
177
+ if (genPolicy) {
178
+ const sections = generatePolicyDoc();
179
+ const content = sections.map((s) => s.content).join("\n");
180
+ const outPath = join(outputDir, "security-policy.md");
181
+ writeFileSync(outPath, content);
182
+ generated.push(outPath);
183
+ }
184
+ if (genRemediation) {
185
+ const sections = generateRemediationGuide();
186
+ const content = sections.map((s) => s.content).join("\n");
187
+ const outPath = join(outputDir, "remediation-guide.md");
188
+ writeFileSync(outPath, content);
189
+ generated.push(outPath);
190
+ }
191
+ if (genPlaybook) {
192
+ const sections = generateTeamPlaybook();
193
+ const content = sections.map((s) => s.content).join("\n");
194
+ const outPath = join(outputDir, "team-playbook.md");
195
+ writeFileSync(outPath, content);
196
+ generated.push(outPath);
197
+ }
198
+ if (format === "json") {
199
+ console.log(JSON.stringify({ generated, outputDir, timestamp: new Date().toISOString() }, null, 2));
200
+ }
201
+ else {
202
+ console.log(`\n Documentation Generated\n ──────────────────────────`);
203
+ for (const g of generated) {
204
+ console.log(` ✅ ${g}`);
205
+ }
206
+ console.log(`\n Output directory: ${outputDir}\n`);
207
+ }
208
+ }
209
+ //# sourceMappingURL=doc-gen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-gen.js","sourceRoot":"","sources":["../../src/commands/doc-gen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Custom judge authoring toolkit — scaffolds, validates,
3
+ * and tests new judge definitions.
4
+ *
5
+ * All data stored locally.
6
+ */
7
+ export declare function runJudgeAuthor(argv: string[]): void;
8
+ //# sourceMappingURL=judge-author.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge-author.d.ts","sourceRoot":"","sources":["../../src/commands/judge-author.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2JH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA6InD"}
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Custom judge authoring toolkit — scaffolds, validates,
3
+ * and tests new judge definitions.
4
+ *
5
+ * All data stored locally.
6
+ */
7
+ import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
8
+ import { join } from "path";
9
+ import { defaultRegistry } from "../judge-registry.js";
10
+ // ─── Scaffold ───────────────────────────────────────────────────────────────
11
+ function scaffoldJudge(id, opts) {
12
+ return {
13
+ id,
14
+ name: opts.name || id.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
15
+ description: `Custom judge: ${id}`,
16
+ category: opts.category || "custom",
17
+ severity: opts.severity || "medium",
18
+ rules: [
19
+ {
20
+ id: `${id}-001`,
21
+ pattern: "TODO: define pattern",
22
+ message: "TODO: describe what this rule detects",
23
+ severity: opts.severity || "medium",
24
+ },
25
+ ],
26
+ };
27
+ }
28
+ function generateJudgeFile(scaffold) {
29
+ return `/**
30
+ * ${scaffold.name}
31
+ *
32
+ * ${scaffold.description}
33
+ * Category: ${scaffold.category}
34
+ */
35
+
36
+ import type { Finding } from "../types.js";
37
+
38
+ export const judgeId = "${scaffold.id}";
39
+ export const judgeName = "${scaffold.name}";
40
+ export const judgeDescription = "${scaffold.description}";
41
+ export const judgeCategory = "${scaffold.category}";
42
+
43
+ interface Rule {
44
+ id: string;
45
+ pattern: RegExp;
46
+ message: string;
47
+ severity: string;
48
+ }
49
+
50
+ const rules: Rule[] = [
51
+ ${scaffold.rules
52
+ .map((r) => ` {
53
+ id: "${r.id}",
54
+ pattern: /${r.pattern.replace(/\//g, "\\/")}/g,
55
+ message: "${r.message}",
56
+ severity: "${r.severity}",
57
+ },`)
58
+ .join("\n")}
59
+ ];
60
+
61
+ export function evaluate(code: string, _filename: string): Finding[] {
62
+ const findings: Finding[] = [];
63
+ const lines = code.split("\\n");
64
+
65
+ for (const rule of rules) {
66
+ for (let i = 0; i < lines.length; i++) {
67
+ if (rule.pattern.test(lines[i])) {
68
+ findings.push({
69
+ ruleId: rule.id,
70
+ severity: rule.severity as Finding["severity"],
71
+ title: rule.message,
72
+ description: \`Detected by custom judge \${judgeId} at line \${i + 1}\`,
73
+ lineNumbers: [i + 1],
74
+ recommendation: "Review and fix the detected pattern",
75
+ });
76
+ rule.pattern.lastIndex = 0; // reset global regex
77
+ }
78
+ }
79
+ }
80
+
81
+ return findings;
82
+ }
83
+ `;
84
+ }
85
+ // ─── Validation ─────────────────────────────────────────────────────────────
86
+ function validateJudge(path) {
87
+ const errors = [];
88
+ const warnings = [];
89
+ if (!existsSync(path)) {
90
+ return { valid: false, errors: [`File not found: ${path}`], warnings: [] };
91
+ }
92
+ let content;
93
+ try {
94
+ content = readFileSync(path, "utf-8");
95
+ }
96
+ catch {
97
+ return { valid: false, errors: [`Cannot read file: ${path}`], warnings: [] };
98
+ }
99
+ // Check for required exports
100
+ if (!content.includes("export const judgeId"))
101
+ errors.push("Missing 'export const judgeId'");
102
+ if (!content.includes("export const judgeName"))
103
+ errors.push("Missing 'export const judgeName'");
104
+ if (!content.includes("export function evaluate"))
105
+ errors.push("Missing 'export function evaluate'");
106
+ // Check for Finding type
107
+ if (!content.includes("Finding"))
108
+ warnings.push("No reference to Finding type — ensure findings match expected shape");
109
+ // Check for severity values
110
+ const validSeverities = ["critical", "high", "medium", "low", "info"];
111
+ const sevMatches = content.match(/severity:\s*["'](\w+)["']/g) || [];
112
+ for (const m of sevMatches) {
113
+ const val = m.match(/["'](\w+)["']/)?.[1];
114
+ if (val && !validSeverities.includes(val)) {
115
+ errors.push(`Invalid severity '${val}' — must be: ${validSeverities.join(", ")}`);
116
+ }
117
+ }
118
+ // Check for rule IDs
119
+ const ruleIds = content.match(/id:\s*["']([^"']+)["']/g) || [];
120
+ if (ruleIds.length === 0)
121
+ warnings.push("No rule IDs found — each rule should have a unique id");
122
+ return { valid: errors.length === 0, errors, warnings };
123
+ }
124
+ // ─── CLI ────────────────────────────────────────────────────────────────────
125
+ const STORE = ".judges-custom";
126
+ export function runJudgeAuthor(argv) {
127
+ if (argv.includes("--help") || argv.includes("-h")) {
128
+ console.log(`
129
+ judges judge-author — Custom judge authoring toolkit
130
+
131
+ Usage:
132
+ judges judge-author --scaffold <id>
133
+ judges judge-author --validate <file>
134
+ judges judge-author --list
135
+ judges judge-author --test <file> --code <sample>
136
+
137
+ Options:
138
+ --scaffold <id> Generate a new judge scaffold
139
+ --name <name> Judge display name
140
+ --category <cat> Category (default: custom)
141
+ --severity <sev> Default severity (default: medium)
142
+ --validate <file> Validate judge file structure
143
+ --list List existing custom judges
144
+ --test <file> Test a judge against sample code
145
+ --code <sample> Sample code file to test against
146
+ --output <dir> Output directory (default: .judges-custom)
147
+ --format json JSON output
148
+ --help, -h Show this help
149
+ `);
150
+ return;
151
+ }
152
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
153
+ // List existing judges
154
+ if (argv.includes("--list")) {
155
+ const builtin = defaultRegistry.getJudges();
156
+ const customDir = STORE;
157
+ let customCount = 0;
158
+ if (existsSync(customDir)) {
159
+ try {
160
+ const { readdirSync } = require("fs");
161
+ customCount = readdirSync(customDir).filter((f) => f.endsWith(".ts") || f.endsWith(".json")).length;
162
+ }
163
+ catch {
164
+ /* skip */
165
+ }
166
+ }
167
+ if (format === "json") {
168
+ console.log(JSON.stringify({ builtin: builtin.length, custom: customCount, judges: builtin.map((j) => j.id) }, null, 2));
169
+ }
170
+ else {
171
+ console.log(`\n Judges Registry\n ──────────────────────────`);
172
+ console.log(` Built-in: ${builtin.length}`);
173
+ console.log(` Custom: ${customCount}`);
174
+ console.log(`\n Built-in judges:`);
175
+ for (const j of builtin) {
176
+ console.log(` ${j.id}`);
177
+ }
178
+ console.log("");
179
+ }
180
+ return;
181
+ }
182
+ // Scaffold
183
+ const scaffoldId = argv.find((_a, i) => argv[i - 1] === "--scaffold");
184
+ if (scaffoldId) {
185
+ const name = argv.find((_a, i) => argv[i - 1] === "--name");
186
+ const category = argv.find((_a, i) => argv[i - 1] === "--category");
187
+ const severity = argv.find((_a, i) => argv[i - 1] === "--severity");
188
+ const outputDir = argv.find((_a, i) => argv[i - 1] === "--output") || STORE;
189
+ const scaffold = scaffoldJudge(scaffoldId, {
190
+ name: name || undefined,
191
+ category: category || undefined,
192
+ severity: severity || undefined,
193
+ });
194
+ const code = generateJudgeFile(scaffold);
195
+ if (!existsSync(outputDir))
196
+ mkdirSync(outputDir, { recursive: true });
197
+ const outPath = join(outputDir, `${scaffoldId}.ts`);
198
+ writeFileSync(outPath, code);
199
+ // Also write the JSON definition
200
+ const jsonPath = join(outputDir, `${scaffoldId}.json`);
201
+ writeFileSync(jsonPath, JSON.stringify(scaffold, null, 2));
202
+ if (format === "json") {
203
+ console.log(JSON.stringify({ scaffold, files: [outPath, jsonPath] }, null, 2));
204
+ }
205
+ else {
206
+ console.log(`\n Judge Scaffolded: ${scaffoldId}\n ──────────────────────────`);
207
+ console.log(` TypeScript: ${outPath}`);
208
+ console.log(` Definition: ${jsonPath}`);
209
+ console.log(`\n Next steps:`);
210
+ console.log(` 1. Edit ${outPath} to add detection patterns`);
211
+ console.log(` 2. Validate with: judges judge-author --validate ${outPath}`);
212
+ console.log(` 3. Test with: judges judge-author --test ${outPath} --code sample.ts\n`);
213
+ }
214
+ return;
215
+ }
216
+ // Validate
217
+ const validatePath = argv.find((_a, i) => argv[i - 1] === "--validate");
218
+ if (validatePath) {
219
+ const result = validateJudge(validatePath);
220
+ if (format === "json") {
221
+ console.log(JSON.stringify(result, null, 2));
222
+ }
223
+ else {
224
+ console.log(`\n Validation: ${validatePath}`);
225
+ console.log(` Status: ${result.valid ? "✅ Valid" : "❌ Invalid"}\n ──────────────────────────`);
226
+ for (const e of result.errors)
227
+ console.log(` ❌ ${e}`);
228
+ for (const w of result.warnings)
229
+ console.log(` ⚠️ ${w}`);
230
+ if (result.valid && result.warnings.length === 0)
231
+ console.log(` All checks passed`);
232
+ console.log("");
233
+ }
234
+ return;
235
+ }
236
+ // Test
237
+ const testPath = argv.find((_a, i) => argv[i - 1] === "--test");
238
+ const codePath = argv.find((_a, i) => argv[i - 1] === "--code");
239
+ if (testPath) {
240
+ if (!codePath || !existsSync(codePath)) {
241
+ console.error(" Provide --code <file> with a sample code file to test against.");
242
+ return;
243
+ }
244
+ // Validate first
245
+ const validation = validateJudge(testPath);
246
+ if (!validation.valid) {
247
+ console.error(" Judge file has validation errors. Fix errors before testing.");
248
+ for (const e of validation.errors)
249
+ console.error(` ❌ ${e}`);
250
+ return;
251
+ }
252
+ console.log(`\n Testing ${testPath} against ${codePath}`);
253
+ console.log(` (Note: full testing requires loading the judge module at runtime)\n`);
254
+ console.log(` Validation: ✅ Passed`);
255
+ console.log(` Structure: ✅ Valid`);
256
+ console.log(`\n To run a full test, import and call the evaluate() function directly.\n`);
257
+ return;
258
+ }
259
+ console.log(" Use --scaffold, --validate, --list, or --test. Run --help for details.");
260
+ }
261
+ //# sourceMappingURL=judge-author.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge-author.js","sourceRoot":"","sources":["../../src/commands/judge-author.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Pattern registry — team knowledge sharing via a local
3
+ * repository of security patterns and anti-patterns.
4
+ *
5
+ * All data stays in .judges-patterns/ directory.
6
+ */
7
+ interface SecurityPattern {
8
+ id: string;
9
+ title: string;
10
+ category: string;
11
+ type: "pattern" | "anti-pattern";
12
+ language: string;
13
+ description: string;
14
+ example: string;
15
+ fix?: string;
16
+ author: string;
17
+ tags: string[];
18
+ createdAt: string;
19
+ }
20
+ export declare function addPattern(pattern: Omit<SecurityPattern, "id" | "createdAt">): SecurityPattern;
21
+ export declare function runPatternRegistry(argv: string[]): void;
22
+ export {};
23
+ //# sourceMappingURL=pattern-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-registry.d.ts","sourceRoot":"","sources":["../../src/commands/pattern-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,GAAG,cAAc,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAsFD,wBAAgB,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,WAAW,CAAC,GAAG,eAAe,CAU9F;AAID,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoIvD"}