pumuki 6.3.219 → 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.
- package/core/facts/detectors/text/ios.test.ts +78 -0
- package/core/facts/detectors/text/ios.ts +14 -0
- package/core/facts/extractHeuristicFacts.ts +2 -0
- package/core/rules/presets/heuristics/ios.ts +36 -0
- package/integrations/config/skillsDetectorRegistry.ts +8 -0
- package/integrations/config/skillsMarkdownRules.ts +14 -0
- package/package.json +1 -1
- package/skills.lock.json +4 -4
|
@@ -61,6 +61,8 @@ import {
|
|
|
61
61
|
hasSwiftSensitiveUserDefaultsStorageUsage,
|
|
62
62
|
hasSwiftInsecureTransportUsage,
|
|
63
63
|
hasSwiftJSONSerializationUsage,
|
|
64
|
+
hasSwiftExplicitColorStaticMemberUsage,
|
|
65
|
+
hasSwiftInlineForEachTransformUsage,
|
|
64
66
|
hasSwiftStringFormatUsage,
|
|
65
67
|
hasSwiftStrongDelegateReferenceUsage,
|
|
66
68
|
hasSwiftStrongSelfEscapingClosureUsage,
|
|
@@ -732,10 +734,14 @@ GeometryReader { proxy in
|
|
|
732
734
|
Text("x").frame(width: proxy.size.width)
|
|
733
735
|
}
|
|
734
736
|
Text("Headline").fontWeight(.bold)
|
|
737
|
+
Text("State").foregroundStyle(Color.green)
|
|
735
738
|
let filtered = items.filter { $0.title.contains(searchText) }
|
|
736
739
|
ForEach(items.indices, id: \\.self) { index in
|
|
737
740
|
Text(items[index].title)
|
|
738
741
|
}
|
|
742
|
+
ForEach(items.filter { $0.isVisible }) { item in
|
|
743
|
+
Text(item.title)
|
|
744
|
+
}
|
|
739
745
|
Text("Primary").foregroundColor(.blue)
|
|
740
746
|
Image("hero").cornerRadius(12)
|
|
741
747
|
TabView {
|
|
@@ -771,9 +777,11 @@ MainActor.assumeIsolated { reload() }
|
|
|
771
777
|
assert.equal(hasSwiftNonisolatedUnsafeUsage(source), true);
|
|
772
778
|
assert.equal(hasSwiftAssumeIsolatedUsage(source), true);
|
|
773
779
|
assert.equal(hasSwiftForEachIndicesUsage(source), true);
|
|
780
|
+
assert.equal(hasSwiftInlineForEachTransformUsage(source), true);
|
|
774
781
|
assert.equal(hasSwiftContainsUserFilterUsage(source), true);
|
|
775
782
|
assert.equal(hasSwiftGeometryReaderUsage(source), true);
|
|
776
783
|
assert.equal(hasSwiftFontWeightBoldUsage(source), true);
|
|
784
|
+
assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), true);
|
|
777
785
|
assert.equal(hasSwiftObservableObjectUsage(source), true);
|
|
778
786
|
assert.equal(hasSwiftLegacySwiftUiObservableWrapperUsage(source), true);
|
|
779
787
|
assert.equal(hasSwiftNavigationViewUsage(source), true);
|
|
@@ -812,14 +820,18 @@ let q = ".fontWeight(.bold)"
|
|
|
812
820
|
let r = "@preconcurrency import LegacyFramework"
|
|
813
821
|
let s = "nonisolated(unsafe) static var sharedBridge: Model?"
|
|
814
822
|
let t = "MainActor.assumeIsolated { reload() }"
|
|
823
|
+
let u = "ForEach(items.filter { $0.isVisible }) { item in }"
|
|
824
|
+
let v = "Color.green"
|
|
815
825
|
`;
|
|
816
826
|
assert.equal(hasSwiftPreconcurrencyUsage(source), false);
|
|
817
827
|
assert.equal(hasSwiftNonisolatedUnsafeUsage(source), false);
|
|
818
828
|
assert.equal(hasSwiftAssumeIsolatedUsage(source), false);
|
|
819
829
|
assert.equal(hasSwiftForEachIndicesUsage(source), false);
|
|
830
|
+
assert.equal(hasSwiftInlineForEachTransformUsage(source), false);
|
|
820
831
|
assert.equal(hasSwiftContainsUserFilterUsage(source), false);
|
|
821
832
|
assert.equal(hasSwiftGeometryReaderUsage(source), false);
|
|
822
833
|
assert.equal(hasSwiftFontWeightBoldUsage(source), false);
|
|
834
|
+
assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
|
|
823
835
|
assert.equal(hasSwiftTaskDetachedUsage(source), false);
|
|
824
836
|
assert.equal(hasSwiftNavigationViewUsage(source), false);
|
|
825
837
|
assert.equal(hasSwiftForegroundColorUsage(source), false);
|
|
@@ -837,6 +849,7 @@ let t = "MainActor.assumeIsolated { reload() }"
|
|
|
837
849
|
test('detectores snapshot SwiftUI ignoran reemplazos modernos', () => {
|
|
838
850
|
const source = `
|
|
839
851
|
Text("Primary").foregroundStyle(.blue)
|
|
852
|
+
Text("State").foregroundStyle(.green)
|
|
840
853
|
Image("hero").clipShape(.rect(cornerRadius: 12))
|
|
841
854
|
Text("Headline").bold()
|
|
842
855
|
TabView {
|
|
@@ -870,6 +883,7 @@ ScrollView {
|
|
|
870
883
|
assert.equal(hasSwiftContainsUserFilterUsage(source), false);
|
|
871
884
|
assert.equal(hasSwiftGeometryReaderUsage(source), false);
|
|
872
885
|
assert.equal(hasSwiftFontWeightBoldUsage(source), false);
|
|
886
|
+
assert.equal(hasSwiftExplicitColorStaticMemberUsage(source), false);
|
|
873
887
|
assert.equal(hasSwiftForegroundColorUsage(source), false);
|
|
874
888
|
assert.equal(hasSwiftCornerRadiusUsage(source), false);
|
|
875
889
|
assert.equal(hasSwiftTabItemUsage(source), false);
|
|
@@ -878,6 +892,31 @@ ScrollView {
|
|
|
878
892
|
assert.equal(hasSwiftLegacyOnChangeUsage(source), false);
|
|
879
893
|
});
|
|
880
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
|
+
|
|
881
920
|
test('hasSwiftLegacyXCTestImportUsage detecta XCTest unitario y excluye UI/performance', () => {
|
|
882
921
|
const unitTest = `
|
|
883
922
|
import XCTest
|
|
@@ -949,6 +988,45 @@ struct DashboardView: View {
|
|
|
949
988
|
assert.equal(hasSwiftNonPrivateStateOwnershipUsage(safe), false);
|
|
950
989
|
});
|
|
951
990
|
|
|
991
|
+
test('hasSwiftInlineForEachTransformUsage detecta transformaciones inline y preserva colecciones precomputadas', () => {
|
|
992
|
+
const source = `
|
|
993
|
+
struct FeedView: View {
|
|
994
|
+
var body: some View {
|
|
995
|
+
List {
|
|
996
|
+
ForEach(items.filter { $0.isVisible }) { item in
|
|
997
|
+
Text(item.title)
|
|
998
|
+
}
|
|
999
|
+
ForEach(Array(sections.sorted(by: { $0.title < $1.title }))) { section in
|
|
1000
|
+
Text(section.title)
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
`;
|
|
1006
|
+
const safe = `
|
|
1007
|
+
struct FeedView: View {
|
|
1008
|
+
let filteredItems: [Item]
|
|
1009
|
+
let sortedSections: [Section]
|
|
1010
|
+
|
|
1011
|
+
var body: some View {
|
|
1012
|
+
List {
|
|
1013
|
+
ForEach(filteredItems) { item in
|
|
1014
|
+
Text(item.title)
|
|
1015
|
+
}
|
|
1016
|
+
ForEach(sortedSections) { section in
|
|
1017
|
+
Text(section.title)
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
let ignored = "ForEach(items.filter { $0.isVisible }) { item in }"
|
|
1023
|
+
// ForEach(items.filter { $0.isVisible }) { item in }
|
|
1024
|
+
`;
|
|
1025
|
+
|
|
1026
|
+
assert.equal(hasSwiftInlineForEachTransformUsage(source), true);
|
|
1027
|
+
assert.equal(hasSwiftInlineForEachTransformUsage(safe), false);
|
|
1028
|
+
});
|
|
1029
|
+
|
|
952
1030
|
test('hasSwiftPassedValueStateWrapperUsage detecta valores inyectados guardados como @State o @StateObject', () => {
|
|
953
1031
|
const invalidOwnership = `
|
|
954
1032
|
struct DetailView: View {
|
|
@@ -810,6 +810,13 @@ export const hasSwiftForEachIndicesUsage = (source: string): boolean => {
|
|
|
810
810
|
);
|
|
811
811
|
};
|
|
812
812
|
|
|
813
|
+
export const hasSwiftInlineForEachTransformUsage = (source: string): boolean => {
|
|
814
|
+
const sanitized = sanitizeSwiftSourceForMultilineRegex(source);
|
|
815
|
+
return /\bForEach\s*\(\s*(?:Array\s*\(\s*)?[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*\s*\.\s*(?:filter|map|compactMap|sorted)\s*(?:\{|\()/g.test(
|
|
816
|
+
sanitized
|
|
817
|
+
);
|
|
818
|
+
};
|
|
819
|
+
|
|
813
820
|
const isUserSearchIdentifier = (value: string): boolean => {
|
|
814
821
|
return /^(?:query|search(?:Text|Term|Query|Value)?|filter(?:Text|Value)?|text|term|input)$/i.test(
|
|
815
822
|
value
|
|
@@ -856,6 +863,13 @@ export const hasSwiftFontWeightBoldUsage = (source: string): boolean => {
|
|
|
856
863
|
return hasSwiftSanitizedRegexMatch(source, /\.\s*fontWeight\s*\(\s*\.bold\s*\)/g);
|
|
857
864
|
};
|
|
858
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
|
+
|
|
859
873
|
export const hasSwiftLegacySwiftUiObservableWrapperUsage = (source: string): boolean => {
|
|
860
874
|
return hasSwiftSanitizedRegexMatch(source, /@\s*(?:StateObject|ObservedObject)\b/);
|
|
861
875
|
};
|
|
@@ -678,9 +678,11 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
|
|
|
678
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.' },
|
|
679
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.' },
|
|
680
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.' },
|
|
681
|
+
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftInlineForEachTransformUsage, ruleId: 'heuristics.ios.swiftui.inline-foreach-transform.ast', code: 'HEURISTICS_IOS_SWIFTUI_INLINE_FOREACH_TRANSFORM_AST', message: 'AST heuristic detected inline filter/map/sort work inside ForEach; prefiltered or cached collections remain the preferred baseline.' },
|
|
681
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.' },
|
|
682
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.' },
|
|
683
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.' },
|
|
684
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.' },
|
|
685
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.' },
|
|
686
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.' },
|
|
@@ -785,6 +785,24 @@ export const iosRules: RuleSet = [
|
|
|
785
785
|
code: 'HEURISTICS_IOS_FOREACH_INDICES_AST',
|
|
786
786
|
},
|
|
787
787
|
},
|
|
788
|
+
{
|
|
789
|
+
id: 'heuristics.ios.swiftui.inline-foreach-transform.ast',
|
|
790
|
+
description: 'Detects inline filter/map/sort transformations inside SwiftUI ForEach calls.',
|
|
791
|
+
severity: 'WARN',
|
|
792
|
+
platform: 'ios',
|
|
793
|
+
locked: true,
|
|
794
|
+
when: {
|
|
795
|
+
kind: 'Heuristic',
|
|
796
|
+
where: {
|
|
797
|
+
ruleId: 'heuristics.ios.swiftui.inline-foreach-transform.ast',
|
|
798
|
+
},
|
|
799
|
+
},
|
|
800
|
+
then: {
|
|
801
|
+
kind: 'Finding',
|
|
802
|
+
message: 'AST heuristic detected inline filter/map/sort work inside ForEach; prefiltered or cached collections remain the preferred baseline.',
|
|
803
|
+
code: 'HEURISTICS_IOS_SWIFTUI_INLINE_FOREACH_TRANSFORM_AST',
|
|
804
|
+
},
|
|
805
|
+
},
|
|
788
806
|
{
|
|
789
807
|
id: 'heuristics.ios.contains-user-filter.ast',
|
|
790
808
|
description: 'Detects contains() usage in user-facing filter flows where localizedStandardContains() may be preferred.',
|
|
@@ -839,6 +857,24 @@ export const iosRules: RuleSet = [
|
|
|
839
857
|
code: 'HEURISTICS_IOS_FONT_WEIGHT_BOLD_AST',
|
|
840
858
|
},
|
|
841
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
|
+
},
|
|
842
878
|
{
|
|
843
879
|
id: 'heuristics.ios.navigation-view.ast',
|
|
844
880
|
description: 'Detects NavigationView usage in iOS production code.',
|
|
@@ -229,6 +229,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
|
|
|
229
229
|
'skills.ios.no-foreach-indices': heuristicDetector('ios.foreach-indices', [
|
|
230
230
|
'heuristics.ios.foreach-indices.ast',
|
|
231
231
|
]),
|
|
232
|
+
'skills.ios.guideline.ios-swiftui-expert.avoid-inline-filtering-in-foreach-prefilter-and-cache':
|
|
233
|
+
heuristicDetector('ios.swiftui.inline-foreach-transform', [
|
|
234
|
+
'heuristics.ios.swiftui.inline-foreach-transform.ast',
|
|
235
|
+
]),
|
|
232
236
|
'skills.ios.no-contains-user-filter': heuristicDetector('ios.contains-user-filter', [
|
|
233
237
|
'heuristics.ios.contains-user-filter.ast',
|
|
234
238
|
]),
|
|
@@ -238,6 +242,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
|
|
|
238
242
|
'skills.ios.no-font-weight-bold': heuristicDetector('ios.font-weight-bold', [
|
|
239
243
|
'heuristics.ios.font-weight-bold.ast',
|
|
240
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
|
+
]),
|
|
241
249
|
'skills.ios.no-scrollview-shows-indicators': heuristicDetector(
|
|
242
250
|
'ios.scrollview-shows-indicators',
|
|
243
251
|
['heuristics.ios.scrollview-shows-indicators.ast']
|
|
@@ -309,6 +309,13 @@ const normalizeKnownRuleTarget = (
|
|
|
309
309
|
) {
|
|
310
310
|
return 'skills.ios.no-foreach-indices';
|
|
311
311
|
}
|
|
312
|
+
if (
|
|
313
|
+
(includes('inline filtering') && includes('foreach')) ||
|
|
314
|
+
(includes('no inline filtering') && includes('foreach')) ||
|
|
315
|
+
(includes('prefilter') && includes('cache') && includes('foreach'))
|
|
316
|
+
) {
|
|
317
|
+
return 'skills.ios.guideline.ios-swiftui-expert.avoid-inline-filtering-in-foreach-prefilter-and-cache';
|
|
318
|
+
}
|
|
312
319
|
if (
|
|
313
320
|
includes('localizedstandardcontains') ||
|
|
314
321
|
includes('localized standard contains') ||
|
|
@@ -332,6 +339,13 @@ const normalizeKnownRuleTarget = (
|
|
|
332
339
|
) {
|
|
333
340
|
return 'skills.ios.no-font-weight-bold';
|
|
334
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
|
+
}
|
|
335
349
|
if (
|
|
336
350
|
includes('scrollindicators hidden') ||
|
|
337
351
|
includes('scroll indicators hidden') ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
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-
|
|
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": "
|
|
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",
|
|
@@ -8655,7 +8655,7 @@
|
|
|
8655
8655
|
"sourcePath": "vendor/skills/swiftui-expert-skill/SKILL.md",
|
|
8656
8656
|
"confidence": "MEDIUM",
|
|
8657
8657
|
"locked": true,
|
|
8658
|
-
"evaluationMode": "
|
|
8658
|
+
"evaluationMode": "AUTO",
|
|
8659
8659
|
"origin": "core"
|
|
8660
8660
|
},
|
|
8661
8661
|
{
|
|
@@ -8715,7 +8715,7 @@
|
|
|
8715
8715
|
"sourcePath": "vendor/skills/swiftui-expert-skill/SKILL.md",
|
|
8716
8716
|
"confidence": "MEDIUM",
|
|
8717
8717
|
"locked": true,
|
|
8718
|
-
"evaluationMode": "
|
|
8718
|
+
"evaluationMode": "AUTO",
|
|
8719
8719
|
"origin": "core"
|
|
8720
8720
|
},
|
|
8721
8721
|
{
|