@kevinrabun/judges 3.55.0 → 3.57.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 (70) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +112 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/api-versioning-audit.d.ts +6 -0
  6. package/dist/commands/api-versioning-audit.d.ts.map +1 -0
  7. package/dist/commands/api-versioning-audit.js +234 -0
  8. package/dist/commands/api-versioning-audit.js.map +1 -0
  9. package/dist/commands/boundary-enforce.d.ts +6 -0
  10. package/dist/commands/boundary-enforce.d.ts.map +1 -0
  11. package/dist/commands/boundary-enforce.js +256 -0
  12. package/dist/commands/boundary-enforce.js.map +1 -0
  13. package/dist/commands/cache-audit.d.ts +5 -0
  14. package/dist/commands/cache-audit.d.ts.map +1 -0
  15. package/dist/commands/cache-audit.js +220 -0
  16. package/dist/commands/cache-audit.js.map +1 -0
  17. package/dist/commands/comment-drift.d.ts +5 -0
  18. package/dist/commands/comment-drift.d.ts.map +1 -0
  19. package/dist/commands/comment-drift.js +229 -0
  20. package/dist/commands/comment-drift.js.map +1 -0
  21. package/dist/commands/error-taxonomy.d.ts +6 -0
  22. package/dist/commands/error-taxonomy.d.ts.map +1 -0
  23. package/dist/commands/error-taxonomy.js +227 -0
  24. package/dist/commands/error-taxonomy.js.map +1 -0
  25. package/dist/commands/error-ux.d.ts +5 -0
  26. package/dist/commands/error-ux.d.ts.map +1 -0
  27. package/dist/commands/error-ux.js +253 -0
  28. package/dist/commands/error-ux.js.map +1 -0
  29. package/dist/commands/event-leak.d.ts +5 -0
  30. package/dist/commands/event-leak.d.ts.map +1 -0
  31. package/dist/commands/event-leak.js +263 -0
  32. package/dist/commands/event-leak.js.map +1 -0
  33. package/dist/commands/idempotency-audit.d.ts +5 -0
  34. package/dist/commands/idempotency-audit.d.ts.map +1 -0
  35. package/dist/commands/idempotency-audit.js +223 -0
  36. package/dist/commands/idempotency-audit.js.map +1 -0
  37. package/dist/commands/log-quality.d.ts +6 -0
  38. package/dist/commands/log-quality.d.ts.map +1 -0
  39. package/dist/commands/log-quality.js +212 -0
  40. package/dist/commands/log-quality.js.map +1 -0
  41. package/dist/commands/null-safety-audit.d.ts +6 -0
  42. package/dist/commands/null-safety-audit.d.ts.map +1 -0
  43. package/dist/commands/null-safety-audit.js +222 -0
  44. package/dist/commands/null-safety-audit.js.map +1 -0
  45. package/dist/commands/ownership-map.d.ts +6 -0
  46. package/dist/commands/ownership-map.d.ts.map +1 -0
  47. package/dist/commands/ownership-map.js +229 -0
  48. package/dist/commands/ownership-map.js.map +1 -0
  49. package/dist/commands/privilege-path.d.ts +5 -0
  50. package/dist/commands/privilege-path.d.ts.map +1 -0
  51. package/dist/commands/privilege-path.js +234 -0
  52. package/dist/commands/privilege-path.js.map +1 -0
  53. package/dist/commands/retry-pattern-audit.d.ts +6 -0
  54. package/dist/commands/retry-pattern-audit.d.ts.map +1 -0
  55. package/dist/commands/retry-pattern-audit.js +216 -0
  56. package/dist/commands/retry-pattern-audit.js.map +1 -0
  57. package/dist/commands/test-isolation.d.ts +6 -0
  58. package/dist/commands/test-isolation.d.ts.map +1 -0
  59. package/dist/commands/test-isolation.js +235 -0
  60. package/dist/commands/test-isolation.js.map +1 -0
  61. package/dist/commands/timeout-audit.d.ts +5 -0
  62. package/dist/commands/timeout-audit.d.ts.map +1 -0
  63. package/dist/commands/timeout-audit.js +211 -0
  64. package/dist/commands/timeout-audit.js.map +1 -0
  65. package/dist/commands/type-boundary.d.ts +5 -0
  66. package/dist/commands/type-boundary.d.ts.map +1 -0
  67. package/dist/commands/type-boundary.js +236 -0
  68. package/dist/commands/type-boundary.js.map +1 -0
  69. package/package.json +1 -1
  70. package/server.json +2 -2
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Log quality — assess logging hygiene: structured format consistency,
3
+ * PII leaks, level correctness, and coverage gaps.
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", ".rs"]);
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
+ const PII_PATTERNS = [
43
+ { pattern: /(?:email|e-mail|user_?email)\s*[:=]/i, name: "email" },
44
+ { pattern: /(?:password|passwd|pwd|secret)\s*[:=]/i, name: "password" },
45
+ { pattern: /(?:ssn|social.?security|national.?id)\s*[:=]/i, name: "SSN/national ID" },
46
+ { pattern: /(?:credit.?card|card.?number|ccn)\s*[:=]/i, name: "credit card" },
47
+ { pattern: /(?:phone.?number|mobile|cell)\s*[:=]/i, name: "phone number" },
48
+ { pattern: /(?:date.?of.?birth|dob|birthday)\s*[:=]/i, name: "date of birth" },
49
+ { pattern: /(?:ip.?address|client.?ip|remote.?addr)\s*[:=]/i, name: "IP address" },
50
+ ];
51
+ function analyzeFile(filepath) {
52
+ const issues = [];
53
+ let content;
54
+ try {
55
+ content = readFileSync(filepath, "utf-8");
56
+ }
57
+ catch {
58
+ return issues;
59
+ }
60
+ const lines = content.split("\n");
61
+ const isTestFile = /\.test\.|\.spec\.|__test__/i.test(filepath);
62
+ if (isTestFile)
63
+ return issues;
64
+ for (let i = 0; i < lines.length; i++) {
65
+ const line = lines[i];
66
+ // Console.log in production code
67
+ if (/console\.log\s*\(/.test(line) && !/\/\//.test(line.split("console")[0])) {
68
+ issues.push({
69
+ file: filepath,
70
+ line: i + 1,
71
+ issue: "console.log in production code",
72
+ severity: "medium",
73
+ suggestion: "Use a structured logger (winston, pino, bunyan)",
74
+ });
75
+ }
76
+ // Wrong log level
77
+ if (/console\.log\s*\(\s*['"`](?:error|err|fail|exception|crash)/i.test(line)) {
78
+ issues.push({
79
+ file: filepath,
80
+ line: i + 1,
81
+ issue: "Error logged at info/debug level",
82
+ severity: "high",
83
+ suggestion: "Use console.error or logger.error for error conditions",
84
+ });
85
+ }
86
+ if (/(?:logger|log)\.(?:debug|info|trace)\s*\(\s*['"`](?:error|fail|exception|crash)/i.test(line)) {
87
+ issues.push({
88
+ file: filepath,
89
+ line: i + 1,
90
+ issue: "Error logged at info/debug level",
91
+ severity: "high",
92
+ suggestion: "Use logger.error() for error conditions",
93
+ });
94
+ }
95
+ // String interpolation in structured logger
96
+ if (/(?:logger|log)\.\w+\s*\(\s*`/.test(line)) {
97
+ issues.push({
98
+ file: filepath,
99
+ line: i + 1,
100
+ issue: "Template literal in structured logger",
101
+ severity: "medium",
102
+ suggestion: "Use structured fields: logger.info('msg', { key: value }) for queryability",
103
+ });
104
+ }
105
+ // PII in log statements
106
+ if (/(?:console|log|logger)\.\w+\s*\(/.test(line)) {
107
+ for (const pii of PII_PATTERNS) {
108
+ if (pii.pattern.test(line)) {
109
+ issues.push({
110
+ file: filepath,
111
+ line: i + 1,
112
+ issue: `Potential ${pii.name} in log output`,
113
+ severity: "high",
114
+ suggestion: "Mask or redact PII before logging — may violate GDPR/CCPA",
115
+ });
116
+ }
117
+ }
118
+ }
119
+ // Logging full objects/errors without selection
120
+ if (/(?:console|log|logger)\.\w+\s*\(\s*(?:err|error|exception|e)\s*\)/.test(line)) {
121
+ issues.push({
122
+ file: filepath,
123
+ line: i + 1,
124
+ issue: "Logging full error object",
125
+ severity: "low",
126
+ suggestion: "Log error.message and error.stack separately for structured parsing",
127
+ });
128
+ }
129
+ // Log statements with string concatenation (not structured)
130
+ if (/(?:console|log|logger)\.\w+\s*\(\s*['"].*['"]\s*\+/.test(line)) {
131
+ issues.push({
132
+ file: filepath,
133
+ line: i + 1,
134
+ issue: "String concatenation in log",
135
+ severity: "low",
136
+ suggestion: "Use structured logging with key-value pairs",
137
+ });
138
+ }
139
+ }
140
+ // Check for catch blocks without logging
141
+ for (let i = 0; i < lines.length; i++) {
142
+ if (/\bcatch\s*\(/.test(lines[i])) {
143
+ const block = lines.slice(i, Math.min(i + 8, lines.length)).join("\n");
144
+ if (!/log|logger|console\.(error|warn|log)|print|println/i.test(block) && !/throw|rethrow|reject/i.test(block)) {
145
+ issues.push({
146
+ file: filepath,
147
+ line: i + 1,
148
+ issue: "Silent catch block",
149
+ severity: "high",
150
+ suggestion: "Log errors in catch blocks or explicitly re-throw",
151
+ });
152
+ }
153
+ }
154
+ }
155
+ return issues;
156
+ }
157
+ // ─── CLI ────────────────────────────────────────────────────────────────────
158
+ export function runLogQuality(argv) {
159
+ if (argv.includes("--help") || argv.includes("-h")) {
160
+ console.log(`
161
+ judges log-quality — Assess logging hygiene and quality
162
+
163
+ Usage:
164
+ judges log-quality [dir]
165
+ judges log-quality src/ --format json
166
+
167
+ Options:
168
+ [dir] Directory to scan (default: .)
169
+ --format json JSON output
170
+ --help, -h Show this help
171
+
172
+ Checks: wrong log levels, PII in logs, unstructured logging, string concatenation,
173
+ template literals in structured loggers, silent catch blocks.
174
+ `);
175
+ return;
176
+ }
177
+ const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
178
+ const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
179
+ const files = collectFiles(dir);
180
+ const allIssues = [];
181
+ for (const f of files)
182
+ allIssues.push(...analyzeFile(f));
183
+ const highCount = allIssues.filter((i) => i.severity === "high").length;
184
+ const medCount = allIssues.filter((i) => i.severity === "medium").length;
185
+ const score = Math.max(0, 100 - highCount * 10 - medCount * 3);
186
+ if (format === "json") {
187
+ console.log(JSON.stringify({
188
+ issues: allIssues,
189
+ score,
190
+ summary: { high: highCount, medium: medCount, total: allIssues.length },
191
+ timestamp: new Date().toISOString(),
192
+ }, null, 2));
193
+ }
194
+ else {
195
+ const badge = score >= 80 ? "✅ GOOD" : score >= 50 ? "⚠️ NEEDS WORK" : "❌ POOR";
196
+ console.log(`\n Log Quality: ${badge} (${score}/100)\n ─────────────────────────`);
197
+ if (allIssues.length === 0) {
198
+ console.log(" No logging issues detected.\n");
199
+ return;
200
+ }
201
+ for (const issue of allIssues.slice(0, 25)) {
202
+ const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
203
+ console.log(` ${icon} ${issue.issue}`);
204
+ console.log(` ${issue.file}:${issue.line}`);
205
+ console.log(` → ${issue.suggestion}`);
206
+ }
207
+ if (allIssues.length > 25)
208
+ console.log(` ... and ${allIssues.length - 25} more`);
209
+ console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
210
+ }
211
+ }
212
+ //# sourceMappingURL=log-quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-quality.js","sourceRoot":"","sources":["../../src/commands/log-quality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Null safety audit — identify null/undefined dereference risks, missing
3
+ * guards, and inconsistent nullability patterns.
4
+ */
5
+ export declare function runNullSafetyAudit(argv: string[]): void;
6
+ //# sourceMappingURL=null-safety-audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"null-safety-audit.d.ts","sourceRoot":"","sources":["../../src/commands/null-safety-audit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4LH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+DvD"}
@@ -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,6 @@
1
+ /**
2
+ * Ownership map — generate and validate code ownership coverage from
3
+ * CODEOWNERS, git history, and module boundaries.
4
+ */
5
+ export declare function runOwnershipMap(argv: string[]): void;
6
+ //# sourceMappingURL=ownership-map.d.ts.map
@@ -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"}