slopbrick 0.24.0 → 0.25.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.
- package/dist/engine/worker.cjs +121 -37
- package/dist/engine/worker.js +122 -38
- package/dist/index.cjs +173 -94
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +203 -124
- package/package.json +1 -1
package/dist/engine/worker.cjs
CHANGED
|
@@ -37,6 +37,7 @@ module.exports = __toCommonJS(worker_exports);
|
|
|
37
37
|
var import_node_worker_threads = require("worker_threads");
|
|
38
38
|
var import_node_path9 = require("path");
|
|
39
39
|
var import_node_path10 = require("path");
|
|
40
|
+
var import_minimatch = require("minimatch");
|
|
40
41
|
|
|
41
42
|
// ../engine/dist/index.js
|
|
42
43
|
var import_promises = require("fs/promises");
|
|
@@ -4364,6 +4365,7 @@ function parseSource(source, filePath) {
|
|
|
4364
4365
|
case "py":
|
|
4365
4366
|
case "go":
|
|
4366
4367
|
case "rs":
|
|
4368
|
+
case "java":
|
|
4367
4369
|
return parseBlankModule(source);
|
|
4368
4370
|
default:
|
|
4369
4371
|
return parseWithSwc(source, filePath);
|
|
@@ -37820,6 +37822,43 @@ var DEFAULT_CONFIG3 = {
|
|
|
37820
37822
|
*/
|
|
37821
37823
|
testIntelligence: {
|
|
37822
37824
|
missingEdgeCase: false
|
|
37825
|
+
},
|
|
37826
|
+
/**
|
|
37827
|
+
* v0.25.0: self-scan exclude paths. Defaults cover the three paths
|
|
37828
|
+
* that are always false positives when scanning the slopbrick repo
|
|
37829
|
+
* itself:
|
|
37830
|
+
*
|
|
37831
|
+
* - `src/rules/**` — rule definitions contain example patterns
|
|
37832
|
+
* the rules themselves detect (self-fire). E.g. a
|
|
37833
|
+
* `security/sql-construction` rule's source file has a SQL
|
|
37834
|
+
* concat string literal that fires its own regex.
|
|
37835
|
+
* - `tests/fixtures/**` — test fixtures contain intentional bad
|
|
37836
|
+
* code that the rules must fire on to be useful (each fixture
|
|
37837
|
+
* is a positive test case). Scanning them in a self-scan
|
|
37838
|
+
* produces ~70 false-positive "issues" that are really just
|
|
37839
|
+
* test data.
|
|
37840
|
+
* - `tests/rules/**` — rule test files contain expected-issue
|
|
37841
|
+
* assertions, also meta-code.
|
|
37842
|
+
*
|
|
37843
|
+
* Three patterns (broadened in v0.25.1 from the v0.25.0 narrow
|
|
37844
|
+
* set, which missed `tests/engine/**`, `tests/cli/**`, and
|
|
37845
|
+
* `snippet/**`), ~80 issues removed per self-scan. Combined
|
|
37846
|
+
* with the v0.25.0 graded security cap, this restores the
|
|
37847
|
+
* v9 plan's "security ≥ 80" criterion (unachievable in
|
|
37848
|
+
* v0.24.0 due to 90 self-scan FPs collapsing the score to 0).
|
|
37849
|
+
*
|
|
37850
|
+
* Set `selfScan: { excludePaths: [] }` in `slopbrick.config.mjs`
|
|
37851
|
+
* to opt out and scan every file (legacy behavior).
|
|
37852
|
+
*/
|
|
37853
|
+
selfScan: {
|
|
37854
|
+
excludePaths: [
|
|
37855
|
+
"**/src/rules/**",
|
|
37856
|
+
// rule definitions are meta-code
|
|
37857
|
+
"**/snippet/**",
|
|
37858
|
+
// RULE_HINTS examples are intentional bad code
|
|
37859
|
+
"**/tests/**"
|
|
37860
|
+
// all test files (fixtures + unit + integration)
|
|
37861
|
+
]
|
|
37823
37862
|
}
|
|
37824
37863
|
};
|
|
37825
37864
|
|
|
@@ -43822,13 +43861,13 @@ var signal_strength_default = {
|
|
|
43822
43861
|
defaultOff: true
|
|
43823
43862
|
},
|
|
43824
43863
|
"java/arraylist-vs-linkedlist": {
|
|
43825
|
-
recall:
|
|
43826
|
-
fpRate:
|
|
43827
|
-
ratio:
|
|
43828
|
-
precision: 0,
|
|
43829
|
-
lastCalibratedAt: "2026-07-
|
|
43864
|
+
recall: 35e-4,
|
|
43865
|
+
fpRate: 94e-4,
|
|
43866
|
+
ratio: 0.37,
|
|
43867
|
+
precision: 0.0446,
|
|
43868
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43830
43869
|
verdict: "DORMANT",
|
|
43831
|
-
_calibrationNote: "v0.20: new rule (new LinkedList<>() \u2014 use ArrayList
|
|
43870
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files = 92196 total. v9 TP=36, FP=771, P=4.46%, FPR=0.94%, recall=0.35%, ratio=0.37, lift=P/FPR=4.74. Rule fires more on legacy enterprise Java (neg) than on AI/ML-integration Java (pos) because modern Java idiom defaults to ArrayList. v0.20: new rule (new LinkedList<>() \u2014 use ArrayList, Effective Java Item 28).",
|
|
43832
43871
|
aiSpecific: true,
|
|
43833
43872
|
_v7Verdict: "DORMANT",
|
|
43834
43873
|
_v7Lift: 1,
|
|
@@ -43837,16 +43876,21 @@ var signal_strength_default = {
|
|
|
43837
43876
|
_v7Precision: 0,
|
|
43838
43877
|
_v8Verdict: "DORMANT",
|
|
43839
43878
|
_v8Lift: 1,
|
|
43879
|
+
_v9Verdict: "DORMANT",
|
|
43880
|
+
_v9Lift: 4.74,
|
|
43881
|
+
_v9Recall: 35e-4,
|
|
43882
|
+
_v9FpRate: 94e-4,
|
|
43883
|
+
_v9Precision: 0.0446,
|
|
43840
43884
|
defaultOff: true
|
|
43841
43885
|
},
|
|
43842
43886
|
"java/empty-catch-block": {
|
|
43843
|
-
recall:
|
|
43844
|
-
fpRate: 0,
|
|
43845
|
-
ratio:
|
|
43846
|
-
precision:
|
|
43847
|
-
lastCalibratedAt: "2026-07-
|
|
43887
|
+
recall: 8e-3,
|
|
43888
|
+
fpRate: 0.1118,
|
|
43889
|
+
ratio: 0.07,
|
|
43890
|
+
precision: 89e-4,
|
|
43891
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43848
43892
|
verdict: "DORMANT",
|
|
43849
|
-
_calibrationNote: "v0.
|
|
43893
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=82, FP=9159, P=0.89%, FPR=11.18%, recall=0.80%, ratio=0.07, lift=P/FPR=0.08. Strongly INVERTED: empty catch blocks are 14x more common in legacy enterprise Java than in AI/Java-modern pos repos. Heuristic likely needs to be tightened (e.g., require at least a comment) before it can serve as a meaningful discriminator. v0.20: new rule.",
|
|
43850
43894
|
aiSpecific: true,
|
|
43851
43895
|
_v7Verdict: "DORMANT",
|
|
43852
43896
|
_v7Lift: 1,
|
|
@@ -43855,16 +43899,21 @@ var signal_strength_default = {
|
|
|
43855
43899
|
_v7Precision: 0,
|
|
43856
43900
|
_v8Verdict: "DORMANT",
|
|
43857
43901
|
_v8Lift: 1,
|
|
43902
|
+
_v9Verdict: "DORMANT",
|
|
43903
|
+
_v9Lift: 0.08,
|
|
43904
|
+
_v9Recall: 8e-3,
|
|
43905
|
+
_v9FpRate: 0.1118,
|
|
43906
|
+
_v9Precision: 89e-4,
|
|
43858
43907
|
defaultOff: true
|
|
43859
43908
|
},
|
|
43860
43909
|
"java/legacy-date-api": {
|
|
43861
|
-
recall: 0,
|
|
43862
|
-
fpRate: 0,
|
|
43863
|
-
ratio:
|
|
43864
|
-
precision: 0,
|
|
43865
|
-
lastCalibratedAt: "2026-07-
|
|
43910
|
+
recall: 0.0285,
|
|
43911
|
+
fpRate: 0.0511,
|
|
43912
|
+
ratio: 0.56,
|
|
43913
|
+
precision: 0.0657,
|
|
43914
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43866
43915
|
verdict: "DORMANT",
|
|
43867
|
-
_calibrationNote: "v0.
|
|
43916
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=294, FP=4181, P=6.57%, FPR=5.11%, recall=2.85%, ratio=0.56, lift=P/FPR=1.29. INVERTED-to-NOISY: legacy date API is more common in older enterprise Java (neg) than in modern AI/Java repos (pos). The heuristic correctly flags the legacy pattern, but the legacy pattern is over-represented in the neg baseline (older codebases). v0.20: new rule.",
|
|
43868
43917
|
aiSpecific: true,
|
|
43869
43918
|
_v7Verdict: "DORMANT",
|
|
43870
43919
|
_v7Lift: 1,
|
|
@@ -43873,16 +43922,21 @@ var signal_strength_default = {
|
|
|
43873
43922
|
_v7Precision: 0,
|
|
43874
43923
|
_v8Verdict: "DORMANT",
|
|
43875
43924
|
_v8Lift: 1,
|
|
43925
|
+
_v9Verdict: "DORMANT",
|
|
43926
|
+
_v9Lift: 1.29,
|
|
43927
|
+
_v9Recall: 0.0285,
|
|
43928
|
+
_v9FpRate: 0.0511,
|
|
43929
|
+
_v9Precision: 0.0657,
|
|
43876
43930
|
defaultOff: true
|
|
43877
43931
|
},
|
|
43878
43932
|
"java/raw-type-overuse": {
|
|
43879
|
-
recall: 0,
|
|
43880
|
-
fpRate: 0,
|
|
43881
|
-
ratio:
|
|
43882
|
-
precision: 0,
|
|
43883
|
-
lastCalibratedAt: "2026-07-
|
|
43933
|
+
recall: 0.1093,
|
|
43934
|
+
fpRate: 0.2041,
|
|
43935
|
+
ratio: 0.54,
|
|
43936
|
+
precision: 0.0632,
|
|
43937
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43884
43938
|
verdict: "DORMANT",
|
|
43885
|
-
_calibrationNote: "v0.20:
|
|
43939
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=1126, FP=16712, P=6.32%, FPR=20.41%, recall=10.93%, ratio=0.54, lift=P/FPR=0.31. Strongly INVERTED: raw types (no generics) are 2x more common in legacy enterprise Java (neg) than in modern Java repos (pos). Heuristic is correctly identifying the legacy anti-pattern, but it's an age marker more than an AI-fingerprint. v0.20: new rule.",
|
|
43886
43940
|
aiSpecific: true,
|
|
43887
43941
|
_v7Verdict: "DORMANT",
|
|
43888
43942
|
_v7Lift: 1,
|
|
@@ -43891,16 +43945,21 @@ var signal_strength_default = {
|
|
|
43891
43945
|
_v7Precision: 0,
|
|
43892
43946
|
_v8Verdict: "DORMANT",
|
|
43893
43947
|
_v8Lift: 1,
|
|
43948
|
+
_v9Verdict: "DORMANT",
|
|
43949
|
+
_v9Lift: 0.31,
|
|
43950
|
+
_v9Recall: 0.1093,
|
|
43951
|
+
_v9FpRate: 0.2041,
|
|
43952
|
+
_v9Precision: 0.0632,
|
|
43894
43953
|
defaultOff: true
|
|
43895
43954
|
},
|
|
43896
43955
|
"java/string-concat-loop": {
|
|
43897
|
-
recall:
|
|
43898
|
-
fpRate: 0,
|
|
43899
|
-
ratio:
|
|
43900
|
-
precision: 0,
|
|
43901
|
-
lastCalibratedAt: "2026-07-
|
|
43956
|
+
recall: 46e-4,
|
|
43957
|
+
fpRate: 0.0358,
|
|
43958
|
+
ratio: 0.13,
|
|
43959
|
+
precision: 0.0158,
|
|
43960
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43902
43961
|
verdict: "DORMANT",
|
|
43903
|
-
_calibrationNote: "v0.
|
|
43962
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=47, FP=2933, P=1.58%, FPR=3.58%, recall=0.46%, ratio=0.13, lift=P/FPR=0.44. Strongly INVERTED: string concatenation in a loop is 8x more common in legacy enterprise Java (neg) than in AI/ML/Java-modern pos repos. Modern Java training data and modern IDE warnings discourage the pattern. v0.20: new rule.",
|
|
43904
43963
|
aiSpecific: true,
|
|
43905
43964
|
_v7Verdict: "DORMANT",
|
|
43906
43965
|
_v7Lift: 1,
|
|
@@ -43909,16 +43968,21 @@ var signal_strength_default = {
|
|
|
43909
43968
|
_v7Precision: 0,
|
|
43910
43969
|
_v8Verdict: "DORMANT",
|
|
43911
43970
|
_v8Lift: 1,
|
|
43971
|
+
_v9Verdict: "DORMANT",
|
|
43972
|
+
_v9Lift: 0.44,
|
|
43973
|
+
_v9Recall: 46e-4,
|
|
43974
|
+
_v9FpRate: 0.0358,
|
|
43975
|
+
_v9Precision: 0.0158,
|
|
43912
43976
|
defaultOff: true
|
|
43913
43977
|
},
|
|
43914
43978
|
"java/system-out-println": {
|
|
43915
|
-
recall: 0,
|
|
43916
|
-
fpRate: 0,
|
|
43917
|
-
ratio:
|
|
43918
|
-
precision: 0,
|
|
43919
|
-
lastCalibratedAt: "2026-07-
|
|
43979
|
+
recall: 0.1503,
|
|
43980
|
+
fpRate: 0.2533,
|
|
43981
|
+
ratio: 0.59,
|
|
43982
|
+
precision: 0.0695,
|
|
43983
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43920
43984
|
verdict: "DORMANT",
|
|
43921
|
-
_calibrationNote: "v0.
|
|
43985
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=1549, FP=20737, P=6.95%, FPR=25.32%, recall=15.03%, ratio=0.59, lift=P/FPR=0.27. INVERTED: System.out.println is more common in legacy enterprise Java (neg) than in modern AI/Java repos (pos). Modern Java defaults to SLF4J/Log4j, AI-generated Java starts with a logger import. The pattern is the opposite of the v0.20 design intent (which assumed println was the AI-fingerprint signal). v0.25.x: consider gating this rule by Java era (recent file mtime) or making it an age-fingerprint rather than AI-fingerprint. v0.20: new rule.",
|
|
43922
43986
|
aiSpecific: true,
|
|
43923
43987
|
_v7Verdict: "DORMANT",
|
|
43924
43988
|
_v7Lift: 1,
|
|
@@ -43927,6 +43991,11 @@ var signal_strength_default = {
|
|
|
43927
43991
|
_v7Precision: 0,
|
|
43928
43992
|
_v8Verdict: "DORMANT",
|
|
43929
43993
|
_v8Lift: 1,
|
|
43994
|
+
_v9Verdict: "DORMANT",
|
|
43995
|
+
_v9Lift: 0.27,
|
|
43996
|
+
_v9Recall: 0.1503,
|
|
43997
|
+
_v9FpRate: 0.2533,
|
|
43998
|
+
_v9Precision: 0.0695,
|
|
43930
43999
|
defaultOff: true
|
|
43931
44000
|
},
|
|
43932
44001
|
"layout/forced-layout": {
|
|
@@ -45471,7 +45540,23 @@ function applyRuleOverrides(issues, rules) {
|
|
|
45471
45540
|
}
|
|
45472
45541
|
return result;
|
|
45473
45542
|
}
|
|
45543
|
+
function isExcludedBySelfScan(filePath, cwd, excludePaths) {
|
|
45544
|
+
if (!excludePaths || excludePaths.length === 0) return false;
|
|
45545
|
+
const rel = (0, import_node_path10.relative)(cwd, filePath).split(import_node_path10.sep).join("/");
|
|
45546
|
+
return excludePaths.some((pattern) => (0, import_minimatch.minimatch)(rel, pattern, { dot: true }));
|
|
45547
|
+
}
|
|
45474
45548
|
async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
45549
|
+
if (isExcludedBySelfScan(filePath, cwd, config.selfScan?.excludePaths)) {
|
|
45550
|
+
return {
|
|
45551
|
+
filePath,
|
|
45552
|
+
componentCount: 0,
|
|
45553
|
+
issues: [],
|
|
45554
|
+
gapValues: [],
|
|
45555
|
+
styleSources: [],
|
|
45556
|
+
elementTags: [],
|
|
45557
|
+
unmatchedStringLiterals: []
|
|
45558
|
+
};
|
|
45559
|
+
}
|
|
45475
45560
|
const cache = buildParserCacheConfig(cwd);
|
|
45476
45561
|
const ext = (0, import_node_path9.extname)(filePath).toLowerCase();
|
|
45477
45562
|
const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
|
|
@@ -45486,7 +45571,6 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
|
45486
45571
|
".h",
|
|
45487
45572
|
".hpp",
|
|
45488
45573
|
".hxx",
|
|
45489
|
-
".java",
|
|
45490
45574
|
".rb",
|
|
45491
45575
|
".php"
|
|
45492
45576
|
]);
|
package/dist/engine/worker.js
CHANGED
|
@@ -7,7 +7,8 @@ var __export = (target, all) => {
|
|
|
7
7
|
// src/engine/worker.ts
|
|
8
8
|
import { isMainThread, parentPort, workerData } from "worker_threads";
|
|
9
9
|
import { extname as extname4 } from "path";
|
|
10
|
-
import { join as join11 } from "path";
|
|
10
|
+
import { join as join11, relative as relative2, sep } from "path";
|
|
11
|
+
import { minimatch } from "minimatch";
|
|
11
12
|
|
|
12
13
|
// ../engine/dist/index.js
|
|
13
14
|
import { readFile, writeFile, mkdir, access } from "fs/promises";
|
|
@@ -4335,6 +4336,7 @@ function parseSource(source, filePath) {
|
|
|
4335
4336
|
case "py":
|
|
4336
4337
|
case "go":
|
|
4337
4338
|
case "rs":
|
|
4339
|
+
case "java":
|
|
4338
4340
|
return parseBlankModule(source);
|
|
4339
4341
|
default:
|
|
4340
4342
|
return parseWithSwc(source, filePath);
|
|
@@ -37791,6 +37793,43 @@ var DEFAULT_CONFIG3 = {
|
|
|
37791
37793
|
*/
|
|
37792
37794
|
testIntelligence: {
|
|
37793
37795
|
missingEdgeCase: false
|
|
37796
|
+
},
|
|
37797
|
+
/**
|
|
37798
|
+
* v0.25.0: self-scan exclude paths. Defaults cover the three paths
|
|
37799
|
+
* that are always false positives when scanning the slopbrick repo
|
|
37800
|
+
* itself:
|
|
37801
|
+
*
|
|
37802
|
+
* - `src/rules/**` — rule definitions contain example patterns
|
|
37803
|
+
* the rules themselves detect (self-fire). E.g. a
|
|
37804
|
+
* `security/sql-construction` rule's source file has a SQL
|
|
37805
|
+
* concat string literal that fires its own regex.
|
|
37806
|
+
* - `tests/fixtures/**` — test fixtures contain intentional bad
|
|
37807
|
+
* code that the rules must fire on to be useful (each fixture
|
|
37808
|
+
* is a positive test case). Scanning them in a self-scan
|
|
37809
|
+
* produces ~70 false-positive "issues" that are really just
|
|
37810
|
+
* test data.
|
|
37811
|
+
* - `tests/rules/**` — rule test files contain expected-issue
|
|
37812
|
+
* assertions, also meta-code.
|
|
37813
|
+
*
|
|
37814
|
+
* Three patterns (broadened in v0.25.1 from the v0.25.0 narrow
|
|
37815
|
+
* set, which missed `tests/engine/**`, `tests/cli/**`, and
|
|
37816
|
+
* `snippet/**`), ~80 issues removed per self-scan. Combined
|
|
37817
|
+
* with the v0.25.0 graded security cap, this restores the
|
|
37818
|
+
* v9 plan's "security ≥ 80" criterion (unachievable in
|
|
37819
|
+
* v0.24.0 due to 90 self-scan FPs collapsing the score to 0).
|
|
37820
|
+
*
|
|
37821
|
+
* Set `selfScan: { excludePaths: [] }` in `slopbrick.config.mjs`
|
|
37822
|
+
* to opt out and scan every file (legacy behavior).
|
|
37823
|
+
*/
|
|
37824
|
+
selfScan: {
|
|
37825
|
+
excludePaths: [
|
|
37826
|
+
"**/src/rules/**",
|
|
37827
|
+
// rule definitions are meta-code
|
|
37828
|
+
"**/snippet/**",
|
|
37829
|
+
// RULE_HINTS examples are intentional bad code
|
|
37830
|
+
"**/tests/**"
|
|
37831
|
+
// all test files (fixtures + unit + integration)
|
|
37832
|
+
]
|
|
37794
37833
|
}
|
|
37795
37834
|
};
|
|
37796
37835
|
|
|
@@ -43793,13 +43832,13 @@ var signal_strength_default = {
|
|
|
43793
43832
|
defaultOff: true
|
|
43794
43833
|
},
|
|
43795
43834
|
"java/arraylist-vs-linkedlist": {
|
|
43796
|
-
recall:
|
|
43797
|
-
fpRate:
|
|
43798
|
-
ratio:
|
|
43799
|
-
precision: 0,
|
|
43800
|
-
lastCalibratedAt: "2026-07-
|
|
43835
|
+
recall: 35e-4,
|
|
43836
|
+
fpRate: 94e-4,
|
|
43837
|
+
ratio: 0.37,
|
|
43838
|
+
precision: 0.0446,
|
|
43839
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43801
43840
|
verdict: "DORMANT",
|
|
43802
|
-
_calibrationNote: "v0.20: new rule (new LinkedList<>() \u2014 use ArrayList
|
|
43841
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files = 92196 total. v9 TP=36, FP=771, P=4.46%, FPR=0.94%, recall=0.35%, ratio=0.37, lift=P/FPR=4.74. Rule fires more on legacy enterprise Java (neg) than on AI/ML-integration Java (pos) because modern Java idiom defaults to ArrayList. v0.20: new rule (new LinkedList<>() \u2014 use ArrayList, Effective Java Item 28).",
|
|
43803
43842
|
aiSpecific: true,
|
|
43804
43843
|
_v7Verdict: "DORMANT",
|
|
43805
43844
|
_v7Lift: 1,
|
|
@@ -43808,16 +43847,21 @@ var signal_strength_default = {
|
|
|
43808
43847
|
_v7Precision: 0,
|
|
43809
43848
|
_v8Verdict: "DORMANT",
|
|
43810
43849
|
_v8Lift: 1,
|
|
43850
|
+
_v9Verdict: "DORMANT",
|
|
43851
|
+
_v9Lift: 4.74,
|
|
43852
|
+
_v9Recall: 35e-4,
|
|
43853
|
+
_v9FpRate: 94e-4,
|
|
43854
|
+
_v9Precision: 0.0446,
|
|
43811
43855
|
defaultOff: true
|
|
43812
43856
|
},
|
|
43813
43857
|
"java/empty-catch-block": {
|
|
43814
|
-
recall:
|
|
43815
|
-
fpRate: 0,
|
|
43816
|
-
ratio:
|
|
43817
|
-
precision:
|
|
43818
|
-
lastCalibratedAt: "2026-07-
|
|
43858
|
+
recall: 8e-3,
|
|
43859
|
+
fpRate: 0.1118,
|
|
43860
|
+
ratio: 0.07,
|
|
43861
|
+
precision: 89e-4,
|
|
43862
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43819
43863
|
verdict: "DORMANT",
|
|
43820
|
-
_calibrationNote: "v0.
|
|
43864
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=82, FP=9159, P=0.89%, FPR=11.18%, recall=0.80%, ratio=0.07, lift=P/FPR=0.08. Strongly INVERTED: empty catch blocks are 14x more common in legacy enterprise Java than in AI/Java-modern pos repos. Heuristic likely needs to be tightened (e.g., require at least a comment) before it can serve as a meaningful discriminator. v0.20: new rule.",
|
|
43821
43865
|
aiSpecific: true,
|
|
43822
43866
|
_v7Verdict: "DORMANT",
|
|
43823
43867
|
_v7Lift: 1,
|
|
@@ -43826,16 +43870,21 @@ var signal_strength_default = {
|
|
|
43826
43870
|
_v7Precision: 0,
|
|
43827
43871
|
_v8Verdict: "DORMANT",
|
|
43828
43872
|
_v8Lift: 1,
|
|
43873
|
+
_v9Verdict: "DORMANT",
|
|
43874
|
+
_v9Lift: 0.08,
|
|
43875
|
+
_v9Recall: 8e-3,
|
|
43876
|
+
_v9FpRate: 0.1118,
|
|
43877
|
+
_v9Precision: 89e-4,
|
|
43829
43878
|
defaultOff: true
|
|
43830
43879
|
},
|
|
43831
43880
|
"java/legacy-date-api": {
|
|
43832
|
-
recall: 0,
|
|
43833
|
-
fpRate: 0,
|
|
43834
|
-
ratio:
|
|
43835
|
-
precision: 0,
|
|
43836
|
-
lastCalibratedAt: "2026-07-
|
|
43881
|
+
recall: 0.0285,
|
|
43882
|
+
fpRate: 0.0511,
|
|
43883
|
+
ratio: 0.56,
|
|
43884
|
+
precision: 0.0657,
|
|
43885
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43837
43886
|
verdict: "DORMANT",
|
|
43838
|
-
_calibrationNote: "v0.
|
|
43887
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=294, FP=4181, P=6.57%, FPR=5.11%, recall=2.85%, ratio=0.56, lift=P/FPR=1.29. INVERTED-to-NOISY: legacy date API is more common in older enterprise Java (neg) than in modern AI/Java repos (pos). The heuristic correctly flags the legacy pattern, but the legacy pattern is over-represented in the neg baseline (older codebases). v0.20: new rule.",
|
|
43839
43888
|
aiSpecific: true,
|
|
43840
43889
|
_v7Verdict: "DORMANT",
|
|
43841
43890
|
_v7Lift: 1,
|
|
@@ -43844,16 +43893,21 @@ var signal_strength_default = {
|
|
|
43844
43893
|
_v7Precision: 0,
|
|
43845
43894
|
_v8Verdict: "DORMANT",
|
|
43846
43895
|
_v8Lift: 1,
|
|
43896
|
+
_v9Verdict: "DORMANT",
|
|
43897
|
+
_v9Lift: 1.29,
|
|
43898
|
+
_v9Recall: 0.0285,
|
|
43899
|
+
_v9FpRate: 0.0511,
|
|
43900
|
+
_v9Precision: 0.0657,
|
|
43847
43901
|
defaultOff: true
|
|
43848
43902
|
},
|
|
43849
43903
|
"java/raw-type-overuse": {
|
|
43850
|
-
recall: 0,
|
|
43851
|
-
fpRate: 0,
|
|
43852
|
-
ratio:
|
|
43853
|
-
precision: 0,
|
|
43854
|
-
lastCalibratedAt: "2026-07-
|
|
43904
|
+
recall: 0.1093,
|
|
43905
|
+
fpRate: 0.2041,
|
|
43906
|
+
ratio: 0.54,
|
|
43907
|
+
precision: 0.0632,
|
|
43908
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43855
43909
|
verdict: "DORMANT",
|
|
43856
|
-
_calibrationNote: "v0.20:
|
|
43910
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=1126, FP=16712, P=6.32%, FPR=20.41%, recall=10.93%, ratio=0.54, lift=P/FPR=0.31. Strongly INVERTED: raw types (no generics) are 2x more common in legacy enterprise Java (neg) than in modern Java repos (pos). Heuristic is correctly identifying the legacy anti-pattern, but it's an age marker more than an AI-fingerprint. v0.20: new rule.",
|
|
43857
43911
|
aiSpecific: true,
|
|
43858
43912
|
_v7Verdict: "DORMANT",
|
|
43859
43913
|
_v7Lift: 1,
|
|
@@ -43862,16 +43916,21 @@ var signal_strength_default = {
|
|
|
43862
43916
|
_v7Precision: 0,
|
|
43863
43917
|
_v8Verdict: "DORMANT",
|
|
43864
43918
|
_v8Lift: 1,
|
|
43919
|
+
_v9Verdict: "DORMANT",
|
|
43920
|
+
_v9Lift: 0.31,
|
|
43921
|
+
_v9Recall: 0.1093,
|
|
43922
|
+
_v9FpRate: 0.2041,
|
|
43923
|
+
_v9Precision: 0.0632,
|
|
43865
43924
|
defaultOff: true
|
|
43866
43925
|
},
|
|
43867
43926
|
"java/string-concat-loop": {
|
|
43868
|
-
recall:
|
|
43869
|
-
fpRate: 0,
|
|
43870
|
-
ratio:
|
|
43871
|
-
precision: 0,
|
|
43872
|
-
lastCalibratedAt: "2026-07-
|
|
43927
|
+
recall: 46e-4,
|
|
43928
|
+
fpRate: 0.0358,
|
|
43929
|
+
ratio: 0.13,
|
|
43930
|
+
precision: 0.0158,
|
|
43931
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43873
43932
|
verdict: "DORMANT",
|
|
43874
|
-
_calibrationNote: "v0.
|
|
43933
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=47, FP=2933, P=1.58%, FPR=3.58%, recall=0.46%, ratio=0.13, lift=P/FPR=0.44. Strongly INVERTED: string concatenation in a loop is 8x more common in legacy enterprise Java (neg) than in AI/ML/Java-modern pos repos. Modern Java training data and modern IDE warnings discourage the pattern. v0.20: new rule.",
|
|
43875
43934
|
aiSpecific: true,
|
|
43876
43935
|
_v7Verdict: "DORMANT",
|
|
43877
43936
|
_v7Lift: 1,
|
|
@@ -43880,16 +43939,21 @@ var signal_strength_default = {
|
|
|
43880
43939
|
_v7Precision: 0,
|
|
43881
43940
|
_v8Verdict: "DORMANT",
|
|
43882
43941
|
_v8Lift: 1,
|
|
43942
|
+
_v9Verdict: "DORMANT",
|
|
43943
|
+
_v9Lift: 0.44,
|
|
43944
|
+
_v9Recall: 46e-4,
|
|
43945
|
+
_v9FpRate: 0.0358,
|
|
43946
|
+
_v9Precision: 0.0158,
|
|
43883
43947
|
defaultOff: true
|
|
43884
43948
|
},
|
|
43885
43949
|
"java/system-out-println": {
|
|
43886
|
-
recall: 0,
|
|
43887
|
-
fpRate: 0,
|
|
43888
|
-
ratio:
|
|
43889
|
-
precision: 0,
|
|
43890
|
-
lastCalibratedAt: "2026-07-
|
|
43950
|
+
recall: 0.1503,
|
|
43951
|
+
fpRate: 0.2533,
|
|
43952
|
+
ratio: 0.59,
|
|
43953
|
+
precision: 0.0695,
|
|
43954
|
+
lastCalibratedAt: "2026-07-02T19:34:00Z",
|
|
43891
43955
|
verdict: "DORMANT",
|
|
43892
|
-
_calibrationNote: "v0.
|
|
43956
|
+
_calibrationNote: "v9 Java corpus calibration (v0.25.0, 2026-07-02): 81891 neg + 10305 pos Java files. v9 TP=1549, FP=20737, P=6.95%, FPR=25.32%, recall=15.03%, ratio=0.59, lift=P/FPR=0.27. INVERTED: System.out.println is more common in legacy enterprise Java (neg) than in modern AI/Java repos (pos). Modern Java defaults to SLF4J/Log4j, AI-generated Java starts with a logger import. The pattern is the opposite of the v0.20 design intent (which assumed println was the AI-fingerprint signal). v0.25.x: consider gating this rule by Java era (recent file mtime) or making it an age-fingerprint rather than AI-fingerprint. v0.20: new rule.",
|
|
43893
43957
|
aiSpecific: true,
|
|
43894
43958
|
_v7Verdict: "DORMANT",
|
|
43895
43959
|
_v7Lift: 1,
|
|
@@ -43898,6 +43962,11 @@ var signal_strength_default = {
|
|
|
43898
43962
|
_v7Precision: 0,
|
|
43899
43963
|
_v8Verdict: "DORMANT",
|
|
43900
43964
|
_v8Lift: 1,
|
|
43965
|
+
_v9Verdict: "DORMANT",
|
|
43966
|
+
_v9Lift: 0.27,
|
|
43967
|
+
_v9Recall: 0.1503,
|
|
43968
|
+
_v9FpRate: 0.2533,
|
|
43969
|
+
_v9Precision: 0.0695,
|
|
43901
43970
|
defaultOff: true
|
|
43902
43971
|
},
|
|
43903
43972
|
"layout/forced-layout": {
|
|
@@ -45442,7 +45511,23 @@ function applyRuleOverrides(issues, rules) {
|
|
|
45442
45511
|
}
|
|
45443
45512
|
return result;
|
|
45444
45513
|
}
|
|
45514
|
+
function isExcludedBySelfScan(filePath, cwd, excludePaths) {
|
|
45515
|
+
if (!excludePaths || excludePaths.length === 0) return false;
|
|
45516
|
+
const rel = relative2(cwd, filePath).split(sep).join("/");
|
|
45517
|
+
return excludePaths.some((pattern) => minimatch(rel, pattern, { dot: true }));
|
|
45518
|
+
}
|
|
45445
45519
|
async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
45520
|
+
if (isExcludedBySelfScan(filePath, cwd, config.selfScan?.excludePaths)) {
|
|
45521
|
+
return {
|
|
45522
|
+
filePath,
|
|
45523
|
+
componentCount: 0,
|
|
45524
|
+
issues: [],
|
|
45525
|
+
gapValues: [],
|
|
45526
|
+
styleSources: [],
|
|
45527
|
+
elementTags: [],
|
|
45528
|
+
unmatchedStringLiterals: []
|
|
45529
|
+
};
|
|
45530
|
+
}
|
|
45446
45531
|
const cache = buildParserCacheConfig(cwd);
|
|
45447
45532
|
const ext = extname4(filePath).toLowerCase();
|
|
45448
45533
|
const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
|
|
@@ -45457,7 +45542,6 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
|
|
|
45457
45542
|
".h",
|
|
45458
45543
|
".hpp",
|
|
45459
45544
|
".hxx",
|
|
45460
|
-
".java",
|
|
45461
45545
|
".rb",
|
|
45462
45546
|
".php"
|
|
45463
45547
|
]);
|