CredentialDetectionRunner.java

1
package org.egothor.methodatlas.command;
2
3
import java.io.IOException;
4
import java.io.PrintWriter;
5
import java.nio.charset.StandardCharsets;
6
import java.nio.file.Files;
7
import java.nio.file.Path;
8
import java.util.ArrayList;
9
import java.util.LinkedHashMap;
10
import java.util.List;
11
import java.util.Map;
12
import java.util.Objects;
13
import java.util.Optional;
14
import java.util.logging.Level;
15
import java.util.logging.Logger;
16
import java.util.stream.Collectors;
17
import java.util.stream.IntStream;
18
19
import org.egothor.methodatlas.CliConfig;
20
import org.egothor.methodatlas.ai.AiSuggestionEngine;
21
import org.egothor.methodatlas.ai.AiSuggestionException;
22
import org.egothor.methodatlas.ai.PromptBuilder;
23
import org.egothor.methodatlas.ai.CredentialTriageVerdict;
24
import org.egothor.methodatlas.api.DiscoveredMethod;
25
import org.egothor.methodatlas.api.CredentialCandidate;
26
import org.egothor.methodatlas.api.CredentialDetector;
27
import org.egothor.methodatlas.api.CredentialDetectorConfig;
28
import org.egothor.methodatlas.api.CredentialScanUnit;
29
import org.egothor.methodatlas.api.TestDiscovery;
30
import org.egothor.methodatlas.api.TestDiscoveryConfig;
31
import org.egothor.methodatlas.emit.SarifEmitter;
32
import org.egothor.methodatlas.emit.CredentialCsvEmitter;
33
import org.egothor.methodatlas.emit.CredentialFinding;
34
import org.egothor.methodatlas.emit.CredentialMasker;
35
36
/**
37
 * Shared orchestration for the {@code -detect-secrets} feature.
38
 *
39
 * <p>
40
 * Two triage strategies are supported, both producing the same outputs (log,
41
 * secrets CSV, and — in SARIF mode — secret results embedded in the document):
42
 * </p>
43
 * <ul>
44
 *   <li><b>Folded</b> (default scope with AI enabled): the command runs detection
45
 *       up-front via {@link #detect(List)}, hands the resulting
46
 *       {@link CredentialTriageContext} to the scan so each per-class classification
47
 *       call <em>also</em> triages that class's candidates — the class source is
48
 *       sent to the provider once. The command then calls
49
 *       {@link #applyFoldedVerdicts(List, Map)} and {@link #emitFindings}.</li>
50
 *   <li><b>Separate</b> ({@link #run(List, SarifEmitter)}): used with no AI, or
51
 *       with a {@code -secrets-include} glob (which scans files outside the
52
 *       discovered classes). Detection is followed by an optional dedicated triage
53
 *       call per file.</li>
54
 * </ul>
55
 *
56
 * <p>
57
 * The deterministic detection itself never calls AI; a failed triage degrades to
58
 * unverified candidates.
59
 * </p>
60
 *
61
 * @since 4.1.0
62
 */
63
final class CredentialDetectionRunner {
64
65
    private static final Logger LOG = Logger.getLogger(CredentialDetectionRunner.class.getName());
66
67
    /** Default Shannon-entropy floor handed to the detectors. */
68
    private static final double DEFAULT_ENTROPY = 4.0;
69
70
    /** Extension appended when deriving a SARIF artifact URI from an FQCN. */
71
    private static final String JAVA_EXTENSION = ".java";
72
73
    /** Grouping key used for findings that carry no fully qualified class name. */
74
    private static final String NO_FQCN = "";
75
76
    private final CliConfig cfg;
77
    private final TestDiscoveryConfig discoveryConfig;
78
    private final PluginLoader pluginLoader;
79
    private final ScanOrchestrator orchestrator;
80
    private final AiSuggestionEngine aiEngine;
81
    /** Redaction service applied to every source before triage when {@code -redact-comments} is set. */
82
    private final CommentRedaction redaction;
83
84
    /** Whether triage is folded into the scan's classification call (set by {@link #prepare}). */
85
    private boolean folded;
86
    /** Up-front detection result captured by {@link #prepare} for the folded path. */
87
    private DetectionResult preparedDetection;
88
    /** Triage context handed to the scan in the folded path. */
89
    private CredentialTriageContext preparedContext;
90
91
    /**
92
     * Creates a runner.
93
     *
94
     * @param cfg             parsed CLI configuration; never {@code null}
95
     * @param discoveryConfig discovery configuration used to enumerate test classes
96
     *                        and build the attribution index; never {@code null}
97
     * @param pluginLoader    loader used to resolve discovery providers and secret
98
     *                        detectors; never {@code null}
99
     * @param orchestrator    orchestrator used to group discovered methods by file;
100
     *                        never {@code null}
101
     * @param aiEngine        AI engine used for triage, or {@code null} when AI is
102
     *                        disabled (deterministic candidates are still emitted)
103
     */
104
    /* default */ CredentialDetectionRunner(CliConfig cfg, TestDiscoveryConfig discoveryConfig,
105
            PluginLoader pluginLoader, ScanOrchestrator orchestrator, AiSuggestionEngine aiEngine) {
106
        this.cfg = cfg;
107
        this.discoveryConfig = discoveryConfig;
108
        this.pluginLoader = pluginLoader;
109
        this.orchestrator = orchestrator;
110
        this.aiEngine = aiEngine;
111
        this.redaction = orchestrator.redaction();
112
    }
113
114
    /**
115
     * Deterministic detection result, plus the per-class candidate spans needed to
116
     * fold triage into the scan and the per-file source used for separate triage.
117
     *
118
     * <p>
119
     * When {@code -redact-comments} is active, {@code sourceByFile} holds the
120
     * <em>redacted</em> text and {@code candidatesByFqcn} omits candidates located
121
     * inside comments; {@code findings} always lists every candidate, because the
122
     * local report never leaves the machine.
123
     * </p>
124
     *
125
     * @param findings         all deterministic findings (triage fields {@code null})
126
     * @param candidatesByFqcn AI-triage candidate spans per class, in finding order;
127
     *                         indices refer to the position within the class's findings
128
     * @param refsByFile       AI-triage candidate refs per file for the separate-call path,
129
     *                         indices being positions within the file's findings
130
     * @param sourceByFile     file source text sent for separate-call triage
131
     *                         (redacted when {@code -redact-comments} is on)
132
     * @since 4.1.0
133
     */
134
    /* default */ record DetectionResult(List<CredentialFinding> findings,
135
            Map<String, List<PromptBuilder.CredentialCandidateRef>> candidatesByFqcn,
136
            Map<Path, List<PromptBuilder.CredentialCandidateRef>> refsByFile,
137
            Map<Path, String> sourceByFile) {
138
    }
139
140
    // ---------------------------------------------------------------------
141
    // Command-facing lifecycle (folded or separate, decided here)
142
    // ---------------------------------------------------------------------
143
144
    /**
145
     * Prepares credential detection before the scan. When triage can be folded
146
     * into the per-class classification call (AI enabled, default test-class scope,
147
     * and {@code -secrets-separate-llm} not set), this runs deterministic detection
148
     * up-front and returns the {@link CredentialTriageContext} the scan must thread
149
     * through so the class source is sent to the provider once. Otherwise returns
150
     * {@code null} and {@link #finish} performs detection (and any separate triage)
151
     * after the scan.
152
     *
153
     * @param roots scan roots; never {@code null}
154
     * @return the triage context to pass to the scan, or {@code null} when not folding
155
     * @throws IOException if up-front detection fails
156
     */
157
    /* default */ CredentialTriageContext prepare(List<Path> roots) throws IOException {
158 6 1. prepare : removed conditional - replaced equality check with true → SURVIVED
2. prepare : removed conditional - replaced equality check with true → SURVIVED
3. prepare : removed conditional - replaced equality check with true → SURVIVED
4. prepare : removed conditional - replaced equality check with false → KILLED
5. prepare : removed conditional - replaced equality check with false → KILLED
6. prepare : removed conditional - replaced equality check with false → KILLED
        this.folded = aiEngine != null && cfg.secretsInclude() == null && !cfg.secretsSeparateLlm();
159 2 1. prepare : removed conditional - replaced equality check with true → SURVIVED
2. prepare : removed conditional - replaced equality check with false → KILLED
        if (folded) {
160
            this.preparedDetection = detect(roots);
161
            this.preparedContext = toContext(preparedDetection);
162 1 1. prepare : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::prepare → KILLED
            return preparedContext;
163
        }
164
        return null;
165
    }
166
167
    /**
168
     * Completes credential detection after the scan: in the folded path it merges
169
     * the verdicts the scan collected and emits; otherwise it runs detection plus
170
     * optional separate-call triage and emits.
171
     *
172
     * @param roots        scan roots; never {@code null}
173
     * @param sarifEmitter SARIF emitter to record findings into, or {@code null}
174
     * @throws IOException if collecting files or writing the CSV fails
175
     */
176
    /* default */ void finish(List<Path> roots, SarifEmitter sarifEmitter) throws IOException {
177 2 1. finish : removed conditional - replaced equality check with true → SURVIVED
2. finish : removed conditional - replaced equality check with false → KILLED
        if (folded) {
178
            emitFindings(applyFoldedVerdicts(preparedDetection.findings(),
179
                    preparedContext.verdictsByFqcn()), sarifEmitter);
180
        } else {
181
            run(roots, sarifEmitter);
182
        }
183
    }
184
185
    // ---------------------------------------------------------------------
186
    // Separate-call path
187
    // ---------------------------------------------------------------------
188
189
    /**
190
     * Runs detection, optional separate-call triage, and emission. Used when AI is
191
     * disabled or a {@code -secrets-include} glob is active.
192
     *
193
     * @param roots        scan roots; never {@code null}
194
     * @param sarifEmitter SARIF emitter to record findings into, or {@code null}
195
     * @throws IOException if collecting files or writing the CSV fails
196
     */
197
    /* default */ void run(List<Path> roots, SarifEmitter sarifEmitter) throws IOException {
198
        DetectionResult dr = detect(roots);
199 2 1. run : removed conditional - replaced equality check with false → SURVIVED
2. run : removed conditional - replaced equality check with true → KILLED
        List<CredentialFinding> triaged = aiEngine == null
200
                ? dr.findings()
201
                : triageSeparately(dr.findings(), dr.refsByFile(), dr.sourceByFile());
202
        emitFindings(triaged, sarifEmitter);
203
    }
204
205
    // ---------------------------------------------------------------------
206
    // Folded path (used by the command together with the scan)
207
    // ---------------------------------------------------------------------
208
209
    /**
210
     * Runs deterministic detection only, returning the findings plus the data the
211
     * folded path needs to triage during the scan.
212
     *
213
     * @param roots scan roots; never {@code null}
214
     * @return the detection result; never {@code null}
215
     * @throws IOException if collecting files fails
216
     */
217
    /* default */ DetectionResult detect(List<Path> roots) throws IOException {
218
        Map<Path, List<DiscoveredMethod>> byFile = discoverByFile(roots);
219
        Map<Path, List<DetectCredentialsStage.MethodRange>> attribution = toAttribution(byFile);
220
        List<CredentialScanUnit> units = selectUnits(roots, byFile);
221
        Map<Path, String> originalByFile = units.stream()
222 1 1. lambda$detect$0 : replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$detect$0 → NO_COVERAGE
                .collect(Collectors.toMap(CredentialScanUnit::filePath, CredentialScanUnit::source, (a, b) -> a));
223
        // Fail-closed pre-flight: redact every unit before anything is sent to the provider,
224
        // so a single unredactable file aborts the whole run with zero provider calls.
225 2 1. detect : removed conditional - replaced equality check with false → KILLED
2. detect : removed conditional - replaced equality check with true → KILLED
        Map<Path, String> redactedByFile = redactActive() ? redactAll(originalByFile) : null;
226
        List<CredentialFinding> findings = runDetectors(units, attribution);
227 2 1. detect : removed conditional - replaced equality check with true → KILLED
2. detect : removed conditional - replaced equality check with false → KILLED
        Map<Path, String> triageSource = redactedByFile != null ? redactedByFile : originalByFile;
228 1 1. detect : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::detect → KILLED
        return new DetectionResult(findings, candidatesByFqcn(findings, originalByFile, redactedByFile),
229
                refsByFile(findings, originalByFile, redactedByFile), triageSource);
230
    }
231
232
    /**
233
     * Reports whether source must be redacted before reaching the AI provider.
234
     *
235
     * @return {@code true} when an AI engine is active and {@code -redact-comments} is set
236
     */
237
    private boolean redactActive() {
238 7 1. redactActive : removed conditional - replaced equality check with true → SURVIVED
2. redactActive : removed conditional - replaced equality check with true → SURVIVED
3. redactActive : removed conditional - replaced equality check with false → KILLED
4. redactActive : removed conditional - replaced equality check with true → KILLED
5. redactActive : replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::redactActive → KILLED
6. redactActive : removed conditional - replaced equality check with false → KILLED
7. redactActive : removed conditional - replaced equality check with false → KILLED
        return aiEngine != null && cfg.aiOptions() != null && cfg.aiOptions().redactComments();
239
    }
240
241
    private Map<Path, String> redactAll(Map<Path, String> originalByFile) {
242 1 1. redactAll : Replaced integer multiplication with division → SURVIVED
        Map<Path, String> redacted = new LinkedHashMap<>(originalByFile.size() * 2);
243
        for (Map.Entry<Path, String> e : originalByFile.entrySet()) {
244
            redacted.put(e.getKey(), redaction.redactOrThrow(e.getKey(), e.getValue()));
245
        }
246 1 1. redactAll : replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::redactAll → KILLED
        return redacted;
247
    }
248
249
    /**
250
     * Decides whether a candidate lies in text that redaction blanked (a comment).
251
     *
252
     * <p>
253
     * The redacted text shares offsets with the original, so the candidate's
254
     * line/column span is mapped to offsets and the two texts are compared over it.
255
     * Any differing character puts the candidate in a comment. The check fails
256
     * closed: a span that cannot be mapped inside the text is treated as blanked.
257
     * </p>
258
     *
259
     * @param original  the original source; never {@code null}
260
     * @param redacted  the redacted source, same length as {@code original}; never {@code null}
261
     * @param candidate the candidate to test; never {@code null}
262
     * @return {@code true} when the candidate must not be sent to the AI
263
     */
264
    /* default */ static boolean overlapsBlankedText(String original, String redacted,
265
            CredentialCandidate candidate) {
266 2 1. overlapsBlankedText : removed conditional - replaced equality check with false → KILLED
2. overlapsBlankedText : removed conditional - replaced equality check with true → KILLED
        if (original.length() != redacted.length()) {
267 1 1. overlapsBlankedText : replaced boolean return with false for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED
            return true;
268
        }
269
        int start = offsetOf(original, candidate.beginLine(), candidate.beginColumn());
270
        int end;
271 5 1. overlapsBlankedText : removed conditional - replaced equality check with true → SURVIVED
2. overlapsBlankedText : removed conditional - replaced comparison check with true → SURVIVED
3. overlapsBlankedText : removed conditional - replaced comparison check with false → SURVIVED
4. overlapsBlankedText : changed conditional boundary → SURVIVED
5. overlapsBlankedText : removed conditional - replaced equality check with false → SURVIVED
        if (candidate.endColumn() == 1 && candidate.endLine() >= candidate.beginLine()) {
272
            // The detector reports the column of the offset after the match; column 1 means
273
            // the match ended exactly at a line break, i.e. at the start of the next line.
274 1 1. overlapsBlankedText : Replaced integer addition with subtraction → SURVIVED
            end = offsetOf(original, candidate.endLine() + 1, 1);
275
        } else {
276
            end = offsetOf(original, candidate.endLine(), candidate.endColumn());
277
        }
278 9 1. overlapsBlankedText : changed conditional boundary → SURVIVED
2. overlapsBlankedText : removed conditional - replaced comparison check with false → SURVIVED
3. overlapsBlankedText : changed conditional boundary → SURVIVED
4. overlapsBlankedText : removed conditional - replaced comparison check with true → SURVIVED
5. overlapsBlankedText : removed conditional - replaced comparison check with false → KILLED
6. overlapsBlankedText : removed conditional - replaced comparison check with true → KILLED
7. overlapsBlankedText : changed conditional boundary → KILLED
8. overlapsBlankedText : removed conditional - replaced comparison check with true → KILLED
9. overlapsBlankedText : removed conditional - replaced comparison check with false → KILLED
        if (start < 0 || end < start || end > original.length()) {
279 1 1. overlapsBlankedText : replaced boolean return with false for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED
            return true;
280
        }
281 7 1. overlapsBlankedText : removed conditional - replaced comparison check with true → SURVIVED
2. overlapsBlankedText : Replaced integer addition with subtraction → SURVIVED
3. overlapsBlankedText : changed conditional boundary → SURVIVED
4. overlapsBlankedText : removed conditional - replaced comparison check with false → KILLED
5. overlapsBlankedText : changed conditional boundary → KILLED
6. overlapsBlankedText : removed conditional - replaced comparison check with false → KILLED
7. overlapsBlankedText : removed conditional - replaced comparison check with true → KILLED
        for (int i = start; i < Math.max(end, start + 1) && i < original.length(); i++) {
282 2 1. overlapsBlankedText : removed conditional - replaced equality check with false → KILLED
2. overlapsBlankedText : removed conditional - replaced equality check with true → KILLED
            if (original.charAt(i) != redacted.charAt(i)) {
283 1 1. overlapsBlankedText : replaced boolean return with false for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED
                return true;
284
            }
285
        }
286 1 1. overlapsBlankedText : replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED
        return false;
287
    }
288
289
    /**
290
     * Maps a one-based line and column to a character offset, lines being split on
291
     * {@code '\n'} exactly as the detector splits them.
292
     *
293
     * @return the offset, or {@code -1} when the line does not exist
294
     */
295
    private static int offsetOf(String text, int line, int column) {
296
        int lineStart = 0;
297 3 1. offsetOf : removed conditional - replaced comparison check with true → KILLED
2. offsetOf : changed conditional boundary → KILLED
3. offsetOf : removed conditional - replaced comparison check with false → KILLED
        for (int l = 1; l < line; l++) {
298
            int nl = text.indexOf('\n', lineStart);
299 3 1. offsetOf : changed conditional boundary → SURVIVED
2. offsetOf : removed conditional - replaced comparison check with false → KILLED
3. offsetOf : removed conditional - replaced comparison check with true → KILLED
            if (nl < 0) {
300 6 1. offsetOf : removed conditional - replaced equality check with false → NO_COVERAGE
2. offsetOf : Replaced integer addition with subtraction → SURVIVED
3. offsetOf : removed conditional - replaced equality check with true → NO_COVERAGE
4. offsetOf : removed conditional - replaced equality check with true → SURVIVED
5. offsetOf : removed conditional - replaced equality check with false → SURVIVED
6. offsetOf : replaced int return with 0 for org/egothor/methodatlas/command/CredentialDetectionRunner::offsetOf → KILLED
                return line == l + 1 && column == 1 ? text.length() : -1;
301
            }
302 1 1. offsetOf : Replaced integer addition with subtraction → KILLED
            lineStart = nl + 1;
303
        }
304 3 1. offsetOf : Replaced integer subtraction with addition → KILLED
2. offsetOf : Replaced integer addition with subtraction → KILLED
3. offsetOf : replaced int return with 0 for org/egothor/methodatlas/command/CredentialDetectionRunner::offsetOf → KILLED
        return lineStart + column - 1;
305
    }
306
307
    /**
308
     * Wraps a detection result in a triage context for the scan to fill.
309
     *
310
     * @param detection the detection result; never {@code null}
311
     * @return a context carrying the per-class candidates
312
     */
313
    /* default */ CredentialTriageContext toContext(DetectionResult detection) {
314 1 1. toContext : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::toContext → KILLED
        return new CredentialTriageContext(detection.candidatesByFqcn());
315
    }
316
317
    /**
318
     * Merges the verdicts the scan collected (keyed by class) back into the
319
     * findings, by class and candidate index.
320
     *
321
     * @param findings         the deterministic findings; never {@code null}
322
     * @param verdictsByFqcn   verdicts collected during the folded scan; never {@code null}
323
     * @return findings with triage fields populated where a verdict exists
324
     */
325
    /* default */ List<CredentialFinding> applyFoldedVerdicts(List<CredentialFinding> findings,
326
            Map<String, List<CredentialTriageVerdict>> verdictsByFqcn) {
327
        List<CredentialFinding> out = new ArrayList<>(findings.size());
328
        groupByFqcn(findings).forEach((fqcn, group) -> {
329
            Map<Integer, CredentialTriageVerdict> byIndex = verdictsByFqcn.getOrDefault(fqcn, List.of()).stream()
330 2 1. lambda$applyFoldedVerdicts$2 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$applyFoldedVerdicts$2 → NO_COVERAGE
2. lambda$applyFoldedVerdicts$1 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$applyFoldedVerdicts$1 → KILLED
                    .collect(Collectors.toMap(CredentialTriageVerdict::candidateIndex, v -> v, (a, b) -> a));
331
            out.addAll(DetectCredentialsStage.mergeVerdicts(group, byIndex));
332
        });
333 1 1. applyFoldedVerdicts : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::applyFoldedVerdicts → KILLED
        return out;
334
    }
335
336
    /**
337
     * Applies the min-score filter and emits all outputs.
338
     *
339
     * @param findings     findings to emit; never {@code null}
340
     * @param sarifEmitter SARIF emitter to record findings into, or {@code null}
341
     * @throws IOException if writing the CSV fails
342
     */
343
    /* default */ void emitFindings(List<CredentialFinding> findings, SarifEmitter sarifEmitter) throws IOException {
344
        List<CredentialFinding> kept = filterByMinScore(findings);
345
        logSummary(kept);
346
        logFindings(kept);
347
        recordIntoSarif(kept, sarifEmitter);
348
        writeCsv(kept);
349
    }
350
351
    // ---------------------------------------------------------------------
352
    // Internals
353
    // ---------------------------------------------------------------------
354
355
    private Map<Path, List<DiscoveredMethod>> discoverByFile(List<Path> roots) throws IOException {
356
        List<TestDiscovery> providers = pluginLoader.loadProviders(discoveryConfig);
357
        try {
358 1 1. discoverByFile : replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::discoverByFile → KILLED
            return orchestrator.collectMethodsByFile(roots, providers);
359
        } finally {
360
            pluginLoader.closeAll(providers);
361
        }
362
    }
363
364
    private static Map<Path, List<DetectCredentialsStage.MethodRange>> toAttribution(
365
            Map<Path, List<DiscoveredMethod>> byFile) {
366
        Map<Path, List<DetectCredentialsStage.MethodRange>> attribution = new LinkedHashMap<>();
367
        byFile.forEach((file, methods) -> attribution.put(file.toAbsolutePath(), methods.stream()
368 1 1. lambda$toAttribution$4 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$toAttribution$4 → KILLED
                .map(m -> new DetectCredentialsStage.MethodRange(m.method(), m.beginLine(), m.endLine()))
369
                .toList()));
370 1 1. toAttribution : replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::toAttribution → SURVIVED
        return attribution;
371
    }
372
373
    private List<CredentialScanUnit> selectUnits(List<Path> roots,
374
            Map<Path, List<DiscoveredMethod>> byFile) {
375 2 1. selectUnits : removed conditional - replaced equality check with false → KILLED
2. selectUnits : removed conditional - replaced equality check with true → KILLED
        if (cfg.secretsInclude() != null) {
376 1 1. selectUnits : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::selectUnits → KILLED
            return new CredentialScanUnitSource(cfg.fileSuffixes(), cfg.secretsInclude()).collect(roots);
377
        }
378 1 1. selectUnits : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::selectUnits → KILLED
        return byFile.entrySet().stream()
379 1 1. lambda$selectUnits$6 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$selectUnits$6 → KILLED
                .map(entry -> toUnit(entry.getKey(), entry.getValue()))
380
                .filter(Objects::nonNull)
381
                .toList();
382
    }
383
384
    private static CredentialScanUnit toUnit(Path file, List<DiscoveredMethod> methods) {
385 2 1. toUnit : removed conditional - replaced equality check with false → SURVIVED
2. toUnit : removed conditional - replaced equality check with true → KILLED
        if (methods.isEmpty()) {
386
            return null;
387
        }
388
        Path abs = file.toAbsolutePath();
389
        try {
390
            String text = Files.readString(abs, StandardCharsets.UTF_8);
391 1 1. toUnit : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::toUnit → KILLED
            return new CredentialScanUnit(abs, methods.get(0).fqcn(), text,
392
                    CredentialScanUnitSource.languageOf(abs));
393
        } catch (IOException e) {
394
            LOG.log(Level.FINE, e, () -> "Skipping unreadable discovered file: " + abs);
395
            return null;
396
        }
397
    }
398
399
    private List<CredentialFinding> runDetectors(List<CredentialScanUnit> units,
400
            Map<Path, List<DetectCredentialsStage.MethodRange>> attribution) {
401
        CredentialDetectorConfig sdc = new CredentialDetectorConfig(
402
                DEFAULT_ENTROPY, Optional.ofNullable(cfg.secretsRules()), Map.of());
403
        List<CredentialDetector> detectors = pluginLoader.loadCredentialDetectors(sdc);
404
        try {
405 1 1. runDetectors : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::runDetectors → KILLED
            return new DetectCredentialsStage(detectors, attribution).run(units);
406
        } finally {
407
            pluginLoader.closeAllCredentialDetectors(detectors);
408
        }
409
    }
410
411
    private static Map<String, List<CredentialFinding>> groupByFqcn(List<CredentialFinding> findings) {
412 1 1. groupByFqcn : replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::groupByFqcn → KILLED
        return findings.stream().collect(Collectors.groupingBy(
413 3 1. lambda$groupByFqcn$8 : removed conditional - replaced equality check with false → SURVIVED
2. lambda$groupByFqcn$8 : replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$groupByFqcn$8 → KILLED
3. lambda$groupByFqcn$8 : removed conditional - replaced equality check with true → KILLED
                f -> f.fqcn() == null ? NO_FQCN : f.fqcn(), LinkedHashMap::new, Collectors.toList()));
414
    }
415
416
    /**
417
     * Builds the AI-triage candidate refs of one finding group. Candidate indices are
418
     * positions within the group, so verdicts still merge by index even when
419
     * comment-resident candidates (omitted here) leave gaps.
420
     *
421
     * @param group       findings of one class or file; never {@code null}
422
     * @param original    original source by absolute file path; never {@code null}
423
     * @param redacted    redacted source by path, or {@code null} when redaction is off
424
     * @return refs for the candidates that may be sent to the AI; never {@code null}
425
     */
426
    private static List<PromptBuilder.CredentialCandidateRef> refsFor(List<CredentialFinding> group,
427
            Map<Path, String> original, Map<Path, String> redacted) {
428 1 1. refsFor : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::refsFor → KILLED
        return IntStream.range(0, group.size())
429 5 1. lambda$refsFor$9 : replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$refsFor$9 → KILLED
2. lambda$refsFor$9 : removed conditional - replaced equality check with false → KILLED
3. lambda$refsFor$9 : removed conditional - replaced equality check with false → KILLED
4. lambda$refsFor$9 : removed conditional - replaced equality check with true → KILLED
5. lambda$refsFor$9 : removed conditional - replaced equality check with true → KILLED
                .filter(i -> redacted == null || !inComment(group.get(i), original, redacted))
430 1 1. lambda$refsFor$10 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$refsFor$10 → KILLED
                .mapToObj(i -> new PromptBuilder.CredentialCandidateRef(i,
431
                        group.get(i).candidate().beginLine(), group.get(i).candidate().matchedValue()))
432
                .toList();
433
    }
434
435
    private static boolean inComment(CredentialFinding finding, Map<Path, String> original,
436
            Map<Path, String> redacted) {
437
        String orig = original.get(finding.filePath());
438
        String red = redacted.get(finding.filePath());
439 7 1. inComment : removed conditional - replaced equality check with true → SURVIVED
2. inComment : removed conditional - replaced equality check with true → SURVIVED
3. inComment : removed conditional - replaced equality check with true → KILLED
4. inComment : removed conditional - replaced equality check with false → KILLED
5. inComment : removed conditional - replaced equality check with false → KILLED
6. inComment : replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::inComment → KILLED
7. inComment : removed conditional - replaced equality check with false → KILLED
        return orig == null || red == null || overlapsBlankedText(orig, red, finding.candidate());
440
    }
441
442
    private static Map<Path, List<PromptBuilder.CredentialCandidateRef>> refsByFile(
443
            List<CredentialFinding> findings, Map<Path, String> original, Map<Path, String> redacted) {
444
        Map<Path, List<CredentialFinding>> byFile = findings.stream().collect(
445
                Collectors.groupingBy(CredentialFinding::filePath, LinkedHashMap::new, Collectors.toList()));
446
        Map<Path, List<PromptBuilder.CredentialCandidateRef>> out = new LinkedHashMap<>();
447
        byFile.forEach((file, group) -> out.put(file, refsFor(group, original, redacted)));
448 1 1. refsByFile : replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::refsByFile → KILLED
        return out;
449
    }
450
451
    private static Map<String, List<PromptBuilder.CredentialCandidateRef>> candidatesByFqcn(
452
            List<CredentialFinding> findings, Map<Path, String> original, Map<Path, String> redacted) {
453
        Map<String, List<PromptBuilder.CredentialCandidateRef>> byFqcn = new LinkedHashMap<>();
454
        groupByFqcn(findings).forEach((fqcn, group) -> {
455 2 1. lambda$candidatesByFqcn$12 : removed conditional - replaced equality check with true → SURVIVED
2. lambda$candidatesByFqcn$12 : removed conditional - replaced equality check with false → KILLED
            if (!NO_FQCN.equals(fqcn)) {
456
                byFqcn.put(fqcn, refsFor(group, original, redacted));
457
            }
458
        });
459 1 1. candidatesByFqcn : replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::candidatesByFqcn → KILLED
        return byFqcn;
460
    }
461
462
    private List<CredentialFinding> triageSeparately(List<CredentialFinding> findings,
463
            Map<Path, List<PromptBuilder.CredentialCandidateRef>> refsByFile, Map<Path, String> sourceByFile) {
464 2 1. triageSeparately : removed conditional - replaced equality check with false → SURVIVED
2. triageSeparately : removed conditional - replaced equality check with true → KILLED
        if (findings.isEmpty()) {
465 1 1. triageSeparately : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageSeparately → NO_COVERAGE
            return findings;
466
        }
467
        Map<Path, List<CredentialFinding>> byFile = findings.stream()
468
                .collect(Collectors.groupingBy(CredentialFinding::filePath, LinkedHashMap::new, Collectors.toList()));
469
        List<CredentialFinding> result = new ArrayList<>(findings.size());
470
        byFile.forEach((file, group) ->
471
                result.addAll(triageGroup(file, group, refsByFile.getOrDefault(file, List.of()),
472
                        sourceByFile.getOrDefault(file, ""))));
473 1 1. triageSeparately : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageSeparately → KILLED
        return result;
474
    }
475
476
    private List<CredentialFinding> triageGroup(Path file, List<CredentialFinding> group,
477
            List<PromptBuilder.CredentialCandidateRef> refs, String source) {
478 2 1. triageGroup : removed conditional - replaced equality check with true → KILLED
2. triageGroup : removed conditional - replaced equality check with false → KILLED
        if (refs.isEmpty()) {
479 1 1. triageGroup : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageGroup → KILLED
            return group;
480
        }
481 2 1. triageGroup : removed conditional - replaced equality check with true → SURVIVED
2. triageGroup : removed conditional - replaced equality check with false → SURVIVED
        String fqcn = group.get(0).fqcn() != null
482
                ? group.get(0).fqcn()
483
                : file.toString().replace('\\', '/');
484
        try {
485
            List<CredentialTriageVerdict> verdicts = aiEngine.triageSecrets(fqcn, source, refs);
486
            Map<Integer, CredentialTriageVerdict> byIndex = verdicts.stream()
487 2 1. lambda$triageGroup$15 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$triageGroup$15 → NO_COVERAGE
2. lambda$triageGroup$14 : replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$triageGroup$14 → KILLED
                    .collect(Collectors.toMap(CredentialTriageVerdict::candidateIndex, v -> v, (a, b) -> a));
488 1 1. triageGroup : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageGroup → KILLED
            return DetectCredentialsStage.mergeVerdicts(group, byIndex);
489
        } catch (AiSuggestionException e) {
490
            LOG.log(Level.WARNING, e,
491 1 1. lambda$triageGroup$16 : replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$triageGroup$16 → NO_COVERAGE
                    () -> "Secret triage failed for " + fqcn + "; emitting unverified candidates");
492 1 1. triageGroup : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageGroup → NO_COVERAGE
            return group;
493
        }
494
    }
495
496
    private List<CredentialFinding> filterByMinScore(List<CredentialFinding> findings) {
497
        double minScore = cfg.secretsMinScore();
498
        List<CredentialFinding> kept = new ArrayList<>(findings.size());
499
        for (CredentialFinding f : findings) {
500 5 1. filterByMinScore : removed conditional - replaced comparison check with true → SURVIVED
2. filterByMinScore : removed conditional - replaced equality check with false → SURVIVED
3. filterByMinScore : changed conditional boundary → SURVIVED
4. filterByMinScore : removed conditional - replaced comparison check with false → KILLED
5. filterByMinScore : removed conditional - replaced equality check with true → KILLED
            if (f.credibilityScore() == null || f.credibilityScore() >= minScore) {
501
                kept.add(f);
502
            }
503
        }
504 1 1. filterByMinScore : replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::filterByMinScore → KILLED
        return kept;
505
    }
506
507
    private static void logSummary(List<CredentialFinding> kept) {
508
        if (LOG.isLoggable(Level.INFO)) {
509
            long files = kept.stream().map(CredentialFinding::filePath).distinct().count();
510
            LOG.log(Level.INFO, "Credential detection: {0} finding(s) across {1} file(s)",
511
                    new Object[] { kept.size(), files });
512
        }
513
    }
514
515
    private void logFindings(List<CredentialFinding> kept) {
516
        for (CredentialFinding f : kept) {
517
            String raw = f.candidate().matchedValue();
518 2 1. logFindings : removed conditional - replaced equality check with false → SURVIVED
2. logFindings : removed conditional - replaced equality check with true → SURVIVED
            String snippet = cfg.secretsShowValues() ? raw : CredentialMasker.mask(raw);
519
            // Supplier form is lazy: the message is only assembled when INFO is loggable.
520
            LOG.info(() -> "  " + f.filePath().toString().replace('\\', '/')
521
                    + ":" + f.candidate().beginLine()
522
                    + " [" + f.candidate().ruleId() + "] " + snippet);
523
        }
524
    }
525
526
    private void recordIntoSarif(List<CredentialFinding> kept, SarifEmitter sarifEmitter) {
527 2 1. recordIntoSarif : removed conditional - replaced equality check with true → SURVIVED
2. recordIntoSarif : removed conditional - replaced equality check with false → KILLED
        if (sarifEmitter == null) {
528
            return;
529
        }
530
        for (CredentialFinding f : kept) {
531
            sarifEmitter.recordSecret(fileUri(f), f);
532
        }
533
    }
534
535
    private static String fileUri(CredentialFinding f) {
536 2 1. fileUri : removed conditional - replaced equality check with true → NO_COVERAGE
2. fileUri : removed conditional - replaced equality check with false → NO_COVERAGE
        if (f.fqcn() != null) {
537 1 1. fileUri : replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::fileUri → NO_COVERAGE
            return f.fqcn().replace('.', '/') + JAVA_EXTENSION;
538
        }
539 1 1. fileUri : replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::fileUri → NO_COVERAGE
        return f.filePath().toString().replace('\\', '/');
540
    }
541
542
    private void writeCsv(List<CredentialFinding> kept) throws IOException {
543
        try (PrintWriter w = new PrintWriter(Files.newBufferedWriter(cfg.secretsOut()))) {
544
            new CredentialCsvEmitter(cfg.secretsShowValues()).flush(w, kept);
545
        }
546
    }
547
}

Mutations

158

1.1
Location : prepare
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : prepare
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

3.3
Location : prepare
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

4.4
Location : prepare
Killed by : none
removed conditional - replaced equality check with true → SURVIVED Covering tests

5.5
Location : prepare
Killed by : none
removed conditional - replaced equality check with true → SURVIVED Covering tests

6.6
Location : prepare
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

159

1.1
Location : prepare
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : prepare
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

162

1.1
Location : prepare
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::prepare → KILLED

177

1.1
Location : finish
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : finish
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

199

1.1
Location : run
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

2.2
Location : run
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

222

1.1
Location : lambda$detect$0
Killed by : none
replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$detect$0 → NO_COVERAGE

225

1.1
Location : detect
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_unredactableFileAbortsBeforeAnyProviderCall()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : detect
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

227

1.1
Location : detect
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

2.2
Location : detect
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

228

1.1
Location : detect
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::detect → KILLED

238

1.1
Location : redactActive
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_unredactableFileAbortsBeforeAnyProviderCall()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : redactActive
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

3.3
Location : redactActive
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::redactActive → KILLED

4.4
Location : redactActive
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

5.5
Location : redactActive
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_unredactableFileAbortsBeforeAnyProviderCall()]
removed conditional - replaced equality check with false → KILLED

6.6
Location : redactActive
Killed by : none
removed conditional - replaced equality check with true → SURVIVED Covering tests

7.7
Location : redactActive
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_unredactableFileAbortsBeforeAnyProviderCall()]
removed conditional - replaced equality check with false → KILLED

242

1.1
Location : redactAll
Killed by : none
Replaced integer multiplication with division → SURVIVED
Covering tests

246

1.1
Location : redactAll
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::redactAll → KILLED

266

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced equality check with true → KILLED

267

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
replaced boolean return with false for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED

271

1.1
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced comparison check with true → SURVIVED Covering tests

3.3
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced comparison check with false → SURVIVED Covering tests

4.4
Location : overlapsBlankedText
Killed by : none
changed conditional boundary → SURVIVED Covering tests

5.5
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced equality check with false → SURVIVED Covering tests

274

1.1
Location : overlapsBlankedText
Killed by : none
Replaced integer addition with subtraction → SURVIVED
Covering tests

278

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with false → KILLED

2.2
Location : overlapsBlankedText
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with true → KILLED

4.4
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
changed conditional boundary → KILLED

5.5
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
removed conditional - replaced comparison check with true → KILLED

6.6
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced comparison check with false → SURVIVED Covering tests

7.7
Location : overlapsBlankedText
Killed by : none
changed conditional boundary → SURVIVED Covering tests

8.8
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with false → KILLED

9.9
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced comparison check with true → SURVIVED Covering tests

279

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
replaced boolean return with false for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED

281

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with false → KILLED

2.2
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
changed conditional boundary → KILLED

3.3
Location : overlapsBlankedText
Killed by : none
removed conditional - replaced comparison check with true → SURVIVED
Covering tests

4.4
Location : overlapsBlankedText
Killed by : none
Replaced integer addition with subtraction → SURVIVED Covering tests

5.5
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with false → KILLED

6.6
Location : overlapsBlankedText
Killed by : none
changed conditional boundary → SURVIVED Covering tests

7.7
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with true → KILLED

282

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced equality check with true → KILLED

283

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
replaced boolean return with false for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED

286

1.1
Location : overlapsBlankedText
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::overlapsBlankedText → KILLED

297

1.1
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with true → KILLED

2.2
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
changed conditional boundary → KILLED

3.3
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
removed conditional - replaced comparison check with false → KILLED

299

1.1
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
removed conditional - replaced comparison check with false → KILLED

2.2
Location : offsetOf
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
removed conditional - replaced comparison check with true → KILLED

300

1.1
Location : offsetOf
Killed by : none
removed conditional - replaced equality check with false → NO_COVERAGE

2.2
Location : offsetOf
Killed by : none
Replaced integer addition with subtraction → SURVIVED
Covering tests

3.3
Location : offsetOf
Killed by : none
removed conditional - replaced equality check with true → NO_COVERAGE

4.4
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
replaced int return with 0 for org/egothor/methodatlas/command/CredentialDetectionRunner::offsetOf → KILLED

5.5
Location : offsetOf
Killed by : none
removed conditional - replaced equality check with true → SURVIVED Covering tests

6.6
Location : offsetOf
Killed by : none
removed conditional - replaced equality check with false → SURVIVED Covering tests

302

1.1
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_failsClosedOnUnmappableSpanOrLengthMismatch()]
Replaced integer addition with subtraction → KILLED

304

1.1
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
Replaced integer subtraction with addition → KILLED

2.2
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
Replaced integer addition with subtraction → KILLED

3.3
Location : offsetOf
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:overlapsBlankedText_handlesMultiLineSpansAndLineEndBoundary()]
replaced int return with 0 for org/egothor/methodatlas/command/CredentialDetectionRunner::offsetOf → KILLED

314

1.1
Location : toContext
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::toContext → KILLED

330

1.1
Location : lambda$applyFoldedVerdicts$2
Killed by : none
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$applyFoldedVerdicts$2 → NO_COVERAGE

2.2
Location : lambda$applyFoldedVerdicts$1
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$applyFoldedVerdicts$1 → KILLED

333

1.1
Location : applyFoldedVerdicts
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::applyFoldedVerdicts → KILLED

358

1.1
Location : discoverByFile
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::discoverByFile → KILLED

368

1.1
Location : lambda$toAttribution$4
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$toAttribution$4 → KILLED

370

1.1
Location : toAttribution
Killed by : none
replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::toAttribution → SURVIVED
Covering tests

375

1.1
Location : selectUnits
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_unredactableFileAbortsBeforeAnyProviderCall()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : selectUnits
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with true → KILLED

376

1.1
Location : selectUnits
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_unredactableFileAbortsBeforeAnyProviderCall()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::selectUnits → KILLED

378

1.1
Location : selectUnits
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::selectUnits → KILLED

379

1.1
Location : lambda$selectUnits$6
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$selectUnits$6 → KILLED

385

1.1
Location : toUnit
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

2.2
Location : toUnit
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

391

1.1
Location : toUnit
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::toUnit → KILLED

405

1.1
Location : runDetectors
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::runDetectors → KILLED

412

1.1
Location : groupByFqcn
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::groupByFqcn → KILLED

413

1.1
Location : lambda$groupByFqcn$8
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$groupByFqcn$8 → KILLED

2.2
Location : lambda$groupByFqcn$8
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

3.3
Location : lambda$groupByFqcn$8
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with true → KILLED

428

1.1
Location : refsFor
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::refsFor → KILLED

429

1.1
Location : lambda$refsFor$9
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$refsFor$9 → KILLED

2.2
Location : lambda$refsFor$9
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

3.3
Location : lambda$refsFor$9
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

4.4
Location : lambda$refsFor$9
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with true → KILLED

5.5
Location : lambda$refsFor$9
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

430

1.1
Location : lambda$refsFor$10
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$refsFor$10 → KILLED

439

1.1
Location : inComment
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with true → KILLED

2.2
Location : inComment
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

3.3
Location : inComment
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

4.4
Location : inComment
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

5.5
Location : inComment
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
replaced boolean return with true for org/egothor/methodatlas/command/CredentialDetectionRunner::inComment → KILLED

6.6
Location : inComment
Killed by : none
removed conditional - replaced equality check with true → SURVIVED Covering tests

7.7
Location : inComment
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

448

1.1
Location : refsByFile
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::refsByFile → KILLED

455

1.1
Location : lambda$candidatesByFqcn$12
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : lambda$candidatesByFqcn$12
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with false → KILLED

459

1.1
Location : candidatesByFqcn
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:foldedPath_redactsClassSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyMap for org/egothor/methodatlas/command/CredentialDetectionRunner::candidatesByFqcn → KILLED

464

1.1
Location : triageSeparately
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

2.2
Location : triageSeparately
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

465

1.1
Location : triageSeparately
Killed by : none
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageSeparately → NO_COVERAGE

473

1.1
Location : triageSeparately
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageSeparately → KILLED

478

1.1
Location : triageGroup
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with true → KILLED

2.2
Location : triageGroup
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:secretsOnlyInComments_noTriageCallIsMadeAndReportStillListsThem()]
removed conditional - replaced equality check with false → KILLED

479

1.1
Location : triageGroup
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:secretsOnlyInComments_noTriageCallIsMadeAndReportStillListsThem()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageGroup → KILLED

481

1.1
Location : triageGroup
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : triageGroup
Killed by : none
removed conditional - replaced equality check with false → SURVIVED Covering tests

487

1.1
Location : lambda$triageGroup$14
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$triageGroup$14 → KILLED

2.2
Location : lambda$triageGroup$15
Killed by : none
replaced return value with null for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$triageGroup$15 → NO_COVERAGE

488

1.1
Location : triageGroup
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageGroup → KILLED

491

1.1
Location : lambda$triageGroup$16
Killed by : none
replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::lambda$triageGroup$16 → NO_COVERAGE

492

1.1
Location : triageGroup
Killed by : none
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::triageGroup → NO_COVERAGE

500

1.1
Location : filterByMinScore
Killed by : none
removed conditional - replaced comparison check with true → SURVIVED
Covering tests

2.2
Location : filterByMinScore
Killed by : none
removed conditional - replaced equality check with false → SURVIVED Covering tests

3.3
Location : filterByMinScore
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced comparison check with false → KILLED

4.4
Location : filterByMinScore
Killed by : none
changed conditional boundary → SURVIVED Covering tests

5.5
Location : filterByMinScore
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
removed conditional - replaced equality check with true → KILLED

504

1.1
Location : filterByMinScore
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_redactsSourceAndWithholdsCommentSecretFromAi()]
replaced return value with Collections.emptyList for org/egothor/methodatlas/command/CredentialDetectionRunner::filterByMinScore → KILLED

518

1.1
Location : logFindings
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

2.2
Location : logFindings
Killed by : none
removed conditional - replaced equality check with true → SURVIVED Covering tests

527

1.1
Location : recordIntoSarif
Killed by : none
removed conditional - replaced equality check with true → SURVIVED
Covering tests

2.2
Location : recordIntoSarif
Killed by : org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.command.CredentialDetectionRunnerRedactionTest]/[method:separatePath_withoutRedaction_sendsEverythingAsBefore()]
removed conditional - replaced equality check with false → KILLED

536

1.1
Location : fileUri
Killed by : none
removed conditional - replaced equality check with true → NO_COVERAGE

2.2
Location : fileUri
Killed by : none
removed conditional - replaced equality check with false → NO_COVERAGE

537

1.1
Location : fileUri
Killed by : none
replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::fileUri → NO_COVERAGE

539

1.1
Location : fileUri
Killed by : none
replaced return value with "" for org/egothor/methodatlas/command/CredentialDetectionRunner::fileUri → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.30.1 support