slopbrick 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine/worker.cjs +69 -37
- package/dist/engine/worker.js +69 -37
- package/dist/index.cjs +70 -38
- package/dist/index.js +70 -38
- package/package.json +1 -1
package/dist/engine/worker.cjs
CHANGED
|
@@ -4366,6 +4366,15 @@ function parseSource(source, filePath) {
|
|
|
4366
4366
|
case "go":
|
|
4367
4367
|
case "rs":
|
|
4368
4368
|
case "java":
|
|
4369
|
+
// v0.28.0: Kotlin files get the same parseBlankModule path as
|
|
4370
|
+
// Java (v0.24.5). All 5 `kotlin/*` rules are regex-based and
|
|
4371
|
+
// gate themselves on `/\.kts?$/i.test(filePath)` inside their
|
|
4372
|
+
// `analyze()`. The tree-sitter Kotlin integration is a larger
|
|
4373
|
+
// lift; the v0.27.0 methodology paper confirmed era-confounding
|
|
4374
|
+
// is the dominant signal anyway, so a regex-only Kotlin pass is
|
|
4375
|
+
// sufficient for the v9 calibration goal.
|
|
4376
|
+
case "kt":
|
|
4377
|
+
case "kts":
|
|
4369
4378
|
return parseBlankModule(source);
|
|
4370
4379
|
default:
|
|
4371
4380
|
return parseWithSwc(source, filePath);
|
|
@@ -37006,7 +37015,7 @@ var kotlinCoroutineGlobalScopeRule = createRule({
|
|
|
37006
37015
|
const issues = [];
|
|
37007
37016
|
const source = facts.v2?._source;
|
|
37008
37017
|
if (!source) return issues;
|
|
37009
|
-
if (!/\.
|
|
37018
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37010
37019
|
let m;
|
|
37011
37020
|
GLOBAL_SCOPE_REGEX.lastIndex = 0;
|
|
37012
37021
|
while ((m = GLOBAL_SCOPE_REGEX.exec(source)) !== null) {
|
|
@@ -37043,7 +37052,7 @@ var kotlinDataClassDefaultsOveruseRule = createRule({
|
|
|
37043
37052
|
const issues = [];
|
|
37044
37053
|
const source = facts.v2?._source;
|
|
37045
37054
|
if (!source) return issues;
|
|
37046
|
-
if (!/\.
|
|
37055
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37047
37056
|
let m;
|
|
37048
37057
|
DATA_CLASS_HEAD_REGEX.lastIndex = 0;
|
|
37049
37058
|
while ((m = DATA_CLASS_HEAD_REGEX.exec(source)) !== null) {
|
|
@@ -37098,7 +37107,7 @@ var kotlinObjectSingletonMisuseRule = createRule({
|
|
|
37098
37107
|
const issues = [];
|
|
37099
37108
|
const source = facts.v2?._source;
|
|
37100
37109
|
if (!source) return issues;
|
|
37101
|
-
if (!/\.
|
|
37110
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37102
37111
|
let m;
|
|
37103
37112
|
OBJECT_DECL_REGEX.lastIndex = 0;
|
|
37104
37113
|
while ((m = OBJECT_DECL_REGEX.exec(source)) !== null) {
|
|
@@ -37149,7 +37158,7 @@ var kotlinPrintlnDebugRule = createRule({
|
|
|
37149
37158
|
const issues = [];
|
|
37150
37159
|
const source = facts.v2?._source;
|
|
37151
37160
|
if (!source) return issues;
|
|
37152
|
-
if (!/\.
|
|
37161
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37153
37162
|
const matches = [];
|
|
37154
37163
|
let m;
|
|
37155
37164
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -37191,7 +37200,7 @@ var kotlinStringConcatLoopRule = createRule({
|
|
|
37191
37200
|
const issues = [];
|
|
37192
37201
|
const source = facts.v2?._source;
|
|
37193
37202
|
if (!source) return issues;
|
|
37194
|
-
if (!/\.
|
|
37203
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37195
37204
|
if (!/\b(?:for|while|repeat|forEach)\b/.test(source)) return issues;
|
|
37196
37205
|
let m;
|
|
37197
37206
|
STRING_CONCAT_REGEX.lastIndex = 0;
|
|
@@ -44844,13 +44853,13 @@ var signal_strength_default = {
|
|
|
44844
44853
|
defaultOff: true
|
|
44845
44854
|
},
|
|
44846
44855
|
"kotlin/data-class-defaults-overuse": {
|
|
44847
|
-
recall:
|
|
44848
|
-
fpRate:
|
|
44849
|
-
ratio:
|
|
44850
|
-
precision: 0,
|
|
44851
|
-
lastCalibratedAt: "2026-07-
|
|
44856
|
+
recall: 469e-5,
|
|
44857
|
+
fpRate: 222e-5,
|
|
44858
|
+
ratio: 2.11,
|
|
44859
|
+
precision: 0.1429,
|
|
44860
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44852
44861
|
verdict: "DORMANT",
|
|
44853
|
-
_calibrationNote: "v0.
|
|
44862
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=2.11 (\u22651.5) but precision=14.3% (<50%) \u2014 verdict DORMANT. Era-confounding: pre-2022 Kotlin is sparse; the rule fires on the rare .kt file with multiple default values regardless of authorship.",
|
|
44854
44863
|
aiSpecific: true,
|
|
44855
44864
|
_v7Verdict: "DORMANT",
|
|
44856
44865
|
_v7Lift: 1,
|
|
@@ -44859,16 +44868,21 @@ var signal_strength_default = {
|
|
|
44859
44868
|
_v7Precision: 0,
|
|
44860
44869
|
_v8Verdict: "DORMANT",
|
|
44861
44870
|
_v8Lift: 1,
|
|
44871
|
+
_v9Verdict: "DORMANT",
|
|
44872
|
+
_v9Lift: 2.11,
|
|
44873
|
+
_v9Recall: 469e-5,
|
|
44874
|
+
_v9FpRate: 222e-5,
|
|
44875
|
+
_v9Precision: 0.1429,
|
|
44862
44876
|
defaultOff: true
|
|
44863
44877
|
},
|
|
44864
44878
|
"kotlin/coroutine-global-scope": {
|
|
44865
|
-
recall:
|
|
44866
|
-
fpRate: 0,
|
|
44867
|
-
ratio:
|
|
44868
|
-
precision:
|
|
44869
|
-
lastCalibratedAt: "2026-07-
|
|
44879
|
+
recall: 469e-5,
|
|
44880
|
+
fpRate: 0.05004,
|
|
44881
|
+
ratio: 0.09,
|
|
44882
|
+
precision: 735e-5,
|
|
44883
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44870
44884
|
verdict: "DORMANT",
|
|
44871
|
-
_calibrationNote: "v0.
|
|
44885
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.09 (FAR <1.0) \u2014 fires 135x more on neg than pos. Classic era-confound: pre-2022 Kotlin coroutines had GlobalScope as the default; modern Kotlin uses viewModelScope / lifecycleScope. The rule detects era, not AI authorship.",
|
|
44872
44886
|
aiSpecific: true,
|
|
44873
44887
|
_v7Verdict: "DORMANT",
|
|
44874
44888
|
_v7Lift: 1,
|
|
@@ -44877,16 +44891,21 @@ var signal_strength_default = {
|
|
|
44877
44891
|
_v7Precision: 0,
|
|
44878
44892
|
_v8Verdict: "DORMANT",
|
|
44879
44893
|
_v8Lift: 1,
|
|
44894
|
+
_v9Verdict: "DORMANT",
|
|
44895
|
+
_v9Lift: 0.09,
|
|
44896
|
+
_v9Recall: 469e-5,
|
|
44897
|
+
_v9FpRate: 0.05004,
|
|
44898
|
+
_v9Precision: 735e-5,
|
|
44880
44899
|
defaultOff: true
|
|
44881
44900
|
},
|
|
44882
44901
|
"kotlin/println-debug": {
|
|
44883
|
-
recall: 0,
|
|
44884
|
-
fpRate: 0,
|
|
44885
|
-
ratio:
|
|
44886
|
-
precision: 0,
|
|
44887
|
-
lastCalibratedAt: "2026-07-
|
|
44902
|
+
recall: 0.07042,
|
|
44903
|
+
fpRate: 0.11379,
|
|
44904
|
+
ratio: 0.62,
|
|
44905
|
+
precision: 0.04659,
|
|
44906
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44888
44907
|
verdict: "DORMANT",
|
|
44889
|
-
_calibrationNote: "v0.
|
|
44908
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.62 (\u226A1.0) \u2014 fires 20x more on neg than pos. Classic era-confound: pre-2022 Kotlin code uses println() for debug; modern Kotlin uses Timber / android.util.Log / kermit.",
|
|
44890
44909
|
aiSpecific: true,
|
|
44891
44910
|
_v7Verdict: "DORMANT",
|
|
44892
44911
|
_v7Lift: 1,
|
|
@@ -44895,16 +44914,21 @@ var signal_strength_default = {
|
|
|
44895
44914
|
_v7Precision: 0,
|
|
44896
44915
|
_v8Verdict: "DORMANT",
|
|
44897
44916
|
_v8Lift: 1,
|
|
44917
|
+
_v9Verdict: "DORMANT",
|
|
44918
|
+
_v9Lift: 0.62,
|
|
44919
|
+
_v9Recall: 0.07042,
|
|
44920
|
+
_v9FpRate: 0.11379,
|
|
44921
|
+
_v9Precision: 0.04659,
|
|
44898
44922
|
defaultOff: true
|
|
44899
44923
|
},
|
|
44900
44924
|
"kotlin/object-singleton-misuse": {
|
|
44901
|
-
recall:
|
|
44902
|
-
fpRate:
|
|
44903
|
-
ratio: 1,
|
|
44904
|
-
precision: 0,
|
|
44905
|
-
lastCalibratedAt: "2026-07-
|
|
44925
|
+
recall: 469e-5,
|
|
44926
|
+
fpRate: 371e-5,
|
|
44927
|
+
ratio: 1.27,
|
|
44928
|
+
precision: 0.09091,
|
|
44929
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44906
44930
|
verdict: "DORMANT",
|
|
44907
|
-
_calibrationNote: "v0.
|
|
44931
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.27 (\u22651.0) but <1.5; precision=9.1% \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files (under 10k minimum).",
|
|
44908
44932
|
aiSpecific: true,
|
|
44909
44933
|
_v7Verdict: "DORMANT",
|
|
44910
44934
|
_v7Lift: 1,
|
|
@@ -44913,16 +44937,21 @@ var signal_strength_default = {
|
|
|
44913
44937
|
_v7Precision: 0,
|
|
44914
44938
|
_v8Verdict: "DORMANT",
|
|
44915
44939
|
_v8Lift: 1,
|
|
44940
|
+
_v9Verdict: "DORMANT",
|
|
44941
|
+
_v9Lift: 1.27,
|
|
44942
|
+
_v9Recall: 469e-5,
|
|
44943
|
+
_v9FpRate: 371e-5,
|
|
44944
|
+
_v9Precision: 0.09091,
|
|
44916
44945
|
defaultOff: true
|
|
44917
44946
|
},
|
|
44918
44947
|
"kotlin/string-concat-loop": {
|
|
44919
|
-
recall:
|
|
44920
|
-
fpRate:
|
|
44921
|
-
ratio: 1,
|
|
44922
|
-
precision: 0,
|
|
44923
|
-
lastCalibratedAt: "2026-07-
|
|
44948
|
+
recall: 939e-5,
|
|
44949
|
+
fpRate: 519e-5,
|
|
44950
|
+
ratio: 1.81,
|
|
44951
|
+
precision: 0.125,
|
|
44952
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44924
44953
|
verdict: "DORMANT",
|
|
44925
|
-
_calibrationNote: "v0.
|
|
44954
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.81 (\u22651.5) but precision=12.5% (<50%) \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files.",
|
|
44926
44955
|
aiSpecific: true,
|
|
44927
44956
|
_v7Verdict: "DORMANT",
|
|
44928
44957
|
_v7Lift: 1,
|
|
@@ -44931,6 +44960,11 @@ var signal_strength_default = {
|
|
|
44931
44960
|
_v7Precision: 0,
|
|
44932
44961
|
_v8Verdict: "DORMANT",
|
|
44933
44962
|
_v8Lift: 1,
|
|
44963
|
+
_v9Verdict: "DORMANT",
|
|
44964
|
+
_v9Lift: 1.81,
|
|
44965
|
+
_v9Recall: 939e-5,
|
|
44966
|
+
_v9FpRate: 519e-5,
|
|
44967
|
+
_v9Precision: 0.125,
|
|
44934
44968
|
defaultOff: true
|
|
44935
44969
|
},
|
|
44936
44970
|
"swift/force-unwrap": {
|
|
@@ -45163,8 +45197,6 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
|
45163
45197
|
const ext = (0, import_node_path9.extname)(filePath).toLowerCase();
|
|
45164
45198
|
const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
|
|
45165
45199
|
".swift",
|
|
45166
|
-
".kt",
|
|
45167
|
-
".kts",
|
|
45168
45200
|
".dart",
|
|
45169
45201
|
".cpp",
|
|
45170
45202
|
".cc",
|
package/dist/engine/worker.js
CHANGED
|
@@ -4337,6 +4337,15 @@ function parseSource(source, filePath) {
|
|
|
4337
4337
|
case "go":
|
|
4338
4338
|
case "rs":
|
|
4339
4339
|
case "java":
|
|
4340
|
+
// v0.28.0: Kotlin files get the same parseBlankModule path as
|
|
4341
|
+
// Java (v0.24.5). All 5 `kotlin/*` rules are regex-based and
|
|
4342
|
+
// gate themselves on `/\.kts?$/i.test(filePath)` inside their
|
|
4343
|
+
// `analyze()`. The tree-sitter Kotlin integration is a larger
|
|
4344
|
+
// lift; the v0.27.0 methodology paper confirmed era-confounding
|
|
4345
|
+
// is the dominant signal anyway, so a regex-only Kotlin pass is
|
|
4346
|
+
// sufficient for the v9 calibration goal.
|
|
4347
|
+
case "kt":
|
|
4348
|
+
case "kts":
|
|
4340
4349
|
return parseBlankModule(source);
|
|
4341
4350
|
default:
|
|
4342
4351
|
return parseWithSwc(source, filePath);
|
|
@@ -36977,7 +36986,7 @@ var kotlinCoroutineGlobalScopeRule = createRule({
|
|
|
36977
36986
|
const issues = [];
|
|
36978
36987
|
const source = facts.v2?._source;
|
|
36979
36988
|
if (!source) return issues;
|
|
36980
|
-
if (!/\.
|
|
36989
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
36981
36990
|
let m;
|
|
36982
36991
|
GLOBAL_SCOPE_REGEX.lastIndex = 0;
|
|
36983
36992
|
while ((m = GLOBAL_SCOPE_REGEX.exec(source)) !== null) {
|
|
@@ -37014,7 +37023,7 @@ var kotlinDataClassDefaultsOveruseRule = createRule({
|
|
|
37014
37023
|
const issues = [];
|
|
37015
37024
|
const source = facts.v2?._source;
|
|
37016
37025
|
if (!source) return issues;
|
|
37017
|
-
if (!/\.
|
|
37026
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37018
37027
|
let m;
|
|
37019
37028
|
DATA_CLASS_HEAD_REGEX.lastIndex = 0;
|
|
37020
37029
|
while ((m = DATA_CLASS_HEAD_REGEX.exec(source)) !== null) {
|
|
@@ -37069,7 +37078,7 @@ var kotlinObjectSingletonMisuseRule = createRule({
|
|
|
37069
37078
|
const issues = [];
|
|
37070
37079
|
const source = facts.v2?._source;
|
|
37071
37080
|
if (!source) return issues;
|
|
37072
|
-
if (!/\.
|
|
37081
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37073
37082
|
let m;
|
|
37074
37083
|
OBJECT_DECL_REGEX.lastIndex = 0;
|
|
37075
37084
|
while ((m = OBJECT_DECL_REGEX.exec(source)) !== null) {
|
|
@@ -37120,7 +37129,7 @@ var kotlinPrintlnDebugRule = createRule({
|
|
|
37120
37129
|
const issues = [];
|
|
37121
37130
|
const source = facts.v2?._source;
|
|
37122
37131
|
if (!source) return issues;
|
|
37123
|
-
if (!/\.
|
|
37132
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37124
37133
|
const matches = [];
|
|
37125
37134
|
let m;
|
|
37126
37135
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -37162,7 +37171,7 @@ var kotlinStringConcatLoopRule = createRule({
|
|
|
37162
37171
|
const issues = [];
|
|
37163
37172
|
const source = facts.v2?._source;
|
|
37164
37173
|
if (!source) return issues;
|
|
37165
|
-
if (!/\.
|
|
37174
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
37166
37175
|
if (!/\b(?:for|while|repeat|forEach)\b/.test(source)) return issues;
|
|
37167
37176
|
let m;
|
|
37168
37177
|
STRING_CONCAT_REGEX.lastIndex = 0;
|
|
@@ -44815,13 +44824,13 @@ var signal_strength_default = {
|
|
|
44815
44824
|
defaultOff: true
|
|
44816
44825
|
},
|
|
44817
44826
|
"kotlin/data-class-defaults-overuse": {
|
|
44818
|
-
recall:
|
|
44819
|
-
fpRate:
|
|
44820
|
-
ratio:
|
|
44821
|
-
precision: 0,
|
|
44822
|
-
lastCalibratedAt: "2026-07-
|
|
44827
|
+
recall: 469e-5,
|
|
44828
|
+
fpRate: 222e-5,
|
|
44829
|
+
ratio: 2.11,
|
|
44830
|
+
precision: 0.1429,
|
|
44831
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44823
44832
|
verdict: "DORMANT",
|
|
44824
|
-
_calibrationNote: "v0.
|
|
44833
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=2.11 (\u22651.5) but precision=14.3% (<50%) \u2014 verdict DORMANT. Era-confounding: pre-2022 Kotlin is sparse; the rule fires on the rare .kt file with multiple default values regardless of authorship.",
|
|
44825
44834
|
aiSpecific: true,
|
|
44826
44835
|
_v7Verdict: "DORMANT",
|
|
44827
44836
|
_v7Lift: 1,
|
|
@@ -44830,16 +44839,21 @@ var signal_strength_default = {
|
|
|
44830
44839
|
_v7Precision: 0,
|
|
44831
44840
|
_v8Verdict: "DORMANT",
|
|
44832
44841
|
_v8Lift: 1,
|
|
44842
|
+
_v9Verdict: "DORMANT",
|
|
44843
|
+
_v9Lift: 2.11,
|
|
44844
|
+
_v9Recall: 469e-5,
|
|
44845
|
+
_v9FpRate: 222e-5,
|
|
44846
|
+
_v9Precision: 0.1429,
|
|
44833
44847
|
defaultOff: true
|
|
44834
44848
|
},
|
|
44835
44849
|
"kotlin/coroutine-global-scope": {
|
|
44836
|
-
recall:
|
|
44837
|
-
fpRate: 0,
|
|
44838
|
-
ratio:
|
|
44839
|
-
precision:
|
|
44840
|
-
lastCalibratedAt: "2026-07-
|
|
44850
|
+
recall: 469e-5,
|
|
44851
|
+
fpRate: 0.05004,
|
|
44852
|
+
ratio: 0.09,
|
|
44853
|
+
precision: 735e-5,
|
|
44854
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44841
44855
|
verdict: "DORMANT",
|
|
44842
|
-
_calibrationNote: "v0.
|
|
44856
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.09 (FAR <1.0) \u2014 fires 135x more on neg than pos. Classic era-confound: pre-2022 Kotlin coroutines had GlobalScope as the default; modern Kotlin uses viewModelScope / lifecycleScope. The rule detects era, not AI authorship.",
|
|
44843
44857
|
aiSpecific: true,
|
|
44844
44858
|
_v7Verdict: "DORMANT",
|
|
44845
44859
|
_v7Lift: 1,
|
|
@@ -44848,16 +44862,21 @@ var signal_strength_default = {
|
|
|
44848
44862
|
_v7Precision: 0,
|
|
44849
44863
|
_v8Verdict: "DORMANT",
|
|
44850
44864
|
_v8Lift: 1,
|
|
44865
|
+
_v9Verdict: "DORMANT",
|
|
44866
|
+
_v9Lift: 0.09,
|
|
44867
|
+
_v9Recall: 469e-5,
|
|
44868
|
+
_v9FpRate: 0.05004,
|
|
44869
|
+
_v9Precision: 735e-5,
|
|
44851
44870
|
defaultOff: true
|
|
44852
44871
|
},
|
|
44853
44872
|
"kotlin/println-debug": {
|
|
44854
|
-
recall: 0,
|
|
44855
|
-
fpRate: 0,
|
|
44856
|
-
ratio:
|
|
44857
|
-
precision: 0,
|
|
44858
|
-
lastCalibratedAt: "2026-07-
|
|
44873
|
+
recall: 0.07042,
|
|
44874
|
+
fpRate: 0.11379,
|
|
44875
|
+
ratio: 0.62,
|
|
44876
|
+
precision: 0.04659,
|
|
44877
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44859
44878
|
verdict: "DORMANT",
|
|
44860
|
-
_calibrationNote: "v0.
|
|
44879
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.62 (\u226A1.0) \u2014 fires 20x more on neg than pos. Classic era-confound: pre-2022 Kotlin code uses println() for debug; modern Kotlin uses Timber / android.util.Log / kermit.",
|
|
44861
44880
|
aiSpecific: true,
|
|
44862
44881
|
_v7Verdict: "DORMANT",
|
|
44863
44882
|
_v7Lift: 1,
|
|
@@ -44866,16 +44885,21 @@ var signal_strength_default = {
|
|
|
44866
44885
|
_v7Precision: 0,
|
|
44867
44886
|
_v8Verdict: "DORMANT",
|
|
44868
44887
|
_v8Lift: 1,
|
|
44888
|
+
_v9Verdict: "DORMANT",
|
|
44889
|
+
_v9Lift: 0.62,
|
|
44890
|
+
_v9Recall: 0.07042,
|
|
44891
|
+
_v9FpRate: 0.11379,
|
|
44892
|
+
_v9Precision: 0.04659,
|
|
44869
44893
|
defaultOff: true
|
|
44870
44894
|
},
|
|
44871
44895
|
"kotlin/object-singleton-misuse": {
|
|
44872
|
-
recall:
|
|
44873
|
-
fpRate:
|
|
44874
|
-
ratio: 1,
|
|
44875
|
-
precision: 0,
|
|
44876
|
-
lastCalibratedAt: "2026-07-
|
|
44896
|
+
recall: 469e-5,
|
|
44897
|
+
fpRate: 371e-5,
|
|
44898
|
+
ratio: 1.27,
|
|
44899
|
+
precision: 0.09091,
|
|
44900
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44877
44901
|
verdict: "DORMANT",
|
|
44878
|
-
_calibrationNote: "v0.
|
|
44902
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.27 (\u22651.0) but <1.5; precision=9.1% \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files (under 10k minimum).",
|
|
44879
44903
|
aiSpecific: true,
|
|
44880
44904
|
_v7Verdict: "DORMANT",
|
|
44881
44905
|
_v7Lift: 1,
|
|
@@ -44884,16 +44908,21 @@ var signal_strength_default = {
|
|
|
44884
44908
|
_v7Precision: 0,
|
|
44885
44909
|
_v8Verdict: "DORMANT",
|
|
44886
44910
|
_v8Lift: 1,
|
|
44911
|
+
_v9Verdict: "DORMANT",
|
|
44912
|
+
_v9Lift: 1.27,
|
|
44913
|
+
_v9Recall: 469e-5,
|
|
44914
|
+
_v9FpRate: 371e-5,
|
|
44915
|
+
_v9Precision: 0.09091,
|
|
44887
44916
|
defaultOff: true
|
|
44888
44917
|
},
|
|
44889
44918
|
"kotlin/string-concat-loop": {
|
|
44890
|
-
recall:
|
|
44891
|
-
fpRate:
|
|
44892
|
-
ratio: 1,
|
|
44893
|
-
precision: 0,
|
|
44894
|
-
lastCalibratedAt: "2026-07-
|
|
44919
|
+
recall: 939e-5,
|
|
44920
|
+
fpRate: 519e-5,
|
|
44921
|
+
ratio: 1.81,
|
|
44922
|
+
precision: 0.125,
|
|
44923
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
44895
44924
|
verdict: "DORMANT",
|
|
44896
|
-
_calibrationNote: "v0.
|
|
44925
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.81 (\u22651.5) but precision=12.5% (<50%) \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files.",
|
|
44897
44926
|
aiSpecific: true,
|
|
44898
44927
|
_v7Verdict: "DORMANT",
|
|
44899
44928
|
_v7Lift: 1,
|
|
@@ -44902,6 +44931,11 @@ var signal_strength_default = {
|
|
|
44902
44931
|
_v7Precision: 0,
|
|
44903
44932
|
_v8Verdict: "DORMANT",
|
|
44904
44933
|
_v8Lift: 1,
|
|
44934
|
+
_v9Verdict: "DORMANT",
|
|
44935
|
+
_v9Lift: 1.81,
|
|
44936
|
+
_v9Recall: 939e-5,
|
|
44937
|
+
_v9FpRate: 519e-5,
|
|
44938
|
+
_v9Precision: 0.125,
|
|
44905
44939
|
defaultOff: true
|
|
44906
44940
|
},
|
|
44907
44941
|
"swift/force-unwrap": {
|
|
@@ -45134,8 +45168,6 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
|
45134
45168
|
const ext = extname4(filePath).toLowerCase();
|
|
45135
45169
|
const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
|
|
45136
45170
|
".swift",
|
|
45137
|
-
".kt",
|
|
45138
|
-
".kts",
|
|
45139
45171
|
".dart",
|
|
45140
45172
|
".cpp",
|
|
45141
45173
|
".cc",
|
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ var VERSION;
|
|
|
36
36
|
var init_header = __esm({
|
|
37
37
|
"src/types/_header.ts"() {
|
|
38
38
|
"use strict";
|
|
39
|
-
VERSION = "0.
|
|
39
|
+
VERSION = "0.28.0";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -30682,7 +30682,7 @@ var init_coroutine_global_scope = __esm({
|
|
|
30682
30682
|
const issues = [];
|
|
30683
30683
|
const source = facts.v2?._source;
|
|
30684
30684
|
if (!source) return issues;
|
|
30685
|
-
if (!/\.
|
|
30685
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30686
30686
|
let m;
|
|
30687
30687
|
GLOBAL_SCOPE_REGEX.lastIndex = 0;
|
|
30688
30688
|
while ((m = GLOBAL_SCOPE_REGEX.exec(source)) !== null) {
|
|
@@ -30726,7 +30726,7 @@ var init_data_class_defaults_overuse = __esm({
|
|
|
30726
30726
|
const issues = [];
|
|
30727
30727
|
const source = facts.v2?._source;
|
|
30728
30728
|
if (!source) return issues;
|
|
30729
|
-
if (!/\.
|
|
30729
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30730
30730
|
let m;
|
|
30731
30731
|
DATA_CLASS_HEAD_REGEX.lastIndex = 0;
|
|
30732
30732
|
while ((m = DATA_CLASS_HEAD_REGEX.exec(source)) !== null) {
|
|
@@ -30788,7 +30788,7 @@ var init_object_singleton_misuse = __esm({
|
|
|
30788
30788
|
const issues = [];
|
|
30789
30789
|
const source = facts.v2?._source;
|
|
30790
30790
|
if (!source) return issues;
|
|
30791
|
-
if (!/\.
|
|
30791
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30792
30792
|
let m;
|
|
30793
30793
|
OBJECT_DECL_REGEX.lastIndex = 0;
|
|
30794
30794
|
while ((m = OBJECT_DECL_REGEX.exec(source)) !== null) {
|
|
@@ -30846,7 +30846,7 @@ var init_println_debug = __esm({
|
|
|
30846
30846
|
const issues = [];
|
|
30847
30847
|
const source = facts.v2?._source;
|
|
30848
30848
|
if (!source) return issues;
|
|
30849
|
-
if (!/\.
|
|
30849
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30850
30850
|
const matches = [];
|
|
30851
30851
|
let m;
|
|
30852
30852
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -30895,7 +30895,7 @@ var init_string_concat_loop = __esm({
|
|
|
30895
30895
|
const issues = [];
|
|
30896
30896
|
const source = facts.v2?._source;
|
|
30897
30897
|
if (!source) return issues;
|
|
30898
|
-
if (!/\.
|
|
30898
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30899
30899
|
if (!/\b(?:for|while|repeat|forEach)\b/.test(source)) return issues;
|
|
30900
30900
|
let m;
|
|
30901
30901
|
STRING_CONCAT_REGEX.lastIndex = 0;
|
|
@@ -36117,6 +36117,15 @@ function parseSource(source, filePath) {
|
|
|
36117
36117
|
case "go":
|
|
36118
36118
|
case "rs":
|
|
36119
36119
|
case "java":
|
|
36120
|
+
// v0.28.0: Kotlin files get the same parseBlankModule path as
|
|
36121
|
+
// Java (v0.24.5). All 5 `kotlin/*` rules are regex-based and
|
|
36122
|
+
// gate themselves on `/\.kts?$/i.test(filePath)` inside their
|
|
36123
|
+
// `analyze()`. The tree-sitter Kotlin integration is a larger
|
|
36124
|
+
// lift; the v0.27.0 methodology paper confirmed era-confounding
|
|
36125
|
+
// is the dominant signal anyway, so a regex-only Kotlin pass is
|
|
36126
|
+
// sufficient for the v9 calibration goal.
|
|
36127
|
+
case "kt":
|
|
36128
|
+
case "kts":
|
|
36120
36129
|
return parseBlankModule(source);
|
|
36121
36130
|
default:
|
|
36122
36131
|
return parseWithSwc(source, filePath);
|
|
@@ -50851,13 +50860,13 @@ var init_signal_strength = __esm({
|
|
|
50851
50860
|
defaultOff: true
|
|
50852
50861
|
},
|
|
50853
50862
|
"kotlin/data-class-defaults-overuse": {
|
|
50854
|
-
recall:
|
|
50855
|
-
fpRate:
|
|
50856
|
-
ratio:
|
|
50857
|
-
precision: 0,
|
|
50858
|
-
lastCalibratedAt: "2026-07-
|
|
50863
|
+
recall: 469e-5,
|
|
50864
|
+
fpRate: 222e-5,
|
|
50865
|
+
ratio: 2.11,
|
|
50866
|
+
precision: 0.1429,
|
|
50867
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50859
50868
|
verdict: "DORMANT",
|
|
50860
|
-
_calibrationNote: "v0.
|
|
50869
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=2.11 (\u22651.5) but precision=14.3% (<50%) \u2014 verdict DORMANT. Era-confounding: pre-2022 Kotlin is sparse; the rule fires on the rare .kt file with multiple default values regardless of authorship.",
|
|
50861
50870
|
aiSpecific: true,
|
|
50862
50871
|
_v7Verdict: "DORMANT",
|
|
50863
50872
|
_v7Lift: 1,
|
|
@@ -50866,16 +50875,21 @@ var init_signal_strength = __esm({
|
|
|
50866
50875
|
_v7Precision: 0,
|
|
50867
50876
|
_v8Verdict: "DORMANT",
|
|
50868
50877
|
_v8Lift: 1,
|
|
50878
|
+
_v9Verdict: "DORMANT",
|
|
50879
|
+
_v9Lift: 2.11,
|
|
50880
|
+
_v9Recall: 469e-5,
|
|
50881
|
+
_v9FpRate: 222e-5,
|
|
50882
|
+
_v9Precision: 0.1429,
|
|
50869
50883
|
defaultOff: true
|
|
50870
50884
|
},
|
|
50871
50885
|
"kotlin/coroutine-global-scope": {
|
|
50872
|
-
recall:
|
|
50873
|
-
fpRate: 0,
|
|
50874
|
-
ratio:
|
|
50875
|
-
precision:
|
|
50876
|
-
lastCalibratedAt: "2026-07-
|
|
50886
|
+
recall: 469e-5,
|
|
50887
|
+
fpRate: 0.05004,
|
|
50888
|
+
ratio: 0.09,
|
|
50889
|
+
precision: 735e-5,
|
|
50890
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50877
50891
|
verdict: "DORMANT",
|
|
50878
|
-
_calibrationNote: "v0.
|
|
50892
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.09 (FAR <1.0) \u2014 fires 135x more on neg than pos. Classic era-confound: pre-2022 Kotlin coroutines had GlobalScope as the default; modern Kotlin uses viewModelScope / lifecycleScope. The rule detects era, not AI authorship.",
|
|
50879
50893
|
aiSpecific: true,
|
|
50880
50894
|
_v7Verdict: "DORMANT",
|
|
50881
50895
|
_v7Lift: 1,
|
|
@@ -50884,16 +50898,21 @@ var init_signal_strength = __esm({
|
|
|
50884
50898
|
_v7Precision: 0,
|
|
50885
50899
|
_v8Verdict: "DORMANT",
|
|
50886
50900
|
_v8Lift: 1,
|
|
50901
|
+
_v9Verdict: "DORMANT",
|
|
50902
|
+
_v9Lift: 0.09,
|
|
50903
|
+
_v9Recall: 469e-5,
|
|
50904
|
+
_v9FpRate: 0.05004,
|
|
50905
|
+
_v9Precision: 735e-5,
|
|
50887
50906
|
defaultOff: true
|
|
50888
50907
|
},
|
|
50889
50908
|
"kotlin/println-debug": {
|
|
50890
|
-
recall: 0,
|
|
50891
|
-
fpRate: 0,
|
|
50892
|
-
ratio:
|
|
50893
|
-
precision: 0,
|
|
50894
|
-
lastCalibratedAt: "2026-07-
|
|
50909
|
+
recall: 0.07042,
|
|
50910
|
+
fpRate: 0.11379,
|
|
50911
|
+
ratio: 0.62,
|
|
50912
|
+
precision: 0.04659,
|
|
50913
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50895
50914
|
verdict: "DORMANT",
|
|
50896
|
-
_calibrationNote: "v0.
|
|
50915
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.62 (\u226A1.0) \u2014 fires 20x more on neg than pos. Classic era-confound: pre-2022 Kotlin code uses println() for debug; modern Kotlin uses Timber / android.util.Log / kermit.",
|
|
50897
50916
|
aiSpecific: true,
|
|
50898
50917
|
_v7Verdict: "DORMANT",
|
|
50899
50918
|
_v7Lift: 1,
|
|
@@ -50902,16 +50921,21 @@ var init_signal_strength = __esm({
|
|
|
50902
50921
|
_v7Precision: 0,
|
|
50903
50922
|
_v8Verdict: "DORMANT",
|
|
50904
50923
|
_v8Lift: 1,
|
|
50924
|
+
_v9Verdict: "DORMANT",
|
|
50925
|
+
_v9Lift: 0.62,
|
|
50926
|
+
_v9Recall: 0.07042,
|
|
50927
|
+
_v9FpRate: 0.11379,
|
|
50928
|
+
_v9Precision: 0.04659,
|
|
50905
50929
|
defaultOff: true
|
|
50906
50930
|
},
|
|
50907
50931
|
"kotlin/object-singleton-misuse": {
|
|
50908
|
-
recall:
|
|
50909
|
-
fpRate:
|
|
50910
|
-
ratio: 1,
|
|
50911
|
-
precision: 0,
|
|
50912
|
-
lastCalibratedAt: "2026-07-
|
|
50932
|
+
recall: 469e-5,
|
|
50933
|
+
fpRate: 371e-5,
|
|
50934
|
+
ratio: 1.27,
|
|
50935
|
+
precision: 0.09091,
|
|
50936
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50913
50937
|
verdict: "DORMANT",
|
|
50914
|
-
_calibrationNote: "v0.
|
|
50938
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.27 (\u22651.0) but <1.5; precision=9.1% \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files (under 10k minimum).",
|
|
50915
50939
|
aiSpecific: true,
|
|
50916
50940
|
_v7Verdict: "DORMANT",
|
|
50917
50941
|
_v7Lift: 1,
|
|
@@ -50920,16 +50944,21 @@ var init_signal_strength = __esm({
|
|
|
50920
50944
|
_v7Precision: 0,
|
|
50921
50945
|
_v8Verdict: "DORMANT",
|
|
50922
50946
|
_v8Lift: 1,
|
|
50947
|
+
_v9Verdict: "DORMANT",
|
|
50948
|
+
_v9Lift: 1.27,
|
|
50949
|
+
_v9Recall: 469e-5,
|
|
50950
|
+
_v9FpRate: 371e-5,
|
|
50951
|
+
_v9Precision: 0.09091,
|
|
50923
50952
|
defaultOff: true
|
|
50924
50953
|
},
|
|
50925
50954
|
"kotlin/string-concat-loop": {
|
|
50926
|
-
recall:
|
|
50927
|
-
fpRate:
|
|
50928
|
-
ratio: 1,
|
|
50929
|
-
precision: 0,
|
|
50930
|
-
lastCalibratedAt: "2026-07-
|
|
50955
|
+
recall: 939e-5,
|
|
50956
|
+
fpRate: 519e-5,
|
|
50957
|
+
ratio: 1.81,
|
|
50958
|
+
precision: 0.125,
|
|
50959
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50931
50960
|
verdict: "DORMANT",
|
|
50932
|
-
_calibrationNote: "v0.
|
|
50961
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.81 (\u22651.5) but precision=12.5% (<50%) \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files.",
|
|
50933
50962
|
aiSpecific: true,
|
|
50934
50963
|
_v7Verdict: "DORMANT",
|
|
50935
50964
|
_v7Lift: 1,
|
|
@@ -50938,6 +50967,11 @@ var init_signal_strength = __esm({
|
|
|
50938
50967
|
_v7Precision: 0,
|
|
50939
50968
|
_v8Verdict: "DORMANT",
|
|
50940
50969
|
_v8Lift: 1,
|
|
50970
|
+
_v9Verdict: "DORMANT",
|
|
50971
|
+
_v9Lift: 1.81,
|
|
50972
|
+
_v9Recall: 939e-5,
|
|
50973
|
+
_v9FpRate: 519e-5,
|
|
50974
|
+
_v9Precision: 0.125,
|
|
50941
50975
|
defaultOff: true
|
|
50942
50976
|
},
|
|
50943
50977
|
"swift/force-unwrap": {
|
|
@@ -51198,8 +51232,6 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
|
51198
51232
|
const ext = (0, import_node_path12.extname)(filePath).toLowerCase();
|
|
51199
51233
|
const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
|
|
51200
51234
|
".swift",
|
|
51201
|
-
".kt",
|
|
51202
|
-
".kts",
|
|
51203
51235
|
".dart",
|
|
51204
51236
|
".cpp",
|
|
51205
51237
|
".cc",
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var VERSION;
|
|
|
19
19
|
var init_header = __esm({
|
|
20
20
|
"src/types/_header.ts"() {
|
|
21
21
|
"use strict";
|
|
22
|
-
VERSION = "0.
|
|
22
|
+
VERSION = "0.28.0";
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -30663,7 +30663,7 @@ var init_coroutine_global_scope = __esm({
|
|
|
30663
30663
|
const issues = [];
|
|
30664
30664
|
const source = facts.v2?._source;
|
|
30665
30665
|
if (!source) return issues;
|
|
30666
|
-
if (!/\.
|
|
30666
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30667
30667
|
let m;
|
|
30668
30668
|
GLOBAL_SCOPE_REGEX.lastIndex = 0;
|
|
30669
30669
|
while ((m = GLOBAL_SCOPE_REGEX.exec(source)) !== null) {
|
|
@@ -30707,7 +30707,7 @@ var init_data_class_defaults_overuse = __esm({
|
|
|
30707
30707
|
const issues = [];
|
|
30708
30708
|
const source = facts.v2?._source;
|
|
30709
30709
|
if (!source) return issues;
|
|
30710
|
-
if (!/\.
|
|
30710
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30711
30711
|
let m;
|
|
30712
30712
|
DATA_CLASS_HEAD_REGEX.lastIndex = 0;
|
|
30713
30713
|
while ((m = DATA_CLASS_HEAD_REGEX.exec(source)) !== null) {
|
|
@@ -30769,7 +30769,7 @@ var init_object_singleton_misuse = __esm({
|
|
|
30769
30769
|
const issues = [];
|
|
30770
30770
|
const source = facts.v2?._source;
|
|
30771
30771
|
if (!source) return issues;
|
|
30772
|
-
if (!/\.
|
|
30772
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30773
30773
|
let m;
|
|
30774
30774
|
OBJECT_DECL_REGEX.lastIndex = 0;
|
|
30775
30775
|
while ((m = OBJECT_DECL_REGEX.exec(source)) !== null) {
|
|
@@ -30827,7 +30827,7 @@ var init_println_debug = __esm({
|
|
|
30827
30827
|
const issues = [];
|
|
30828
30828
|
const source = facts.v2?._source;
|
|
30829
30829
|
if (!source) return issues;
|
|
30830
|
-
if (!/\.
|
|
30830
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30831
30831
|
const matches = [];
|
|
30832
30832
|
let m;
|
|
30833
30833
|
PRINTLN_REGEX.lastIndex = 0;
|
|
@@ -30876,7 +30876,7 @@ var init_string_concat_loop = __esm({
|
|
|
30876
30876
|
const issues = [];
|
|
30877
30877
|
const source = facts.v2?._source;
|
|
30878
30878
|
if (!source) return issues;
|
|
30879
|
-
if (!/\.
|
|
30879
|
+
if (!/\.kts?$/i.test(facts.filePath)) return issues;
|
|
30880
30880
|
if (!/\b(?:for|while|repeat|forEach)\b/.test(source)) return issues;
|
|
30881
30881
|
let m;
|
|
30882
30882
|
STRING_CONCAT_REGEX.lastIndex = 0;
|
|
@@ -36107,6 +36107,15 @@ function parseSource(source, filePath) {
|
|
|
36107
36107
|
case "go":
|
|
36108
36108
|
case "rs":
|
|
36109
36109
|
case "java":
|
|
36110
|
+
// v0.28.0: Kotlin files get the same parseBlankModule path as
|
|
36111
|
+
// Java (v0.24.5). All 5 `kotlin/*` rules are regex-based and
|
|
36112
|
+
// gate themselves on `/\.kts?$/i.test(filePath)` inside their
|
|
36113
|
+
// `analyze()`. The tree-sitter Kotlin integration is a larger
|
|
36114
|
+
// lift; the v0.27.0 methodology paper confirmed era-confounding
|
|
36115
|
+
// is the dominant signal anyway, so a regex-only Kotlin pass is
|
|
36116
|
+
// sufficient for the v9 calibration goal.
|
|
36117
|
+
case "kt":
|
|
36118
|
+
case "kts":
|
|
36110
36119
|
return parseBlankModule(source);
|
|
36111
36120
|
default:
|
|
36112
36121
|
return parseWithSwc(source, filePath);
|
|
@@ -50829,13 +50838,13 @@ var init_signal_strength = __esm({
|
|
|
50829
50838
|
defaultOff: true
|
|
50830
50839
|
},
|
|
50831
50840
|
"kotlin/data-class-defaults-overuse": {
|
|
50832
|
-
recall:
|
|
50833
|
-
fpRate:
|
|
50834
|
-
ratio:
|
|
50835
|
-
precision: 0,
|
|
50836
|
-
lastCalibratedAt: "2026-07-
|
|
50841
|
+
recall: 469e-5,
|
|
50842
|
+
fpRate: 222e-5,
|
|
50843
|
+
ratio: 2.11,
|
|
50844
|
+
precision: 0.1429,
|
|
50845
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50837
50846
|
verdict: "DORMANT",
|
|
50838
|
-
_calibrationNote: "v0.
|
|
50847
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=2.11 (\u22651.5) but precision=14.3% (<50%) \u2014 verdict DORMANT. Era-confounding: pre-2022 Kotlin is sparse; the rule fires on the rare .kt file with multiple default values regardless of authorship.",
|
|
50839
50848
|
aiSpecific: true,
|
|
50840
50849
|
_v7Verdict: "DORMANT",
|
|
50841
50850
|
_v7Lift: 1,
|
|
@@ -50844,16 +50853,21 @@ var init_signal_strength = __esm({
|
|
|
50844
50853
|
_v7Precision: 0,
|
|
50845
50854
|
_v8Verdict: "DORMANT",
|
|
50846
50855
|
_v8Lift: 1,
|
|
50856
|
+
_v9Verdict: "DORMANT",
|
|
50857
|
+
_v9Lift: 2.11,
|
|
50858
|
+
_v9Recall: 469e-5,
|
|
50859
|
+
_v9FpRate: 222e-5,
|
|
50860
|
+
_v9Precision: 0.1429,
|
|
50847
50861
|
defaultOff: true
|
|
50848
50862
|
},
|
|
50849
50863
|
"kotlin/coroutine-global-scope": {
|
|
50850
|
-
recall:
|
|
50851
|
-
fpRate: 0,
|
|
50852
|
-
ratio:
|
|
50853
|
-
precision:
|
|
50854
|
-
lastCalibratedAt: "2026-07-
|
|
50864
|
+
recall: 469e-5,
|
|
50865
|
+
fpRate: 0.05004,
|
|
50866
|
+
ratio: 0.09,
|
|
50867
|
+
precision: 735e-5,
|
|
50868
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50855
50869
|
verdict: "DORMANT",
|
|
50856
|
-
_calibrationNote: "v0.
|
|
50870
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.09 (FAR <1.0) \u2014 fires 135x more on neg than pos. Classic era-confound: pre-2022 Kotlin coroutines had GlobalScope as the default; modern Kotlin uses viewModelScope / lifecycleScope. The rule detects era, not AI authorship.",
|
|
50857
50871
|
aiSpecific: true,
|
|
50858
50872
|
_v7Verdict: "DORMANT",
|
|
50859
50873
|
_v7Lift: 1,
|
|
@@ -50862,16 +50876,21 @@ var init_signal_strength = __esm({
|
|
|
50862
50876
|
_v7Precision: 0,
|
|
50863
50877
|
_v8Verdict: "DORMANT",
|
|
50864
50878
|
_v8Lift: 1,
|
|
50879
|
+
_v9Verdict: "DORMANT",
|
|
50880
|
+
_v9Lift: 0.09,
|
|
50881
|
+
_v9Recall: 469e-5,
|
|
50882
|
+
_v9FpRate: 0.05004,
|
|
50883
|
+
_v9Precision: 735e-5,
|
|
50865
50884
|
defaultOff: true
|
|
50866
50885
|
},
|
|
50867
50886
|
"kotlin/println-debug": {
|
|
50868
|
-
recall: 0,
|
|
50869
|
-
fpRate: 0,
|
|
50870
|
-
ratio:
|
|
50871
|
-
precision: 0,
|
|
50872
|
-
lastCalibratedAt: "2026-07-
|
|
50887
|
+
recall: 0.07042,
|
|
50888
|
+
fpRate: 0.11379,
|
|
50889
|
+
ratio: 0.62,
|
|
50890
|
+
precision: 0.04659,
|
|
50891
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50873
50892
|
verdict: "DORMANT",
|
|
50874
|
-
_calibrationNote: "v0.
|
|
50893
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=0.62 (\u226A1.0) \u2014 fires 20x more on neg than pos. Classic era-confound: pre-2022 Kotlin code uses println() for debug; modern Kotlin uses Timber / android.util.Log / kermit.",
|
|
50875
50894
|
aiSpecific: true,
|
|
50876
50895
|
_v7Verdict: "DORMANT",
|
|
50877
50896
|
_v7Lift: 1,
|
|
@@ -50880,16 +50899,21 @@ var init_signal_strength = __esm({
|
|
|
50880
50899
|
_v7Precision: 0,
|
|
50881
50900
|
_v8Verdict: "DORMANT",
|
|
50882
50901
|
_v8Lift: 1,
|
|
50902
|
+
_v9Verdict: "DORMANT",
|
|
50903
|
+
_v9Lift: 0.62,
|
|
50904
|
+
_v9Recall: 0.07042,
|
|
50905
|
+
_v9FpRate: 0.11379,
|
|
50906
|
+
_v9Precision: 0.04659,
|
|
50883
50907
|
defaultOff: true
|
|
50884
50908
|
},
|
|
50885
50909
|
"kotlin/object-singleton-misuse": {
|
|
50886
|
-
recall:
|
|
50887
|
-
fpRate:
|
|
50888
|
-
ratio: 1,
|
|
50889
|
-
precision: 0,
|
|
50890
|
-
lastCalibratedAt: "2026-07-
|
|
50910
|
+
recall: 469e-5,
|
|
50911
|
+
fpRate: 371e-5,
|
|
50912
|
+
ratio: 1.27,
|
|
50913
|
+
precision: 0.09091,
|
|
50914
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50891
50915
|
verdict: "DORMANT",
|
|
50892
|
-
_calibrationNote: "v0.
|
|
50916
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.27 (\u22651.0) but <1.5; precision=9.1% \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files (under 10k minimum).",
|
|
50893
50917
|
aiSpecific: true,
|
|
50894
50918
|
_v7Verdict: "DORMANT",
|
|
50895
50919
|
_v7Lift: 1,
|
|
@@ -50898,16 +50922,21 @@ var init_signal_strength = __esm({
|
|
|
50898
50922
|
_v7Precision: 0,
|
|
50899
50923
|
_v8Verdict: "DORMANT",
|
|
50900
50924
|
_v8Lift: 1,
|
|
50925
|
+
_v9Verdict: "DORMANT",
|
|
50926
|
+
_v9Lift: 1.27,
|
|
50927
|
+
_v9Recall: 469e-5,
|
|
50928
|
+
_v9FpRate: 371e-5,
|
|
50929
|
+
_v9Precision: 0.09091,
|
|
50901
50930
|
defaultOff: true
|
|
50902
50931
|
},
|
|
50903
50932
|
"kotlin/string-concat-loop": {
|
|
50904
|
-
recall:
|
|
50905
|
-
fpRate:
|
|
50906
|
-
ratio: 1,
|
|
50907
|
-
precision: 0,
|
|
50908
|
-
lastCalibratedAt: "2026-07-
|
|
50933
|
+
recall: 939e-5,
|
|
50934
|
+
fpRate: 519e-5,
|
|
50935
|
+
ratio: 1.81,
|
|
50936
|
+
precision: 0.125,
|
|
50937
|
+
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
50909
50938
|
verdict: "DORMANT",
|
|
50910
|
-
_calibrationNote: "v0.
|
|
50939
|
+
_calibrationNote: "v0.28: v9 Kotlin calibration (2698 neg, 213 pos). ratio=1.81 (\u22651.5) but precision=12.5% (<50%) \u2014 verdict DORMANT. INSUFFICIENT_DATA: pos arm only 213 files.",
|
|
50911
50940
|
aiSpecific: true,
|
|
50912
50941
|
_v7Verdict: "DORMANT",
|
|
50913
50942
|
_v7Lift: 1,
|
|
@@ -50916,6 +50945,11 @@ var init_signal_strength = __esm({
|
|
|
50916
50945
|
_v7Precision: 0,
|
|
50917
50946
|
_v8Verdict: "DORMANT",
|
|
50918
50947
|
_v8Lift: 1,
|
|
50948
|
+
_v9Verdict: "DORMANT",
|
|
50949
|
+
_v9Lift: 1.81,
|
|
50950
|
+
_v9Recall: 939e-5,
|
|
50951
|
+
_v9FpRate: 519e-5,
|
|
50952
|
+
_v9Precision: 0.125,
|
|
50919
50953
|
defaultOff: true
|
|
50920
50954
|
},
|
|
50921
50955
|
"swift/force-unwrap": {
|
|
@@ -51180,8 +51214,6 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
|
51180
51214
|
const ext = extname5(filePath).toLowerCase();
|
|
51181
51215
|
const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
|
|
51182
51216
|
".swift",
|
|
51183
|
-
".kt",
|
|
51184
|
-
".kts",
|
|
51185
51217
|
".dart",
|
|
51186
51218
|
".cpp",
|
|
51187
51219
|
".cc",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slopbrick",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Discovered, modeled, and governed repository structure. SlopBrick scans source code, classifies it against 95+ rules in 15 categories, computes 4 scores (aiSlopScore: lower=cleaner, engineeringHygiene, security, repositoryHealth composite), and persists the structure for AI agents and CI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|