clean-slop 2.0.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.
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Core types for the clean-slop production readiness engine.
3
+ */
4
+ type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
5
+ type Confidence = 'certain' | 'high' | 'medium' | 'low';
6
+ type RuleCategory = 'ai-slop' | 'security' | 'reliability' | 'maintainability' | 'production-readiness';
7
+ interface Location {
8
+ file: string;
9
+ line: number;
10
+ column: number;
11
+ endLine?: number;
12
+ endColumn?: number;
13
+ }
14
+ interface IssueFix {
15
+ description: string;
16
+ code?: string;
17
+ }
18
+ interface Issue {
19
+ /** Rule identifier that produced this issue, e.g. "security/sql-injection" */
20
+ ruleId: string;
21
+ /** Human-readable rule name */
22
+ ruleName: string;
23
+ /** Category the rule belongs to */
24
+ category: RuleCategory;
25
+ /** Severity of the issue */
26
+ severity: Severity;
27
+ /** Confidence that this is a real issue */
28
+ confidence: Confidence;
29
+ /** Short summary of what was found */
30
+ message: string;
31
+ /** Detailed explanation of the issue */
32
+ explanation: string;
33
+ /** Why this matters in production */
34
+ impact: string;
35
+ /** Location in source */
36
+ location: Location;
37
+ /** Extracted source snippet */
38
+ snippet?: string;
39
+ /** Suggested fix */
40
+ fix?: IssueFix;
41
+ /** URL to extended documentation */
42
+ docsUrl?: string;
43
+ /** Additional metadata from the rule */
44
+ metadata?: Record<string, unknown>;
45
+ }
46
+ interface CategoryScore {
47
+ category: RuleCategory;
48
+ score: number;
49
+ issueCount: number;
50
+ criticalCount: number;
51
+ highCount: number;
52
+ mediumCount: number;
53
+ lowCount: number;
54
+ }
55
+ interface ScanScore {
56
+ overall: number;
57
+ categories: CategoryScore[];
58
+ grade: 'A' | 'B' | 'C' | 'D' | 'F';
59
+ productionReady: boolean;
60
+ }
61
+ interface FileResult {
62
+ file: string;
63
+ issues: Issue[];
64
+ parseError?: string;
65
+ skipped?: boolean;
66
+ skipReason?: string;
67
+ }
68
+ interface ScanResult {
69
+ /** Absolute path of the scanned project root */
70
+ root: string;
71
+ /** ISO timestamp of the scan */
72
+ timestamp: string;
73
+ /** clean-slop version */
74
+ version: string;
75
+ /** Files that were scanned */
76
+ files: FileResult[];
77
+ /** All issues aggregated */
78
+ issues: Issue[];
79
+ /** Scores per category and overall */
80
+ score: ScanScore;
81
+ /** Duration in milliseconds */
82
+ durationMs: number;
83
+ /** Configuration used for this scan */
84
+ config: ResolvedConfig;
85
+ }
86
+ interface RuleMeta {
87
+ id: string;
88
+ name: string;
89
+ category: RuleCategory;
90
+ severity: Severity;
91
+ confidence: Confidence;
92
+ description: string;
93
+ rationale: string;
94
+ docsUrl: string;
95
+ fixable: boolean;
96
+ frameworks?: string[];
97
+ }
98
+ interface RuleContext {
99
+ filePath: string;
100
+ source: string;
101
+ ast: unknown;
102
+ config: ResolvedConfig;
103
+ report(issue: Omit<Issue, 'ruleId' | 'ruleName' | 'category' | 'severity' | 'confidence' | 'docsUrl'>): void;
104
+ }
105
+ interface Rule {
106
+ meta: RuleMeta;
107
+ create(context: RuleContext): void;
108
+ }
109
+ type RuleSeverityOverride = Severity | 'off';
110
+ interface RuleConfig {
111
+ severity?: RuleSeverityOverride;
112
+ options?: Record<string, unknown>;
113
+ }
114
+ interface UserConfig {
115
+ /** Glob patterns of files to include (default: all JS/TS files) */
116
+ include?: string[];
117
+ /** Glob patterns of files to exclude */
118
+ exclude?: string[];
119
+ /** Rule category toggles */
120
+ categories?: Record<RuleCategory, boolean>;
121
+ /** Per-rule overrides */
122
+ rules?: Record<string, RuleSeverityOverride | RuleConfig>;
123
+ /** Threshold below which the process exits non-zero */
124
+ failThreshold?: number;
125
+ /** Maximum issues of each severity before failing */
126
+ maxIssues?: Partial<Record<Severity, number>>;
127
+ /** Plugins to load */
128
+ plugins?: string[];
129
+ /** Output reporter */
130
+ reporter?: 'text' | 'json' | 'html' | 'markdown' | 'sarif';
131
+ /** Output file for reports */
132
+ output?: string;
133
+ /** Whether to enable verbose output */
134
+ verbose?: boolean;
135
+ /** Ignore patterns (in addition to .gitignore) */
136
+ ignorePatterns?: string[];
137
+ /** TypeScript project file */
138
+ tsConfigPath?: string;
139
+ }
140
+ type ResolvedConfig = Required<Omit<UserConfig, 'output' | 'tsConfigPath'>> & {
141
+ output: string | null;
142
+ tsConfigPath: string | null;
143
+ root: string;
144
+ version: string;
145
+ };
146
+ interface Plugin {
147
+ name: string;
148
+ version: string;
149
+ rules: Rule[];
150
+ }
151
+ interface Reporter {
152
+ name: string;
153
+ generate(result: ScanResult): string;
154
+ }
155
+ type Language = 'javascript' | 'typescript' | 'jsx' | 'tsx';
156
+ interface ParsedFile {
157
+ filePath: string;
158
+ source: string;
159
+ ast: unknown;
160
+ language: Language;
161
+ }
162
+
163
+ declare function loadConfig(cwd: string, configPath?: string): Promise<ResolvedConfig>;
164
+ declare function resolveConfig(userConfig: UserConfig, cwd: string): ResolvedConfig;
165
+ declare function generateDefaultConfig(): string;
166
+
167
+ interface ScanOptions {
168
+ config: ResolvedConfig;
169
+ onFile?: (filePath: string, index: number, total: number) => void;
170
+ onIssue?: (issue: Issue) => void;
171
+ }
172
+ declare function discoverFiles(config: ResolvedConfig): Promise<string[]>;
173
+ declare function scan(options: ScanOptions): Promise<ScanResult>;
174
+
175
+ declare class RuleEngine {
176
+ private rules;
177
+ register(rule: Rule): void;
178
+ registerAll(rules: Rule[]): void;
179
+ getRule(id: string): Rule | undefined;
180
+ getRules(): Rule[];
181
+ getRulesByCategory(category: RuleCategory): Rule[];
182
+ runOnFile(parsedFile: ParsedFile, config: ResolvedConfig): Issue[];
183
+ private resolveSeverityOverride;
184
+ }
185
+
186
+ declare const BUILT_IN_RULES: Rule[];
187
+
188
+ type ReporterName = 'text' | 'json' | 'html' | 'markdown' | 'sarif';
189
+ declare function generate(result: ScanResult, reporter?: ReporterName): string;
190
+ declare function writeReport(content: string, outputPath: string): Promise<void>;
191
+
192
+ declare class ParseError extends Error {
193
+ readonly filePath: string;
194
+ readonly cause?: unknown | undefined;
195
+ constructor(message: string, filePath: string, cause?: unknown | undefined);
196
+ }
197
+ declare function parseFile(filePath: string): Promise<ParsedFile>;
198
+ declare function parseSource(filePath: string, source: string): ParsedFile;
199
+ declare function extractSnippet(source: string, line: number, contextLines?: number): string;
200
+
201
+ declare const PACKAGE_VERSION = "1.0.0";
202
+
203
+ /**
204
+ * clean-slop - Production Readiness Engine
205
+ *
206
+ * Public JavaScript/TypeScript API.
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * import { scanDirectory, loadConfig } from 'clean-slop';
211
+ *
212
+ * const config = await loadConfig(process.cwd());
213
+ * const result = await scanDirectory(process.cwd(), config);
214
+ *
215
+ * console.log(`Score: ${result.score.overall}/100`);
216
+ * console.log(`Issues: ${result.issues.length}`);
217
+ * ```
218
+ */
219
+
220
+ /**
221
+ * Convenience: scan a directory and return the full result.
222
+ */
223
+ declare function scanDirectory(directory: string, userConfig?: UserConfig): Promise<ScanResult>;
224
+
225
+ export { BUILT_IN_RULES, type CategoryScore, type Confidence, type FileResult, type Issue, type IssueFix, type Language, type Location, ParseError, type ParsedFile, type Plugin, type Reporter, type ResolvedConfig, type Rule, type RuleCategory, type RuleContext, RuleEngine, type RuleMeta, type ScanResult, type ScanScore, type Severity, type UserConfig, discoverFiles, extractSnippet, generateDefaultConfig, generate as generateReport, loadConfig, parseFile, parseSource, resolveConfig, scan, scanDirectory, PACKAGE_VERSION as version, writeReport };
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Core types for the clean-slop production readiness engine.
3
+ */
4
+ type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
5
+ type Confidence = 'certain' | 'high' | 'medium' | 'low';
6
+ type RuleCategory = 'ai-slop' | 'security' | 'reliability' | 'maintainability' | 'production-readiness';
7
+ interface Location {
8
+ file: string;
9
+ line: number;
10
+ column: number;
11
+ endLine?: number;
12
+ endColumn?: number;
13
+ }
14
+ interface IssueFix {
15
+ description: string;
16
+ code?: string;
17
+ }
18
+ interface Issue {
19
+ /** Rule identifier that produced this issue, e.g. "security/sql-injection" */
20
+ ruleId: string;
21
+ /** Human-readable rule name */
22
+ ruleName: string;
23
+ /** Category the rule belongs to */
24
+ category: RuleCategory;
25
+ /** Severity of the issue */
26
+ severity: Severity;
27
+ /** Confidence that this is a real issue */
28
+ confidence: Confidence;
29
+ /** Short summary of what was found */
30
+ message: string;
31
+ /** Detailed explanation of the issue */
32
+ explanation: string;
33
+ /** Why this matters in production */
34
+ impact: string;
35
+ /** Location in source */
36
+ location: Location;
37
+ /** Extracted source snippet */
38
+ snippet?: string;
39
+ /** Suggested fix */
40
+ fix?: IssueFix;
41
+ /** URL to extended documentation */
42
+ docsUrl?: string;
43
+ /** Additional metadata from the rule */
44
+ metadata?: Record<string, unknown>;
45
+ }
46
+ interface CategoryScore {
47
+ category: RuleCategory;
48
+ score: number;
49
+ issueCount: number;
50
+ criticalCount: number;
51
+ highCount: number;
52
+ mediumCount: number;
53
+ lowCount: number;
54
+ }
55
+ interface ScanScore {
56
+ overall: number;
57
+ categories: CategoryScore[];
58
+ grade: 'A' | 'B' | 'C' | 'D' | 'F';
59
+ productionReady: boolean;
60
+ }
61
+ interface FileResult {
62
+ file: string;
63
+ issues: Issue[];
64
+ parseError?: string;
65
+ skipped?: boolean;
66
+ skipReason?: string;
67
+ }
68
+ interface ScanResult {
69
+ /** Absolute path of the scanned project root */
70
+ root: string;
71
+ /** ISO timestamp of the scan */
72
+ timestamp: string;
73
+ /** clean-slop version */
74
+ version: string;
75
+ /** Files that were scanned */
76
+ files: FileResult[];
77
+ /** All issues aggregated */
78
+ issues: Issue[];
79
+ /** Scores per category and overall */
80
+ score: ScanScore;
81
+ /** Duration in milliseconds */
82
+ durationMs: number;
83
+ /** Configuration used for this scan */
84
+ config: ResolvedConfig;
85
+ }
86
+ interface RuleMeta {
87
+ id: string;
88
+ name: string;
89
+ category: RuleCategory;
90
+ severity: Severity;
91
+ confidence: Confidence;
92
+ description: string;
93
+ rationale: string;
94
+ docsUrl: string;
95
+ fixable: boolean;
96
+ frameworks?: string[];
97
+ }
98
+ interface RuleContext {
99
+ filePath: string;
100
+ source: string;
101
+ ast: unknown;
102
+ config: ResolvedConfig;
103
+ report(issue: Omit<Issue, 'ruleId' | 'ruleName' | 'category' | 'severity' | 'confidence' | 'docsUrl'>): void;
104
+ }
105
+ interface Rule {
106
+ meta: RuleMeta;
107
+ create(context: RuleContext): void;
108
+ }
109
+ type RuleSeverityOverride = Severity | 'off';
110
+ interface RuleConfig {
111
+ severity?: RuleSeverityOverride;
112
+ options?: Record<string, unknown>;
113
+ }
114
+ interface UserConfig {
115
+ /** Glob patterns of files to include (default: all JS/TS files) */
116
+ include?: string[];
117
+ /** Glob patterns of files to exclude */
118
+ exclude?: string[];
119
+ /** Rule category toggles */
120
+ categories?: Record<RuleCategory, boolean>;
121
+ /** Per-rule overrides */
122
+ rules?: Record<string, RuleSeverityOverride | RuleConfig>;
123
+ /** Threshold below which the process exits non-zero */
124
+ failThreshold?: number;
125
+ /** Maximum issues of each severity before failing */
126
+ maxIssues?: Partial<Record<Severity, number>>;
127
+ /** Plugins to load */
128
+ plugins?: string[];
129
+ /** Output reporter */
130
+ reporter?: 'text' | 'json' | 'html' | 'markdown' | 'sarif';
131
+ /** Output file for reports */
132
+ output?: string;
133
+ /** Whether to enable verbose output */
134
+ verbose?: boolean;
135
+ /** Ignore patterns (in addition to .gitignore) */
136
+ ignorePatterns?: string[];
137
+ /** TypeScript project file */
138
+ tsConfigPath?: string;
139
+ }
140
+ type ResolvedConfig = Required<Omit<UserConfig, 'output' | 'tsConfigPath'>> & {
141
+ output: string | null;
142
+ tsConfigPath: string | null;
143
+ root: string;
144
+ version: string;
145
+ };
146
+ interface Plugin {
147
+ name: string;
148
+ version: string;
149
+ rules: Rule[];
150
+ }
151
+ interface Reporter {
152
+ name: string;
153
+ generate(result: ScanResult): string;
154
+ }
155
+ type Language = 'javascript' | 'typescript' | 'jsx' | 'tsx';
156
+ interface ParsedFile {
157
+ filePath: string;
158
+ source: string;
159
+ ast: unknown;
160
+ language: Language;
161
+ }
162
+
163
+ declare function loadConfig(cwd: string, configPath?: string): Promise<ResolvedConfig>;
164
+ declare function resolveConfig(userConfig: UserConfig, cwd: string): ResolvedConfig;
165
+ declare function generateDefaultConfig(): string;
166
+
167
+ interface ScanOptions {
168
+ config: ResolvedConfig;
169
+ onFile?: (filePath: string, index: number, total: number) => void;
170
+ onIssue?: (issue: Issue) => void;
171
+ }
172
+ declare function discoverFiles(config: ResolvedConfig): Promise<string[]>;
173
+ declare function scan(options: ScanOptions): Promise<ScanResult>;
174
+
175
+ declare class RuleEngine {
176
+ private rules;
177
+ register(rule: Rule): void;
178
+ registerAll(rules: Rule[]): void;
179
+ getRule(id: string): Rule | undefined;
180
+ getRules(): Rule[];
181
+ getRulesByCategory(category: RuleCategory): Rule[];
182
+ runOnFile(parsedFile: ParsedFile, config: ResolvedConfig): Issue[];
183
+ private resolveSeverityOverride;
184
+ }
185
+
186
+ declare const BUILT_IN_RULES: Rule[];
187
+
188
+ type ReporterName = 'text' | 'json' | 'html' | 'markdown' | 'sarif';
189
+ declare function generate(result: ScanResult, reporter?: ReporterName): string;
190
+ declare function writeReport(content: string, outputPath: string): Promise<void>;
191
+
192
+ declare class ParseError extends Error {
193
+ readonly filePath: string;
194
+ readonly cause?: unknown | undefined;
195
+ constructor(message: string, filePath: string, cause?: unknown | undefined);
196
+ }
197
+ declare function parseFile(filePath: string): Promise<ParsedFile>;
198
+ declare function parseSource(filePath: string, source: string): ParsedFile;
199
+ declare function extractSnippet(source: string, line: number, contextLines?: number): string;
200
+
201
+ declare const PACKAGE_VERSION = "1.0.0";
202
+
203
+ /**
204
+ * clean-slop - Production Readiness Engine
205
+ *
206
+ * Public JavaScript/TypeScript API.
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * import { scanDirectory, loadConfig } from 'clean-slop';
211
+ *
212
+ * const config = await loadConfig(process.cwd());
213
+ * const result = await scanDirectory(process.cwd(), config);
214
+ *
215
+ * console.log(`Score: ${result.score.overall}/100`);
216
+ * console.log(`Issues: ${result.issues.length}`);
217
+ * ```
218
+ */
219
+
220
+ /**
221
+ * Convenience: scan a directory and return the full result.
222
+ */
223
+ declare function scanDirectory(directory: string, userConfig?: UserConfig): Promise<ScanResult>;
224
+
225
+ export { BUILT_IN_RULES, type CategoryScore, type Confidence, type FileResult, type Issue, type IssueFix, type Language, type Location, ParseError, type ParsedFile, type Plugin, type Reporter, type ResolvedConfig, type Rule, type RuleCategory, type RuleContext, RuleEngine, type RuleMeta, type ScanResult, type ScanScore, type Severity, type UserConfig, discoverFiles, extractSnippet, generateDefaultConfig, generate as generateReport, loadConfig, parseFile, parseSource, resolveConfig, scan, scanDirectory, PACKAGE_VERSION as version, writeReport };