slopbrick 0.31.0 → 0.33.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.
@@ -4375,6 +4375,24 @@ function parseSource(source, filePath) {
4375
4375
  // sufficient for the v9 calibration goal.
4376
4376
  case "kt":
4377
4377
  case "kts":
4378
+ // v0.32.0: Swift files get the same parseBlankModule path.
4379
+ // All 5 `swift/*` rules (force-unwrap, print-debug, fatal-error-
4380
+ // thrown, implicitly-unwrapped-optional, strong-self-capture)
4381
+ // are regex-based and gate themselves on `/\.swift$/i.test(filePath)`
4382
+ // inside their `analyze()`. Same trade-off as Java/Kotlin.
4383
+ case "swift":
4384
+ // v0.33.0: C++ files get the same parseBlankModule path.
4385
+ // All 5 `cpp/*` rules (using-namespace-std, raw-new-delete,
4386
+ // c-style-cast, printf-debug, magic-numbers) are regex-based
4387
+ // and gate themselves on `/\.c(c|pp|xx)?$|^\.h(pp|xx)?$/i.test(filePath)`
4388
+ // inside their `analyze()`. Same trade-off as Java/Kotlin/Swift.
4389
+ case "cpp":
4390
+ case "cc":
4391
+ case "cxx":
4392
+ case "c":
4393
+ case "h":
4394
+ case "hpp":
4395
+ case "hxx":
4378
4396
  return parseBlankModule(source);
4379
4397
  default:
4380
4398
  return parseWithSwc(source, filePath);
@@ -45551,13 +45569,13 @@ var signal_strength_default = {
45551
45569
  defaultOff: true
45552
45570
  },
45553
45571
  "swift/force-unwrap": {
45554
- recall: 0,
45555
- fpRate: 0,
45556
- ratio: 1,
45557
- precision: 0,
45558
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45572
+ recall: 0.10211,
45573
+ fpRate: 0.21462,
45574
+ ratio: 0.48,
45575
+ precision: 0.1721,
45576
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45559
45577
  verdict: "DORMANT",
45560
- _calibrationNote: "v0.24: new rule (Swift force-unwrap \u2014 `as!`, `try!`, `var!.prop` in production). DORMANT until v9 Swift corpus calibration.",
45578
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique measurement: 58 TP files, 279 FP files, ratio=0.48. Era-confounded: pre-2022 Swift used ! freely (the only way to unwrap); modern Swift uses guard let / if let / try?. Same direction as kotlin/force-unwrap (0.35) and kotlin/runblocking-misuse (0.50). INSUFFICIENT_DATA: pos arm 568 files (below 10k floor).",
45561
45579
  aiSpecific: true,
45562
45580
  _v7Verdict: "DORMANT",
45563
45581
  _v7Lift: 1,
@@ -45566,16 +45584,21 @@ var signal_strength_default = {
45566
45584
  _v7Precision: 0,
45567
45585
  _v8Verdict: "DORMANT",
45568
45586
  _v8Lift: 1,
45587
+ _v9Verdict: "DORMANT",
45588
+ _v9Lift: 0.48,
45589
+ _v9Recall: 0.10211,
45590
+ _v9FpRate: 0.21462,
45591
+ _v9Precision: 0.1721,
45569
45592
  defaultOff: true
45570
45593
  },
45571
45594
  "swift/print-debug": {
45572
- recall: 0,
45573
- fpRate: 0,
45574
- ratio: 1,
45575
- precision: 0,
45576
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45577
- verdict: "DORMANT",
45578
- _calibrationNote: "v0.24: new rule (multi-print in Swift source \u2014 use Logger / os.log). DORMANT until v9 Swift corpus calibration.",
45595
+ recall: 0.06866,
45596
+ fpRate: 0.06077,
45597
+ ratio: 1.13,
45598
+ precision: 0.3305,
45599
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45600
+ verdict: "OK",
45601
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 39 TP files, 79 FP files, ratio=1.13 (\u22651.0, OK). Total-fires measurement was ratio=1.78 (1.6x higher) but per-file is more conservative. precision=33.05% (below 50% USEFUL threshold); verdict=OK. The direction is positive: post-2024 Swift (especially AI-generated examples in OpenAI Swift, WhisperKit) uses print() for output; pre-2022 production Swift (Alamofire, Vapor, Moya) uses os.Logger / OSLog. 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).",
45579
45602
  aiSpecific: true,
45580
45603
  _v7Verdict: "DORMANT",
45581
45604
  _v7Lift: 1,
@@ -45584,16 +45607,21 @@ var signal_strength_default = {
45584
45607
  _v7Precision: 0,
45585
45608
  _v8Verdict: "DORMANT",
45586
45609
  _v8Lift: 1,
45610
+ _v9Verdict: "OK",
45611
+ _v9Lift: 1.13,
45612
+ _v9Recall: 0.06866,
45613
+ _v9FpRate: 0.06077,
45614
+ _v9Precision: 0.3305,
45587
45615
  defaultOff: true
45588
45616
  },
45589
45617
  "swift/fatal-error-thrown": {
45590
- recall: 0,
45591
- fpRate: 0,
45592
- ratio: 1,
45593
- precision: 0,
45594
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45618
+ recall: 0.06514,
45619
+ fpRate: 0.11462,
45620
+ ratio: 0.57,
45621
+ precision: 0.1989,
45622
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45595
45623
  verdict: "DORMANT",
45596
- _calibrationNote: "v0.24: new rule (`fatalError` / `preconditionFailure` in production Swift \u2014 replaces with typed default). DORMANT until v9 Swift corpus calibration.",
45624
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 37 TP files, 149 FP files, ratio=0.57. Era-confounded: pre-2022 Swift used fatalError liberally for unrecoverable states; modern Swift uses typed errors (throws) and Result types. INSUFFICIENT_DATA: pos arm 568 files.",
45597
45625
  aiSpecific: true,
45598
45626
  _v7Verdict: "DORMANT",
45599
45627
  _v7Lift: 1,
@@ -45602,16 +45630,21 @@ var signal_strength_default = {
45602
45630
  _v7Precision: 0,
45603
45631
  _v8Verdict: "DORMANT",
45604
45632
  _v8Lift: 1,
45633
+ _v9Verdict: "DORMANT",
45634
+ _v9Lift: 0.57,
45635
+ _v9Recall: 0.06514,
45636
+ _v9FpRate: 0.11462,
45637
+ _v9Precision: 0.1989,
45605
45638
  defaultOff: true
45606
45639
  },
45607
45640
  "swift/implicitly-unwrapped-optional": {
45608
- recall: 0,
45609
- fpRate: 0,
45610
- ratio: 1,
45611
- precision: 0,
45612
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45641
+ recall: 0.01937,
45642
+ fpRate: 0.10692,
45643
+ ratio: 0.18,
45644
+ precision: 0.0733,
45645
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45613
45646
  verdict: "DORMANT",
45614
- _calibrationNote: "v0.24: new rule (Swift implicitly unwrapped optional \u2014 declare as Type? and unwrap with guard let). DORMANT until v9 Swift corpus calibration.",
45647
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 11 TP files, 139 FP files, ratio=0.18 \u2014 strong era-confound. Pre-2022 Swift used `var foo: Bar!` for IBOutlets and delegates; modern Swift uses `weak var` or declares as `Bar?` and unwraps with guard let. Same magnitude as kotlin/coroutine-global-scope (0.09) \u2014 strongest era-confound in v9 history. INSUFFICIENT_DATA: pos arm 568 files.",
45615
45648
  aiSpecific: true,
45616
45649
  _v7Verdict: "DORMANT",
45617
45650
  _v7Lift: 1,
@@ -45620,16 +45653,21 @@ var signal_strength_default = {
45620
45653
  _v7Precision: 0,
45621
45654
  _v8Verdict: "DORMANT",
45622
45655
  _v8Lift: 1,
45656
+ _v9Verdict: "DORMANT",
45657
+ _v9Lift: 0.18,
45658
+ _v9Recall: 0.01937,
45659
+ _v9FpRate: 0.10692,
45660
+ _v9Precision: 0.0733,
45623
45661
  defaultOff: true
45624
45662
  },
45625
45663
  "swift/strong-self-capture": {
45626
- recall: 0,
45627
- fpRate: 0,
45628
- ratio: 1,
45629
- precision: 0,
45630
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45664
+ recall: 0.24824,
45665
+ fpRate: 0.44308,
45666
+ ratio: 0.56,
45667
+ precision: 0.1967,
45668
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45631
45669
  verdict: "DORMANT",
45632
- _calibrationNote: "v0.24: new rule (Swift closure captures `self` strongly \u2014 retain cycle. Use [weak self] / [unowned self]). DORMANT until v9 Swift corpus calibration.",
45670
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 141 TP files, 576 FP files, ratio=0.56. Era-confounded: pre-2022 Swift closures defaulted to strong self capture; modern Swift (Swift 5.7+) emits a warning for implicit self capture in escaping closures. The rule fires multiple times per file (multiple closures) \u2014 total fires were 2316 TP, 8913 FP, but per-file is 141 TP, 576 FP. INSUFFICIENT_DATA: pos arm 568 files.",
45633
45671
  aiSpecific: true,
45634
45672
  _v7Verdict: "DORMANT",
45635
45673
  _v7Lift: 1,
@@ -45638,16 +45676,21 @@ var signal_strength_default = {
45638
45676
  _v7Precision: 0,
45639
45677
  _v8Verdict: "DORMANT",
45640
45678
  _v8Lift: 1,
45679
+ _v9Verdict: "DORMANT",
45680
+ _v9Lift: 0.56,
45681
+ _v9Recall: 0.24824,
45682
+ _v9FpRate: 0.44308,
45683
+ _v9Precision: 0.1967,
45641
45684
  defaultOff: true
45642
45685
  },
45643
45686
  "cpp/using-namespace-std": {
45644
45687
  recall: 0,
45645
- fpRate: 0,
45646
- ratio: 1,
45688
+ fpRate: 2e-4,
45689
+ ratio: 0,
45647
45690
  precision: 0,
45648
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45691
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45649
45692
  verdict: "DORMANT",
45650
- _calibrationNote: "v0.24: new rule (`using namespace std;` in C++ header \u2014 pollutes every consumer). DORMANT until v9 C++ corpus calibration.",
45693
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). 1 fire total (in neg). Pre-2022 C++ used `using namespace std;` extensively (it's idiomatic in tutorials); modern C++ deprecated it. INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
45651
45694
  aiSpecific: true,
45652
45695
  _v7Verdict: "DORMANT",
45653
45696
  _v7Lift: 1,
@@ -45656,16 +45699,21 @@ var signal_strength_default = {
45656
45699
  _v7Precision: 0,
45657
45700
  _v8Verdict: "DORMANT",
45658
45701
  _v8Lift: 1,
45702
+ _v9Verdict: "DORMANT",
45703
+ _v9Lift: 0,
45704
+ _v9Recall: 0,
45705
+ _v9FpRate: 2e-4,
45706
+ _v9Precision: 0,
45659
45707
  defaultOff: true
45660
45708
  },
45661
45709
  "cpp/raw-new-delete": {
45662
- recall: 0,
45663
- fpRate: 0,
45664
- ratio: 1,
45665
- precision: 0,
45666
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45710
+ recall: 967e-5,
45711
+ fpRate: 0.01077,
45712
+ ratio: 0.9,
45713
+ precision: 0.2254,
45714
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45667
45715
  verdict: "DORMANT",
45668
- _calibrationNote: "v0.24: new rule (manual `new` / `delete` pairing in C++ \u2014 use std::make_unique / std::unique_ptr). DORMANT until v9 C++ corpus calibration.",
45716
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 16 TP, 55 FP, ratio=0.90. Era-confounded: pre-2022 C++ used raw new/delete extensively; modern C++ uses std::make_unique. INSUFFICIENT_DATA: pos arm 1655 files.",
45669
45717
  aiSpecific: true,
45670
45718
  _v7Verdict: "DORMANT",
45671
45719
  _v7Lift: 1,
@@ -45674,16 +45722,21 @@ var signal_strength_default = {
45674
45722
  _v7Precision: 0,
45675
45723
  _v8Verdict: "DORMANT",
45676
45724
  _v8Lift: 1,
45725
+ _v9Verdict: "DORMANT",
45726
+ _v9Lift: 0.9,
45727
+ _v9Recall: 967e-5,
45728
+ _v9FpRate: 0.01077,
45729
+ _v9Precision: 0.2254,
45677
45730
  defaultOff: true
45678
45731
  },
45679
45732
  "cpp/c-style-cast": {
45680
- recall: 0,
45681
- fpRate: 0,
45682
- ratio: 1,
45683
- precision: 0,
45684
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45733
+ recall: 0.5281,
45734
+ fpRate: 0.56491,
45735
+ ratio: 0.93,
45736
+ precision: 0.2325,
45737
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45685
45738
  verdict: "DORMANT",
45686
- _calibrationNote: "v0.24: new rule (C-style cast `(int)x` in C++ \u2014 use static_cast / reinterpret_cast / const_cast). DORMANT until v9 C++ corpus calibration.",
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.",
45687
45740
  aiSpecific: true,
45688
45741
  _v7Verdict: "DORMANT",
45689
45742
  _v7Lift: 1,
@@ -45692,16 +45745,21 @@ var signal_strength_default = {
45692
45745
  _v7Precision: 0,
45693
45746
  _v8Verdict: "DORMANT",
45694
45747
  _v8Lift: 1,
45748
+ _v9Verdict: "DORMANT",
45749
+ _v9Lift: 0.93,
45750
+ _v9Recall: 0.5281,
45751
+ _v9FpRate: 0.56491,
45752
+ _v9Precision: 0.2325,
45695
45753
  defaultOff: true
45696
45754
  },
45697
45755
  "cpp/printf-debug": {
45698
- recall: 0,
45699
- fpRate: 0,
45700
- ratio: 1,
45701
- precision: 0,
45702
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45703
- verdict: "DORMANT",
45704
- _calibrationNote: "v0.24: new rule (printf family / std::cout debug printing in C++ \u2014 use spdlog / glog / AbslLog). DORMANT until v9 C++ corpus calibration.",
45756
+ recall: 0.09426,
45757
+ fpRate: 0.03877,
45758
+ ratio: 2.43,
45759
+ precision: 0.4407,
45760
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45761
+ verdict: "OK",
45762
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 156 TP files, 198 FP files, ratio=2.43 (\u22651.5) \u2014 fourth positive-signal rule in v9 history (and the strongest ratio so far). precision=44.07% (just below 50% USEFUL threshold); verdict=OK. Total fires: 182 TP, 198 FP. The signal is real: post-2024 C++ (mostly AI-generated demos in llama.cpp, whisper.cpp, openai-cpp) uses printf/cout for output; pre-2022 production C++ (folly, protobuf, abseil) uses spdlog / glog / AbslLog. Same direction as kotlin/println-as-log (1.84), java/system-out-println (1.73 refined), swift/print-debug (1.13). INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
45705
45763
  aiSpecific: true,
45706
45764
  _v7Verdict: "DORMANT",
45707
45765
  _v7Lift: 1,
@@ -45710,16 +45768,21 @@ var signal_strength_default = {
45710
45768
  _v7Precision: 0,
45711
45769
  _v8Verdict: "DORMANT",
45712
45770
  _v8Lift: 1,
45771
+ _v9Verdict: "OK",
45772
+ _v9Lift: 2.43,
45773
+ _v9Recall: 0.09426,
45774
+ _v9FpRate: 0.03877,
45775
+ _v9Precision: 0.4407,
45713
45776
  defaultOff: true
45714
45777
  },
45715
45778
  "cpp/magic-numbers": {
45716
- recall: 0,
45717
- fpRate: 0,
45718
- ratio: 1,
45719
- precision: 0,
45720
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45779
+ recall: 0.13293,
45780
+ fpRate: 0.15391,
45781
+ ratio: 0.86,
45782
+ precision: 0.2187,
45783
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45721
45784
  verdict: "DORMANT",
45722
- _calibrationNote: "v0.24: new rule (magic-number literal in C++ comparison / return \u2014 name it `constexpr int MAX = ...`). DORMANT until v9 C++ corpus calibration.",
45785
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 220 TP, 786 FP, ratio=0.86. Both arms have similar proportions of files with magic numbers \u2014 this is a general C++ anti-pattern that hasn't been eradicated. INSUFFICIENT_DATA: pos arm 1655 files.",
45723
45786
  aiSpecific: true,
45724
45787
  _v7Verdict: "DORMANT",
45725
45788
  _v7Lift: 1,
@@ -45728,6 +45791,11 @@ var signal_strength_default = {
45728
45791
  _v7Precision: 0,
45729
45792
  _v8Verdict: "DORMANT",
45730
45793
  _v8Lift: 1,
45794
+ _v9Verdict: "DORMANT",
45795
+ _v9Lift: 0.86,
45796
+ _v9Recall: 0.13293,
45797
+ _v9FpRate: 0.15391,
45798
+ _v9Precision: 0.2187,
45731
45799
  defaultOff: true
45732
45800
  }
45733
45801
  };
@@ -45779,15 +45847,7 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
45779
45847
  const cache = buildParserCacheConfig(cwd);
45780
45848
  const ext = (0, import_node_path9.extname)(filePath).toLowerCase();
45781
45849
  const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
45782
- ".swift",
45783
45850
  ".dart",
45784
- ".cpp",
45785
- ".cc",
45786
- ".cxx",
45787
- ".c",
45788
- ".h",
45789
- ".hpp",
45790
- ".hxx",
45791
45851
  ".rb",
45792
45852
  ".php"
45793
45853
  ]);
@@ -4346,6 +4346,24 @@ function parseSource(source, filePath) {
4346
4346
  // sufficient for the v9 calibration goal.
4347
4347
  case "kt":
4348
4348
  case "kts":
4349
+ // v0.32.0: Swift files get the same parseBlankModule path.
4350
+ // All 5 `swift/*` rules (force-unwrap, print-debug, fatal-error-
4351
+ // thrown, implicitly-unwrapped-optional, strong-self-capture)
4352
+ // are regex-based and gate themselves on `/\.swift$/i.test(filePath)`
4353
+ // inside their `analyze()`. Same trade-off as Java/Kotlin.
4354
+ case "swift":
4355
+ // v0.33.0: C++ files get the same parseBlankModule path.
4356
+ // All 5 `cpp/*` rules (using-namespace-std, raw-new-delete,
4357
+ // c-style-cast, printf-debug, magic-numbers) are regex-based
4358
+ // and gate themselves on `/\.c(c|pp|xx)?$|^\.h(pp|xx)?$/i.test(filePath)`
4359
+ // inside their `analyze()`. Same trade-off as Java/Kotlin/Swift.
4360
+ case "cpp":
4361
+ case "cc":
4362
+ case "cxx":
4363
+ case "c":
4364
+ case "h":
4365
+ case "hpp":
4366
+ case "hxx":
4349
4367
  return parseBlankModule(source);
4350
4368
  default:
4351
4369
  return parseWithSwc(source, filePath);
@@ -45522,13 +45540,13 @@ var signal_strength_default = {
45522
45540
  defaultOff: true
45523
45541
  },
45524
45542
  "swift/force-unwrap": {
45525
- recall: 0,
45526
- fpRate: 0,
45527
- ratio: 1,
45528
- precision: 0,
45529
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45543
+ recall: 0.10211,
45544
+ fpRate: 0.21462,
45545
+ ratio: 0.48,
45546
+ precision: 0.1721,
45547
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45530
45548
  verdict: "DORMANT",
45531
- _calibrationNote: "v0.24: new rule (Swift force-unwrap \u2014 `as!`, `try!`, `var!.prop` in production). DORMANT until v9 Swift corpus calibration.",
45549
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique measurement: 58 TP files, 279 FP files, ratio=0.48. Era-confounded: pre-2022 Swift used ! freely (the only way to unwrap); modern Swift uses guard let / if let / try?. Same direction as kotlin/force-unwrap (0.35) and kotlin/runblocking-misuse (0.50). INSUFFICIENT_DATA: pos arm 568 files (below 10k floor).",
45532
45550
  aiSpecific: true,
45533
45551
  _v7Verdict: "DORMANT",
45534
45552
  _v7Lift: 1,
@@ -45537,16 +45555,21 @@ var signal_strength_default = {
45537
45555
  _v7Precision: 0,
45538
45556
  _v8Verdict: "DORMANT",
45539
45557
  _v8Lift: 1,
45558
+ _v9Verdict: "DORMANT",
45559
+ _v9Lift: 0.48,
45560
+ _v9Recall: 0.10211,
45561
+ _v9FpRate: 0.21462,
45562
+ _v9Precision: 0.1721,
45540
45563
  defaultOff: true
45541
45564
  },
45542
45565
  "swift/print-debug": {
45543
- recall: 0,
45544
- fpRate: 0,
45545
- ratio: 1,
45546
- precision: 0,
45547
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45548
- verdict: "DORMANT",
45549
- _calibrationNote: "v0.24: new rule (multi-print in Swift source \u2014 use Logger / os.log). DORMANT until v9 Swift corpus calibration.",
45566
+ recall: 0.06866,
45567
+ fpRate: 0.06077,
45568
+ ratio: 1.13,
45569
+ precision: 0.3305,
45570
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45571
+ verdict: "OK",
45572
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 39 TP files, 79 FP files, ratio=1.13 (\u22651.0, OK). Total-fires measurement was ratio=1.78 (1.6x higher) but per-file is more conservative. precision=33.05% (below 50% USEFUL threshold); verdict=OK. The direction is positive: post-2024 Swift (especially AI-generated examples in OpenAI Swift, WhisperKit) uses print() for output; pre-2022 production Swift (Alamofire, Vapor, Moya) uses os.Logger / OSLog. 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).",
45550
45573
  aiSpecific: true,
45551
45574
  _v7Verdict: "DORMANT",
45552
45575
  _v7Lift: 1,
@@ -45555,16 +45578,21 @@ var signal_strength_default = {
45555
45578
  _v7Precision: 0,
45556
45579
  _v8Verdict: "DORMANT",
45557
45580
  _v8Lift: 1,
45581
+ _v9Verdict: "OK",
45582
+ _v9Lift: 1.13,
45583
+ _v9Recall: 0.06866,
45584
+ _v9FpRate: 0.06077,
45585
+ _v9Precision: 0.3305,
45558
45586
  defaultOff: true
45559
45587
  },
45560
45588
  "swift/fatal-error-thrown": {
45561
- recall: 0,
45562
- fpRate: 0,
45563
- ratio: 1,
45564
- precision: 0,
45565
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45589
+ recall: 0.06514,
45590
+ fpRate: 0.11462,
45591
+ ratio: 0.57,
45592
+ precision: 0.1989,
45593
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45566
45594
  verdict: "DORMANT",
45567
- _calibrationNote: "v0.24: new rule (`fatalError` / `preconditionFailure` in production Swift \u2014 replaces with typed default). DORMANT until v9 Swift corpus calibration.",
45595
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 37 TP files, 149 FP files, ratio=0.57. Era-confounded: pre-2022 Swift used fatalError liberally for unrecoverable states; modern Swift uses typed errors (throws) and Result types. INSUFFICIENT_DATA: pos arm 568 files.",
45568
45596
  aiSpecific: true,
45569
45597
  _v7Verdict: "DORMANT",
45570
45598
  _v7Lift: 1,
@@ -45573,16 +45601,21 @@ var signal_strength_default = {
45573
45601
  _v7Precision: 0,
45574
45602
  _v8Verdict: "DORMANT",
45575
45603
  _v8Lift: 1,
45604
+ _v9Verdict: "DORMANT",
45605
+ _v9Lift: 0.57,
45606
+ _v9Recall: 0.06514,
45607
+ _v9FpRate: 0.11462,
45608
+ _v9Precision: 0.1989,
45576
45609
  defaultOff: true
45577
45610
  },
45578
45611
  "swift/implicitly-unwrapped-optional": {
45579
- recall: 0,
45580
- fpRate: 0,
45581
- ratio: 1,
45582
- precision: 0,
45583
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45612
+ recall: 0.01937,
45613
+ fpRate: 0.10692,
45614
+ ratio: 0.18,
45615
+ precision: 0.0733,
45616
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45584
45617
  verdict: "DORMANT",
45585
- _calibrationNote: "v0.24: new rule (Swift implicitly unwrapped optional \u2014 declare as Type? and unwrap with guard let). DORMANT until v9 Swift corpus calibration.",
45618
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 11 TP files, 139 FP files, ratio=0.18 \u2014 strong era-confound. Pre-2022 Swift used `var foo: Bar!` for IBOutlets and delegates; modern Swift uses `weak var` or declares as `Bar?` and unwraps with guard let. Same magnitude as kotlin/coroutine-global-scope (0.09) \u2014 strongest era-confound in v9 history. INSUFFICIENT_DATA: pos arm 568 files.",
45586
45619
  aiSpecific: true,
45587
45620
  _v7Verdict: "DORMANT",
45588
45621
  _v7Lift: 1,
@@ -45591,16 +45624,21 @@ var signal_strength_default = {
45591
45624
  _v7Precision: 0,
45592
45625
  _v8Verdict: "DORMANT",
45593
45626
  _v8Lift: 1,
45627
+ _v9Verdict: "DORMANT",
45628
+ _v9Lift: 0.18,
45629
+ _v9Recall: 0.01937,
45630
+ _v9FpRate: 0.10692,
45631
+ _v9Precision: 0.0733,
45594
45632
  defaultOff: true
45595
45633
  },
45596
45634
  "swift/strong-self-capture": {
45597
- recall: 0,
45598
- fpRate: 0,
45599
- ratio: 1,
45600
- precision: 0,
45601
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45635
+ recall: 0.24824,
45636
+ fpRate: 0.44308,
45637
+ ratio: 0.56,
45638
+ precision: 0.1967,
45639
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45602
45640
  verdict: "DORMANT",
45603
- _calibrationNote: "v0.24: new rule (Swift closure captures `self` strongly \u2014 retain cycle. Use [weak self] / [unowned self]). DORMANT until v9 Swift corpus calibration.",
45641
+ _calibrationNote: "v0.32: v9 Swift calibration (1300 neg, 568 pos). Per-file unique: 141 TP files, 576 FP files, ratio=0.56. Era-confounded: pre-2022 Swift closures defaulted to strong self capture; modern Swift (Swift 5.7+) emits a warning for implicit self capture in escaping closures. The rule fires multiple times per file (multiple closures) \u2014 total fires were 2316 TP, 8913 FP, but per-file is 141 TP, 576 FP. INSUFFICIENT_DATA: pos arm 568 files.",
45604
45642
  aiSpecific: true,
45605
45643
  _v7Verdict: "DORMANT",
45606
45644
  _v7Lift: 1,
@@ -45609,16 +45647,21 @@ var signal_strength_default = {
45609
45647
  _v7Precision: 0,
45610
45648
  _v8Verdict: "DORMANT",
45611
45649
  _v8Lift: 1,
45650
+ _v9Verdict: "DORMANT",
45651
+ _v9Lift: 0.56,
45652
+ _v9Recall: 0.24824,
45653
+ _v9FpRate: 0.44308,
45654
+ _v9Precision: 0.1967,
45612
45655
  defaultOff: true
45613
45656
  },
45614
45657
  "cpp/using-namespace-std": {
45615
45658
  recall: 0,
45616
- fpRate: 0,
45617
- ratio: 1,
45659
+ fpRate: 2e-4,
45660
+ ratio: 0,
45618
45661
  precision: 0,
45619
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45662
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45620
45663
  verdict: "DORMANT",
45621
- _calibrationNote: "v0.24: new rule (`using namespace std;` in C++ header \u2014 pollutes every consumer). DORMANT until v9 C++ corpus calibration.",
45664
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). 1 fire total (in neg). Pre-2022 C++ used `using namespace std;` extensively (it's idiomatic in tutorials); modern C++ deprecated it. INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
45622
45665
  aiSpecific: true,
45623
45666
  _v7Verdict: "DORMANT",
45624
45667
  _v7Lift: 1,
@@ -45627,16 +45670,21 @@ var signal_strength_default = {
45627
45670
  _v7Precision: 0,
45628
45671
  _v8Verdict: "DORMANT",
45629
45672
  _v8Lift: 1,
45673
+ _v9Verdict: "DORMANT",
45674
+ _v9Lift: 0,
45675
+ _v9Recall: 0,
45676
+ _v9FpRate: 2e-4,
45677
+ _v9Precision: 0,
45630
45678
  defaultOff: true
45631
45679
  },
45632
45680
  "cpp/raw-new-delete": {
45633
- recall: 0,
45634
- fpRate: 0,
45635
- ratio: 1,
45636
- precision: 0,
45637
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45681
+ recall: 967e-5,
45682
+ fpRate: 0.01077,
45683
+ ratio: 0.9,
45684
+ precision: 0.2254,
45685
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45638
45686
  verdict: "DORMANT",
45639
- _calibrationNote: "v0.24: new rule (manual `new` / `delete` pairing in C++ \u2014 use std::make_unique / std::unique_ptr). DORMANT until v9 C++ corpus calibration.",
45687
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 16 TP, 55 FP, ratio=0.90. Era-confounded: pre-2022 C++ used raw new/delete extensively; modern C++ uses std::make_unique. INSUFFICIENT_DATA: pos arm 1655 files.",
45640
45688
  aiSpecific: true,
45641
45689
  _v7Verdict: "DORMANT",
45642
45690
  _v7Lift: 1,
@@ -45645,16 +45693,21 @@ var signal_strength_default = {
45645
45693
  _v7Precision: 0,
45646
45694
  _v8Verdict: "DORMANT",
45647
45695
  _v8Lift: 1,
45696
+ _v9Verdict: "DORMANT",
45697
+ _v9Lift: 0.9,
45698
+ _v9Recall: 967e-5,
45699
+ _v9FpRate: 0.01077,
45700
+ _v9Precision: 0.2254,
45648
45701
  defaultOff: true
45649
45702
  },
45650
45703
  "cpp/c-style-cast": {
45651
- recall: 0,
45652
- fpRate: 0,
45653
- ratio: 1,
45654
- precision: 0,
45655
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45704
+ recall: 0.5281,
45705
+ fpRate: 0.56491,
45706
+ ratio: 0.93,
45707
+ precision: 0.2325,
45708
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45656
45709
  verdict: "DORMANT",
45657
- _calibrationNote: "v0.24: new rule (C-style cast `(int)x` in C++ \u2014 use static_cast / reinterpret_cast / const_cast). DORMANT until v9 C++ corpus calibration.",
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.",
45658
45711
  aiSpecific: true,
45659
45712
  _v7Verdict: "DORMANT",
45660
45713
  _v7Lift: 1,
@@ -45663,16 +45716,21 @@ var signal_strength_default = {
45663
45716
  _v7Precision: 0,
45664
45717
  _v8Verdict: "DORMANT",
45665
45718
  _v8Lift: 1,
45719
+ _v9Verdict: "DORMANT",
45720
+ _v9Lift: 0.93,
45721
+ _v9Recall: 0.5281,
45722
+ _v9FpRate: 0.56491,
45723
+ _v9Precision: 0.2325,
45666
45724
  defaultOff: true
45667
45725
  },
45668
45726
  "cpp/printf-debug": {
45669
- recall: 0,
45670
- fpRate: 0,
45671
- ratio: 1,
45672
- precision: 0,
45673
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45674
- verdict: "DORMANT",
45675
- _calibrationNote: "v0.24: new rule (printf family / std::cout debug printing in C++ \u2014 use spdlog / glog / AbslLog). DORMANT until v9 C++ corpus calibration.",
45727
+ recall: 0.09426,
45728
+ fpRate: 0.03877,
45729
+ ratio: 2.43,
45730
+ precision: 0.4407,
45731
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45732
+ verdict: "OK",
45733
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 156 TP files, 198 FP files, ratio=2.43 (\u22651.5) \u2014 fourth positive-signal rule in v9 history (and the strongest ratio so far). precision=44.07% (just below 50% USEFUL threshold); verdict=OK. Total fires: 182 TP, 198 FP. The signal is real: post-2024 C++ (mostly AI-generated demos in llama.cpp, whisper.cpp, openai-cpp) uses printf/cout for output; pre-2022 production C++ (folly, protobuf, abseil) uses spdlog / glog / AbslLog. Same direction as kotlin/println-as-log (1.84), java/system-out-println (1.73 refined), swift/print-debug (1.13). INSUFFICIENT_DATA: pos arm 1655 files (below 10k floor).",
45676
45734
  aiSpecific: true,
45677
45735
  _v7Verdict: "DORMANT",
45678
45736
  _v7Lift: 1,
@@ -45681,16 +45739,21 @@ var signal_strength_default = {
45681
45739
  _v7Precision: 0,
45682
45740
  _v8Verdict: "DORMANT",
45683
45741
  _v8Lift: 1,
45742
+ _v9Verdict: "OK",
45743
+ _v9Lift: 2.43,
45744
+ _v9Recall: 0.09426,
45745
+ _v9FpRate: 0.03877,
45746
+ _v9Precision: 0.4407,
45684
45747
  defaultOff: true
45685
45748
  },
45686
45749
  "cpp/magic-numbers": {
45687
- recall: 0,
45688
- fpRate: 0,
45689
- ratio: 1,
45690
- precision: 0,
45691
- lastCalibratedAt: "2026-07-02T00:00:00Z",
45750
+ recall: 0.13293,
45751
+ fpRate: 0.15391,
45752
+ ratio: 0.86,
45753
+ precision: 0.2187,
45754
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
45692
45755
  verdict: "DORMANT",
45693
- _calibrationNote: "v0.24: new rule (magic-number literal in C++ comparison / return \u2014 name it `constexpr int MAX = ...`). DORMANT until v9 C++ corpus calibration.",
45756
+ _calibrationNote: "v0.33: v9 C++ calibration (5107 neg, 1655 pos). Per-file unique: 220 TP, 786 FP, ratio=0.86. Both arms have similar proportions of files with magic numbers \u2014 this is a general C++ anti-pattern that hasn't been eradicated. INSUFFICIENT_DATA: pos arm 1655 files.",
45694
45757
  aiSpecific: true,
45695
45758
  _v7Verdict: "DORMANT",
45696
45759
  _v7Lift: 1,
@@ -45699,6 +45762,11 @@ var signal_strength_default = {
45699
45762
  _v7Precision: 0,
45700
45763
  _v8Verdict: "DORMANT",
45701
45764
  _v8Lift: 1,
45765
+ _v9Verdict: "DORMANT",
45766
+ _v9Lift: 0.86,
45767
+ _v9Recall: 0.13293,
45768
+ _v9FpRate: 0.15391,
45769
+ _v9Precision: 0.2187,
45702
45770
  defaultOff: true
45703
45771
  }
45704
45772
  };
@@ -45750,15 +45818,7 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
45750
45818
  const cache = buildParserCacheConfig(cwd);
45751
45819
  const ext = extname4(filePath).toLowerCase();
45752
45820
  const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
45753
- ".swift",
45754
45821
  ".dart",
45755
- ".cpp",
45756
- ".cc",
45757
- ".cxx",
45758
- ".c",
45759
- ".h",
45760
- ".hpp",
45761
- ".hxx",
45762
45822
  ".rb",
45763
45823
  ".php"
45764
45824
  ]);