slopbrick 0.25.1 → 0.26.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.
@@ -37026,6 +37026,48 @@ var javaArraylistVsLinkedlistRule = createRule({
37026
37026
  }
37027
37027
  });
37028
37028
 
37029
+ // src/rules/java/builder-overuse.ts
37030
+ var BUILDER_ANNOTATION_REGEX = /@Builder\b/;
37031
+ var FIELD_DECL_REGEX = /(?:private|public|protected)\s+(?:final\s+)?[\w<>,\s]+\s+(\w+)\s*[=;]/g;
37032
+ var DEFAULT_FIELD_COUNT_CAP = 3;
37033
+ var javaBuilderOveruseRule = createRule({
37034
+ id: "java/builder-overuse",
37035
+ category: "typo",
37036
+ severity: "low",
37037
+ aiSpecific: true,
37038
+ description: "@Builder on a class with few fields \u2014 plain constructor is simpler",
37039
+ create(_context) {
37040
+ return { fieldCountCap: DEFAULT_FIELD_COUNT_CAP };
37041
+ },
37042
+ analyze(context, facts) {
37043
+ const issues = [];
37044
+ const source = facts.v2?._source;
37045
+ if (!source) return issues;
37046
+ if (!/\.java$/i.test(facts.filePath)) return issues;
37047
+ BUILDER_ANNOTATION_REGEX.lastIndex = 0;
37048
+ const builderMatch = BUILDER_ANNOTATION_REGEX.exec(source);
37049
+ if (!builderMatch) return issues;
37050
+ const firstBuilderLine = source.slice(0, builderMatch.index).split("\n").length;
37051
+ FIELD_DECL_REGEX.lastIndex = 0;
37052
+ let fieldCount = 0;
37053
+ while (FIELD_DECL_REGEX.exec(source) !== null) {
37054
+ fieldCount++;
37055
+ }
37056
+ if (fieldCount > context.fieldCountCap) return issues;
37057
+ issues.push({
37058
+ ruleId: "java/builder-overuse",
37059
+ category: "typo",
37060
+ severity: "low",
37061
+ aiSpecific: true,
37062
+ message: `@Builder on a class with ${fieldCount} field(s) \u2014 plain constructor is simpler`,
37063
+ line: firstBuilderLine,
37064
+ column: 1,
37065
+ advice: "Use a plain constructor for classes with \u2264 3 fields. AI agents default to @Builder because their training data emphasizes the pattern. Builder adds Lombok dependency and a Builder inner class for every annotated class. Reference: java/builder-overuse v0.26.0."
37066
+ });
37067
+ return issues;
37068
+ }
37069
+ });
37070
+
37029
37071
  // src/rules/java/empty-catch-block.ts
37030
37072
  var SINGLE_LINE_EMPTY_CATCH_REGEX = /catch\s*\([^)]*\)\s*\{\s*\}/g;
37031
37073
  var javaEmptyCatchBlockRule = createRule({
@@ -37061,6 +37103,58 @@ var javaEmptyCatchBlockRule = createRule({
37061
37103
  }
37062
37104
  });
37063
37105
 
37106
+ // src/rules/java/immutable-collection-preference.ts
37107
+ var IMMUTABLE_REGEX = /\b(List|Map|Set)\.of\s*\(/g;
37108
+ var MUTABLE_REGEX = /new\s+(ArrayList|HashMap|HashSet|LinkedList|TreeMap)\s*[<(]/g;
37109
+ var DEFAULT_IMMUTABLE_THRESHOLD = 5;
37110
+ var DEFAULT_MUTABLE_CAP = 1;
37111
+ var javaImmutableCollectionPreferenceRule = createRule({
37112
+ id: "java/immutable-collection-preference",
37113
+ category: "typo",
37114
+ severity: "low",
37115
+ aiSpecific: true,
37116
+ description: "Immutable factory method over-use \u2014 prefer mutable when collection will be modified",
37117
+ create(_context) {
37118
+ return {
37119
+ immutableThreshold: DEFAULT_IMMUTABLE_THRESHOLD,
37120
+ mutableCap: DEFAULT_MUTABLE_CAP
37121
+ };
37122
+ },
37123
+ analyze(context, facts) {
37124
+ const issues = [];
37125
+ const source = facts.v2?._source;
37126
+ if (!source) return issues;
37127
+ if (!/\.java$/i.test(facts.filePath)) return issues;
37128
+ IMMUTABLE_REGEX.lastIndex = 0;
37129
+ let immutableCount = 0;
37130
+ let firstIdx = 0;
37131
+ let m;
37132
+ while ((m = IMMUTABLE_REGEX.exec(source)) !== null) {
37133
+ immutableCount++;
37134
+ if (firstIdx === 0) firstIdx = m.index;
37135
+ }
37136
+ if (immutableCount < context.immutableThreshold) return issues;
37137
+ MUTABLE_REGEX.lastIndex = 0;
37138
+ let mutableCount = 0;
37139
+ while ((m = MUTABLE_REGEX.exec(source)) !== null) {
37140
+ mutableCount++;
37141
+ }
37142
+ if (mutableCount > context.mutableCap) return issues;
37143
+ const line = source.slice(0, firstIdx).split("\n").length;
37144
+ issues.push({
37145
+ ruleId: "java/immutable-collection-preference",
37146
+ category: "typo",
37147
+ severity: "low",
37148
+ aiSpecific: true,
37149
+ message: `${immutableCount} immutable factory calls (List/Map/Set.of) with only ${mutableCount} mutable collection \u2014 likely over-preferring immutability`,
37150
+ line,
37151
+ column: 1,
37152
+ advice: "Prefer mutable collections (new ArrayList<>()) when the collection will be modified later. AI agents default to List.of/Map.of/Set.of because their training data emphasizes functional-style Java. Reference: java/immutable-collection-preference v0.26.0."
37153
+ });
37154
+ return issues;
37155
+ }
37156
+ });
37157
+
37064
37158
  // src/rules/java/legacy-date-api.ts
37065
37159
  var LEGACY_IMPORT_REGEX = /^import\s+(?:static\s+)?java\.(?:util|sql)\.(?:Date|Calendar|GregorianCalendar)\s*;/gm;
37066
37160
  var LEGACY_USAGE_REGEX = /\bnew\s+(?:Date|GregorianCalendar)\s*\(/g;
@@ -37130,6 +37224,52 @@ var javaLegacyDateApiRule = createRule({
37130
37224
  }
37131
37225
  });
37132
37226
 
37227
+ // src/rules/java/optional-overuse.ts
37228
+ var OR_ELSE_THROW_REGEX = /\.orElseThrow\s*\(/g;
37229
+ var NULL_CHECK_REGEX = /Objects\.requireNonNull\s*\(|if\s*\([^)]*==\s*null\)\s*(?:throw|return)/g;
37230
+ var DEFAULT_THRESHOLD = 2;
37231
+ var javaOptionalOveruseRule = createRule({
37232
+ id: "java/optional-overuse",
37233
+ category: "typo",
37234
+ severity: "low",
37235
+ aiSpecific: true,
37236
+ description: "Optional chain over-use \u2014 null check or Objects.requireNonNull is faster",
37237
+ create(_context) {
37238
+ return { threshold: DEFAULT_THRESHOLD };
37239
+ },
37240
+ analyze(context, facts) {
37241
+ const issues = [];
37242
+ const source = facts.v2?._source;
37243
+ if (!source) return issues;
37244
+ if (!/\.java$/i.test(facts.filePath)) return issues;
37245
+ OR_ELSE_THROW_REGEX.lastIndex = 0;
37246
+ let orElseThrowCount = 0;
37247
+ let firstIdx = 0;
37248
+ let m;
37249
+ while ((m = OR_ELSE_THROW_REGEX.exec(source)) !== null) {
37250
+ orElseThrowCount++;
37251
+ if (firstIdx === 0) firstIdx = m.index;
37252
+ }
37253
+ if (orElseThrowCount < context.threshold) return issues;
37254
+ NULL_CHECK_REGEX.lastIndex = 0;
37255
+ const nullCheckCount = (source.match(NULL_CHECK_REGEX) ?? []).length;
37256
+ const optionalRatio = orElseThrowCount / Math.max(orElseThrowCount + nullCheckCount, 1);
37257
+ if (optionalRatio < 0.6) return issues;
37258
+ const line = source.slice(0, firstIdx).split("\n").length;
37259
+ issues.push({
37260
+ ruleId: "java/optional-overuse",
37261
+ category: "typo",
37262
+ severity: "low",
37263
+ aiSpecific: true,
37264
+ message: `${orElseThrowCount} .orElseThrow() calls with ${nullCheckCount} null checks \u2014 Optional chain over-use`,
37265
+ line,
37266
+ column: 1,
37267
+ advice: 'Use Objects.requireNonNull(x, "msg") for null checks; reserve Optional for return values. AI agents default to Optional chains because their training data emphasizes null-safety. Real Java code uses null checks in hot paths. Reference: java/optional-overuse v0.26.0.'
37268
+ });
37269
+ return issues;
37270
+ }
37271
+ });
37272
+
37133
37273
  // src/rules/java/raw-type-overuse.ts
37134
37274
  var RAW_TYPE_REGEX = /\b(List|Map|Set|Collection|Iterable)\s+(?![<A-Z])(\w+)/g;
37135
37275
  var javaRawTypeOveruseRule = createRule({
@@ -37166,6 +37306,68 @@ var javaRawTypeOveruseRule = createRule({
37166
37306
  }
37167
37307
  });
37168
37308
 
37309
+ // src/rules/java/stream-overuse.ts
37310
+ var STREAM_OPS = [
37311
+ ".map(",
37312
+ ".filter(",
37313
+ ".flatMap(",
37314
+ ".collect(",
37315
+ ".reduce(",
37316
+ ".sorted(",
37317
+ ".distinct(",
37318
+ ".limit(",
37319
+ ".skip(",
37320
+ ".anyMatch(",
37321
+ ".allMatch(",
37322
+ ".noneMatch(",
37323
+ ".findFirst(",
37324
+ ".findAny("
37325
+ ];
37326
+ var DEFAULT_CHAIN_THRESHOLD = 3;
37327
+ var javaStreamOveruseRule = createRule({
37328
+ id: "java/stream-overuse",
37329
+ category: "typo",
37330
+ severity: "low",
37331
+ aiSpecific: true,
37332
+ description: "Stream API chain over-use \u2014 for-loop is faster for simple transformations",
37333
+ create(_context) {
37334
+ return { chainThreshold: DEFAULT_CHAIN_THRESHOLD };
37335
+ },
37336
+ analyze(context, facts) {
37337
+ const issues = [];
37338
+ const source = facts.v2?._source;
37339
+ if (!source) return issues;
37340
+ if (!/\.java$/i.test(facts.filePath)) return issues;
37341
+ const lines = source.split("\n");
37342
+ const streamOpPattern = new RegExp(STREAM_OPS.map((op) => op.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"), "g");
37343
+ let firstOffendingLine = 0;
37344
+ let firstOffendingCount = 0;
37345
+ for (let i = 0; i < lines.length; i++) {
37346
+ const line = lines[i] ?? "";
37347
+ if (line.trim().startsWith("//") || line.trim().startsWith("*")) continue;
37348
+ const matches = line.match(streamOpPattern);
37349
+ if (matches && matches.length >= context.chainThreshold) {
37350
+ if (firstOffendingLine === 0) {
37351
+ firstOffendingLine = i + 1;
37352
+ firstOffendingCount = matches.length;
37353
+ }
37354
+ }
37355
+ }
37356
+ if (firstOffendingLine === 0) return issues;
37357
+ issues.push({
37358
+ ruleId: "java/stream-overuse",
37359
+ category: "typo",
37360
+ severity: "low",
37361
+ aiSpecific: true,
37362
+ message: `${firstOffendingCount} stream operations on a single line \u2014 for-loop is faster`,
37363
+ line: firstOffendingLine,
37364
+ column: 1,
37365
+ advice: "Prefer a for-loop for simple transformations. AI agents default to Stream API chains because their training data emphasizes functional-style Java. Stream chains allocate intermediate objects; for small collections, a for-loop is faster and more readable. Reference: java/stream-overuse v0.26.0."
37366
+ });
37367
+ return issues;
37368
+ }
37369
+ });
37370
+
37169
37371
  // src/rules/java/string-concat-loop.ts
37170
37372
  var STRING_CONCAT_REGEX = /(\b\w+)\s*=\s*\1\s*\+\s*[^;]+;|(\b\w+)\s*\+=\s*['"`]/g;
37171
37373
  var javaStringConcatLoopRule = createRule({
@@ -37204,7 +37406,7 @@ var javaStringConcatLoopRule = createRule({
37204
37406
 
37205
37407
  // src/rules/java/system-out-println.ts
37206
37408
  var PRINTLN_REGEX = /System\.out\.println\s*\(/g;
37207
- var DEFAULT_THRESHOLD = 1;
37409
+ var DEFAULT_THRESHOLD2 = 1;
37208
37410
  var javaSystemOutPrintlnRule = createRule({
37209
37411
  id: "java/system-out-println",
37210
37412
  category: "typo",
@@ -37212,7 +37414,7 @@ var javaSystemOutPrintlnRule = createRule({
37212
37414
  aiSpecific: true,
37213
37415
  description: "System.out.println in production code \u2014 use a logger (SLF4J, Log4j, etc.)",
37214
37416
  create(_context) {
37215
- return { threshold: DEFAULT_THRESHOLD };
37417
+ return { threshold: DEFAULT_THRESHOLD2 };
37216
37418
  },
37217
37419
  analyze(context, facts) {
37218
37420
  const issues = [];
@@ -37245,6 +37447,56 @@ var javaSystemOutPrintlnRule = createRule({
37245
37447
  }
37246
37448
  });
37247
37449
 
37450
+ // src/rules/java/verbose-javadoc.ts
37451
+ var TAG_REGEX = /@(param|return|throws)\b/g;
37452
+ var DEFAULT_TAG_THRESHOLD = 3;
37453
+ var DEFAULT_BODY_LENGTH_CAP = 5;
37454
+ var javaVerboseJavadocRule = createRule({
37455
+ id: "java/verbose-javadoc",
37456
+ category: "typo",
37457
+ severity: "low",
37458
+ aiSpecific: true,
37459
+ description: "Excessive Javadoc tags on trivial methods \u2014 over-documentation is an AI fingerprint",
37460
+ create(_context) {
37461
+ return {
37462
+ tagThreshold: DEFAULT_TAG_THRESHOLD,
37463
+ bodyLengthCap: DEFAULT_BODY_LENGTH_CAP
37464
+ };
37465
+ },
37466
+ analyze(context, facts) {
37467
+ const issues = [];
37468
+ const source = facts.v2?._source;
37469
+ if (!source) return issues;
37470
+ if (!/\.java$/i.test(facts.filePath)) return issues;
37471
+ TAG_REGEX.lastIndex = 0;
37472
+ let tagCount = 0;
37473
+ let firstTagLine = 0;
37474
+ let m;
37475
+ while ((m = TAG_REGEX.exec(source)) !== null) {
37476
+ tagCount++;
37477
+ if (firstTagLine === 0) {
37478
+ firstTagLine = source.slice(0, m.index).split("\n").length;
37479
+ }
37480
+ }
37481
+ if (tagCount < context.tagThreshold) return issues;
37482
+ const lineCount = source.split("\n").length;
37483
+ const tagDensity = tagCount / Math.max(lineCount, 1);
37484
+ if (tagDensity < 0.05) return issues;
37485
+ if (lineCount > 200) return issues;
37486
+ issues.push({
37487
+ ruleId: "java/verbose-javadoc",
37488
+ category: "typo",
37489
+ severity: "low",
37490
+ aiSpecific: true,
37491
+ message: `${tagCount} Javadoc tags in ${lineCount} lines (density ${(tagDensity * 100).toFixed(1)}%) \u2014 likely over-documented`,
37492
+ line: firstTagLine,
37493
+ column: 1,
37494
+ advice: "Skip Javadoc on trivial methods (getters, setters, builders). AI agents default to over-documentation because their training data has countless textbook Javadoc examples. Real Java code limits Javadoc to public API surface. Reference: java/verbose-javadoc v0.26.0."
37495
+ });
37496
+ return issues;
37497
+ }
37498
+ });
37499
+
37248
37500
  // src/rules/kotlin/coroutine-global-scope.ts
37249
37501
  var GLOBAL_SCOPE_REGEX = /GlobalScope\s*\.\s*(?:launch|async|runBlocking)\s*[({]/g;
37250
37502
  var kotlinCoroutineGlobalScopeRule = createRule({
@@ -37389,7 +37641,7 @@ var kotlinObjectSingletonMisuseRule = createRule({
37389
37641
 
37390
37642
  // src/rules/kotlin/println-debug.ts
37391
37643
  var PRINTLN_REGEX2 = /^\s*println\s*\(/gm;
37392
- var DEFAULT_THRESHOLD2 = 1;
37644
+ var DEFAULT_THRESHOLD3 = 1;
37393
37645
  var kotlinPrintlnDebugRule = createRule({
37394
37646
  id: "kotlin/println-debug",
37395
37647
  category: "typo",
@@ -37397,7 +37649,7 @@ var kotlinPrintlnDebugRule = createRule({
37397
37649
  aiSpecific: true,
37398
37650
  description: "println(...) in production code \u2014 use Timber, android.util.Log, or an SLF4J facade",
37399
37651
  create(_context) {
37400
- return { threshold: DEFAULT_THRESHOLD2 };
37652
+ return { threshold: DEFAULT_THRESHOLD3 };
37401
37653
  },
37402
37654
  analyze(context, facts) {
37403
37655
  const issues = [];
@@ -40327,7 +40579,7 @@ var swiftImplicitlyUnwrappedOptionalRule = createRule({
40327
40579
 
40328
40580
  // src/rules/swift/print-debug.ts
40329
40581
  var PRINT_REGEX = /\bprint\s*\(/g;
40330
- var DEFAULT_THRESHOLD3 = 1;
40582
+ var DEFAULT_THRESHOLD4 = 1;
40331
40583
  var swiftPrintDebugRule = createRule({
40332
40584
  id: "swift/print-debug",
40333
40585
  category: "typo",
@@ -40335,7 +40587,7 @@ var swiftPrintDebugRule = createRule({
40335
40587
  aiSpecific: true,
40336
40588
  description: "print(...) in production Swift \u2014 use Logger (os.log) for level-controlled output",
40337
40589
  create(_context) {
40338
- return { threshold: DEFAULT_THRESHOLD3 };
40590
+ return { threshold: DEFAULT_THRESHOLD4 };
40339
40591
  },
40340
40592
  analyze(context, facts) {
40341
40593
  const issues = [];
@@ -42991,11 +43243,16 @@ var builtinRules = [
42991
43243
  goNilSliceVsEmptyRule,
42992
43244
  goStructTagInconsistencyRule,
42993
43245
  javaArraylistVsLinkedlistRule,
43246
+ javaBuilderOveruseRule,
42994
43247
  javaEmptyCatchBlockRule,
43248
+ javaImmutableCollectionPreferenceRule,
42995
43249
  javaLegacyDateApiRule,
43250
+ javaOptionalOveruseRule,
42996
43251
  javaRawTypeOveruseRule,
43252
+ javaStreamOveruseRule,
42997
43253
  javaStringConcatLoopRule,
42998
43254
  javaSystemOutPrintlnRule,
43255
+ javaVerboseJavadocRule,
42999
43256
  kotlinCoroutineGlobalScopeRule,
43000
43257
  kotlinDataClassDefaultsOveruseRule,
43001
43258
  kotlinObjectSingletonMisuseRule,
@@ -43929,6 +44186,86 @@ var signal_strength_default = {
43929
44186
  _v9Precision: 0.0657,
43930
44187
  defaultOff: true
43931
44188
  },
44189
+ "java/verbose-javadoc": {
44190
+ recall: 0,
44191
+ fpRate: 0,
44192
+ ratio: 1,
44193
+ precision: 0,
44194
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
44195
+ verdict: "DORMANT",
44196
+ _calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a small Java file (< 200 lines) has 3+ Javadoc tags with density >= 0.05. v0.26.1 CALIBRATION (14769-file biased sample from v9-java corpus, files that fired >=1 of the 6 existing java rules): TP=0, FP=0, ratio=N/A. HYPOTHESIS FAILED. The v0.26.0 intuition that 'AI over-documents trivial methods' is NOT supported by the v9 corpus \u2014 AI code in Spring AI, LangChain4j, etc. has the same Javadoc density as human code. v0.20 hypothesis (humans avoid println/Date/raw types) and v0.26 hypothesis (AI over-documents/over-Opts/over-Builders) are both wrong for the v9 corpus. v0.27+ will redesign with a different approach: either train a classifier on the v9 features or use AST-based detection rather than regex heuristics. Reference: java/verbose-javadoc v0.26.0; calibration v0.26.1.",
44197
+ aiSpecific: true,
44198
+ _v9Verdict: "DORMANT",
44199
+ _v9Lift: 1,
44200
+ _v9Recall: 0,
44201
+ _v9FpRate: 0,
44202
+ _v9Precision: 0,
44203
+ defaultOff: true
44204
+ },
44205
+ "java/optional-overuse": {
44206
+ recall: 0,
44207
+ fpRate: 0,
44208
+ ratio: 1,
44209
+ precision: 0,
44210
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
44211
+ verdict: "DORMANT",
44212
+ _calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a Java file has 2+ .orElseThrow() calls AND 0 Objects.requireNonNull()/null checks (optionalRatio > 0.6). v0.26.1 CALIBRATION (14769-file biased sample): TP=0, FP=0, ratio=N/A. HYPOTHESIS FAILED. AI in the v9 corpus does NOT use Optional chains more than humans. v0.27+ will redesign. Reference: java/optional-overuse v0.26.0; calibration v0.26.1.",
44213
+ aiSpecific: true,
44214
+ _v9Verdict: "DORMANT",
44215
+ _v9Lift: 1,
44216
+ _v9Recall: 0,
44217
+ _v9FpRate: 0,
44218
+ _v9Precision: 0,
44219
+ defaultOff: true
44220
+ },
44221
+ "java/immutable-collection-preference": {
44222
+ recall: 0,
44223
+ fpRate: 0,
44224
+ ratio: 1,
44225
+ precision: 0,
44226
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
44227
+ verdict: "DORMANT",
44228
+ _calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a Java file has 5+ List.of/Map.of/Set.of calls AND < 1 new ArrayList/HashMap/HashSet/LinkedList/TreeMap calls. v0.26.1 CALIBRATION (14769-file biased sample): TP=0, FP=0, ratio=N/A. HYPOTHESIS FAILED. AI does NOT use immutable factory methods more than humans. v0.27+ will redesign. Reference: java/immutable-collection-preference v0.26.0; calibration v0.26.1.",
44229
+ aiSpecific: true,
44230
+ _v9Verdict: "DORMANT",
44231
+ _v9Lift: 1,
44232
+ _v9Recall: 0,
44233
+ _v9FpRate: 0,
44234
+ _v9Precision: 0,
44235
+ defaultOff: true
44236
+ },
44237
+ "java/builder-overuse": {
44238
+ recall: 0,
44239
+ fpRate: 0,
44240
+ ratio: 1,
44241
+ precision: 0,
44242
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
44243
+ verdict: "DORMANT",
44244
+ _calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when @Builder annotation (Lombok) is used on a class with <= 3 fields. v0.26.1 CALIBRATION (14769-file biased sample): TP=0, FP=0, ratio=N/A. HYPOTHESIS FAILED. AI does NOT use @Builder on small classes more than humans. v0.27+ will redesign. Reference: java/builder-overuse v0.26.0; calibration v0.26.1.",
44245
+ aiSpecific: true,
44246
+ _v9Verdict: "DORMANT",
44247
+ _v9Lift: 1,
44248
+ _v9Recall: 0,
44249
+ _v9FpRate: 0,
44250
+ _v9Precision: 0,
44251
+ defaultOff: true
44252
+ },
44253
+ "java/stream-overuse": {
44254
+ recall: 0,
44255
+ fpRate: 0,
44256
+ ratio: 1,
44257
+ precision: 0,
44258
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
44259
+ verdict: "DORMANT",
44260
+ _calibrationNote: "v0.26.0: new positive AI-signal rule. Triggers when a single line has 3+ Stream API operations (.map, .filter, .flatMap, .collect, .reduce, .sorted, .distinct, .limit, .skip, .anyMatch, .allMatch, .noneMatch, .findFirst, .findAny). v0.26.1 CALIBRATION (14769-file biased sample): TP=0, FP=0, ratio=N/A. HYPOTHESIS FAILED. AI does NOT use Stream API chains more than humans. v0.27+ will redesign. Reference: java/stream-overuse v0.26.0; calibration v0.26.1.",
44261
+ aiSpecific: true,
44262
+ _v9Verdict: "DORMANT",
44263
+ _v9Lift: 1,
44264
+ _v9Recall: 0,
44265
+ _v9FpRate: 0,
44266
+ _v9Precision: 0,
44267
+ defaultOff: true
44268
+ },
43932
44269
  "java/raw-type-overuse": {
43933
44270
  recall: 0.1093,
43934
44271
  fpRate: 0.2041,