pumuki 6.3.210 → 6.3.211
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 +22 -0
- package/core/facts/detectors/text/ios.ts +15 -0
- package/core/facts/extractHeuristicFacts.ts +1 -0
- package/core/rules/presets/heuristics/ios.ts +19 -0
- package/integrations/config/skillsDetectorRegistry.ts +8 -0
- package/integrations/config/skillsMarkdownRules.ts +8 -0
- package/package.json +1 -1
- package/skills.lock.json +3 -3
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
hasSwiftNSManagedObjectBoundaryUsage,
|
|
42
42
|
hasSwiftNSManagedObjectStateLeakUsage,
|
|
43
43
|
hasSwiftNavigationViewUsage,
|
|
44
|
+
hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage,
|
|
44
45
|
hasSwiftObservableObjectUsage,
|
|
45
46
|
hasSwiftOnTapGestureUsage,
|
|
46
47
|
hasSwiftOperationQueueUsage,
|
|
@@ -317,6 +318,27 @@ let text = "URLSession.shared.dataTask"
|
|
|
317
318
|
assert.equal(hasSwiftMassiveViewControllerResponsibilityUsage(ignored), false);
|
|
318
319
|
});
|
|
319
320
|
|
|
321
|
+
test('hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage detecta IUO fuera de IBOutlet', () => {
|
|
322
|
+
const source = `
|
|
323
|
+
final class CheckoutViewModel {
|
|
324
|
+
var selectedOrder: Order!
|
|
325
|
+
private let formatter: DateFormatter!
|
|
326
|
+
}
|
|
327
|
+
`;
|
|
328
|
+
const ignored = `
|
|
329
|
+
final class CheckoutViewController: UIViewController {
|
|
330
|
+
@IBOutlet weak var titleLabel: UILabel!
|
|
331
|
+
@IBOutlet
|
|
332
|
+
private weak var tableView: UITableView!
|
|
333
|
+
let text = "var selectedOrder: Order!"
|
|
334
|
+
// var selectedOrder: Order!
|
|
335
|
+
}
|
|
336
|
+
`;
|
|
337
|
+
|
|
338
|
+
assert.equal(hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage(source), true);
|
|
339
|
+
assert.equal(hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage(ignored), false);
|
|
340
|
+
});
|
|
341
|
+
|
|
320
342
|
test('detectores de logging iOS detectan logs ad-hoc y PII en produccion', () => {
|
|
321
343
|
const adHoc = `
|
|
322
344
|
print(user.id)
|
|
@@ -544,6 +544,21 @@ export const hasSwiftMassiveViewControllerResponsibilityUsage = (source: string)
|
|
|
544
544
|
return false;
|
|
545
545
|
};
|
|
546
546
|
|
|
547
|
+
export const hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage = (source: string): boolean => {
|
|
548
|
+
const lines = source.split(/\r?\n/);
|
|
549
|
+
const implicitlyUnwrappedPropertyPattern =
|
|
550
|
+
/\b(?:var|let)\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*(?:[A-Za-z_][A-Za-z0-9_.<>?]*\s*)!\s*(?:[=,{]|$)/;
|
|
551
|
+
|
|
552
|
+
return lines.some((line, index) => {
|
|
553
|
+
const sanitizedLine = stripSwiftLineForSemanticScan(line);
|
|
554
|
+
if (!implicitlyUnwrappedPropertyPattern.test(sanitizedLine)) {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
const previousLine = index > 0 ? stripSwiftLineForSemanticScan(lines[index - 1] ?? '') : '';
|
|
558
|
+
return !/\B@IBOutlet\b/.test(`${previousLine} ${sanitizedLine}`);
|
|
559
|
+
});
|
|
560
|
+
};
|
|
561
|
+
|
|
547
562
|
export const hasSwiftAdHocLoggingUsage = (source: string): boolean => {
|
|
548
563
|
return collectSwiftRegexLines(
|
|
549
564
|
source,
|
|
@@ -650,6 +650,7 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
|
|
|
650
650
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftStrongSelfEscapingClosureUsage, ruleId: 'heuristics.ios.memory.strong-self-escaping-closure.ast', code: 'HEURISTICS_IOS_MEMORY_STRONG_SELF_ESCAPING_CLOSURE_AST', message: 'AST heuristic detected strong self capture in an escaping iOS closure; weak or unowned captures remain the preferred baseline when ownership is not explicit.' },
|
|
651
651
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftCustomSingletonUsage, ruleId: 'heuristics.ios.architecture.custom-singleton.ast', code: 'HEURISTICS_IOS_ARCHITECTURE_CUSTOM_SINGLETON_AST', message: 'AST heuristic detected a custom static shared singleton in iOS production code; dependency injection remains the preferred baseline for app-owned services.' },
|
|
652
652
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftMassiveViewControllerResponsibilityUsage, ruleId: 'heuristics.ios.architecture.massive-view-controller.ast', code: 'HEURISTICS_IOS_ARCHITECTURE_MASSIVE_VIEW_CONTROLLER_AST', message: 'AST heuristic detected a UIViewController with direct infrastructure/data access; move data access behind application/domain boundaries.' },
|
|
653
|
+
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftNonIBOutletImplicitlyUnwrappedOptionalUsage, ruleId: 'heuristics.ios.safety.non-iboutlet-iuo.ast', code: 'HEURISTICS_IOS_SAFETY_NON_IBOUTLET_IUO_AST', message: 'AST heuristic detected an implicitly unwrapped optional outside IBOutlet wiring; explicit optionals or initialization guarantees remain the preferred baseline.' },
|
|
653
654
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftAdHocLoggingUsage, ruleId: 'heuristics.ios.logging.adhoc-print.ast', code: 'HEURISTICS_IOS_LOGGING_ADHOC_PRINT_AST', message: 'AST heuristic detected print/debugPrint/dump/NSLog/os_log usage in iOS production code.' },
|
|
654
655
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftSensitiveLoggingUsage, ruleId: 'heuristics.ios.logging.sensitive-data.ast', code: 'HEURISTICS_IOS_LOGGING_SENSITIVE_DATA_AST', message: 'AST heuristic detected sensitive data in an iOS logging call.' },
|
|
655
656
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftAlamofireUsage, ruleId: 'heuristics.ios.networking.alamofire.ast', code: 'HEURISTICS_IOS_NETWORKING_ALAMOFIRE_AST', message: 'AST heuristic detected Alamofire usage in iOS production code; URLSession remains the preferred baseline for new code.' },
|
|
@@ -257,6 +257,25 @@ export const iosRules: RuleSet = [
|
|
|
257
257
|
code: 'HEURISTICS_IOS_ARCHITECTURE_MASSIVE_VIEW_CONTROLLER_AST',
|
|
258
258
|
},
|
|
259
259
|
},
|
|
260
|
+
{
|
|
261
|
+
id: 'heuristics.ios.safety.non-iboutlet-iuo.ast',
|
|
262
|
+
description: 'Detects implicitly unwrapped optionals outside IBOutlet wiring.',
|
|
263
|
+
severity: 'WARN',
|
|
264
|
+
platform: 'ios',
|
|
265
|
+
locked: true,
|
|
266
|
+
when: {
|
|
267
|
+
kind: 'Heuristic',
|
|
268
|
+
where: {
|
|
269
|
+
ruleId: 'heuristics.ios.safety.non-iboutlet-iuo.ast',
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
then: {
|
|
273
|
+
kind: 'Finding',
|
|
274
|
+
message:
|
|
275
|
+
'AST heuristic detected an implicitly unwrapped optional outside IBOutlet wiring; explicit optionals or initialization guarantees remain the preferred baseline.',
|
|
276
|
+
code: 'HEURISTICS_IOS_SAFETY_NON_IBOUTLET_IUO_AST',
|
|
277
|
+
},
|
|
278
|
+
},
|
|
260
279
|
{
|
|
261
280
|
id: 'heuristics.ios.logging.adhoc-print.ast',
|
|
262
281
|
description: 'Detects print/debugPrint/dump/NSLog/os_log usage in iOS production code.',
|
|
@@ -74,6 +74,14 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
|
|
|
74
74
|
'ios.architecture.massive-view-controller',
|
|
75
75
|
['heuristics.ios.architecture.massive-view-controller.ast']
|
|
76
76
|
),
|
|
77
|
+
'skills.ios.guideline.ios.implicitly-unwrapped-solo-para-iboutlets-y-casos-muy-especi-ficos': heuristicDetector(
|
|
78
|
+
'ios.safety.non-iboutlet-iuo',
|
|
79
|
+
['heuristics.ios.safety.non-iboutlet-iuo.ast']
|
|
80
|
+
),
|
|
81
|
+
'skills.ios.guideline.ios.singletons-dificultan-testing': heuristicDetector(
|
|
82
|
+
'ios.architecture.custom-singleton',
|
|
83
|
+
['heuristics.ios.architecture.custom-singleton.ast']
|
|
84
|
+
),
|
|
77
85
|
'skills.ios.guideline.ios.prohibido-print-y-logs-ad-hoc': heuristicDetector(
|
|
78
86
|
'ios.logging.adhoc-print',
|
|
79
87
|
['heuristics.ios.logging.adhoc-print.ast']
|
|
@@ -453,6 +453,14 @@ const normalizeKnownRuleTarget = (
|
|
|
453
453
|
) {
|
|
454
454
|
return 'skills.ios.guideline.ios.massive-view-controllers-viewcontrollers-que-mezclan-presentacio-n-nav';
|
|
455
455
|
}
|
|
456
|
+
if (
|
|
457
|
+
includes('implicitly unwrapped') ||
|
|
458
|
+
includes('implicit unwrapped') ||
|
|
459
|
+
includes('iboutlet') ||
|
|
460
|
+
includes('iboutlets')
|
|
461
|
+
) {
|
|
462
|
+
return 'skills.ios.guideline.ios.implicitly-unwrapped-solo-para-iboutlets-y-casos-muy-especi-ficos';
|
|
463
|
+
}
|
|
456
464
|
if (
|
|
457
465
|
includes('mixing legacy xctest style') ||
|
|
458
466
|
includes('mixed xctest and swift testing') ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.211",
|
|
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-13T12:51
|
|
4
|
+
"generatedAt": "2026-05-13T12:56:51.940Z",
|
|
5
5
|
"bundles": [
|
|
6
6
|
{
|
|
7
7
|
"name": "android-guidelines",
|
|
@@ -5764,7 +5764,7 @@
|
|
|
5764
5764
|
"name": "ios-guidelines",
|
|
5765
5765
|
"version": "1.0.0",
|
|
5766
5766
|
"source": "file:vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
5767
|
-
"hash": "
|
|
5767
|
+
"hash": "1395678f8abd2b8eddb9d4270fd205517ed4ce4e3796def5f7846592990ec778",
|
|
5768
5768
|
"rules": [
|
|
5769
5769
|
{
|
|
5770
5770
|
"id": "skills.ios.guideline.ios.accessibility-identifiers-para-localizar-elementos",
|
|
@@ -6736,7 +6736,7 @@
|
|
|
6736
6736
|
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
6737
6737
|
"confidence": "MEDIUM",
|
|
6738
6738
|
"locked": true,
|
|
6739
|
-
"evaluationMode": "
|
|
6739
|
+
"evaluationMode": "AUTO",
|
|
6740
6740
|
"origin": "core"
|
|
6741
6741
|
},
|
|
6742
6742
|
{
|