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.
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.31.0";
22
+ VERSION = "0.33.0";
23
23
  }
24
24
  });
25
25
 
@@ -36599,6 +36599,24 @@ function parseSource(source, filePath) {
36599
36599
  // sufficient for the v9 calibration goal.
36600
36600
  case "kt":
36601
36601
  case "kts":
36602
+ // v0.32.0: Swift files get the same parseBlankModule path.
36603
+ // All 5 `swift/*` rules (force-unwrap, print-debug, fatal-error-
36604
+ // thrown, implicitly-unwrapped-optional, strong-self-capture)
36605
+ // are regex-based and gate themselves on `/\.swift$/i.test(filePath)`
36606
+ // inside their `analyze()`. Same trade-off as Java/Kotlin.
36607
+ case "swift":
36608
+ // v0.33.0: C++ files get the same parseBlankModule path.
36609
+ // All 5 `cpp/*` rules (using-namespace-std, raw-new-delete,
36610
+ // c-style-cast, printf-debug, magic-numbers) are regex-based
36611
+ // and gate themselves on `/\.c(c|pp|xx)?$|^\.h(pp|xx)?$/i.test(filePath)`
36612
+ // inside their `analyze()`. Same trade-off as Java/Kotlin/Swift.
36613
+ case "cpp":
36614
+ case "cc":
36615
+ case "cxx":
36616
+ case "c":
36617
+ case "h":
36618
+ case "hpp":
36619
+ case "hxx":
36602
36620
  return parseBlankModule(source);
36603
36621
  default:
36604
36622
  return parseWithSwc(source, filePath);
@@ -51616,13 +51634,13 @@ var init_signal_strength = __esm({
51616
51634
  defaultOff: true
51617
51635
  },
51618
51636
  "swift/force-unwrap": {
51619
- recall: 0,
51620
- fpRate: 0,
51621
- ratio: 1,
51622
- precision: 0,
51623
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51637
+ recall: 0.10211,
51638
+ fpRate: 0.21462,
51639
+ ratio: 0.48,
51640
+ precision: 0.1721,
51641
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51624
51642
  verdict: "DORMANT",
51625
- _calibrationNote: "v0.24: new rule (Swift force-unwrap \u2014 `as!`, `try!`, `var!.prop` in production). DORMANT until v9 Swift corpus calibration.",
51643
+ _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).",
51626
51644
  aiSpecific: true,
51627
51645
  _v7Verdict: "DORMANT",
51628
51646
  _v7Lift: 1,
@@ -51631,16 +51649,21 @@ var init_signal_strength = __esm({
51631
51649
  _v7Precision: 0,
51632
51650
  _v8Verdict: "DORMANT",
51633
51651
  _v8Lift: 1,
51652
+ _v9Verdict: "DORMANT",
51653
+ _v9Lift: 0.48,
51654
+ _v9Recall: 0.10211,
51655
+ _v9FpRate: 0.21462,
51656
+ _v9Precision: 0.1721,
51634
51657
  defaultOff: true
51635
51658
  },
51636
51659
  "swift/print-debug": {
51637
- recall: 0,
51638
- fpRate: 0,
51639
- ratio: 1,
51640
- precision: 0,
51641
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51642
- verdict: "DORMANT",
51643
- _calibrationNote: "v0.24: new rule (multi-print in Swift source \u2014 use Logger / os.log). DORMANT until v9 Swift corpus calibration.",
51660
+ recall: 0.06866,
51661
+ fpRate: 0.06077,
51662
+ ratio: 1.13,
51663
+ precision: 0.3305,
51664
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51665
+ verdict: "OK",
51666
+ _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).",
51644
51667
  aiSpecific: true,
51645
51668
  _v7Verdict: "DORMANT",
51646
51669
  _v7Lift: 1,
@@ -51649,16 +51672,21 @@ var init_signal_strength = __esm({
51649
51672
  _v7Precision: 0,
51650
51673
  _v8Verdict: "DORMANT",
51651
51674
  _v8Lift: 1,
51675
+ _v9Verdict: "OK",
51676
+ _v9Lift: 1.13,
51677
+ _v9Recall: 0.06866,
51678
+ _v9FpRate: 0.06077,
51679
+ _v9Precision: 0.3305,
51652
51680
  defaultOff: true
51653
51681
  },
51654
51682
  "swift/fatal-error-thrown": {
51655
- recall: 0,
51656
- fpRate: 0,
51657
- ratio: 1,
51658
- precision: 0,
51659
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51683
+ recall: 0.06514,
51684
+ fpRate: 0.11462,
51685
+ ratio: 0.57,
51686
+ precision: 0.1989,
51687
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51660
51688
  verdict: "DORMANT",
51661
- _calibrationNote: "v0.24: new rule (`fatalError` / `preconditionFailure` in production Swift \u2014 replaces with typed default). DORMANT until v9 Swift corpus calibration.",
51689
+ _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.",
51662
51690
  aiSpecific: true,
51663
51691
  _v7Verdict: "DORMANT",
51664
51692
  _v7Lift: 1,
@@ -51667,16 +51695,21 @@ var init_signal_strength = __esm({
51667
51695
  _v7Precision: 0,
51668
51696
  _v8Verdict: "DORMANT",
51669
51697
  _v8Lift: 1,
51698
+ _v9Verdict: "DORMANT",
51699
+ _v9Lift: 0.57,
51700
+ _v9Recall: 0.06514,
51701
+ _v9FpRate: 0.11462,
51702
+ _v9Precision: 0.1989,
51670
51703
  defaultOff: true
51671
51704
  },
51672
51705
  "swift/implicitly-unwrapped-optional": {
51673
- recall: 0,
51674
- fpRate: 0,
51675
- ratio: 1,
51676
- precision: 0,
51677
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51706
+ recall: 0.01937,
51707
+ fpRate: 0.10692,
51708
+ ratio: 0.18,
51709
+ precision: 0.0733,
51710
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51678
51711
  verdict: "DORMANT",
51679
- _calibrationNote: "v0.24: new rule (Swift implicitly unwrapped optional \u2014 declare as Type? and unwrap with guard let). DORMANT until v9 Swift corpus calibration.",
51712
+ _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.",
51680
51713
  aiSpecific: true,
51681
51714
  _v7Verdict: "DORMANT",
51682
51715
  _v7Lift: 1,
@@ -51685,16 +51718,21 @@ var init_signal_strength = __esm({
51685
51718
  _v7Precision: 0,
51686
51719
  _v8Verdict: "DORMANT",
51687
51720
  _v8Lift: 1,
51721
+ _v9Verdict: "DORMANT",
51722
+ _v9Lift: 0.18,
51723
+ _v9Recall: 0.01937,
51724
+ _v9FpRate: 0.10692,
51725
+ _v9Precision: 0.0733,
51688
51726
  defaultOff: true
51689
51727
  },
51690
51728
  "swift/strong-self-capture": {
51691
- recall: 0,
51692
- fpRate: 0,
51693
- ratio: 1,
51694
- precision: 0,
51695
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51729
+ recall: 0.24824,
51730
+ fpRate: 0.44308,
51731
+ ratio: 0.56,
51732
+ precision: 0.1967,
51733
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51696
51734
  verdict: "DORMANT",
51697
- _calibrationNote: "v0.24: new rule (Swift closure captures `self` strongly \u2014 retain cycle. Use [weak self] / [unowned self]). DORMANT until v9 Swift corpus calibration.",
51735
+ _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.",
51698
51736
  aiSpecific: true,
51699
51737
  _v7Verdict: "DORMANT",
51700
51738
  _v7Lift: 1,
@@ -51703,16 +51741,21 @@ var init_signal_strength = __esm({
51703
51741
  _v7Precision: 0,
51704
51742
  _v8Verdict: "DORMANT",
51705
51743
  _v8Lift: 1,
51744
+ _v9Verdict: "DORMANT",
51745
+ _v9Lift: 0.56,
51746
+ _v9Recall: 0.24824,
51747
+ _v9FpRate: 0.44308,
51748
+ _v9Precision: 0.1967,
51706
51749
  defaultOff: true
51707
51750
  },
51708
51751
  "cpp/using-namespace-std": {
51709
51752
  recall: 0,
51710
- fpRate: 0,
51711
- ratio: 1,
51753
+ fpRate: 2e-4,
51754
+ ratio: 0,
51712
51755
  precision: 0,
51713
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51756
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51714
51757
  verdict: "DORMANT",
51715
- _calibrationNote: "v0.24: new rule (`using namespace std;` in C++ header \u2014 pollutes every consumer). DORMANT until v9 C++ corpus calibration.",
51758
+ _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).",
51716
51759
  aiSpecific: true,
51717
51760
  _v7Verdict: "DORMANT",
51718
51761
  _v7Lift: 1,
@@ -51721,16 +51764,21 @@ var init_signal_strength = __esm({
51721
51764
  _v7Precision: 0,
51722
51765
  _v8Verdict: "DORMANT",
51723
51766
  _v8Lift: 1,
51767
+ _v9Verdict: "DORMANT",
51768
+ _v9Lift: 0,
51769
+ _v9Recall: 0,
51770
+ _v9FpRate: 2e-4,
51771
+ _v9Precision: 0,
51724
51772
  defaultOff: true
51725
51773
  },
51726
51774
  "cpp/raw-new-delete": {
51727
- recall: 0,
51728
- fpRate: 0,
51729
- ratio: 1,
51730
- precision: 0,
51731
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51775
+ recall: 967e-5,
51776
+ fpRate: 0.01077,
51777
+ ratio: 0.9,
51778
+ precision: 0.2254,
51779
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51732
51780
  verdict: "DORMANT",
51733
- _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.",
51781
+ _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.",
51734
51782
  aiSpecific: true,
51735
51783
  _v7Verdict: "DORMANT",
51736
51784
  _v7Lift: 1,
@@ -51739,16 +51787,21 @@ var init_signal_strength = __esm({
51739
51787
  _v7Precision: 0,
51740
51788
  _v8Verdict: "DORMANT",
51741
51789
  _v8Lift: 1,
51790
+ _v9Verdict: "DORMANT",
51791
+ _v9Lift: 0.9,
51792
+ _v9Recall: 967e-5,
51793
+ _v9FpRate: 0.01077,
51794
+ _v9Precision: 0.2254,
51742
51795
  defaultOff: true
51743
51796
  },
51744
51797
  "cpp/c-style-cast": {
51745
- recall: 0,
51746
- fpRate: 0,
51747
- ratio: 1,
51748
- precision: 0,
51749
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51798
+ recall: 0.5281,
51799
+ fpRate: 0.56491,
51800
+ ratio: 0.93,
51801
+ precision: 0.2325,
51802
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51750
51803
  verdict: "DORMANT",
51751
- _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.",
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.",
51752
51805
  aiSpecific: true,
51753
51806
  _v7Verdict: "DORMANT",
51754
51807
  _v7Lift: 1,
@@ -51757,16 +51810,21 @@ var init_signal_strength = __esm({
51757
51810
  _v7Precision: 0,
51758
51811
  _v8Verdict: "DORMANT",
51759
51812
  _v8Lift: 1,
51813
+ _v9Verdict: "DORMANT",
51814
+ _v9Lift: 0.93,
51815
+ _v9Recall: 0.5281,
51816
+ _v9FpRate: 0.56491,
51817
+ _v9Precision: 0.2325,
51760
51818
  defaultOff: true
51761
51819
  },
51762
51820
  "cpp/printf-debug": {
51763
- recall: 0,
51764
- fpRate: 0,
51765
- ratio: 1,
51766
- precision: 0,
51767
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51768
- verdict: "DORMANT",
51769
- _calibrationNote: "v0.24: new rule (printf family / std::cout debug printing in C++ \u2014 use spdlog / glog / AbslLog). DORMANT until v9 C++ corpus calibration.",
51821
+ recall: 0.09426,
51822
+ fpRate: 0.03877,
51823
+ ratio: 2.43,
51824
+ precision: 0.4407,
51825
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51826
+ verdict: "OK",
51827
+ _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).",
51770
51828
  aiSpecific: true,
51771
51829
  _v7Verdict: "DORMANT",
51772
51830
  _v7Lift: 1,
@@ -51775,16 +51833,21 @@ var init_signal_strength = __esm({
51775
51833
  _v7Precision: 0,
51776
51834
  _v8Verdict: "DORMANT",
51777
51835
  _v8Lift: 1,
51836
+ _v9Verdict: "OK",
51837
+ _v9Lift: 2.43,
51838
+ _v9Recall: 0.09426,
51839
+ _v9FpRate: 0.03877,
51840
+ _v9Precision: 0.4407,
51778
51841
  defaultOff: true
51779
51842
  },
51780
51843
  "cpp/magic-numbers": {
51781
- recall: 0,
51782
- fpRate: 0,
51783
- ratio: 1,
51784
- precision: 0,
51785
- lastCalibratedAt: "2026-07-02T00:00:00Z",
51844
+ recall: 0.13293,
51845
+ fpRate: 0.15391,
51846
+ ratio: 0.86,
51847
+ precision: 0.2187,
51848
+ lastCalibratedAt: "2026-07-03T00:00:00Z",
51786
51849
  verdict: "DORMANT",
51787
- _calibrationNote: "v0.24: new rule (magic-number literal in C++ comparison / return \u2014 name it `constexpr int MAX = ...`). DORMANT until v9 C++ corpus calibration.",
51850
+ _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.",
51788
51851
  aiSpecific: true,
51789
51852
  _v7Verdict: "DORMANT",
51790
51853
  _v7Lift: 1,
@@ -51793,6 +51856,11 @@ var init_signal_strength = __esm({
51793
51856
  _v7Precision: 0,
51794
51857
  _v8Verdict: "DORMANT",
51795
51858
  _v8Lift: 1,
51859
+ _v9Verdict: "DORMANT",
51860
+ _v9Lift: 0.86,
51861
+ _v9Recall: 0.13293,
51862
+ _v9FpRate: 0.15391,
51863
+ _v9Precision: 0.2187,
51796
51864
  defaultOff: true
51797
51865
  }
51798
51866
  };
@@ -51876,15 +51944,7 @@ async function scanFile(filePath, config, registry, cwd = process.cwd()) {
51876
51944
  const cache = buildParserCacheConfig(cwd);
51877
51945
  const ext = extname5(filePath).toLowerCase();
51878
51946
  const UNSUPPORTED_LANGS = /* @__PURE__ */ new Set([
51879
- ".swift",
51880
51947
  ".dart",
51881
- ".cpp",
51882
- ".cc",
51883
- ".cxx",
51884
- ".c",
51885
- ".h",
51886
- ".hpp",
51887
- ".hxx",
51888
51948
  ".rb",
51889
51949
  ".php"
51890
51950
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slopbrick",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "description": "Discovered, modeled, and governed repository structure. SlopBrick scans source code, classifies it against 95+ rules in 15 categories, computes 4 scores (aiSlopScore: lower=cleaner, engineeringHygiene, security, repositoryHealth composite), and persists the structure for AI agents and CI.",
5
5
  "type": "module",
6
6
  "bin": {