pumuki 6.3.220 → 6.3.222

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,8 @@ import {
61
61
  hasSwiftSensitiveUserDefaultsStorageUsage,
62
62
  hasSwiftInsecureTransportUsage,
63
63
  hasSwiftJSONSerializationUsage,
64
+ hasSwiftExplicitColorStaticMemberUsage,
65
+ hasSwiftClosureBasedViewBuilderContentUsage,
64
66
  hasSwiftInlineForEachTransformUsage,
65
67
  hasSwiftStringFormatUsage,
66
68
  hasSwiftStrongDelegateReferenceUsage,
@@ -733,6 +735,8 @@ GeometryReader { proxy in
733
735
  Text("x").frame(width: proxy.size.width)
734
736
  }
735
737
  Text("Headline").fontWeight(.bold)
738
+ Text("State").foregroundStyle(Color.green)
739
+ let content: () -> Content
736
740
  let filtered = items.filter { $0.title.contains(searchText) }
737
741
  ForEach(items.indices, id: \\.self) { index in
738
742
  Text(items[index].title)
@@ -779,6 +783,8 @@ MainActor.assumeIsolated { reload() }
779
783
  assert.equal(hasSwiftContainsUserFilterUsage(source), true);
780
784
  assert.equal(hasSwiftGeometryReaderUsage(source), true);
781
785
  assert.equal(hasSwiftFontWeightBoldUsage(source), true);
786
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), true);
787
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), true);
782
788
  assert.equal(hasSwiftObservableObjectUsage(source), true);
783
789
  assert.equal(hasSwiftLegacySwiftUiObservableWrapperUsage(source), true);
784
790
  assert.equal(hasSwiftNavigationViewUsage(source), true);
@@ -818,6 +824,8 @@ let r = "@preconcurrency import LegacyFramework"
818
824
  let s = "nonisolated(unsafe) static var sharedBridge: Model?"
819
825
  let t = "MainActor.assumeIsolated { reload() }"
820
826
  let u = "ForEach(items.filter { $0.isVisible }) { item in }"
827
+ let v = "Color.green"
828
+ let w = "let content: () -> Content"
821
829
  `;
822
830
  assert.equal(hasSwiftPreconcurrencyUsage(source), false);
823
831
  assert.equal(hasSwiftNonisolatedUnsafeUsage(source), false);
@@ -827,6 +835,8 @@ let u = "ForEach(items.filter { $0.isVisible }) { item in }"
827
835
  assert.equal(hasSwiftContainsUserFilterUsage(source), false);
828
836
  assert.equal(hasSwiftGeometryReaderUsage(source), false);
829
837
  assert.equal(hasSwiftFontWeightBoldUsage(source), false);
838
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
839
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), false);
830
840
  assert.equal(hasSwiftTaskDetachedUsage(source), false);
831
841
  assert.equal(hasSwiftNavigationViewUsage(source), false);
832
842
  assert.equal(hasSwiftForegroundColorUsage(source), false);
@@ -844,6 +854,8 @@ let u = "ForEach(items.filter { $0.isVisible }) { item in }"
844
854
  test('detectores snapshot SwiftUI ignoran reemplazos modernos', () => {
845
855
  const source = `
846
856
  Text("Primary").foregroundStyle(.blue)
857
+ Text("State").foregroundStyle(.green)
858
+ @ViewBuilder let content: Content
847
859
  Image("hero").clipShape(.rect(cornerRadius: 12))
848
860
  Text("Headline").bold()
849
861
  TabView {
@@ -877,6 +889,8 @@ ScrollView {
877
889
  assert.equal(hasSwiftContainsUserFilterUsage(source), false);
878
890
  assert.equal(hasSwiftGeometryReaderUsage(source), false);
879
891
  assert.equal(hasSwiftFontWeightBoldUsage(source), false);
892
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
893
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), false);
880
894
  assert.equal(hasSwiftForegroundColorUsage(source), false);
881
895
  assert.equal(hasSwiftCornerRadiusUsage(source), false);
882
896
  assert.equal(hasSwiftTabItemUsage(source), false);
@@ -885,6 +899,53 @@ ScrollView {
885
899
  assert.equal(hasSwiftLegacyOnChangeUsage(source), false);
886
900
  });
887
901
 
902
+ test('hasSwiftExplicitColorStaticMemberUsage detecta Color.* y preserva static member lookup', () => {
903
+ const source = `
904
+ struct StatusView: View {
905
+ var body: some View {
906
+ Text("Ready").foregroundStyle(Color.green)
907
+ Circle().fill(Color.primary)
908
+ }
909
+ }
910
+ `;
911
+ const safe = `
912
+ struct StatusView: View {
913
+ var body: some View {
914
+ Text("Ready").foregroundStyle(.green)
915
+ Circle().fill(.primary)
916
+ Rectangle().fill(Color("BrandPrimary"))
917
+ }
918
+ }
919
+ let ignored = "Color.green"
920
+ // Color.primary
921
+ `;
922
+
923
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), true);
924
+ assert.equal(hasSwiftExplicitColorStaticMemberUsage(safe), false);
925
+ });
926
+
927
+ test('hasSwiftClosureBasedViewBuilderContentUsage detecta content closure y preserva @ViewBuilder let content', () => {
928
+ const source = `
929
+ struct Card<Content: View>: View {
930
+ private let content: () -> Content
931
+
932
+ init(@ViewBuilder content: @escaping () -> Content) {
933
+ self.content = content
934
+ }
935
+ }
936
+ `;
937
+ const safe = `
938
+ struct Card<Content: View>: View {
939
+ @ViewBuilder let content: Content
940
+ }
941
+ let ignored = "let content: () -> Content"
942
+ // let content: () -> Content
943
+ `;
944
+
945
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), true);
946
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(safe), false);
947
+ });
948
+
888
949
  test('hasSwiftLegacyXCTestImportUsage detecta XCTest unitario y excluye UI/performance', () => {
889
950
  const unitTest = `
890
951
  import XCTest
@@ -863,6 +863,20 @@ 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
+
873
+ export const hasSwiftClosureBasedViewBuilderContentUsage = (source: string): boolean => {
874
+ return hasSwiftSanitizedRegexMatch(
875
+ source,
876
+ /\b(?:let|var)\s+content\s*:\s*(?:\(\s*\)\s*->|@\s*escaping\s*\(\s*\)\s*->)\s*(?:some\s+View|Content)\b/g
877
+ );
878
+ };
879
+
866
880
  export const hasSwiftLegacySwiftUiObservableWrapperUsage = (source: string): boolean => {
867
881
  return hasSwiftSanitizedRegexMatch(source, /@\s*(?:StateObject|ObservedObject)\b/);
868
882
  };
@@ -682,6 +682,8 @@ 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.' },
686
+ { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftClosureBasedViewBuilderContentUsage, ruleId: 'heuristics.ios.swiftui.closure-based-viewbuilder-content.ast', code: 'HEURISTICS_IOS_SWIFTUI_CLOSURE_BASED_VIEWBUILDER_CONTENT_AST', message: 'AST heuristic detected closure-based content storage; @ViewBuilder let content: Content remains the preferred SwiftUI container baseline.' },
685
687
  { 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
688
  { 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
689
  { 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,42 @@ 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
+ },
878
+ {
879
+ id: 'heuristics.ios.swiftui.closure-based-viewbuilder-content.ast',
880
+ description: 'Detects closure-based SwiftUI content properties where @ViewBuilder let content: Content is preferred.',
881
+ severity: 'WARN',
882
+ platform: 'ios',
883
+ locked: true,
884
+ when: {
885
+ kind: 'Heuristic',
886
+ where: {
887
+ ruleId: 'heuristics.ios.swiftui.closure-based-viewbuilder-content.ast',
888
+ },
889
+ },
890
+ then: {
891
+ kind: 'Finding',
892
+ message: 'AST heuristic detected closure-based content storage; @ViewBuilder let content: Content remains the preferred SwiftUI container baseline.',
893
+ code: 'HEURISTICS_IOS_SWIFTUI_CLOSURE_BASED_VIEWBUILDER_CONTENT_AST',
894
+ },
895
+ },
860
896
  {
861
897
  id: 'heuristics.ios.navigation-view.ast',
862
898
  description: 'Detects NavigationView usage in iOS production code.',
@@ -242,6 +242,14 @@ 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
+ ]),
249
+ 'skills.ios.guideline.ios-swiftui-expert.prefer-viewbuilder-let-content-content-over-closure-based-content-prop':
250
+ heuristicDetector('ios.swiftui.closure-based-viewbuilder-content', [
251
+ 'heuristics.ios.swiftui.closure-based-viewbuilder-content.ast',
252
+ ]),
245
253
  'skills.ios.no-scrollview-shows-indicators': heuristicDetector(
246
254
  'ios.scrollview-shows-indicators',
247
255
  ['heuristics.ios.scrollview-shows-indicators.ast']
@@ -339,6 +339,20 @@ 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
+ }
349
+ if (
350
+ includes('viewbuilder let content') ||
351
+ (includes('closure-based content') && includes('content')) ||
352
+ (includes('content: content') && includes('viewbuilder'))
353
+ ) {
354
+ return 'skills.ios.guideline.ios-swiftui-expert.prefer-viewbuilder-let-content-content-over-closure-based-content-prop';
355
+ }
342
356
  if (
343
357
  includes('scrollindicators hidden') ||
344
358
  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.222",
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:04:37.359Z",
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": "938525eec7fea70ecba6c27711800036b964e4b668f80b177cc918cb268e08c5",
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
  {
@@ -8727,7 +8727,7 @@
8727
8727
  "sourcePath": "vendor/skills/swiftui-expert-skill/SKILL.md",
8728
8728
  "confidence": "MEDIUM",
8729
8729
  "locked": true,
8730
- "evaluationMode": "DECLARATIVE",
8730
+ "evaluationMode": "AUTO",
8731
8731
  "origin": "core"
8732
8732
  },
8733
8733
  {