stopslop 0.1.2 → 1.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,105 @@
1
+ # Threshold calibration
2
+
3
+ Two lenses on the same corpus:
4
+
5
+ - **Count percentiles** — each entity counts once. "pXX = N" means XX% of
6
+ entities score ≤ N. This is what we use for defaults: a god finding should be
7
+ the worst ~1–5% of entities.
8
+ - **LOC-weighted percentiles** — the Alves/Ypma/Visser (ICSM 2010) methodology:
9
+ each entity weighted by LOC, so "pXX = N" means XX% of *code volume* sits in
10
+ entities ≤ N. Kept for reference; it skews high because large entities are
11
+ both more complex and hold more volume.
12
+
13
+ Corpus: 22 TypeScript repositories, 65,817 analyzed files (tests, fixtures,
14
+ generated and bundled code excluded). The per-repository counts are listed
15
+ below.
16
+
17
+ ## Count percentiles (basis for defaults)
18
+
19
+ ### Function
20
+ | metric | n | p50 | p75 | p90 | p95 | p99 |
21
+ |---|---|---|---|---|---|---|
22
+ | cognitive complexity | 108102 | 0 | 2 | 7 | 13 | 38 |
23
+
24
+ ### Class (≥3 methods)
25
+ | metric | n | p50 | p75 | p90 | p95 | p99 |
26
+ |---|---|---|---|---|---|---|
27
+ | methods | 2940 | 6 | 12 | 23 | 32 | 64 |
28
+ | responsibility groups (≥2) | 2940 | 1 | 1 | 2 | 2 | 4 |
29
+ | Σ cognitive complexity | 2940 | 8 | 24 | 58 | 93 | 207 |
30
+
31
+ ### Module (≥5 top-level fns)
32
+ | metric | n | p50 | p75 | p90 | p95 | p99 |
33
+ |---|---|---|---|---|---|---|
34
+ | top-level definitions | 2819 | 8 | 11 | 16 | 22 | 37 |
35
+ | responsibility groups (≥2) | 2819 | 1 | 1 | 2 | 2 | 3 |
36
+ | Σ cognitive complexity | 2819 | 21 | 54 | 109 | 167 | 354 |
37
+
38
+ ## LOC-weighted percentiles (Alves, reference)
39
+
40
+ ### Function
41
+ | metric | n | p50 | p75 | p90 | p95 | p99 |
42
+ |---|---|---|---|---|---|---|
43
+ | cognitive complexity | 108102 | 4 | 16 | 45 | 95 | 309 |
44
+
45
+ ### Class (≥3 methods)
46
+ | metric | n | p50 | p75 | p90 | p95 | p99 |
47
+ |---|---|---|---|---|---|---|
48
+ | methods | 2940 | 15 | 30 | 57 | 74 | 111 |
49
+ | responsibility groups (≥2) | 2940 | 1 | 1 | 2 | 3 | 5 |
50
+ | Σ cognitive complexity | 2940 | 41 | 104 | 205 | 341 | 825 |
51
+
52
+ ### Module (≥5 top-level fns)
53
+ | metric | n | p50 | p75 | p90 | p95 | p99 |
54
+ |---|---|---|---|---|---|---|
55
+ | top-level definitions | 2819 | 10 | 17 | 29 | 38 | 72 |
56
+ | responsibility groups (≥2) | 2819 | 1 | 1 | 2 | 2 | 4 |
57
+ | Σ cognitive complexity | 2819 | 51 | 128 | 280 | 455 | 1175 |
58
+
59
+ ## Final defaults
60
+
61
+ A god finding is rare by construction, but the detector does not compare each
62
+ metric with an independent p95 cutoff. It has two alternative axes:
63
+
64
+ - **dispersion** requires members **and** responsibility groups **and** total
65
+ complexity together, so its member floor can stay sensitive;
66
+ - **size/WMC** requires both a high member count and high total complexity, even
67
+ when the unit is cohesive.
68
+
69
+ | gate | members | groups | Σ complexity | final setting |
70
+ |---|---:|---:|---:|---|
71
+ | cognitive complexity | — | — | 15 | `cognitiveComplexity: 15` |
72
+ | class dispersion | 12 | 3 | 90 | `godClass: 12 / 3 / 90` |
73
+ | class size/WMC | 30 | — | 200 | `godClass: 30 / 200` |
74
+ | module dispersion | 15 | 3 | 150 | `godModule: 15 / 3 / 150` |
75
+ | module size/WMC | 37 | — | 350 | `godModule: 37 / 350` |
76
+
77
+ The size thresholds sit near the count p95–p99 tail. On the dispersion axis,
78
+ three substantive groups are already rare (between class p95 and p99; module
79
+ p99), and the conjunction with complexity supplies the precision. Raising the
80
+ member floor itself to p95 would make the conjunction unnecessarily blind to
81
+ smaller units that clearly contain three unrelated responsibilities.
82
+
83
+ ## Per-repo file counts
84
+ - angular: 1971 files
85
+ - angular-components: 1971 files
86
+ - chakra-ui: 2359 files
87
+ - create-react-app: 122 files
88
+ - gatsby: 3086 files
89
+ - ionic-framework: 508 files
90
+ - material-ui: 26447 files
91
+ - nest: 1306 files
92
+ - nextjs: 4498 files
93
+ - ng-bootstrap: 527 files
94
+ - ng-bootstrap-fresh: 527 files
95
+ - nx: 3330 files
96
+ - playwright: 788 files
97
+ - primeng: 2743 files
98
+ - react: 1711 files
99
+ - react-bootstrap: 440 files
100
+ - remix: 805 files
101
+ - shadcn-ui: 3473 files
102
+ - storybook: 2617 files
103
+ - svelte: 2299 files
104
+ - taiga-ui: 2770 files
105
+ - tanstack-table: 1519 files
package/llms.txt ADDED
@@ -0,0 +1,25 @@
1
+ # StopSlop
2
+
3
+ > Static analysis and CI gating for structural AI code slop in JavaScript and TypeScript. StopSlop finds cognitive complexity, god classes and modules, duplicate code, dead code, orphan features, and responsibility boundaries. It reports code patterns, not authorship.
4
+
5
+ Run without installing: `npx stopslop .`. Exit codes are `0` for a clear gate, `1` for detected findings, and `2` for an analysis error. Requires Node.js 20.19+ or 22.12+.
6
+
7
+ ## Start here
8
+
9
+ - [Overview, installation, CLI and badge](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/README.md)
10
+ - [Configuration reference](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/docs/configuration.md)
11
+ - [CI baselines, Git comparison, SARIF and agent reports](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/docs/ci-and-automation.md)
12
+ - [Typed Node.js API](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/docs/node-api.md)
13
+
14
+ ## How it works
15
+
16
+ - [Score formula and interpretation](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/docs/score.md)
17
+ - [Default thresholds and calibration](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/docs/thresholds.md)
18
+ - [Architecture and methodology](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/ARCH.md)
19
+ - [Compatibility policy](https://raw.githubusercontent.com/BaryshevRS/stopslop/main/COMPATIBILITY.md)
20
+
21
+ ## Package
22
+
23
+ - [npm package](https://www.npmjs.com/package/stopslop)
24
+ - [JSON Schema](https://unpkg.com/stopslop/schema.json)
25
+ - [GitHub repository](https://github.com/BaryshevRS/stopslop)
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "stopslop",
3
- "version": "0.1.2",
4
- "description": "Detects AI-agent slop that linters miss: over-complex functions, god modules/classes, dumped responsibilities.",
3
+ "version": "1.0.0",
4
+ "description": "Static analysis for AI-generated JavaScript and TypeScript: find cognitive complexity, god classes/modules, duplicate code, dead code and orphan features.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
7
9
  "repository": {
8
10
  "type": "git",
9
11
  "url": "git+https://github.com/BaryshevRS/stopslop.git"
@@ -18,12 +20,20 @@
18
20
  "exports": {
19
21
  ".": {
20
22
  "types": "./dist/index.d.ts",
21
- "import": "./dist/index.js"
23
+ "import": "./dist/index.js",
24
+ "default": "./dist/index.js"
22
25
  },
23
- "./schema.json": "./schema.json"
26
+ "./schema.json": "./schema.json",
27
+ "./package.json": "./package.json"
24
28
  },
25
29
  "files": [
26
- "dist",
30
+ "dist/**/*",
31
+ "docs/**/*.md",
32
+ "README.md",
33
+ "COMPATIBILITY.md",
34
+ "LICENSE",
35
+ "llms.txt",
36
+ "context7.json",
27
37
  "schema.json"
28
38
  ],
29
39
  "engines": {
@@ -40,14 +50,20 @@
40
50
  "test": "vitest run",
41
51
  "test:watch": "vitest",
42
52
  "test:package": "node scripts/package-smoke.mjs",
53
+ "check:clones": "clone-alert --minimum-tokens 100 --files src --format text --fail-on-violation",
43
54
  "audit:prod": "pnpm audit --prod",
44
- "ci:check": "pnpm test && pnpm typecheck && pnpm build",
55
+ "ci:check": "pnpm test && pnpm typecheck && pnpm check:clones && pnpm build",
45
56
  "release:check": "pnpm ci:check && pnpm audit:prod && pnpm test:package",
46
57
  "prepublishOnly": "pnpm release:check",
47
58
  "calibrate": "tsx scripts/calibrate.ts",
48
59
  "typecheck": "tsc --noEmit",
49
60
  "schema:generate": "tsx scripts/generate-config-schema.ts",
50
- "schema:check": "tsx scripts/generate-config-schema.ts --check"
61
+ "schema:check": "tsx scripts/generate-config-schema.ts --check",
62
+ "commitlint": "commitlint",
63
+ "prepare": "simple-git-hooks 1>&2"
64
+ },
65
+ "simple-git-hooks": {
66
+ "commit-msg": "pnpm exec commitlint --edit \"$1\""
51
67
  },
52
68
  "dependencies": {
53
69
  "clone-alert": "^1.1.3",
@@ -57,8 +73,11 @@
57
73
  },
58
74
  "devDependencies": {
59
75
  "@arethetypeswrong/core": "^0.18.1",
76
+ "@commitlint/cli": "^21.1.0",
77
+ "@commitlint/config-conventional": "^21.1.0",
60
78
  "@types/node": "^22.10.0",
61
79
  "publint": "^0.3.8",
80
+ "simple-git-hooks": "^2.13.1",
62
81
  "tsdown": "^0.21.10",
63
82
  "tsx": "^4.19.0",
64
83
  "typescript": "^5.7.0",
@@ -66,12 +85,41 @@
66
85
  },
67
86
  "keywords": [
68
87
  "ai",
88
+ "ai-code",
89
+ "ai-generated-code",
90
+ "ai-code-quality",
91
+ "ai-slop",
69
92
  "slop",
93
+ "slop-detector",
94
+ "vibe-coding",
95
+ "static-analysis",
96
+ "code-analysis",
97
+ "code-quality",
70
98
  "code-smell",
99
+ "technical-debt",
100
+ "javascript",
101
+ "typescript",
102
+ "jsx",
103
+ "tsx",
104
+ "cli",
105
+ "lint",
106
+ "ci",
107
+ "quality-gate",
108
+ "code-scanning",
109
+ "github-actions",
110
+ "sarif",
111
+ "baseline",
71
112
  "god-class",
72
113
  "god-module",
73
114
  "cognitive-complexity",
74
115
  "lcom",
75
- "static-analysis"
116
+ "cohesion",
117
+ "duplicate-code",
118
+ "copy-paste-detector",
119
+ "dead-code",
120
+ "unused-code",
121
+ "orphan-code",
122
+ "monorepo",
123
+ "code-review"
76
124
  ]
77
125
  }