pumuki 6.3.218 → 6.3.219

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.
@@ -43,6 +43,7 @@ import {
43
43
  hasSwiftNSManagedObjectBoundaryUsage,
44
44
  hasSwiftNSManagedObjectStateLeakUsage,
45
45
  hasSwiftNavigationViewUsage,
46
+ hasSwiftNonPrivateStateOwnershipUsage,
46
47
  hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage,
47
48
  hasSwiftObservableObjectUsage,
48
49
  hasSwiftOnAppearTaskUsage,
@@ -928,6 +929,26 @@ struct ContentView: View {
928
929
  assert.equal(hasSwiftLegacySwiftUiObservableWrapperUsage(modernWrapper), false);
929
930
  });
930
931
 
932
+ test('hasSwiftNonPrivateStateOwnershipUsage detecta @State y @StateObject no privados', () => {
933
+ const source = `
934
+ struct DashboardView: View {
935
+ @State var query = ""
936
+ @StateObject var viewModel = DashboardViewModel()
937
+ }
938
+ `;
939
+ const safe = `
940
+ struct DashboardView: View {
941
+ @State private var query = ""
942
+ @StateObject private var viewModel = DashboardViewModel()
943
+ let text = "@State var query = \\"\\""
944
+ // @State var query = ""
945
+ }
946
+ `;
947
+
948
+ assert.equal(hasSwiftNonPrivateStateOwnershipUsage(source), true);
949
+ assert.equal(hasSwiftNonPrivateStateOwnershipUsage(safe), false);
950
+ });
951
+
931
952
  test('hasSwiftPassedValueStateWrapperUsage detecta valores inyectados guardados como @State o @StateObject', () => {
932
953
  const invalidOwnership = `
933
954
  struct DetailView: View {
@@ -860,6 +860,17 @@ export const hasSwiftLegacySwiftUiObservableWrapperUsage = (source: string): boo
860
860
  return hasSwiftSanitizedRegexMatch(source, /@\s*(?:StateObject|ObservedObject)\b/);
861
861
  };
862
862
 
863
+ export const hasSwiftNonPrivateStateOwnershipUsage = (source: string): boolean => {
864
+ return source.split(/\r?\n/).some((line) => {
865
+ const sanitizedLine = stripSwiftLineForSemanticScan(line);
866
+ return (
867
+ /@\s*(?:State|StateObject)\b/.test(sanitizedLine) &&
868
+ /\bvar\b/.test(sanitizedLine) &&
869
+ !/\bprivate\b/.test(sanitizedLine)
870
+ );
871
+ });
872
+ };
873
+
863
874
  const hasSwiftPassedValueWrapperInitialization = (
864
875
  source: string,
865
876
  options: {
@@ -675,6 +675,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
675
675
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftAssumeIsolatedUsage, ruleId: 'heuristics.ios.assume-isolated.ast', code: 'HEURISTICS_IOS_ASSUME_ISOLATED_AST', message: 'AST heuristic detected assumeIsolated usage.' },
676
676
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftObservableObjectUsage, ruleId: 'heuristics.ios.observable-object.ast', code: 'HEURISTICS_IOS_OBSERVABLE_OBJECT_AST', message: 'AST heuristic detected ObservableObject usage.' },
677
677
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftLegacySwiftUiObservableWrapperUsage, ruleId: 'heuristics.ios.legacy-swiftui-observable-wrapper.ast', code: 'HEURISTICS_IOS_LEGACY_SWIFTUI_OBSERVABLE_WRAPPER_AST', message: 'AST heuristic detected @StateObject/@ObservedObject usage in a modern SwiftUI path.' },
678
+ { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNonPrivateStateOwnershipUsage, ruleId: 'heuristics.ios.swiftui.non-private-state-ownership.ast', code: 'HEURISTICS_IOS_SWIFTUI_NON_PRIVATE_STATE_OWNERSHIP_AST', message: 'AST heuristic detected @State/@StateObject without private visibility; SwiftUI owned state should be private.' },
678
679
  { platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftPassedValueStateWrapperUsage, ruleId: 'heuristics.ios.passed-value-state-wrapper.ast', code: 'HEURISTICS_IOS_PASSED_VALUE_STATE_WRAPPER_AST', message: 'AST heuristic detected a passed value stored as @State/@StateObject via init wrapper ownership.' },
679
680
  { platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForEachIndicesUsage, ruleId: 'heuristics.ios.foreach-indices.ast', code: 'HEURISTICS_IOS_FOREACH_INDICES_AST', message: 'AST heuristic detected ForEach(...indices...) usage where stable element identity may be preferred.' },
680
681
  { 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.' },
@@ -730,6 +730,25 @@ export const iosRules: RuleSet = [
730
730
  code: 'HEURISTICS_IOS_LEGACY_SWIFTUI_OBSERVABLE_WRAPPER_AST',
731
731
  },
732
732
  },
733
+ {
734
+ id: 'heuristics.ios.swiftui.non-private-state-ownership.ast',
735
+ description: 'Detects @State/@StateObject declarations without private visibility in SwiftUI presentation code.',
736
+ severity: 'WARN',
737
+ platform: 'ios',
738
+ locked: true,
739
+ when: {
740
+ kind: 'Heuristic',
741
+ where: {
742
+ ruleId: 'heuristics.ios.swiftui.non-private-state-ownership.ast',
743
+ },
744
+ },
745
+ then: {
746
+ kind: 'Finding',
747
+ message:
748
+ 'AST heuristic detected @State/@StateObject without private visibility; SwiftUI owned state should be private.',
749
+ code: 'HEURISTICS_IOS_SWIFTUI_NON_PRIVATE_STATE_OWNERSHIP_AST',
750
+ },
751
+ },
733
752
  {
734
753
  id: 'heuristics.ios.passed-value-state-wrapper.ast',
735
754
  description: 'Detects passed values stored as @State or @StateObject through init ownership in SwiftUI production code.',
@@ -201,6 +201,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
201
201
  'ios.legacy-swiftui-observable-wrapper',
202
202
  ['heuristics.ios.legacy-swiftui-observable-wrapper.ast']
203
203
  ),
204
+ 'skills.ios.guideline.ios-swiftui-expert.always-mark-state-and-stateobject-as-private-makes-dependencies-clear': heuristicDetector(
205
+ 'ios.swiftui.non-private-state-ownership',
206
+ ['heuristics.ios.swiftui.non-private-state-ownership.ast']
207
+ ),
204
208
  'skills.ios.no-passed-value-state-wrapper': heuristicDetector('ios.passed-value-state-wrapper', [
205
209
  'heuristics.ios.passed-value-state-wrapper.ast',
206
210
  ]),
@@ -260,6 +260,13 @@ const normalizeKnownRuleTarget = (
260
260
  ) {
261
261
  return 'skills.ios.no-legacy-swiftui-observable-wrapper';
262
262
  }
263
+ if (
264
+ includes('state and stateobject as private') ||
265
+ includes('stateobject as private') ||
266
+ (includes('mark state') && includes('private'))
267
+ ) {
268
+ return 'skills.ios.guideline.ios-swiftui-expert.always-mark-state-and-stateobject-as-private-makes-dependencies-clear';
269
+ }
263
270
  if (
264
271
  includes('passed values as state') ||
265
272
  includes('passed values as state or stateobject') ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.218",
3
+ "version": "6.3.219",
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-13T13:40:06.121Z",
4
+ "generatedAt": "2026-05-13T15:50:45.972Z",
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": "05e71c648612ed794d4e8122105fc3f508e09b7f92db94a24bd3daa45335d6b7",
8635
+ "hash": "b936508c5fea766c83bca01087374a8c0281ba86c4ee022d43db316b89c07cd6",
8636
8636
  "rules": [
8637
8637
  {
8638
8638
  "id": "skills.ios.guideline.ios-swiftui-expert.always-mark-state-and-stateobject-as-private-makes-dependencies-clear",
@@ -8643,7 +8643,7 @@
8643
8643
  "sourcePath": "vendor/skills/swiftui-expert-skill/SKILL.md",
8644
8644
  "confidence": "MEDIUM",
8645
8645
  "locked": true,
8646
- "evaluationMode": "DECLARATIVE",
8646
+ "evaluationMode": "AUTO",
8647
8647
  "origin": "core"
8648
8648
  },
8649
8649
  {