@poleski/quality-tools 0.1.3

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @poleski/quality-tools
2
+
3
+ ## 0.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - c0b6623: Generalize CRAP coverage config, report output, workspace discovery, and mutation Stryker integration for non-CodeGraphy projects.
8
+
9
+ ## 0.1.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Extract the quality tools into a standalone package repo.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joe Soboleski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,269 @@
1
+ # @poleski/quality-tools
2
+
3
+ Portable TypeScript quality checks for project structure, complexity,
4
+ reachability, mutation, and test health.
5
+
6
+ The tools are intentionally project-agnostic. They discover packages from
7
+ `pnpm-workspace.yaml` or `package.json#workspaces`, accept explicit file/folder
8
+ targets, and read project-specific behavior from `quality.config.json`.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pnpm add -D @poleski/quality-tools
14
+ pnpm exec quality-tools init
15
+ ```
16
+
17
+ Before publish, use a local link from a host project:
18
+
19
+ ```bash
20
+ pnpm add -D link:/absolute/path/to/quality-tools
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```bash
26
+ pnpm exec quality-tools organize .
27
+ pnpm exec quality-tools boundaries . --strict
28
+ pnpm exec quality-tools reachability . --strict
29
+ pnpm exec quality-tools scrap ./tests
30
+ pnpm exec quality-tools crap ./src
31
+ pnpm exec quality-tools mutate .
32
+ pnpm exec quality-tools mutate ./src/parser.ts --force
33
+ pnpm exec quality-tools mutate -- --mutate ./src/parser.ts
34
+ ```
35
+
36
+ Targets can be the repo root, a package shorthand, a package root, a directory,
37
+ or a file. Package shorthand is resolved from workspace package names, not from
38
+ hardcoded folder names. The starter config uses `src` as a conventional default,
39
+ but the tools scope from the target path plus your configured include/exclude
40
+ globs.
41
+
42
+ ## Reports
43
+
44
+ All quality-tool artifacts use one report root:
45
+
46
+ ```json
47
+ {
48
+ "reportsDir": "reports/quality-tools"
49
+ }
50
+ ```
51
+
52
+ Current outputs:
53
+
54
+ - `reportsDir/organize/*.json` for organize baselines
55
+ - `reportsDir/scrap/*.json` for scrap baselines
56
+ - `reportsDir/crap/<target>/coverage-final.json` for CRAP coverage input
57
+ - `reportsDir/mutation/mutation.json` and `mutation.html` from Stryker
58
+ - `reportsDir/mutation/<target>/mutation.json` copied per mutation target
59
+
60
+ CRAP reads the coverage report path you configure. The starter Vitest command
61
+ writes that coverage under `reportsDir/crap/<target>/`.
62
+
63
+ ## Config
64
+
65
+ Run `quality-tools init` to create a starter `quality.config.json`.
66
+
67
+ ```json
68
+ {
69
+ "reportsDir": "reports/quality-tools",
70
+ "defaults": {
71
+ "crap": {
72
+ "coverage": {
73
+ "command": "pnpm",
74
+ "args": [
75
+ "exec",
76
+ "vitest",
77
+ "run",
78
+ "--coverage",
79
+ "--coverage.reportsDirectory",
80
+ "{repoRoot}/{reportsDir}/crap/{reportKey}"
81
+ ],
82
+ "coveragePath": "{repoRoot}/{reportsDir}/crap/{reportKey}/coverage-final.json"
83
+ },
84
+ "exclude": ["**/*.test.ts", "**/*.test.tsx", "**/*.d.ts"]
85
+ },
86
+ "mutation": {
87
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
88
+ "exclude": ["src/**/*.d.ts"]
89
+ },
90
+ "scrap": {
91
+ "include": ["tests/**/*.test.ts", "tests/**/*.test.tsx"],
92
+ "exclude": []
93
+ },
94
+ "boundaries": {
95
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
96
+ "exclude": ["src/**/*.d.ts", "**/*.test.ts", "**/*.test.tsx"],
97
+ "entrypoints": [],
98
+ "layers": []
99
+ },
100
+ "organize": {
101
+ "lowInfoNames": {
102
+ "banned": ["utils", "helpers", "misc", "common", "shared", "_shared", "lib", "index"],
103
+ "discouraged": ["types", "constants", "config", "base", "core"]
104
+ }
105
+ }
106
+ },
107
+ "packages": {}
108
+ }
109
+ ```
110
+
111
+ Package-specific config lives under `packages.<packageName>`. The package name
112
+ is the unscoped manifest name by default, so `@scope/parser` is configured as
113
+ `parser`.
114
+
115
+ ## CRAP
116
+
117
+ CRAP calculates complexity plus coverage risk and fails when a function exceeds
118
+ the threshold. The default threshold is `8`.
119
+
120
+ ```bash
121
+ pnpm exec quality-tools crap ./src
122
+ pnpm exec quality-tools crap parser --threshold 10
123
+ ```
124
+
125
+ CRAP needs Istanbul `coverage-final.json`. Configure the command and report path
126
+ for your project. Put generated coverage under `{reportsDir}` when possible so
127
+ all artifacts stay together:
128
+
129
+ ```json
130
+ {
131
+ "defaults": {
132
+ "crap": {
133
+ "coverage": {
134
+ "command": "pnpm",
135
+ "args": [
136
+ "exec",
137
+ "vitest",
138
+ "run",
139
+ "--coverage",
140
+ "--coverage.reportsDirectory",
141
+ "{repoRoot}/{reportsDir}/crap/{reportKey}"
142
+ ],
143
+ "coveragePath": "{repoRoot}/{reportsDir}/crap/{reportKey}/coverage-final.json"
144
+ }
145
+ }
146
+ },
147
+ "packages": {
148
+ "parser": {
149
+ "crap": {
150
+ "coverage": {
151
+ "command": "pnpm",
152
+ "args": [
153
+ "--filter",
154
+ "{packageJsonName}",
155
+ "exec",
156
+ "vitest",
157
+ "run",
158
+ "--coverage",
159
+ "--coverage.reportsDirectory",
160
+ "{repoRoot}/{reportsDir}/crap/{reportKey}"
161
+ ],
162
+ "coveragePath": "{repoRoot}/{reportsDir}/crap/{reportKey}/coverage-final.json"
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ Supported template values in CRAP coverage command fields:
171
+
172
+ - `{repoRoot}`
173
+ - `{packageRoot}`
174
+ - `{packageName}`
175
+ - `{packageJsonName}`
176
+ - `{reportKey}`
177
+ - `{target}` or `{targetPath}`
178
+ - `{reportsDir}`
179
+
180
+ ## Mutation
181
+
182
+ Mutation runs Stryker against the selected source target. The CLI does not run
183
+ typecheck first and does not assume any package is special.
184
+
185
+ ```bash
186
+ pnpm exec quality-tools mutate .
187
+ pnpm exec quality-tools mutate parser
188
+ pnpm exec quality-tools mutate ./src/parser.ts --force
189
+ pnpm exec quality-tools mutate -- --mutate ./src/parser.ts
190
+ ```
191
+
192
+ `mutate` requires an explicit target. Use `.` for a repo-wide run, a package
193
+ shorthand for a workspace package, or a file/folder path for a narrower run.
194
+ Bare `quality-tools mutate` is intentionally invalid so host projects can own
195
+ their own all-package wrappers. `--force` is passed through to Stryker when you
196
+ need to ignore incremental mutation state.
197
+
198
+ The CLI passes Stryker:
199
+
200
+ - the Stryker config path
201
+ - scoped mutate globs from `quality.config.json`
202
+ - an incremental file path under `reportsDir/mutation/<target>/`
203
+ - `QUALITY_TOOLS_REPORTS_DIR`, so the bundled base config writes to the shared
204
+ report root
205
+
206
+ Long mutation runs print a progress heartbeat once per minute. The bundled base
207
+ config also accepts these environment knobs:
208
+
209
+ - `QUALITY_TOOLS_STRYKER_CONCURRENCY`, default `2`
210
+ - `QUALITY_TOOLS_STRYKER_MAX_TEST_RUNNER_REUSE`, default `0`
211
+
212
+ Use a project Stryker config when you need custom Vitest wiring:
213
+
214
+ ```js
215
+ const base = require('@poleski/quality-tools/stryker.config.cjs');
216
+
217
+ module.exports = {
218
+ ...base,
219
+ vitest: {
220
+ ...base.vitest,
221
+ configFile: 'vitest.config.ts'
222
+ }
223
+ };
224
+ ```
225
+
226
+ Then reference it in `quality.config.json`:
227
+
228
+ ```json
229
+ {
230
+ "defaults": {
231
+ "mutation": {
232
+ "strykerConfig": "stryker.config.cjs",
233
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
234
+ "exclude": ["src/**/*.d.ts"]
235
+ }
236
+ }
237
+ }
238
+ ```
239
+
240
+ If `strykerConfig` is omitted, the tool looks for `stryker.config.cjs`,
241
+ `stryker.config.mjs`, `stryker.config.js`, or `stryker.conf.js` in the repo
242
+ root, then falls back to the bundled base config.
243
+
244
+ ## Other Tools
245
+
246
+ ```bash
247
+ pnpm exec quality-tools organize ./src
248
+ pnpm exec quality-tools boundaries parser --strict
249
+ pnpm exec quality-tools reachability parser --strict
250
+ pnpm exec quality-tools scrap ./tests --strict
251
+ ```
252
+
253
+ - `organize` checks directory size, depth, naming, barrels, and cohesion. Use
254
+ `--write-baseline` and `--compare <path>` for baseline workflows.
255
+ - `boundaries` checks configured layers, entrypoints, dead surfaces, and dead
256
+ ends.
257
+ - `reachability` reports dead surfaces and dead ends without boundary-layer
258
+ failures.
259
+ - `scrap` reviews test files for split pressure, repeated setup, weak
260
+ assertions, validation issues, and refactor recommendations.
261
+
262
+ ## Development
263
+
264
+ ```bash
265
+ pnpm run test
266
+ pnpm run lint
267
+ pnpm run typecheck
268
+ pnpm run build
269
+ ```