aislop 0.10.1 → 0.11.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.
@@ -123,7 +123,7 @@ const runExpoDoctor = async (context) => {
123
123
  rule: "expo-doctor/config-error",
124
124
  severity: "warning",
125
125
  message: configError,
126
- help: "Install project dependencies, then re-run `npx aislop scan`.",
126
+ help: "Install project dependencies, then re-run `aislop scan`.",
127
127
  line: 0,
128
128
  column: 0,
129
129
  category: "Expo",
@@ -124,7 +124,7 @@ const runExpoDoctor = async (context) => {
124
124
  rule: "expo-doctor/config-error",
125
125
  severity: "warning",
126
126
  message: configError,
127
- help: "Install project dependencies, then re-run `npx aislop scan`.",
127
+ help: "Install project dependencies, then re-run `aislop scan`.",
128
128
  line: 0,
129
129
  column: 0,
130
130
  category: "Expo",
@@ -0,0 +1,149 @@
1
+ //#region src/output/engine-info.ts
2
+ const ENGINE_INFO = {
3
+ format: {
4
+ label: "Formatting",
5
+ description: "Whitespace, indentation, line wrapping, and import ordering"
6
+ },
7
+ lint: {
8
+ label: "Linting",
9
+ description: "Static analysis for likely bugs and bad patterns"
10
+ },
11
+ "code-quality": {
12
+ label: "Code Quality",
13
+ description: "Complexity limits, dead code detection, and duplication checks"
14
+ },
15
+ "ai-slop": {
16
+ label: "AI Slop",
17
+ description: "Narrative comments, dead patterns, unsafe type casts, TODO stubs, generic names"
18
+ },
19
+ architecture: {
20
+ label: "Architecture",
21
+ description: "Project-specific import and layering rules"
22
+ },
23
+ security: {
24
+ label: "Security",
25
+ description: "Secret leaks, risky APIs, and dependency vulnerabilities"
26
+ }
27
+ };
28
+ const getEngineLabel = (engine) => ENGINE_INFO[engine].label;
29
+
30
+ //#endregion
31
+ //#region src/output/finding-assessment.ts
32
+ const KNIP_FORCE_RULES = new Set([
33
+ "knip/files",
34
+ "knip/dependencies",
35
+ "knip/devDependencies"
36
+ ]);
37
+ const isForceFixable = (diagnostic) => {
38
+ if (diagnostic.fixable) return false;
39
+ if (KNIP_FORCE_RULES.has(diagnostic.rule)) return true;
40
+ if (diagnostic.rule === "security/vulnerable-dependency") return diagnostic.detail === "npm" || diagnostic.detail === "pnpm";
41
+ if (diagnostic.rule.startsWith("expo-doctor/")) return diagnostic.rule !== "expo-doctor/config-error";
42
+ return false;
43
+ };
44
+ const FINDING_KIND_LABELS = {
45
+ "confirmed-defect": "confirmed defects",
46
+ "conservative-security": "conservative security",
47
+ "style-policy": "style/policy",
48
+ "ai-slop-indicator": "AI-slop indicators"
49
+ };
50
+ const STYLE_POLICY_RULES = new Set([
51
+ "ai-slop/trivial-comment",
52
+ "ai-slop/narrative-comment",
53
+ "ai-slop/meta-comment",
54
+ "ai-slop/console-leftover",
55
+ "ai-slop/ts-directive",
56
+ "complexity/file-too-large",
57
+ "complexity/function-too-long",
58
+ "complexity/deep-nesting",
59
+ "complexity/too-many-params",
60
+ "code-quality/duplicate-block",
61
+ "eslint/no-empty",
62
+ "eslint/no-unused-vars",
63
+ "eslint/no-useless-escape",
64
+ "eslint/no-unused-expressions",
65
+ "unicorn/no-useless-fallback-in-spread",
66
+ "unicorn/prefer-string-starts-ends-with",
67
+ "unicorn/no-new-array",
68
+ "unicorn/no-useless-spread"
69
+ ]);
70
+ const CONFIRMED_DEFECT_RULES = new Set([
71
+ "ai-slop/hallucinated-import",
72
+ "eslint/no-undef",
73
+ "eslint/no-unreachable",
74
+ "security/vulnerable-dependency"
75
+ ]);
76
+ const LOW_CONFIDENCE_SECURITY_RULES = new Set(["security/innerhtml", "security/dangerously-set-innerhtml"]);
77
+ const confidenceFor = (diagnostic, kind) => {
78
+ if (kind === "confirmed-defect") return "high";
79
+ if (kind === "style-policy") return "medium";
80
+ if (kind === "conservative-security") {
81
+ if (LOW_CONFIDENCE_SECURITY_RULES.has(diagnostic.rule)) return "medium";
82
+ return diagnostic.severity === "error" ? "high" : "medium";
83
+ }
84
+ return diagnostic.severity === "error" ? "high" : "medium";
85
+ };
86
+ const classifyKind = (diagnostic) => {
87
+ if (CONFIRMED_DEFECT_RULES.has(diagnostic.rule)) return "confirmed-defect";
88
+ if (diagnostic.engine === "security") return "conservative-security";
89
+ if (STYLE_POLICY_RULES.has(diagnostic.rule)) return "style-policy";
90
+ if (diagnostic.engine === "format" || diagnostic.engine === "code-quality") return "style-policy";
91
+ if (diagnostic.engine === "ai-slop") return "ai-slop-indicator";
92
+ if (diagnostic.severity === "error") return "confirmed-defect";
93
+ return "style-policy";
94
+ };
95
+ const assessDiagnostic = (diagnostic) => {
96
+ const kind = classifyKind(diagnostic);
97
+ return {
98
+ kind,
99
+ confidence: confidenceFor(diagnostic, kind),
100
+ label: FINDING_KIND_LABELS[kind]
101
+ };
102
+ };
103
+ const withFindingAssessments = (diagnostics) => diagnostics.map((diagnostic) => ({
104
+ ...diagnostic,
105
+ assessment: assessDiagnostic(diagnostic),
106
+ forceFixable: isForceFixable(diagnostic)
107
+ }));
108
+ const summarizeFindingAssessments = (diagnostics) => {
109
+ const byKind = {
110
+ "confirmed-defect": 0,
111
+ "conservative-security": 0,
112
+ "style-policy": 0,
113
+ "ai-slop-indicator": 0
114
+ };
115
+ const byConfidence = {
116
+ high: 0,
117
+ medium: 0,
118
+ low: 0
119
+ };
120
+ const rows = /* @__PURE__ */ new Map();
121
+ for (const diagnostic of diagnostics) {
122
+ const assessment = assessDiagnostic(diagnostic);
123
+ byKind[assessment.kind]++;
124
+ byConfidence[assessment.confidence]++;
125
+ const row = rows.get(assessment.kind) ?? {
126
+ kind: assessment.kind,
127
+ label: assessment.label,
128
+ count: 0,
129
+ errors: 0,
130
+ warnings: 0,
131
+ info: 0,
132
+ fixable: 0
133
+ };
134
+ row.count++;
135
+ if (diagnostic.severity === "error") row.errors++;
136
+ else if (diagnostic.severity === "warning") row.warnings++;
137
+ else row.info++;
138
+ if (diagnostic.fixable) row.fixable++;
139
+ rows.set(assessment.kind, row);
140
+ }
141
+ return {
142
+ rows: [...rows.values()].sort((a, b) => b.count - a.count),
143
+ byKind,
144
+ byConfidence
145
+ };
146
+ };
147
+
148
+ //#endregion
149
+ export { getEngineLabel as i, withFindingAssessments as n, ENGINE_INFO as r, summarizeFindingAssessments as t };
package/dist/index.d.ts CHANGED
@@ -52,6 +52,7 @@ declare const AislopConfigSchema: z.ZodObject<{
52
52
  ok: z.ZodDefault<z.ZodNumber>;
53
53
  }, z.core.$strip>>;
54
54
  smoothing: z.ZodDefault<z.ZodNumber>;
55
+ maxPerRule: z.ZodDefault<z.ZodNumber>;
55
56
  }, z.core.$strip>>;
56
57
  ci: z.ZodDefault<z.ZodObject<{
57
58
  failBelow: z.ZodDefault<z.ZodNumber>;
@@ -87,6 +88,8 @@ interface RailStep {
87
88
  interface FixOptions {
88
89
  verbose: boolean;
89
90
  force?: boolean;
91
+ /** Restrict to reversible fixes only (imports, comment removal, formatting) */
92
+ safe?: boolean;
90
93
  /** Agent CLI to launch with remaining issues (e.g. "claude", "codex") */
91
94
  agent?: string;
92
95
  /** Print the prompt to stdout instead of launching an agent */
@@ -121,25 +124,38 @@ interface BuildRulesRenderInput {
121
124
  rules: RuleEntry[];
122
125
  invocation?: string;
123
126
  printBrand?: boolean;
127
+ includeHeader?: boolean;
124
128
  }
125
129
  declare const buildRulesRender: (input: BuildRulesRenderInput) => string;
130
+ declare const buildRuleDetailRender: (rule: RuleEntry, input?: {
131
+ printBrand?: boolean;
132
+ includeHeader?: boolean;
133
+ }) => string;
126
134
  interface RulesOptions {
127
135
  printBrand?: boolean;
136
+ interactive?: boolean;
128
137
  }
129
138
  declare const rulesCommand: (directory: string, options?: RulesOptions) => Promise<void>;
130
139
  //#endregion
131
140
  //#region src/utils/discover.d.ts
132
141
  type Language = "typescript" | "javascript" | "python" | "go" | "rust" | "java" | "ruby" | "php";
133
142
  type Framework = "nextjs" | "react" | "vite" | "remix" | "expo" | "astro" | "django" | "flask" | "fastapi" | "none";
143
+ interface Coverage {
144
+ supportedFiles: number;
145
+ unsupportedFiles: number;
146
+ dominantUnsupported: string | null;
147
+ scoreable: boolean;
148
+ }
134
149
  interface ProjectInfo {
135
150
  rootDirectory: string;
136
151
  projectName: string;
137
152
  languages: Language[];
138
153
  frameworks: Framework[];
139
154
  sourceFileCount: number;
155
+ coverage: Coverage;
140
156
  installedTools: Record<string, boolean>;
141
157
  }
142
- declare const discoverProject: (directory: string) => Promise<ProjectInfo>;
158
+ declare const discoverProject: (directory: string, excludePatterns?: string[]) => Promise<ProjectInfo>;
143
159
  //#endregion
144
160
  //#region src/engines/types.d.ts
145
161
  type Severity = "error" | "warning" | "info";
@@ -169,6 +185,7 @@ interface EngineResult {
169
185
  interface ScanOptions {
170
186
  changes: boolean;
171
187
  staged: boolean;
188
+ base?: string;
172
189
  verbose: boolean;
173
190
  json: boolean;
174
191
  sarif?: boolean;
@@ -191,6 +208,6 @@ interface ScoreResult {
191
208
  declare const calculateScore: (diagnostics: Diagnostic[], weights: Record<string, number>, thresholds: {
192
209
  good: number;
193
210
  ok: number;
194
- }, sourceFileCount?: number, smoothing?: number) => ScoreResult;
211
+ }, sourceFileCount?: number, smoothing?: number, maxPerRule?: number) => ScoreResult;
195
212
  //#endregion
196
- export { type AislopConfig, type Diagnostic, type EngineName, type EngineResult, type Framework, type Language, type ProjectInfo, type ScoreResult, type Severity, buildDoctorRender, buildInitSuccessRender, buildRulesRender, calculateScore, discoverProject, doctorCommand, fixCommand, initCommand, loadConfig, rulesCommand, scanCommand };
213
+ export { type AislopConfig, type Diagnostic, type EngineName, type EngineResult, type Framework, type Language, type ProjectInfo, type ScoreResult, type Severity, buildDoctorRender, buildInitSuccessRender, buildRuleDetailRender, buildRulesRender, calculateScore, discoverProject, doctorCommand, fixCommand, initCommand, loadConfig, rulesCommand, scanCommand };