pumuki 6.3.220 → 6.3.221

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.
@@ -61,6 +61,7 @@ import {
61
61
  hasSwiftSensitiveUserDefaultsStorageUsage,
62
62
  hasSwiftInsecureTransportUsage,
63
63
  hasSwiftJSONSerializationUsage,
64
+ hasSwiftExplicitColorStaticMemberUsage,
64
65
  hasSwiftInlineForEachTransformUsage,
65
66
  hasSwiftStringFormatUsage,
66
67
  hasSwiftStrongDelegateReferenceUsage,
@@ -733,6 +734,7 @@ GeometryReader { proxy in
733
734
  Text("x").frame(width: proxy.size.width)
734
735
  }
735
736
  Text("Headline").fontWeight(.bold)
737
+ Text("State").foregroundStyle(Color.green)
736
738
  let filtered = items.filter { $0.title.contains(searchText) }
737
739
  ForEach(items.indices, id: \\.self) { index in
738
740
  Text(items[index].title)
@@ -779,6 +781,7 @@ MainActor.assumeIsolated { reload() }
779
781
  assert.equal(hasSwiftContainsUserFilterUsage(source), true);
780
782
  assert.equal(hasSwiftGeometryReaderUsage(source), true);
781
783
  assert.equal(hasSwiftFontWeightBoldUsage(source), true);
784
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), true);
782
785
  assert.equal(hasSwiftObservableObjectUsage(source), true);
783
786
  assert.equal(hasSwiftLegacySwiftUiObservableWrapperUsage(source), true);
784
787
  assert.equal(hasSwiftNavigationViewUsage(source), true);
@@ -818,6 +821,7 @@ let r = "@preconcurrency import LegacyFramework"
818
821
  let s = "nonisolated(unsafe) static var sharedBridge: Model?"
819
822
  let t = "MainActor.assumeIsolated { reload() }"
820
823
  let u = "ForEach(items.filter { $0.isVisible }) { item in }"
824
+ let v = "Color.green"
821
825
  `;
822
826
  assert.equal(hasSwiftPreconcurrencyUsage(source), false);
823
827
  assert.equal(hasSwiftNonisolatedUnsafeUsage(source), false);
@@ -827,6 +831,7 @@ let u = "ForEach(items.filter { $0.isVisible }) { item in }"
827
831
  assert.equal(hasSwiftContainsUserFilterUsage(source), false);
828
832
  assert.equal(hasSwiftGeometryReaderUsage(source), false);
829
833
  assert.equal(hasSwiftFontWeightBoldUsage(source), false);
834
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
830
835
  assert.equal(hasSwiftTaskDetachedUsage(source), false);
831
836
  assert.equal(hasSwiftNavigationViewUsage(source), false);
832
837
  assert.equal(hasSwiftForegroundColorUsage(source), false);
@@ -844,6 +849,7 @@ let u = "ForEach(items.filter { $0.isVisible }) { item in }"
844
849
  test('detectores snapshot SwiftUI ignoran reemplazos modernos', () => {
845
850
  const source = `
846
851
  Text("Primary").foregroundStyle(.blue)
852
+ Text("State").foregroundStyle(.green)
847
853
  Image("hero").clipShape(.rect(cornerRadius: 12))
848
854
  Text("Headline").bold()
849
855
  TabView {
@@ -877,6 +883,7 @@ ScrollView {
877
883
  assert.equal(hasSwiftContainsUserFilterUsage(source), false);
878
884
  assert.equal(hasSwiftGeometryReaderUsage(source), false);
879
885
  assert.equal(hasSwiftFontWeightBoldUsage(source), false);
886
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
880
887
  assert.equal(hasSwiftForegroundColorUsage(source), false);
881
888
  assert.equal(hasSwiftCornerRadiusUsage(source), false);
882
889
  assert.equal(hasSwiftTabItemUsage(source), false);
@@ -885,6 +892,31 @@ ScrollView {
885
892
  assert.equal(hasSwiftLegacyOnChangeUsage(source), false);
886
893
  });
887
894
 
895
+ test('hasSwiftExplicitColorStaticMemberUsage detecta Color.* y preserva static member lookup', () => {
896
+ const source = `
897
+ struct StatusView: View {
898
+ var body: some View {
899
+ Text("Ready").foregroundStyle(Color.green)
900
+ Circle().fill(Color.primary)
901
+ }
902
+ }
903
+ `;
904
+ const safe = `
905
+ struct StatusView: View {
906
+ var body: some View {
907
+ Text("Ready").foregroundStyle(.green)
908
+ Circle().fill(.primary)
909
+ Rectangle().fill(Color("BrandPrimary"))
910
+ }
911
+ }
912
+ let ignored = "Color.green"
913
+ // Color.primary
914
+ `;
915
+
916
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), true);
917
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(safe), false);
918
+ });
919
+
888
920
  test('hasSwiftLegacyXCTestImportUsage detecta XCTest unitario y excluye UI/performance', () => {
889
921
  const unitTest = `
890
922
  import XCTest
@@ -863,6 +863,13 @@ export const hasSwiftFontWeightBoldUsage = (source: string): boolean => {
863
863
  return hasSwiftSanitizedRegexMatch(source, /\.\s*fontWeight\s*\(\s*\.bold\s*\)/g);
864
864
  };
865
865
 
866
+ export const hasSwiftExplicitColorStaticMemberUsage = (source: string): boolean => {
867
+ return hasSwiftSanitizedRegexMatch(
868
+ source,
869
+ /\bColor\s*\.\s*(?:accentColor|black|blue|brown|clear|cyan|gray|green|indigo|mint|orange|pink|primary|purple|red|secondary|teal|white|yellow)\b/g
870
+ );
871
+ };
872
+
866
873
  export const hasSwiftLegacySwiftUiObservableWrapperUsage = (source: string): boolean => {
867
874
  return hasSwiftSanitizedRegexMatch(source, /@\s*(?:StateObject|ObservedObject)\b/);
868
875
  };
@@ -682,6 +682,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
682
682
  { platform: 'ios', pathCheck: isIOSApplicationOrPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftContainsUserFilterUsage, ruleId: 'heuristics.ios.contains-user-filter.ast', code: 'HEURISTICS_IOS_CONTAINS_USER_FILTER_AST', message: 'AST heuristic detected contains() in a user-facing filter where localizedStandardContains() may be preferred.' },
683
683
  { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftGeometryReaderUsage, ruleId: 'heuristics.ios.geometryreader.ast', code: 'HEURISTICS_IOS_GEOMETRYREADER_AST', message: 'AST heuristic detected GeometryReader usage that may be replaceable with modern layout APIs.' },
684
684
  { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftFontWeightBoldUsage, ruleId: 'heuristics.ios.font-weight-bold.ast', code: 'HEURISTICS_IOS_FONT_WEIGHT_BOLD_AST', message: 'AST heuristic detected fontWeight(.bold) usage where bold() may be preferred.' },
685
+ { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftExplicitColorStaticMemberUsage, ruleId: 'heuristics.ios.swiftui.explicit-color-static-member.ast', code: 'HEURISTICS_IOS_SWIFTUI_EXPLICIT_COLOR_STATIC_MEMBER_AST', message: 'AST heuristic detected Color.* static member usage where SwiftUI static member lookup may be preferred.' },
685
686
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNavigationViewUsage, ruleId: 'heuristics.ios.navigation-view.ast', code: 'HEURISTICS_IOS_NAVIGATION_VIEW_AST', message: 'AST heuristic detected NavigationView usage.' },
686
687
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForegroundColorUsage, ruleId: 'heuristics.ios.foreground-color.ast', code: 'HEURISTICS_IOS_FOREGROUND_COLOR_AST', message: 'AST heuristic detected foregroundColor usage.' },
687
688
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftCornerRadiusUsage, ruleId: 'heuristics.ios.corner-radius.ast', code: 'HEURISTICS_IOS_CORNER_RADIUS_AST', message: 'AST heuristic detected cornerRadius usage.' },
@@ -857,6 +857,24 @@ export const iosRules: RuleSet = [
857
857
  code: 'HEURISTICS_IOS_FONT_WEIGHT_BOLD_AST',
858
858
  },
859
859
  },
860
+ {
861
+ id: 'heuristics.ios.swiftui.explicit-color-static-member.ast',
862
+ description: 'Detects Color.* static member usage where SwiftUI static member lookup is available.',
863
+ severity: 'WARN',
864
+ platform: 'ios',
865
+ locked: true,
866
+ when: {
867
+ kind: 'Heuristic',
868
+ where: {
869
+ ruleId: 'heuristics.ios.swiftui.explicit-color-static-member.ast',
870
+ },
871
+ },
872
+ then: {
873
+ kind: 'Finding',
874
+ message: 'AST heuristic detected Color.* static member usage where SwiftUI static member lookup may be preferred.',
875
+ code: 'HEURISTICS_IOS_SWIFTUI_EXPLICIT_COLOR_STATIC_MEMBER_AST',
876
+ },
877
+ },
860
878
  {
861
879
  id: 'heuristics.ios.navigation-view.ast',
862
880
  description: 'Detects NavigationView usage in iOS production code.',
@@ -242,6 +242,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
242
242
  'skills.ios.no-font-weight-bold': heuristicDetector('ios.font-weight-bold', [
243
243
  'heuristics.ios.font-weight-bold.ast',
244
244
  ]),
245
+ 'skills.ios.guideline.ios-swiftui-expert.prefer-static-member-lookup-blue-vs-color-blue':
246
+ heuristicDetector('ios.swiftui.explicit-color-static-member', [
247
+ 'heuristics.ios.swiftui.explicit-color-static-member.ast',
248
+ ]),
245
249
  'skills.ios.no-scrollview-shows-indicators': heuristicDetector(
246
250
  'ios.scrollview-shows-indicators',
247
251
  ['heuristics.ios.scrollview-shows-indicators.ast']
@@ -339,6 +339,13 @@ const normalizeKnownRuleTarget = (
339
339
  ) {
340
340
  return 'skills.ios.no-font-weight-bold';
341
341
  }
342
+ if (
343
+ includes('static member lookup') ||
344
+ includes('color.blue') ||
345
+ (includes('.blue') && includes('color'))
346
+ ) {
347
+ return 'skills.ios.guideline.ios-swiftui-expert.prefer-static-member-lookup-blue-vs-color-blue';
348
+ }
342
349
  if (
343
350
  includes('scrollindicators hidden') ||
344
351
  includes('scroll indicators hidden') ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.220",
3
+ "version": "6.3.221",
4
4
  "description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/skills.lock.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "1.0",
3
3
  "compilerVersion": "1.0.0",
4
- "generatedAt": "2026-05-13T15:54:55.035Z",
4
+ "generatedAt": "2026-05-13T16:00:47.572Z",
5
5
  "bundles": [
6
6
  {
7
7
  "name": "android-guidelines",
@@ -8632,7 +8632,7 @@
8632
8632
  "name": "ios-swiftui-expert-guidelines",
8633
8633
  "version": "1.0.0",
8634
8634
  "source": "file:vendor/skills/swiftui-expert-skill/SKILL.md",
8635
- "hash": "ad099eaf37bfe92bde672c1042c7d4c18e3af4bbf91a1b9ee6f6a0dc0e5381b5",
8635
+ "hash": "50cdc96e8e5b03ef6709edea0cde8959344ce5a3c57dfc93fe39d03d5695b7aa",
8636
8636
  "rules": [
8637
8637
  {
8638
8638
  "id": "skills.ios.guideline.ios-swiftui-expert.always-mark-state-and-stateobject-as-private-makes-dependencies-clear",
@@ -8715,7 +8715,7 @@
8715
8715
  "sourcePath": "vendor/skills/swiftui-expert-skill/SKILL.md",
8716
8716
  "confidence": "MEDIUM",
8717
8717
  "locked": true,
8718
- "evaluationMode": "DECLARATIVE",
8718
+ "evaluationMode": "AUTO",
8719
8719
  "origin": "core"
8720
8720
  },
8721
8721
  {