pumuki 6.3.230 → 6.3.231
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 +24 -0
- package/core/facts/detectors/text/ios.ts +4 -0
- package/core/facts/extractHeuristicFacts.ts +1 -0
- package/core/rules/presets/heuristics/ios.ts +19 -0
- package/integrations/config/skillsDetectorRegistry.ts +4 -0
- package/integrations/config/skillsMarkdownRules.ts +3 -0
- package/package.json +1 -1
- package/skills.lock.json +3 -3
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
hasSwiftSheetIsPresentedUsage,
|
|
66
66
|
hasSwiftScrollViewShowsIndicatorsUsage,
|
|
67
67
|
hasSwiftSensitiveLoggingUsage,
|
|
68
|
+
hasSwiftSelfPrintChangesUsage,
|
|
68
69
|
hasSwiftSensitiveUserDefaultsStorageUsage,
|
|
69
70
|
hasSwiftInsecureTransportUsage,
|
|
70
71
|
hasSwiftJSONSerializationUsage,
|
|
@@ -323,6 +324,29 @@ struct FeedView: View {
|
|
|
323
324
|
assert.equal(hasSwiftForEachSelfIdentityUsage(safe), false);
|
|
324
325
|
});
|
|
325
326
|
|
|
327
|
+
test('hasSwiftSelfPrintChangesUsage detecta Self._printChanges y preserva strings y comentarios', () => {
|
|
328
|
+
const source = `
|
|
329
|
+
struct FeedView: View {
|
|
330
|
+
var body: some View {
|
|
331
|
+
Self._printChanges()
|
|
332
|
+
Text("Feed")
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
`;
|
|
336
|
+
const safe = `
|
|
337
|
+
struct FeedView: View {
|
|
338
|
+
var body: some View {
|
|
339
|
+
Text("Feed")
|
|
340
|
+
let sample = "Self._printChanges()"
|
|
341
|
+
// Self._printChanges()
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
`;
|
|
345
|
+
|
|
346
|
+
assert.equal(hasSwiftSelfPrintChangesUsage(source), true);
|
|
347
|
+
assert.equal(hasSwiftSelfPrintChangesUsage(safe), false);
|
|
348
|
+
});
|
|
349
|
+
|
|
326
350
|
test('hasSwiftUntypedNavigationLinkDestinationUsage detecta NavigationLink no tipado y preserva value navigation', () => {
|
|
327
351
|
const source = `
|
|
328
352
|
struct FeedView: View {
|
|
@@ -853,6 +853,10 @@ export const hasSwiftForEachSelfIdentityUsage = (source: string): boolean => {
|
|
|
853
853
|
return hasSwiftSanitizedRegexMatch(source, /\bForEach\s*\([^)]*\bid\s*:\s*\\\.self\b/g);
|
|
854
854
|
};
|
|
855
855
|
|
|
856
|
+
export const hasSwiftSelfPrintChangesUsage = (source: string): boolean => {
|
|
857
|
+
return hasSwiftSanitizedRegexMatch(source, /\bSelf\s*\.\s*_printChanges\s*\(/g);
|
|
858
|
+
};
|
|
859
|
+
|
|
856
860
|
export const hasSwiftInlineForEachTransformUsage = (source: string): boolean => {
|
|
857
861
|
const sanitized = sanitizeSwiftSourceForMultilineRegex(source);
|
|
858
862
|
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(
|
|
@@ -679,6 +679,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
|
|
|
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
681
|
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftForEachSelfIdentityUsage, ruleId: 'heuristics.ios.swiftui.foreach-self-identity.ast', code: 'HEURISTICS_IOS_SWIFTUI_FOREACH_SELF_IDENTITY_AST', message: 'AST heuristic detected ForEach(..., id: \.self) usage; prefer a stable domain identity such as id: \.id or Identifiable models.' },
|
|
682
|
+
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftSelfPrintChangesUsage, ruleId: 'heuristics.ios.swiftui.self-print-changes.ast', code: 'HEURISTICS_IOS_SWIFTUI_SELF_PRINT_CHANGES_AST', message: 'AST heuristic detected Self._printChanges() in SwiftUI presentation; keep this debugging helper out of production view code.' },
|
|
682
683
|
{ 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.' },
|
|
683
684
|
{ platform: 'ios', pathCheck: isIOSPresentationPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftUiForEachConditionalViewCountUsage, ruleId: 'heuristics.ios.swiftui.foreach-conditional-view-count.ast', code: 'HEURISTICS_IOS_SWIFTUI_FOREACH_CONDITIONAL_VIEW_COUNT_AST', message: 'AST heuristic detected conditional view count inside ForEach; keep a constant number of views per element by moving branching into row views or modifiers.' },
|
|
684
685
|
{ 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.' },
|
|
@@ -822,6 +822,25 @@ export const iosRules: RuleSet = [
|
|
|
822
822
|
code: 'HEURISTICS_IOS_SWIFTUI_INLINE_FOREACH_TRANSFORM_AST',
|
|
823
823
|
},
|
|
824
824
|
},
|
|
825
|
+
{
|
|
826
|
+
id: 'heuristics.ios.swiftui.self-print-changes.ast',
|
|
827
|
+
description: 'Detects SwiftUI Self._printChanges() debugging helpers in production views.',
|
|
828
|
+
severity: 'WARN',
|
|
829
|
+
platform: 'ios',
|
|
830
|
+
locked: true,
|
|
831
|
+
when: {
|
|
832
|
+
kind: 'Heuristic',
|
|
833
|
+
where: {
|
|
834
|
+
ruleId: 'heuristics.ios.swiftui.self-print-changes.ast',
|
|
835
|
+
},
|
|
836
|
+
},
|
|
837
|
+
then: {
|
|
838
|
+
kind: 'Finding',
|
|
839
|
+
message:
|
|
840
|
+
'AST heuristic detected Self._printChanges() in SwiftUI presentation code; remove debug-only render diagnostics from production views.',
|
|
841
|
+
code: 'HEURISTICS_IOS_SWIFTUI_SELF_PRINT_CHANGES_AST',
|
|
842
|
+
},
|
|
843
|
+
},
|
|
825
844
|
{
|
|
826
845
|
id: 'heuristics.ios.swiftui.foreach-conditional-view-count.ast',
|
|
827
846
|
description: 'Detects conditional view counts inside SwiftUI ForEach rows.',
|
|
@@ -241,6 +241,10 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
|
|
|
241
241
|
heuristicDetector('ios.swiftui.foreach-self-identity', [
|
|
242
242
|
'heuristics.ios.swiftui.foreach-self-identity.ast',
|
|
243
243
|
]),
|
|
244
|
+
'skills.ios.guideline.ios-swiftui-expert.use-self-printchanges-to-debug-unexpected-view-updates':
|
|
245
|
+
heuristicDetector('ios.swiftui.self-print-changes', [
|
|
246
|
+
'heuristics.ios.swiftui.self-print-changes.ast',
|
|
247
|
+
]),
|
|
244
248
|
'skills.ios.guideline.ios-swiftui-expert.avoid-inline-filtering-in-foreach-prefilter-and-cache':
|
|
245
249
|
heuristicDetector('ios.swiftui.inline-foreach-transform', [
|
|
246
250
|
'heuristics.ios.swiftui.inline-foreach-transform.ast',
|
|
@@ -325,6 +325,9 @@ const normalizeKnownRuleTarget = (
|
|
|
325
325
|
}
|
|
326
326
|
return 'skills.ios.guideline.ios-swiftui-expert.ensure-foreach-uses-stable-identity-see-references-list-patterns-md';
|
|
327
327
|
}
|
|
328
|
+
if (includes('self.printchanges') || includes('unexpected view updates')) {
|
|
329
|
+
return 'skills.ios.guideline.ios-swiftui-expert.use-self-printchanges-to-debug-unexpected-view-updates';
|
|
330
|
+
}
|
|
328
331
|
if (
|
|
329
332
|
(includes('inline filtering') && includes('foreach')) ||
|
|
330
333
|
(includes('no inline filtering') && includes('foreach')) ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.231",
|
|
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:
|
|
4
|
+
"generatedAt": "2026-05-13T16:57:01.364Z",
|
|
5
5
|
"bundles": [
|
|
6
6
|
{
|
|
7
7
|
"name": "android-guidelines",
|
|
@@ -8620,7 +8620,7 @@
|
|
|
8620
8620
|
"name": "ios-swiftui-expert-guidelines",
|
|
8621
8621
|
"version": "1.0.0",
|
|
8622
8622
|
"source": "file:vendor/skills/swiftui-expert-skill/SKILL.md",
|
|
8623
|
-
"hash": "
|
|
8623
|
+
"hash": "4ea50faf9594602eefa6711b818cf4badeb2014ca64eaf00cb2f98f3e11a55f0",
|
|
8624
8624
|
"rules": [
|
|
8625
8625
|
{
|
|
8626
8626
|
"id": "skills.ios.guideline.ios-swiftui-expert.action-handlers-should-reference-methods-not-contain-inline-logic",
|
|
@@ -8931,7 +8931,7 @@
|
|
|
8931
8931
|
"sourcePath": "vendor/skills/swiftui-expert-skill/SKILL.md",
|
|
8932
8932
|
"confidence": "MEDIUM",
|
|
8933
8933
|
"locked": true,
|
|
8934
|
-
"evaluationMode": "
|
|
8934
|
+
"evaluationMode": "AUTO",
|
|
8935
8935
|
"origin": "core"
|
|
8936
8936
|
},
|
|
8937
8937
|
{
|