@redaksjon/brennpunkt 0.0.1

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,172 @@
1
+ # Priority Scoring
2
+
3
+ How brennpunkt calculates priority scores to identify where testing efforts will have the biggest impact.
4
+
5
+ ## The Formula
6
+
7
+ ```
8
+ priorityScore = (branchGap × branchWeight + functionGap × functionWeight + lineGap × lineWeight) × log₁₀(lines + 1)
9
+ ```
10
+
11
+ Where:
12
+ - `branchGap` = 100 - branch coverage percentage
13
+ - `functionGap` = 100 - function coverage percentage
14
+ - `lineGap` = 100 - line coverage percentage
15
+ - `lines` = total lines of code in the file
16
+
17
+ ## Default Weights
18
+
19
+ | Metric | Weight | Reason |
20
+ |--------|--------|--------|
21
+ | Branch Coverage | 0.5 (50%) | Untested branches hide conditional bugs |
22
+ | Function Coverage | 0.3 (30%) | Untested functions indicate dead code or missing tests |
23
+ | Line Coverage | 0.2 (20%) | Basic execution path; high coverage doesn't guarantee correctness |
24
+
25
+ ## Why These Weights?
26
+
27
+ ### Branch Coverage (50%)
28
+
29
+ Branches are the most important because:
30
+ - A function can execute but still have untested error paths
31
+ - Untested `if/else` and `switch` cases often hide bugs
32
+ - Edge cases and error handling live in branches
33
+
34
+ **Example**: A login function might have 100% line coverage but 50% branch coverage because the "invalid password" path was never tested.
35
+
36
+ ### Function Coverage (30%)
37
+
38
+ Untested functions indicate:
39
+ - Dead code that should be removed
40
+ - Missing feature tests
41
+ - Code paths that aren't exercised
42
+
43
+ ### Line Coverage (20%)
44
+
45
+ Line coverage is the baseline but:
46
+ - High line coverage doesn't mean the code is correct
47
+ - It only shows that lines executed, not that they work correctly
48
+ - Often inflated by simple getter/setter tests
49
+
50
+ ## Size Scaling
51
+
52
+ The `log₁₀(lines + 1)` factor means:
53
+ - Larger files with low coverage rank higher
54
+ - A 1000-line file at 50% coverage ranks higher than a 10-line file at 50%
55
+ - The logarithmic scale prevents huge files from dominating
56
+
57
+ **Example scaling**:
58
+ | Lines | Multiplier |
59
+ |-------|------------|
60
+ | 10 | 1.04 |
61
+ | 100 | 2.00 |
62
+ | 500 | 2.70 |
63
+ | 1000 | 3.00 |
64
+ | 5000 | 3.70 |
65
+
66
+ ## Example Calculations
67
+
68
+ ### File A: Large file, low coverage
69
+
70
+ ```
71
+ file: src/complex-module.ts
72
+ lines: 500
73
+ branchCoverage: 40%
74
+ functionCoverage: 60%
75
+ lineCoverage: 70%
76
+
77
+ branchGap = 100 - 40 = 60
78
+ functionGap = 100 - 60 = 40
79
+ lineGap = 100 - 70 = 30
80
+
81
+ weightedGap = (60 × 0.5) + (40 × 0.3) + (30 × 0.2)
82
+ = 30 + 12 + 6 = 48
83
+
84
+ priorityScore = 48 × log₁₀(501)
85
+ = 48 × 2.70
86
+ = 129.6
87
+ ```
88
+
89
+ ### File B: Small file, very low coverage
90
+
91
+ ```
92
+ file: src/tiny-util.ts
93
+ lines: 20
94
+ branchCoverage: 0%
95
+ functionCoverage: 0%
96
+ lineCoverage: 50%
97
+
98
+ branchGap = 100
99
+ functionGap = 100
100
+ lineGap = 50
101
+
102
+ weightedGap = (100 × 0.5) + (100 × 0.3) + (50 × 0.2)
103
+ = 50 + 30 + 10 = 90
104
+
105
+ priorityScore = 90 × log₁₀(21)
106
+ = 90 × 1.32
107
+ = 118.8
108
+ ```
109
+
110
+ Even though File B has worse coverage percentages, File A ranks higher because it's a larger file with more impact.
111
+
112
+ ## Customizing Weights
113
+
114
+ ### Prioritize Branch Coverage
115
+
116
+ When you want to focus on conditional logic:
117
+
118
+ ```bash
119
+ brennpunkt --weights 0.7,0.2,0.1
120
+ ```
121
+
122
+ Good for:
123
+ - Complex business logic
124
+ - Error handling code
125
+ - Authentication/authorization
126
+
127
+ ### Equal Weights
128
+
129
+ When all coverage types matter equally:
130
+
131
+ ```bash
132
+ brennpunkt --weights 0.33,0.33,0.34
133
+ ```
134
+
135
+ Good for:
136
+ - General code quality
137
+ - Balanced improvement
138
+
139
+ ### Prioritize Function Coverage
140
+
141
+ When you suspect dead code:
142
+
143
+ ```bash
144
+ brennpunkt --weights 0.2,0.6,0.2
145
+ ```
146
+
147
+ Good for:
148
+ - Legacy codebases
149
+ - Code cleanup projects
150
+ - Finding unused features
151
+
152
+ ## Interpreting Scores
153
+
154
+ | Score Range | Priority | Action |
155
+ |-------------|----------|--------|
156
+ | > 100 | Critical | Focus testing efforts here immediately |
157
+ | 50-100 | High | Should be addressed in next sprint |
158
+ | 20-50 | Medium | Add to tech debt backlog |
159
+ | < 20 | Low | Acceptable for now |
160
+
161
+ ## Score = 0
162
+
163
+ A score of 0 means:
164
+ - 100% coverage on all metrics, OR
165
+ - File excluded by `--min-lines` filter
166
+
167
+ ## Files Not Scored
168
+
169
+ Files are excluded from scoring if:
170
+ - They have fewer lines than `--min-lines` threshold
171
+ - They have no coverage data (not instrumented)
172
+ - They're test files or config files (depending on your coverage setup)
package/guide/usage.md ADDED
@@ -0,0 +1,249 @@
1
+ # Usage Reference
2
+
3
+ Complete CLI reference for brennpunkt.
4
+
5
+ ## Basic Syntax
6
+
7
+ ```bash
8
+ brennpunkt [coverage-path] [options]
9
+ ```
10
+
11
+ ## Arguments
12
+
13
+ ### `[coverage-path]`
14
+
15
+ Path to the lcov.info file. Optional - if not provided, brennpunkt auto-discovers the file.
16
+
17
+ **Auto-discovery locations** (searched in order):
18
+
19
+ 1. `coverage/lcov.info` - Jest, Vitest, c8
20
+ 2. `.coverage/lcov.info` - Some configurations
21
+ 3. `coverage/lcov/lcov.info` - Karma
22
+ 4. `lcov.info` - Project root
23
+ 5. `.nyc_output/lcov.info` - NYC legacy
24
+ 6. `test-results/lcov.info` - Some CI configs
25
+
26
+ ## Options
27
+
28
+ ### `-w, --weights <weights>`
29
+
30
+ Custom weights for branches, functions, and lines coverage. Must be three comma-separated numbers.
31
+
32
+ ```bash
33
+ # Default: branches=0.5, functions=0.3, lines=0.2
34
+ brennpunkt --weights 0.5,0.3,0.2
35
+
36
+ # Prioritize branch coverage heavily
37
+ brennpunkt --weights 0.7,0.2,0.1
38
+
39
+ # Equal weights
40
+ brennpunkt --weights 0.33,0.33,0.34
41
+
42
+ # Focus on function coverage
43
+ brennpunkt --weights 0.2,0.6,0.2
44
+ ```
45
+
46
+ ### `-m, --min-lines <number>`
47
+
48
+ Exclude files with fewer than N lines. Helps filter out tiny utility files.
49
+
50
+ ```bash
51
+ # Default: 10 lines
52
+ brennpunkt --min-lines 10
53
+
54
+ # Only analyze files with 50+ lines
55
+ brennpunkt --min-lines 50
56
+
57
+ # Include all files (even 1-line files)
58
+ brennpunkt --min-lines 0
59
+ ```
60
+
61
+ ### `-t, --top <number>`
62
+
63
+ Show only the top N priority files.
64
+
65
+ ```bash
66
+ # Show top 10
67
+ brennpunkt --top 10
68
+
69
+ # Show top 3
70
+ brennpunkt --top 3
71
+
72
+ # Show all files (default)
73
+ brennpunkt
74
+ ```
75
+
76
+ ### `-j, --json`
77
+
78
+ Output results as JSON instead of a formatted table.
79
+
80
+ ```bash
81
+ # JSON output
82
+ brennpunkt --json
83
+
84
+ # JSON with top 5
85
+ brennpunkt --json --top 5
86
+
87
+ # Save to file
88
+ brennpunkt --json > coverage-priority.json
89
+
90
+ # Pipe to jq
91
+ brennpunkt --json | jq '.files[0].file'
92
+ ```
93
+
94
+ ### `-c, --config <path>`
95
+
96
+ Specify a custom configuration file path.
97
+
98
+ ```bash
99
+ # Use specific config
100
+ brennpunkt --config .config/brennpunkt.yaml
101
+
102
+ # Use config in different location
103
+ brennpunkt --config ~/brennpunkt-global.yaml
104
+ ```
105
+
106
+ ### `--init-config`
107
+
108
+ Generate a default `brennpunkt.yaml` configuration file.
109
+
110
+ ```bash
111
+ # Create in current directory
112
+ brennpunkt --init-config
113
+
114
+ # Create at specific path
115
+ brennpunkt --init-config --config .config/brennpunkt.yaml
116
+ ```
117
+
118
+ ### `--check-config`
119
+
120
+ Display the resolved configuration with source tracking.
121
+
122
+ ```bash
123
+ brennpunkt --check-config
124
+ ```
125
+
126
+ Output:
127
+
128
+ ```
129
+ ================================================================================
130
+ BRENNPUNKT CONFIGURATION
131
+ ================================================================================
132
+
133
+ Config file: brennpunkt.yaml
134
+ Status: Found
135
+
136
+ RESOLVED CONFIGURATION:
137
+ --------------------------------------------------------------------------------
138
+ [config file] coveragePath : "coverage/lcov.info"
139
+ [config file] weights : "0.6,0.2,0.2"
140
+ [default] minLines : 10
141
+ [default] json : false
142
+ [config file] top : 20
143
+
144
+ ================================================================================
145
+ ```
146
+
147
+ ### `-V, --version`
148
+
149
+ Show version number.
150
+
151
+ ### `-h, --help`
152
+
153
+ Show help message.
154
+
155
+ ## Examples
156
+
157
+ ### Basic Usage
158
+
159
+ ```bash
160
+ # Analyze current project
161
+ brennpunkt
162
+
163
+ # Analyze specific file
164
+ brennpunkt path/to/lcov.info
165
+
166
+ # Show top priorities
167
+ brennpunkt --top 10
168
+ ```
169
+
170
+ ### CI/CD Usage
171
+
172
+ ```bash
173
+ # GitHub Actions / CI pipeline
174
+ npx @redaksjon/brennpunkt --top 10
175
+
176
+ # Save JSON artifact
177
+ npx @redaksjon/brennpunkt --json > coverage-priority.json
178
+ ```
179
+
180
+ ### Automation
181
+
182
+ ```bash
183
+ # Get top priority file
184
+ TOP_FILE=$(brennpunkt --json --top 1 | jq -r '.files[0].file')
185
+ echo "Focus on: $TOP_FILE"
186
+
187
+ # Check if any file has score > 100
188
+ brennpunkt --json | jq '.files[] | select(.priorityScore > 100)'
189
+
190
+ # Fail if highest priority score is too high
191
+ SCORE=$(brennpunkt --json --top 1 | jq '.files[0].priorityScore')
192
+ if (( $(echo "$SCORE > 150" | bc -l) )); then
193
+ echo "Critical coverage gap detected!"
194
+ exit 1
195
+ fi
196
+ ```
197
+
198
+ ### Combining Options
199
+
200
+ ```bash
201
+ # Full analysis with custom weights, filtered
202
+ brennpunkt --weights 0.6,0.2,0.2 --min-lines 50 --top 20
203
+
204
+ # JSON output for top priorities
205
+ brennpunkt --json --top 5 --min-lines 20
206
+ ```
207
+
208
+ ## Exit Codes
209
+
210
+ | Code | Meaning |
211
+ |------|---------|
212
+ | 0 | Success |
213
+ | 1 | Error (file not found, invalid arguments, etc.) |
214
+
215
+ ## Output Formats
216
+
217
+ ### Table Output (Default)
218
+
219
+ Human-readable formatted table with:
220
+ - Overall coverage summary
221
+ - Per-file coverage metrics
222
+ - Priority scores
223
+ - Recommended focus areas
224
+
225
+ ### JSON Output
226
+
227
+ Machine-readable format:
228
+
229
+ ```json
230
+ {
231
+ "overall": {
232
+ "lines": { "found": 1572, "hit": 1234, "coverage": 78.5 },
233
+ "functions": { "found": 190, "hit": 156, "coverage": 82.1 },
234
+ "branches": { "found": 150, "hit": 98, "coverage": 65.3 },
235
+ "fileCount": 25
236
+ },
237
+ "files": [
238
+ {
239
+ "file": "src/auth/login.ts",
240
+ "lines": { "found": 218, "hit": 98, "coverage": 45.0 },
241
+ "functions": { "found": 10, "hit": 5, "coverage": 50.0 },
242
+ "branches": { "found": 20, "hit": 7, "coverage": 35.0 },
243
+ "priorityScore": 156.32,
244
+ "uncoveredLines": 120,
245
+ "uncoveredBranches": 13
246
+ }
247
+ ]
248
+ }
249
+ ```
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@redaksjon/brennpunkt",
3
+ "version": "0.0.1",
4
+ "description": "Coverage priority analyzer - identify where to focus testing efforts",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "brennpunkt": "./dist/main.js",
9
+ "brennpunkt-mcp": "./dist/mcp/server.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "guide",
14
+ "LICENSE"
15
+ ],
16
+ "exports": {
17
+ ".": "./dist/index.js",
18
+ "./mcp": "./dist/mcp/server.js"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/redaksjon/brennpunkt.git"
23
+ },
24
+ "homepage": "https://github.com/redaksjon/brennpunkt",
25
+ "scripts": {
26
+ "build": "npm run lint && tsc --noEmit && vite build && chmod +x dist/main.js dist/mcp/server.js",
27
+ "dev": "vite",
28
+ "watch": "vite build --watch",
29
+ "test": "vitest run --coverage",
30
+ "test:coverage": "vitest run --coverage",
31
+ "lint": "eslint . --ext .ts",
32
+ "lint:fix": "eslint . --ext .ts --fix",
33
+ "clean": "rm -rf dist",
34
+ "precommit": "npm run lint && npm run test",
35
+ "prepublishOnly": "npm run clean && npm run build"
36
+ },
37
+ "keywords": [
38
+ "coverage",
39
+ "testing",
40
+ "lcov",
41
+ "analysis",
42
+ "priority",
43
+ "mcp",
44
+ "ai",
45
+ "cursor",
46
+ "claude",
47
+ "agentic"
48
+ ],
49
+ "author": "Tim O'Brien <tobrien@discursive.com>",
50
+ "license": "Apache-2.0",
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ },
54
+ "dependencies": {
55
+ "@modelcontextprotocol/sdk": "^1.25.2",
56
+ "commander": "^14.0.2",
57
+ "zod": "^4.1.12"
58
+ },
59
+ "devDependencies": {
60
+ "@eslint/eslintrc": "^3.3.1",
61
+ "@eslint/js": "^9.39.1",
62
+ "@rollup/plugin-replace": "^6.0.3",
63
+ "@swc/core": "^1.15.1",
64
+ "@types/node": "^24.10.1",
65
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
66
+ "@typescript-eslint/parser": "^8.46.4",
67
+ "@vitest/coverage-v8": "^4.0.8",
68
+ "eslint": "^9.39.1",
69
+ "eslint-plugin-import": "^2.32.0",
70
+ "globals": "^17.0.0",
71
+ "rollup-plugin-preserve-shebang": "^1.0.1",
72
+ "typescript": "^5.9.3",
73
+ "vite": "^7.2.2",
74
+ "vite-plugin-node": "^7.0.0",
75
+ "vitest": "^4.0.8"
76
+ }
77
+ }