slopbrick 0.34.1 → 0.34.3
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 +10 -6
- package/dist/engine/worker.js +10 -6
- package/dist/index.cjs +13 -9
- package/dist/index.js +13 -9
- package/package.json +1 -1
package/dist/engine/worker.cjs
CHANGED
|
@@ -34436,7 +34436,8 @@ var importPathMismatchRule = createRule({
|
|
|
34436
34436
|
|
|
34437
34437
|
// src/rules/cpp/c-style-cast.ts
|
|
34438
34438
|
var C_STYLE_CAST_REGEX = /\(\s*(?:int|long|short|char|float|double|bool|unsigned\s+\w+|signed\s+\w+|size_t|[A-Za-z_]\w*(?:\s*[*,&][^)]*)?)\s*\)\s*(\w+|[^a-zA-Z_])/g;
|
|
34439
|
-
var NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s
|
|
34439
|
+
var NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s*$/;
|
|
34440
|
+
var VOID_CAST_REGEX = /^\s*void\s*$/;
|
|
34440
34441
|
var cppCStyleCastRule = createRule({
|
|
34441
34442
|
id: "cpp/c-style-cast",
|
|
34442
34443
|
category: "typo",
|
|
@@ -34456,9 +34457,10 @@ var cppCStyleCastRule = createRule({
|
|
|
34456
34457
|
while ((m = C_STYLE_CAST_REGEX.exec(source)) !== null) {
|
|
34457
34458
|
const innerMatch = /\(\s*([^)]+?)\s*\)/.exec(m[0]) ?? [];
|
|
34458
34459
|
const inner = (innerMatch[1] ?? "").trim();
|
|
34460
|
+
if (VOID_CAST_REGEX.test(inner)) continue;
|
|
34459
34461
|
const looksLikeCast = /\b(?:int|long|short|char|float|double|bool|unsigned|signed|size_t)\b/.test(inner) || /[*&]/.test(inner);
|
|
34460
34462
|
if (!looksLikeCast) continue;
|
|
34461
|
-
const before = source.slice(Math.max(0, m.index -
|
|
34463
|
+
const before = source.slice(Math.max(0, m.index - 60), m.index);
|
|
34462
34464
|
if (NAMED_CAST_PREFIX_REGEX.test(before)) continue;
|
|
34463
34465
|
const line = source.slice(0, m.index).split("\n").length;
|
|
34464
34466
|
issues.push({
|
|
@@ -34469,7 +34471,7 @@ var cppCStyleCastRule = createRule({
|
|
|
34469
34471
|
message: `C-style cast at line ${line} \u2014 use static_cast / reinterpret_cast / const_cast`,
|
|
34470
34472
|
line,
|
|
34471
34473
|
column: 1,
|
|
34472
|
-
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.
|
|
34474
|
+
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.34.3 (refined regex selectivity)."
|
|
34473
34475
|
});
|
|
34474
34476
|
}
|
|
34475
34477
|
return issues;
|
|
@@ -40514,6 +40516,7 @@ var swiftImplicitlyUnwrappedOptionalRule = createRule({
|
|
|
40514
40516
|
// src/rules/swift/print-debug.ts
|
|
40515
40517
|
var PRINT_REGEX = /\bprint\s*\(/g;
|
|
40516
40518
|
var DEFAULT_THRESHOLD2 = 1;
|
|
40519
|
+
var TEST_FILE_REGEX = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
40517
40520
|
var swiftPrintDebugRule = createRule({
|
|
40518
40521
|
id: "swift/print-debug",
|
|
40519
40522
|
category: "typo",
|
|
@@ -40528,6 +40531,7 @@ var swiftPrintDebugRule = createRule({
|
|
|
40528
40531
|
const source = facts.v2?._source;
|
|
40529
40532
|
if (!source) return issues;
|
|
40530
40533
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
40534
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
40531
40535
|
const matches = [];
|
|
40532
40536
|
let m;
|
|
40533
40537
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -40547,7 +40551,7 @@ var swiftPrintDebugRule = createRule({
|
|
|
40547
40551
|
message: `print(...) at line ${line} \u2014 use Logger (os.log) for production output`,
|
|
40548
40552
|
line,
|
|
40549
40553
|
column: 1,
|
|
40550
|
-
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.
|
|
40554
|
+
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.34.2 (refined to skip test files for higher precision).'
|
|
40551
40555
|
});
|
|
40552
40556
|
}
|
|
40553
40557
|
return issues;
|
|
@@ -45598,7 +45602,7 @@ var signal_strength_default = {
|
|
|
45598
45602
|
precision: 0.3305,
|
|
45599
45603
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45600
45604
|
verdict: "OK",
|
|
45601
|
-
_calibrationNote: "v0.
|
|
45605
|
+
_calibrationNote: "v0.34.2: REFINED \u2014 rule now skips test files (XCTest naming: *Tests.swift, *Test.swift, Tests/ dir). Per-file unique v9 Swift calibration (1300 neg, 568 pos): 39 TP files, 79 FP files, ratio=1.13 (OK). The refinement is expected to push precision from 33% to 50%+ by removing XCTest output and snapshot test fires (which were ~49% of FPs in the v0.32.0 measurement). The full v9 re-calibration is part of the v0.34.5/v0.34.7 pipeline (same refinement applied to kotlin/println-as-log and cpp/printf-debug); see v0.34.1's Four-language validation section. v0.32.0 baseline: 39 TP files / 568 = 6.87% recall, 79 FP files / 1300 = 6.08% fpRate, ratio 1.13, precision 33.05% (just below 50% USEFUL threshold). Same direction as kotlin/println-as-log (1.84) and java/system-out-println (1.73 refined, 3.29 unrefined). INSUFFICIENT_DATA: pos arm 568 files (below 10k floor).",
|
|
45602
45606
|
aiSpecific: true,
|
|
45603
45607
|
_v7Verdict: "DORMANT",
|
|
45604
45608
|
_v7Lift: 1,
|
|
@@ -45736,7 +45740,7 @@ var signal_strength_default = {
|
|
|
45736
45740
|
precision: 0.2325,
|
|
45737
45741
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45738
45742
|
verdict: "DORMANT",
|
|
45739
|
-
_calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
45743
|
+
_calibrationNote: "v0.34.3: REFINED \u2014 NAMED_CAST_PREFIX_REGEX tightened (the old version required the lookback slice to end with `>(`, which never matched because the slice ends with `>`). Lookback increased 40\u219260 chars. Added `(void)x` discard-idom exclusion. v0.33 baseline: 874 TP / 2885 FP per-file (ratio 0.93, DORMANT). The refinement targets: (1) static_cast/const_cast/reinterpret_cast/dynamic_cast no longer fire when followed by whitespace before `(`; (2) class-type named casts like `static_cast<MyClass*>(p)` now correctly excluded (60-char lookback reaches the long typename); (3) `(void)x` deliberate discards are no longer flagged. Expected post-refinement ratio: 1.0-1.2 (still DORMANT but better-targeted). Full v9 re-calibration is part of the v0.35.0 re-measurement. v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
45740
45744
|
aiSpecific: true,
|
|
45741
45745
|
_v7Verdict: "DORMANT",
|
|
45742
45746
|
_v7Lift: 1,
|
package/dist/engine/worker.js
CHANGED
|
@@ -34407,7 +34407,8 @@ var importPathMismatchRule = createRule({
|
|
|
34407
34407
|
|
|
34408
34408
|
// src/rules/cpp/c-style-cast.ts
|
|
34409
34409
|
var C_STYLE_CAST_REGEX = /\(\s*(?:int|long|short|char|float|double|bool|unsigned\s+\w+|signed\s+\w+|size_t|[A-Za-z_]\w*(?:\s*[*,&][^)]*)?)\s*\)\s*(\w+|[^a-zA-Z_])/g;
|
|
34410
|
-
var NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s
|
|
34410
|
+
var NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s*$/;
|
|
34411
|
+
var VOID_CAST_REGEX = /^\s*void\s*$/;
|
|
34411
34412
|
var cppCStyleCastRule = createRule({
|
|
34412
34413
|
id: "cpp/c-style-cast",
|
|
34413
34414
|
category: "typo",
|
|
@@ -34427,9 +34428,10 @@ var cppCStyleCastRule = createRule({
|
|
|
34427
34428
|
while ((m = C_STYLE_CAST_REGEX.exec(source)) !== null) {
|
|
34428
34429
|
const innerMatch = /\(\s*([^)]+?)\s*\)/.exec(m[0]) ?? [];
|
|
34429
34430
|
const inner = (innerMatch[1] ?? "").trim();
|
|
34431
|
+
if (VOID_CAST_REGEX.test(inner)) continue;
|
|
34430
34432
|
const looksLikeCast = /\b(?:int|long|short|char|float|double|bool|unsigned|signed|size_t)\b/.test(inner) || /[*&]/.test(inner);
|
|
34431
34433
|
if (!looksLikeCast) continue;
|
|
34432
|
-
const before = source.slice(Math.max(0, m.index -
|
|
34434
|
+
const before = source.slice(Math.max(0, m.index - 60), m.index);
|
|
34433
34435
|
if (NAMED_CAST_PREFIX_REGEX.test(before)) continue;
|
|
34434
34436
|
const line = source.slice(0, m.index).split("\n").length;
|
|
34435
34437
|
issues.push({
|
|
@@ -34440,7 +34442,7 @@ var cppCStyleCastRule = createRule({
|
|
|
34440
34442
|
message: `C-style cast at line ${line} \u2014 use static_cast / reinterpret_cast / const_cast`,
|
|
34441
34443
|
line,
|
|
34442
34444
|
column: 1,
|
|
34443
|
-
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.
|
|
34445
|
+
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.34.3 (refined regex selectivity)."
|
|
34444
34446
|
});
|
|
34445
34447
|
}
|
|
34446
34448
|
return issues;
|
|
@@ -40485,6 +40487,7 @@ var swiftImplicitlyUnwrappedOptionalRule = createRule({
|
|
|
40485
40487
|
// src/rules/swift/print-debug.ts
|
|
40486
40488
|
var PRINT_REGEX = /\bprint\s*\(/g;
|
|
40487
40489
|
var DEFAULT_THRESHOLD2 = 1;
|
|
40490
|
+
var TEST_FILE_REGEX = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
40488
40491
|
var swiftPrintDebugRule = createRule({
|
|
40489
40492
|
id: "swift/print-debug",
|
|
40490
40493
|
category: "typo",
|
|
@@ -40499,6 +40502,7 @@ var swiftPrintDebugRule = createRule({
|
|
|
40499
40502
|
const source = facts.v2?._source;
|
|
40500
40503
|
if (!source) return issues;
|
|
40501
40504
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
40505
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
40502
40506
|
const matches = [];
|
|
40503
40507
|
let m;
|
|
40504
40508
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -40518,7 +40522,7 @@ var swiftPrintDebugRule = createRule({
|
|
|
40518
40522
|
message: `print(...) at line ${line} \u2014 use Logger (os.log) for production output`,
|
|
40519
40523
|
line,
|
|
40520
40524
|
column: 1,
|
|
40521
|
-
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.
|
|
40525
|
+
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.34.2 (refined to skip test files for higher precision).'
|
|
40522
40526
|
});
|
|
40523
40527
|
}
|
|
40524
40528
|
return issues;
|
|
@@ -45569,7 +45573,7 @@ var signal_strength_default = {
|
|
|
45569
45573
|
precision: 0.3305,
|
|
45570
45574
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45571
45575
|
verdict: "OK",
|
|
45572
|
-
_calibrationNote: "v0.
|
|
45576
|
+
_calibrationNote: "v0.34.2: REFINED \u2014 rule now skips test files (XCTest naming: *Tests.swift, *Test.swift, Tests/ dir). Per-file unique v9 Swift calibration (1300 neg, 568 pos): 39 TP files, 79 FP files, ratio=1.13 (OK). The refinement is expected to push precision from 33% to 50%+ by removing XCTest output and snapshot test fires (which were ~49% of FPs in the v0.32.0 measurement). The full v9 re-calibration is part of the v0.34.5/v0.34.7 pipeline (same refinement applied to kotlin/println-as-log and cpp/printf-debug); see v0.34.1's Four-language validation section. v0.32.0 baseline: 39 TP files / 568 = 6.87% recall, 79 FP files / 1300 = 6.08% fpRate, ratio 1.13, precision 33.05% (just below 50% USEFUL threshold). Same direction as kotlin/println-as-log (1.84) and java/system-out-println (1.73 refined, 3.29 unrefined). INSUFFICIENT_DATA: pos arm 568 files (below 10k floor).",
|
|
45573
45577
|
aiSpecific: true,
|
|
45574
45578
|
_v7Verdict: "DORMANT",
|
|
45575
45579
|
_v7Lift: 1,
|
|
@@ -45707,7 +45711,7 @@ var signal_strength_default = {
|
|
|
45707
45711
|
precision: 0.2325,
|
|
45708
45712
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
45709
45713
|
verdict: "DORMANT",
|
|
45710
|
-
_calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
45714
|
+
_calibrationNote: "v0.34.3: REFINED \u2014 NAMED_CAST_PREFIX_REGEX tightened (the old version required the lookback slice to end with `>(`, which never matched because the slice ends with `>`). Lookback increased 40\u219260 chars. Added `(void)x` discard-idom exclusion. v0.33 baseline: 874 TP / 2885 FP per-file (ratio 0.93, DORMANT). The refinement targets: (1) static_cast/const_cast/reinterpret_cast/dynamic_cast no longer fire when followed by whitespace before `(`; (2) class-type named casts like `static_cast<MyClass*>(p)` now correctly excluded (60-char lookback reaches the long typename); (3) `(void)x` deliberate discards are no longer flagged. Expected post-refinement ratio: 1.0-1.2 (still DORMANT but better-targeted). Full v9 re-calibration is part of the v0.35.0 re-measurement. v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
45711
45715
|
aiSpecific: true,
|
|
45712
45716
|
_v7Verdict: "DORMANT",
|
|
45713
45717
|
_v7Lift: 1,
|
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.34.
|
|
39
|
+
VERSION = "0.34.3";
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
@@ -27660,13 +27660,14 @@ var init_import_path_mismatch = __esm({
|
|
|
27660
27660
|
});
|
|
27661
27661
|
|
|
27662
27662
|
// src/rules/cpp/c-style-cast.ts
|
|
27663
|
-
var C_STYLE_CAST_REGEX, NAMED_CAST_PREFIX_REGEX, cppCStyleCastRule;
|
|
27663
|
+
var C_STYLE_CAST_REGEX, NAMED_CAST_PREFIX_REGEX, VOID_CAST_REGEX, cppCStyleCastRule;
|
|
27664
27664
|
var init_c_style_cast = __esm({
|
|
27665
27665
|
"src/rules/cpp/c-style-cast.ts"() {
|
|
27666
27666
|
"use strict";
|
|
27667
27667
|
init_rule();
|
|
27668
27668
|
C_STYLE_CAST_REGEX = /\(\s*(?:int|long|short|char|float|double|bool|unsigned\s+\w+|signed\s+\w+|size_t|[A-Za-z_]\w*(?:\s*[*,&][^)]*)?)\s*\)\s*(\w+|[^a-zA-Z_])/g;
|
|
27669
|
-
NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s
|
|
27669
|
+
NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s*$/;
|
|
27670
|
+
VOID_CAST_REGEX = /^\s*void\s*$/;
|
|
27670
27671
|
cppCStyleCastRule = createRule({
|
|
27671
27672
|
id: "cpp/c-style-cast",
|
|
27672
27673
|
category: "typo",
|
|
@@ -27686,9 +27687,10 @@ var init_c_style_cast = __esm({
|
|
|
27686
27687
|
while ((m = C_STYLE_CAST_REGEX.exec(source)) !== null) {
|
|
27687
27688
|
const innerMatch = /\(\s*([^)]+?)\s*\)/.exec(m[0]) ?? [];
|
|
27688
27689
|
const inner = (innerMatch[1] ?? "").trim();
|
|
27690
|
+
if (VOID_CAST_REGEX.test(inner)) continue;
|
|
27689
27691
|
const looksLikeCast = /\b(?:int|long|short|char|float|double|bool|unsigned|signed|size_t)\b/.test(inner) || /[*&]/.test(inner);
|
|
27690
27692
|
if (!looksLikeCast) continue;
|
|
27691
|
-
const before = source.slice(Math.max(0, m.index -
|
|
27693
|
+
const before = source.slice(Math.max(0, m.index - 60), m.index);
|
|
27692
27694
|
if (NAMED_CAST_PREFIX_REGEX.test(before)) continue;
|
|
27693
27695
|
const line = source.slice(0, m.index).split("\n").length;
|
|
27694
27696
|
issues.push({
|
|
@@ -27699,7 +27701,7 @@ var init_c_style_cast = __esm({
|
|
|
27699
27701
|
message: `C-style cast at line ${line} \u2014 use static_cast / reinterpret_cast / const_cast`,
|
|
27700
27702
|
line,
|
|
27701
27703
|
column: 1,
|
|
27702
|
-
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.
|
|
27704
|
+
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.34.3 (refined regex selectivity)."
|
|
27703
27705
|
});
|
|
27704
27706
|
}
|
|
27705
27707
|
return issues;
|
|
@@ -41055,13 +41057,14 @@ var init_implicitly_unwrapped_optional = __esm({
|
|
|
41055
41057
|
});
|
|
41056
41058
|
|
|
41057
41059
|
// src/rules/swift/print-debug.ts
|
|
41058
|
-
var PRINT_REGEX, DEFAULT_THRESHOLD2, swiftPrintDebugRule;
|
|
41060
|
+
var PRINT_REGEX, DEFAULT_THRESHOLD2, TEST_FILE_REGEX, swiftPrintDebugRule;
|
|
41059
41061
|
var init_print_debug = __esm({
|
|
41060
41062
|
"src/rules/swift/print-debug.ts"() {
|
|
41061
41063
|
"use strict";
|
|
41062
41064
|
init_rule();
|
|
41063
41065
|
PRINT_REGEX = /\bprint\s*\(/g;
|
|
41064
41066
|
DEFAULT_THRESHOLD2 = 1;
|
|
41067
|
+
TEST_FILE_REGEX = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
41065
41068
|
swiftPrintDebugRule = createRule({
|
|
41066
41069
|
id: "swift/print-debug",
|
|
41067
41070
|
category: "typo",
|
|
@@ -41076,6 +41079,7 @@ var init_print_debug = __esm({
|
|
|
41076
41079
|
const source = facts.v2?._source;
|
|
41077
41080
|
if (!source) return issues;
|
|
41078
41081
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
41082
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
41079
41083
|
const matches = [];
|
|
41080
41084
|
let m;
|
|
41081
41085
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -41095,7 +41099,7 @@ var init_print_debug = __esm({
|
|
|
41095
41099
|
message: `print(...) at line ${line} \u2014 use Logger (os.log) for production output`,
|
|
41096
41100
|
line,
|
|
41097
41101
|
column: 1,
|
|
41098
|
-
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.
|
|
41102
|
+
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.34.2 (refined to skip test files for higher precision).'
|
|
41099
41103
|
});
|
|
41100
41104
|
}
|
|
41101
41105
|
return issues;
|
|
@@ -51685,7 +51689,7 @@ var init_signal_strength = __esm({
|
|
|
51685
51689
|
precision: 0.3305,
|
|
51686
51690
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51687
51691
|
verdict: "OK",
|
|
51688
|
-
_calibrationNote: "v0.
|
|
51692
|
+
_calibrationNote: "v0.34.2: REFINED \u2014 rule now skips test files (XCTest naming: *Tests.swift, *Test.swift, Tests/ dir). Per-file unique v9 Swift calibration (1300 neg, 568 pos): 39 TP files, 79 FP files, ratio=1.13 (OK). The refinement is expected to push precision from 33% to 50%+ by removing XCTest output and snapshot test fires (which were ~49% of FPs in the v0.32.0 measurement). The full v9 re-calibration is part of the v0.34.5/v0.34.7 pipeline (same refinement applied to kotlin/println-as-log and cpp/printf-debug); see v0.34.1's Four-language validation section. v0.32.0 baseline: 39 TP files / 568 = 6.87% recall, 79 FP files / 1300 = 6.08% fpRate, ratio 1.13, precision 33.05% (just below 50% USEFUL threshold). Same direction as kotlin/println-as-log (1.84) and java/system-out-println (1.73 refined, 3.29 unrefined). INSUFFICIENT_DATA: pos arm 568 files (below 10k floor).",
|
|
51689
51693
|
aiSpecific: true,
|
|
51690
51694
|
_v7Verdict: "DORMANT",
|
|
51691
51695
|
_v7Lift: 1,
|
|
@@ -51823,7 +51827,7 @@ var init_signal_strength = __esm({
|
|
|
51823
51827
|
precision: 0.2325,
|
|
51824
51828
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51825
51829
|
verdict: "DORMANT",
|
|
51826
|
-
_calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
51830
|
+
_calibrationNote: "v0.34.3: REFINED \u2014 NAMED_CAST_PREFIX_REGEX tightened (the old version required the lookback slice to end with `>(`, which never matched because the slice ends with `>`). Lookback increased 40\u219260 chars. Added `(void)x` discard-idom exclusion. v0.33 baseline: 874 TP / 2885 FP per-file (ratio 0.93, DORMANT). The refinement targets: (1) static_cast/const_cast/reinterpret_cast/dynamic_cast no longer fire when followed by whitespace before `(`; (2) class-type named casts like `static_cast<MyClass*>(p)` now correctly excluded (60-char lookback reaches the long typename); (3) `(void)x` deliberate discards are no longer flagged. Expected post-refinement ratio: 1.0-1.2 (still DORMANT but better-targeted). Full v9 re-calibration is part of the v0.35.0 re-measurement. v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
51827
51831
|
aiSpecific: true,
|
|
51828
51832
|
_v7Verdict: "DORMANT",
|
|
51829
51833
|
_v7Lift: 1,
|
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.34.
|
|
22
|
+
VERSION = "0.34.3";
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -27642,13 +27642,14 @@ var init_import_path_mismatch = __esm({
|
|
|
27642
27642
|
});
|
|
27643
27643
|
|
|
27644
27644
|
// src/rules/cpp/c-style-cast.ts
|
|
27645
|
-
var C_STYLE_CAST_REGEX, NAMED_CAST_PREFIX_REGEX, cppCStyleCastRule;
|
|
27645
|
+
var C_STYLE_CAST_REGEX, NAMED_CAST_PREFIX_REGEX, VOID_CAST_REGEX, cppCStyleCastRule;
|
|
27646
27646
|
var init_c_style_cast = __esm({
|
|
27647
27647
|
"src/rules/cpp/c-style-cast.ts"() {
|
|
27648
27648
|
"use strict";
|
|
27649
27649
|
init_rule();
|
|
27650
27650
|
C_STYLE_CAST_REGEX = /\(\s*(?:int|long|short|char|float|double|bool|unsigned\s+\w+|signed\s+\w+|size_t|[A-Za-z_]\w*(?:\s*[*,&][^)]*)?)\s*\)\s*(\w+|[^a-zA-Z_])/g;
|
|
27651
|
-
NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s
|
|
27651
|
+
NAMED_CAST_PREFIX_REGEX = /\b(?:static|reinterpret|const|dynamic)_cast\s*<[^>]*>\s*$/;
|
|
27652
|
+
VOID_CAST_REGEX = /^\s*void\s*$/;
|
|
27652
27653
|
cppCStyleCastRule = createRule({
|
|
27653
27654
|
id: "cpp/c-style-cast",
|
|
27654
27655
|
category: "typo",
|
|
@@ -27668,9 +27669,10 @@ var init_c_style_cast = __esm({
|
|
|
27668
27669
|
while ((m = C_STYLE_CAST_REGEX.exec(source)) !== null) {
|
|
27669
27670
|
const innerMatch = /\(\s*([^)]+?)\s*\)/.exec(m[0]) ?? [];
|
|
27670
27671
|
const inner = (innerMatch[1] ?? "").trim();
|
|
27672
|
+
if (VOID_CAST_REGEX.test(inner)) continue;
|
|
27671
27673
|
const looksLikeCast = /\b(?:int|long|short|char|float|double|bool|unsigned|signed|size_t)\b/.test(inner) || /[*&]/.test(inner);
|
|
27672
27674
|
if (!looksLikeCast) continue;
|
|
27673
|
-
const before = source.slice(Math.max(0, m.index -
|
|
27675
|
+
const before = source.slice(Math.max(0, m.index - 60), m.index);
|
|
27674
27676
|
if (NAMED_CAST_PREFIX_REGEX.test(before)) continue;
|
|
27675
27677
|
const line = source.slice(0, m.index).split("\n").length;
|
|
27676
27678
|
issues.push({
|
|
@@ -27681,7 +27683,7 @@ var init_c_style_cast = __esm({
|
|
|
27681
27683
|
message: `C-style cast at line ${line} \u2014 use static_cast / reinterpret_cast / const_cast`,
|
|
27682
27684
|
line,
|
|
27683
27685
|
column: 1,
|
|
27684
|
-
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.
|
|
27686
|
+
advice: "Use the named cast that matches the intent: `static_cast<int>(x)`, `reinterpret_cast<MyClass*>(p)`, `const_cast<...>(ref)`, or `dynamic_cast<Derived*>(base)` for runtime-checked downcasts. C-style casts silently pick whichever the compiler needs \u2014 `static_cast`, `reinterpret_cast`, OR `const_cast` \u2014 which makes them impossible to grep for and impossible to review. The C++ Core Guidelines (ES.49) call this out by name. AI agents reach for `(int)x` because of training-data C textbooks. Reference: cpp/c-style-cast v0.34.3 (refined regex selectivity)."
|
|
27685
27687
|
});
|
|
27686
27688
|
}
|
|
27687
27689
|
return issues;
|
|
@@ -41036,13 +41038,14 @@ var init_implicitly_unwrapped_optional = __esm({
|
|
|
41036
41038
|
});
|
|
41037
41039
|
|
|
41038
41040
|
// src/rules/swift/print-debug.ts
|
|
41039
|
-
var PRINT_REGEX, DEFAULT_THRESHOLD2, swiftPrintDebugRule;
|
|
41041
|
+
var PRINT_REGEX, DEFAULT_THRESHOLD2, TEST_FILE_REGEX, swiftPrintDebugRule;
|
|
41040
41042
|
var init_print_debug = __esm({
|
|
41041
41043
|
"src/rules/swift/print-debug.ts"() {
|
|
41042
41044
|
"use strict";
|
|
41043
41045
|
init_rule();
|
|
41044
41046
|
PRINT_REGEX = /\bprint\s*\(/g;
|
|
41045
41047
|
DEFAULT_THRESHOLD2 = 1;
|
|
41048
|
+
TEST_FILE_REGEX = /(?:\/Tests\/|\/Tests\.swift|\/Test\.swift|Tests\.swift$|Test\.swift$)/;
|
|
41046
41049
|
swiftPrintDebugRule = createRule({
|
|
41047
41050
|
id: "swift/print-debug",
|
|
41048
41051
|
category: "typo",
|
|
@@ -41057,6 +41060,7 @@ var init_print_debug = __esm({
|
|
|
41057
41060
|
const source = facts.v2?._source;
|
|
41058
41061
|
if (!source) return issues;
|
|
41059
41062
|
if (!/\.swift$/i.test(facts.filePath)) return issues;
|
|
41063
|
+
if (TEST_FILE_REGEX.test(facts.filePath)) return issues;
|
|
41060
41064
|
const matches = [];
|
|
41061
41065
|
let m;
|
|
41062
41066
|
PRINT_REGEX.lastIndex = 0;
|
|
@@ -41076,7 +41080,7 @@ var init_print_debug = __esm({
|
|
|
41076
41080
|
message: `print(...) at line ${line} \u2014 use Logger (os.log) for production output`,
|
|
41077
41081
|
line,
|
|
41078
41082
|
column: 1,
|
|
41079
|
-
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.
|
|
41083
|
+
advice: 'Replace with `Logger(subsystem: "...", category: "...").info("...")` (Unified Logging System, os.log). `print` writes to stdout with no level, no redaction, and no way to silence in release builds. The `Logger` API integrates with Console.app and respects the device\'s privacy settings. Multiple `print` calls in one Swift file is an AI fingerprint \u2014 agents reach for `print` because of training-data examples. Reference: swift/print-debug v0.34.2 (refined to skip test files for higher precision).'
|
|
41080
41084
|
});
|
|
41081
41085
|
}
|
|
41082
41086
|
return issues;
|
|
@@ -51663,7 +51667,7 @@ var init_signal_strength = __esm({
|
|
|
51663
51667
|
precision: 0.3305,
|
|
51664
51668
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51665
51669
|
verdict: "OK",
|
|
51666
|
-
_calibrationNote: "v0.
|
|
51670
|
+
_calibrationNote: "v0.34.2: REFINED \u2014 rule now skips test files (XCTest naming: *Tests.swift, *Test.swift, Tests/ dir). Per-file unique v9 Swift calibration (1300 neg, 568 pos): 39 TP files, 79 FP files, ratio=1.13 (OK). The refinement is expected to push precision from 33% to 50%+ by removing XCTest output and snapshot test fires (which were ~49% of FPs in the v0.32.0 measurement). The full v9 re-calibration is part of the v0.34.5/v0.34.7 pipeline (same refinement applied to kotlin/println-as-log and cpp/printf-debug); see v0.34.1's Four-language validation section. v0.32.0 baseline: 39 TP files / 568 = 6.87% recall, 79 FP files / 1300 = 6.08% fpRate, ratio 1.13, precision 33.05% (just below 50% USEFUL threshold). Same direction as kotlin/println-as-log (1.84) and java/system-out-println (1.73 refined, 3.29 unrefined). INSUFFICIENT_DATA: pos arm 568 files (below 10k floor).",
|
|
51667
51671
|
aiSpecific: true,
|
|
51668
51672
|
_v7Verdict: "DORMANT",
|
|
51669
51673
|
_v7Lift: 1,
|
|
@@ -51801,7 +51805,7 @@ var init_signal_strength = __esm({
|
|
|
51801
51805
|
precision: 0.2325,
|
|
51802
51806
|
lastCalibratedAt: "2026-07-03T00:00:00Z",
|
|
51803
51807
|
verdict: "DORMANT",
|
|
51804
|
-
_calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
51808
|
+
_calibrationNote: "v0.34.3: REFINED \u2014 NAMED_CAST_PREFIX_REGEX tightened (the old version required the lookback slice to end with `>(`, which never matched because the slice ends with `>`). Lookback increased 40\u219260 chars. Added `(void)x` discard-idom exclusion. v0.33 baseline: 874 TP / 2885 FP per-file (ratio 0.93, DORMANT). The refinement targets: (1) static_cast/const_cast/reinterpret_cast/dynamic_cast no longer fire when followed by whitespace before `(`; (2) class-type named casts like `static_cast<MyClass*>(p)` now correctly excluded (60-char lookback reaches the long typename); (3) `(void)x` deliberate discards are no longer flagged. Expected post-refinement ratio: 1.0-1.2 (still DORMANT but better-targeted). Full v9 re-calibration is part of the v0.35.0 re-measurement. v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 874 TP, 2885 FP, ratio=0.93. Total fires were 32265 TP, 39954 FP \u2014 the regex is too broad and fires on every C-style cast including static_cast in template code. The per-file measurement (874/1655 = 53%) is more meaningful \u2014 both arms have similar proportions of files using C-style casts. INSUFFICIENT_DATA: pos arm 1655 files.",
|
|
51805
51809
|
aiSpecific: true,
|
|
51806
51810
|
_v7Verdict: "DORMANT",
|
|
51807
51811
|
_v7Lift: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slopbrick",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.3",
|
|
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": {
|