pumuki 6.3.221 → 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.
@@ -62,6 +62,7 @@ import {
62
62
  hasSwiftInsecureTransportUsage,
63
63
  hasSwiftJSONSerializationUsage,
64
64
  hasSwiftExplicitColorStaticMemberUsage,
65
+ hasSwiftClosureBasedViewBuilderContentUsage,
65
66
  hasSwiftInlineForEachTransformUsage,
66
67
  hasSwiftStringFormatUsage,
67
68
  hasSwiftStrongDelegateReferenceUsage,
@@ -735,6 +736,7 @@ GeometryReader { proxy in
735
736
  }
736
737
  Text("Headline").fontWeight(.bold)
737
738
  Text("State").foregroundStyle(Color.green)
739
+ let content: () -> Content
738
740
  let filtered = items.filter { $0.title.contains(searchText) }
739
741
  ForEach(items.indices, id: \\.self) { index in
740
742
  Text(items[index].title)
@@ -782,6 +784,7 @@ MainActor.assumeIsolated { reload() }
782
784
  assert.equal(hasSwiftGeometryReaderUsage(source), true);
783
785
  assert.equal(hasSwiftFontWeightBoldUsage(source), true);
784
786
  assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), true);
787
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), true);
785
788
  assert.equal(hasSwiftObservableObjectUsage(source), true);
786
789
  assert.equal(hasSwiftLegacySwiftUiObservableWrapperUsage(source), true);
787
790
  assert.equal(hasSwiftNavigationViewUsage(source), true);
@@ -822,6 +825,7 @@ let s = "nonisolated(unsafe) static var sharedBridge: Model?"
822
825
  let t = "MainActor.assumeIsolated { reload() }"
823
826
  let u = "ForEach(items.filter { $0.isVisible }) { item in }"
824
827
  let v = "Color.green"
828
+ let w = "let content: () -> Content"
825
829
  `;
826
830
  assert.equal(hasSwiftPreconcurrencyUsage(source), false);
827
831
  assert.equal(hasSwiftNonisolatedUnsafeUsage(source), false);
@@ -832,6 +836,7 @@ let v = "Color.green"
832
836
  assert.equal(hasSwiftGeometryReaderUsage(source), false);
833
837
  assert.equal(hasSwiftFontWeightBoldUsage(source), false);
834
838
  assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
839
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), false);
835
840
  assert.equal(hasSwiftTaskDetachedUsage(source), false);
836
841
  assert.equal(hasSwiftNavigationViewUsage(source), false);
837
842
  assert.equal(hasSwiftForegroundColorUsage(source), false);
@@ -850,6 +855,7 @@ test('detectores snapshot SwiftUI ignoran reemplazos modernos', () => {
850
855
  const source = `
851
856
  Text("Primary").foregroundStyle(.blue)
852
857
  Text("State").foregroundStyle(.green)
858
+ @ViewBuilder let content: Content
853
859
  Image("hero").clipShape(.rect(cornerRadius: 12))
854
860
  Text("Headline").bold()
855
861
  TabView {
@@ -884,6 +890,7 @@ ScrollView {
884
890
  assert.equal(hasSwiftGeometryReaderUsage(source), false);
885
891
  assert.equal(hasSwiftFontWeightBoldUsage(source), false);
886
892
  assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
893
+ assert.equal(hasSwiftClosureBasedViewBuilderContentUsage(source), false);
887
894
  assert.equal(hasSwiftForegroundColorUsage(source), false);
888
895
  assert.equal(hasSwiftCornerRadiusUsage(source), false);
889
896
  assert.equal(hasSwiftTabItemUsage(source), false);
@@ -917,6 +924,28 @@ let ignored = "Color.green"
917
924
  assert.equal(hasSwiftExplicitColorStaticMemberUsage(safe), false);
918
925
  });
919
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
+
920
949
  test('hasSwiftLegacyXCTestImportUsage detecta XCTest unitario y excluye UI/performance', () => {
921
950
  const unitTest = `
922
951
  import XCTest
@@ -870,6 +870,13 @@ export const hasSwiftExplicitColorStaticMemberUsage = (source: string): boolean
870
870
  );
871
871
  };
872
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
+
873
880
  export const hasSwiftLegacySwiftUiObservableWrapperUsage = (source: string): boolean => {
874
881
  return hasSwiftSanitizedRegexMatch(source, /@\s*(?:StateObject|ObservedObject)\b/);
875
882
  };
@@ -683,6 +683,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
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
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.' },
686
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.' },
687
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.' },
688
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.' },
@@ -875,6 +875,24 @@ export const iosRules: RuleSet = [
875
875
  code: 'HEURISTICS_IOS_SWIFTUI_EXPLICIT_COLOR_STATIC_MEMBER_AST',
876
876
  },
877
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
+ },
878
896
  {
879
897
  id: 'heuristics.ios.navigation-view.ast',
880
898
  description: 'Detects NavigationView usage in iOS production code.',
@@ -246,6 +246,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
246
246
  heuristicDetector('ios.swiftui.explicit-color-static-member', [
247
247
  'heuristics.ios.swiftui.explicit-color-static-member.ast',
248
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
+ ]),
249
253
  'skills.ios.no-scrollview-shows-indicators': heuristicDetector(
250
254
  'ios.scrollview-shows-indicators',
251
255
  ['heuristics.ios.scrollview-shows-indicators.ast']
@@ -346,6 +346,13 @@ const normalizeKnownRuleTarget = (
346
346
  ) {
347
347
  return 'skills.ios.guideline.ios-swiftui-expert.prefer-static-member-lookup-blue-vs-color-blue';
348
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
+ }
349
356
  if (
350
357
  includes('scrollindicators hidden') ||
351
358
  includes('scroll indicators hidden') ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.221",
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-13T16:00:47.572Z",
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": "50cdc96e8e5b03ef6709edea0cde8959344ce5a3c57dfc93fe39d03d5695b7aa",
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",
@@ -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
  {