pumuki 6.3.207 → 6.3.209
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 +74 -0
- package/core/facts/detectors/text/ios.ts +78 -0
- package/core/facts/extractHeuristicFacts.ts +2 -0
- package/core/rules/presets/heuristics/ios.ts +38 -0
- package/integrations/config/skillsDetectorRegistry.ts +13 -2
- package/integrations/config/skillsMarkdownRules.ts +15 -3
- package/package.json +1 -1
- package/skills.lock.json +15 -51
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
hasSwiftOnTapGestureUsage,
|
|
45
45
|
hasSwiftOperationQueueUsage,
|
|
46
46
|
hasSwiftContainsUserFilterUsage,
|
|
47
|
+
hasSwiftCustomSingletonUsage,
|
|
47
48
|
hasSwiftPassedValueStateWrapperUsage,
|
|
48
49
|
hasSwiftPhysicalTextAlignmentUsage,
|
|
49
50
|
hasSwiftPreconcurrencyUsage,
|
|
@@ -55,6 +56,7 @@ import {
|
|
|
55
56
|
hasSwiftJSONSerializationUsage,
|
|
56
57
|
hasSwiftStringFormatUsage,
|
|
57
58
|
hasSwiftStrongDelegateReferenceUsage,
|
|
59
|
+
hasSwiftStrongSelfEscapingClosureUsage,
|
|
58
60
|
hasSwiftTabItemUsage,
|
|
59
61
|
hasSwiftTaskDetachedUsage,
|
|
60
62
|
hasSwiftWaitForExpectationsUsage,
|
|
@@ -209,6 +211,78 @@ final class CheckoutCoordinator {
|
|
|
209
211
|
assert.equal(hasSwiftStrongDelegateReferenceUsage(source), false);
|
|
210
212
|
});
|
|
211
213
|
|
|
214
|
+
test('hasSwiftStrongSelfEscapingClosureUsage detecta self fuerte en closures escapables iOS', () => {
|
|
215
|
+
const source = `
|
|
216
|
+
final class CartViewModel {
|
|
217
|
+
private var cancellables = Set<AnyCancellable>()
|
|
218
|
+
|
|
219
|
+
func bind() {
|
|
220
|
+
Task {
|
|
221
|
+
await self.reload()
|
|
222
|
+
}
|
|
223
|
+
DispatchQueue.main.async {
|
|
224
|
+
self.render()
|
|
225
|
+
}
|
|
226
|
+
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
|
|
227
|
+
self.tick(timer)
|
|
228
|
+
}
|
|
229
|
+
NotificationCenter.default.addObserver(forName: .cartChanged, object: nil, queue: .main) { notification in
|
|
230
|
+
self.handle(notification)
|
|
231
|
+
}
|
|
232
|
+
publisher.sink { value in
|
|
233
|
+
self.consume(value)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
`;
|
|
238
|
+
|
|
239
|
+
assert.equal(hasSwiftStrongSelfEscapingClosureUsage(source), true);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('hasSwiftStrongSelfEscapingClosureUsage preserva capture lists weak/unowned e ignora comentarios y strings', () => {
|
|
243
|
+
const source = `
|
|
244
|
+
final class CartViewModel {
|
|
245
|
+
func bind() {
|
|
246
|
+
Task { [weak self] in
|
|
247
|
+
await self?.reload()
|
|
248
|
+
}
|
|
249
|
+
DispatchQueue.main.async { [unowned self] in
|
|
250
|
+
render()
|
|
251
|
+
}
|
|
252
|
+
publisher.sink(receiveValue: { [weak self] value in
|
|
253
|
+
self?.consume(value)
|
|
254
|
+
})
|
|
255
|
+
let text = "Task { self.reload() }"
|
|
256
|
+
// Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.tick() }
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
`;
|
|
260
|
+
|
|
261
|
+
assert.equal(hasSwiftStrongSelfEscapingClosureUsage(source), false);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test('hasSwiftCustomSingletonUsage detecta singletons propios y excluye usos de singletons del sistema', () => {
|
|
265
|
+
const source = `
|
|
266
|
+
final class SessionStore {
|
|
267
|
+
static let shared = SessionStore()
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
final class MutableStore {
|
|
271
|
+
public static var shared: MutableStore = MutableStore()
|
|
272
|
+
}
|
|
273
|
+
`;
|
|
274
|
+
const ignored = `
|
|
275
|
+
final class APIClient {
|
|
276
|
+
let session = URLSession.shared
|
|
277
|
+
let text = "static let shared = SessionStore()"
|
|
278
|
+
// static let shared = SessionStore()
|
|
279
|
+
}
|
|
280
|
+
`;
|
|
281
|
+
|
|
282
|
+
assert.equal(hasSwiftCustomSingletonUsage(source), true);
|
|
283
|
+
assert.equal(hasSwiftCustomSingletonUsage(ignored), false);
|
|
284
|
+
});
|
|
285
|
+
|
|
212
286
|
test('detectores de logging iOS detectan logs ad-hoc y PII en produccion', () => {
|
|
213
287
|
const adHoc = `
|
|
214
288
|
print(user.id)
|
|
@@ -450,6 +450,84 @@ export const hasSwiftStrongDelegateReferenceUsage = (source: string): boolean =>
|
|
|
450
450
|
});
|
|
451
451
|
};
|
|
452
452
|
|
|
453
|
+
const swiftStrongSelfEscapingClosurePatterns = [
|
|
454
|
+
/\bTask\s*(?:\([^)]*\))?\s*\{/g,
|
|
455
|
+
/\bDispatchQueue\s*\.\s*[A-Za-z0-9_.]+\s*\.\s*async(?:After)?\s*(?:\([^)]*\))?\s*\{/g,
|
|
456
|
+
/\bTimer\s*\.\s*scheduledTimer\s*\([\s\S]{0,320}?\)\s*\{/g,
|
|
457
|
+
/\bNotificationCenter\s*\.\s*default\s*\.\s*addObserver\s*\([\s\S]{0,420}?\busing\s*:\s*\{/g,
|
|
458
|
+
/\.\s*sink\s*\([\s\S]{0,420}?\b(?:receiveValue|receiveCompletion)\s*:\s*\{/g,
|
|
459
|
+
/\.\s*sink\s*\{/g,
|
|
460
|
+
/\.\s*handleEvents\s*\([\s\S]{0,420}?\b(?:receiveOutput|receiveCompletion|receiveCancel)\s*:\s*\{/g,
|
|
461
|
+
];
|
|
462
|
+
|
|
463
|
+
const findMatchingSwiftBraceIndex = (source: string, openingBraceIndex: number): number => {
|
|
464
|
+
let depth = 0;
|
|
465
|
+
for (let index = openingBraceIndex; index < source.length; index += 1) {
|
|
466
|
+
const char = source[index];
|
|
467
|
+
if (char === '{') {
|
|
468
|
+
depth += 1;
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
if (char !== '}') {
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
depth -= 1;
|
|
475
|
+
if (depth === 0) {
|
|
476
|
+
return index;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return -1;
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
const hasWeakOrUnownedSelfCaptureList = (closureBody: string): boolean => {
|
|
483
|
+
const trimmedStart = closureBody.trimStart();
|
|
484
|
+
if (!trimmedStart.startsWith('[')) {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
const captureListEndIndex = trimmedStart.indexOf(']');
|
|
488
|
+
if (captureListEndIndex < 0) {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
const captureList = trimmedStart.slice(1, captureListEndIndex);
|
|
492
|
+
return /\b(?:weak|unowned)\s+self\b/.test(captureList);
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
export const hasSwiftStrongSelfEscapingClosureUsage = (source: string): boolean => {
|
|
496
|
+
const sanitized = sanitizeSwiftSourceForMultilineRegex(source);
|
|
497
|
+
for (const pattern of swiftStrongSelfEscapingClosurePatterns) {
|
|
498
|
+
pattern.lastIndex = 0;
|
|
499
|
+
for (const match of sanitized.matchAll(pattern)) {
|
|
500
|
+
const matchedSource = match[0] ?? '';
|
|
501
|
+
const openingBraceOffset = matchedSource.lastIndexOf('{');
|
|
502
|
+
if (openingBraceOffset < 0 || match.index === undefined) {
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const openingBraceIndex = match.index + openingBraceOffset;
|
|
506
|
+
const closingBraceIndex = findMatchingSwiftBraceIndex(sanitized, openingBraceIndex);
|
|
507
|
+
if (closingBraceIndex < 0) {
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
const closureBody = sanitized.slice(openingBraceIndex + 1, closingBraceIndex);
|
|
511
|
+
if (hasWeakOrUnownedSelfCaptureList(closureBody)) {
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
if (/\bself\s*\./.test(closureBody)) {
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return false;
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
export const hasSwiftCustomSingletonUsage = (source: string): boolean => {
|
|
523
|
+
const singletonDeclarationPattern =
|
|
524
|
+
/^\s*(?:(?:private|fileprivate|internal|public|open)\s+)?static\s+(?:let|var)\s+shared\b(?:\s*:\s*[A-Za-z_][A-Za-z0-9_.<>]*)?\s*=/;
|
|
525
|
+
return source.split(/\r?\n/).some((line) => {
|
|
526
|
+
const sanitizedLine = stripSwiftLineForSemanticScan(line);
|
|
527
|
+
return singletonDeclarationPattern.test(sanitizedLine);
|
|
528
|
+
});
|
|
529
|
+
};
|
|
530
|
+
|
|
453
531
|
export const hasSwiftAdHocLoggingUsage = (source: string): boolean => {
|
|
454
532
|
return collectSwiftRegexLines(
|
|
455
533
|
source,
|
|
@@ -647,6 +647,8 @@ const textDetectorRegistry: ReadonlyArray<TextDetectorRegistryEntry> = [
|
|
|
647
647
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftOperationQueueUsage, ruleId: 'heuristics.ios.operation-queue.ast', code: 'HEURISTICS_IOS_OPERATION_QUEUE_AST', message: 'AST heuristic detected OperationQueue usage.' },
|
|
648
648
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftTaskDetachedUsage, ruleId: 'heuristics.ios.task-detached.ast', code: 'HEURISTICS_IOS_TASK_DETACHED_AST', message: 'AST heuristic detected Task.detached usage.' },
|
|
649
649
|
{ platform: 'ios', pathCheck: isIOSSwiftPath, excludePaths: [isSwiftTestPath], detect: TextIOS.hasSwiftStrongDelegateReferenceUsage, ruleId: 'heuristics.ios.memory.strong-delegate.ast', code: 'HEURISTICS_IOS_MEMORY_STRONG_DELEGATE_AST', message: 'AST heuristic detected a strong delegate/dataSource reference; weak delegates remain the preferred baseline to avoid retain cycles.' },
|
|
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
|
+
{ 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.' },
|
|
650
652
|
{ 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.' },
|
|
651
653
|
{ 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.' },
|
|
652
654
|
{ 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.' },
|
|
@@ -200,6 +200,44 @@ export const iosRules: RuleSet = [
|
|
|
200
200
|
code: 'HEURISTICS_IOS_MEMORY_STRONG_DELEGATE_AST',
|
|
201
201
|
},
|
|
202
202
|
},
|
|
203
|
+
{
|
|
204
|
+
id: 'heuristics.ios.memory.strong-self-escaping-closure.ast',
|
|
205
|
+
description: 'Detects strong self captures in escaping iOS closures.',
|
|
206
|
+
severity: 'WARN',
|
|
207
|
+
platform: 'ios',
|
|
208
|
+
locked: true,
|
|
209
|
+
when: {
|
|
210
|
+
kind: 'Heuristic',
|
|
211
|
+
where: {
|
|
212
|
+
ruleId: 'heuristics.ios.memory.strong-self-escaping-closure.ast',
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
then: {
|
|
216
|
+
kind: 'Finding',
|
|
217
|
+
message:
|
|
218
|
+
'AST heuristic detected strong self capture in an escaping iOS closure; weak or unowned captures remain the preferred baseline when ownership is not explicit.',
|
|
219
|
+
code: 'HEURISTICS_IOS_MEMORY_STRONG_SELF_ESCAPING_CLOSURE_AST',
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 'heuristics.ios.architecture.custom-singleton.ast',
|
|
224
|
+
description: 'Detects custom static shared singletons in iOS production code.',
|
|
225
|
+
severity: 'WARN',
|
|
226
|
+
platform: 'ios',
|
|
227
|
+
locked: true,
|
|
228
|
+
when: {
|
|
229
|
+
kind: 'Heuristic',
|
|
230
|
+
where: {
|
|
231
|
+
ruleId: 'heuristics.ios.architecture.custom-singleton.ast',
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
then: {
|
|
235
|
+
kind: 'Finding',
|
|
236
|
+
message:
|
|
237
|
+
'AST heuristic detected a custom static shared singleton in iOS production code; dependency injection remains the preferred baseline for app-owned services.',
|
|
238
|
+
code: 'HEURISTICS_IOS_ARCHITECTURE_CUSTOM_SINGLETON_AST',
|
|
239
|
+
},
|
|
240
|
+
},
|
|
203
241
|
{
|
|
204
242
|
id: 'heuristics.ios.logging.adhoc-print.ast',
|
|
205
243
|
description: 'Detects print/debugPrint/dump/NSLog/os_log usage in iOS production code.',
|
|
@@ -52,8 +52,19 @@ const registryByRuleId: Record<string, SkillsDetectorBinding> = {
|
|
|
52
52
|
['heuristics.ios.memory.strong-delegate.ast']
|
|
53
53
|
),
|
|
54
54
|
'skills.ios.guideline.ios.evitar-retain-cycles-especialmente-en-closures-delegates': heuristicDetector(
|
|
55
|
-
'ios.memory.
|
|
56
|
-
[
|
|
55
|
+
'ios.memory.retain-cycles',
|
|
56
|
+
[
|
|
57
|
+
'heuristics.ios.memory.strong-delegate.ast',
|
|
58
|
+
'heuristics.ios.memory.strong-self-escaping-closure.ast',
|
|
59
|
+
]
|
|
60
|
+
),
|
|
61
|
+
'skills.ios.guideline.ios.no-singleton-usar-inyeccio-n-de-dependencias-no-compartir-instancias-g': heuristicDetector(
|
|
62
|
+
'ios.architecture.custom-singleton',
|
|
63
|
+
['heuristics.ios.architecture.custom-singleton.ast']
|
|
64
|
+
),
|
|
65
|
+
'skills.ios.guideline.ios.no-singletons-excepto-sistema-urlsession-shared-esta-ok': heuristicDetector(
|
|
66
|
+
'ios.architecture.custom-singleton',
|
|
67
|
+
['heuristics.ios.architecture.custom-singleton.ast']
|
|
57
68
|
),
|
|
58
69
|
'skills.ios.guideline.ios.prohibido-print-y-logs-ad-hoc': heuristicDetector(
|
|
59
70
|
'ios.logging.adhoc-print',
|
|
@@ -423,14 +423,26 @@ const normalizeKnownRuleTarget = (
|
|
|
423
423
|
) {
|
|
424
424
|
return 'skills.ios.guideline.ios.accessibility-labels-accessibilitylabel';
|
|
425
425
|
}
|
|
426
|
+
if (includes('weak delegates') || includes('delegation pattern')) {
|
|
427
|
+
return 'skills.ios.guideline.ios.delegation-pattern-weak-delegates-para-evitar-retain-cycles';
|
|
428
|
+
}
|
|
426
429
|
if (
|
|
427
|
-
includes('weak delegates') ||
|
|
428
|
-
includes('delegation pattern') ||
|
|
429
430
|
includes('closures delegates') ||
|
|
431
|
+
includes('weak self') ||
|
|
432
|
+
includes('capture list') ||
|
|
430
433
|
includes('avoid retain cycles') ||
|
|
431
434
|
includes('evitar retain cycles')
|
|
432
435
|
) {
|
|
433
|
-
return 'skills.ios.guideline.ios.
|
|
436
|
+
return 'skills.ios.guideline.ios.evitar-retain-cycles-especialmente-en-closures-delegates';
|
|
437
|
+
}
|
|
438
|
+
if (
|
|
439
|
+
includes('no singleton') ||
|
|
440
|
+
includes('no singletons') ||
|
|
441
|
+
includes('static shared') ||
|
|
442
|
+
includes('static let shared') ||
|
|
443
|
+
includes('static var shared')
|
|
444
|
+
) {
|
|
445
|
+
return 'skills.ios.guideline.ios.no-singleton-usar-inyeccio-n-de-dependencias-no-compartir-instancias-g';
|
|
434
446
|
}
|
|
435
447
|
if (
|
|
436
448
|
includes('mixing legacy xctest style') ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.209",
|
|
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:
|
|
4
|
+
"generatedAt": "2026-05-13T12:45:06.608Z",
|
|
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": "5c20c168bf6f54010cfac75cce1311a03ed2345ac20eef7b2a4458ad8efd3fc4",
|
|
5768
5768
|
"rules": [
|
|
5769
5769
|
{
|
|
5770
5770
|
"id": "skills.ios.guideline.ios.accessibility-identifiers-para-localizar-elementos",
|
|
@@ -6042,18 +6042,6 @@
|
|
|
6042
6042
|
"evaluationMode": "DECLARATIVE",
|
|
6043
6043
|
"origin": "core"
|
|
6044
6044
|
},
|
|
6045
|
-
{
|
|
6046
|
-
"id": "skills.ios.guideline.ios.capture-lists-capturar-valores-no-referencias",
|
|
6047
|
-
"description": "Capture lists - Capturar valores, no referencias",
|
|
6048
|
-
"severity": "WARN",
|
|
6049
|
-
"platform": "ios",
|
|
6050
|
-
"sourceSkill": "ios-guidelines",
|
|
6051
|
-
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
6052
|
-
"confidence": "MEDIUM",
|
|
6053
|
-
"locked": true,
|
|
6054
|
-
"evaluationMode": "DECLARATIVE",
|
|
6055
|
-
"origin": "core"
|
|
6056
|
-
},
|
|
6057
6045
|
{
|
|
6058
6046
|
"id": "skills.ios.guideline.ios.carthage-prohibido",
|
|
6059
6047
|
"description": "Carthage - Prohibido",
|
|
@@ -6510,6 +6498,18 @@
|
|
|
6510
6498
|
"evaluationMode": "DECLARATIVE",
|
|
6511
6499
|
"origin": "core"
|
|
6512
6500
|
},
|
|
6501
|
+
{
|
|
6502
|
+
"id": "skills.ios.guideline.ios.evitar-retain-cycles-especialmente-en-closures-delegates",
|
|
6503
|
+
"description": "[weak self] - En closures que pueden outlive self",
|
|
6504
|
+
"severity": "WARN",
|
|
6505
|
+
"platform": "ios",
|
|
6506
|
+
"sourceSkill": "ios-guidelines",
|
|
6507
|
+
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
6508
|
+
"confidence": "MEDIUM",
|
|
6509
|
+
"locked": true,
|
|
6510
|
+
"evaluationMode": "AUTO",
|
|
6511
|
+
"origin": "core"
|
|
6512
|
+
},
|
|
6513
6513
|
{
|
|
6514
6514
|
"id": "skills.ios.guideline.ios.expect-y-require-assertions-de-swift-testing",
|
|
6515
6515
|
"description": "#expect y #require - Assertions de Swift Testing",
|
|
@@ -6727,18 +6727,6 @@
|
|
|
6727
6727
|
"evaluationMode": "DECLARATIVE",
|
|
6728
6728
|
"origin": "core"
|
|
6729
6729
|
},
|
|
6730
|
-
{
|
|
6731
|
-
"id": "skills.ios.guideline.ios.implementaciones-inyectadas-en-initializer-no-singleton",
|
|
6732
|
-
"description": "Implementaciones inyectadas - En initializer, no Singleton",
|
|
6733
|
-
"severity": "WARN",
|
|
6734
|
-
"platform": "ios",
|
|
6735
|
-
"sourceSkill": "ios-guidelines",
|
|
6736
|
-
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
6737
|
-
"confidence": "MEDIUM",
|
|
6738
|
-
"locked": true,
|
|
6739
|
-
"evaluationMode": "DECLARATIVE",
|
|
6740
|
-
"origin": "core"
|
|
6741
|
-
},
|
|
6742
6730
|
{
|
|
6743
6731
|
"id": "skills.ios.guideline.ios.implicitly-unwrapped-solo-para-iboutlets-y-casos-muy-especi-ficos",
|
|
6744
6732
|
"description": "Implicitly unwrapped (!) - Solo para IBOutlets y casos muy específicos",
|
|
@@ -7180,19 +7168,7 @@
|
|
|
7180
7168
|
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
7181
7169
|
"confidence": "MEDIUM",
|
|
7182
7170
|
"locked": true,
|
|
7183
|
-
"evaluationMode": "
|
|
7184
|
-
"origin": "core"
|
|
7185
|
-
},
|
|
7186
|
-
{
|
|
7187
|
-
"id": "skills.ios.guideline.ios.no-singletons-excepto-sistema-urlsession-shared-esta-ok",
|
|
7188
|
-
"description": "No singletons - Excepto sistema (URLSession.shared está OK)",
|
|
7189
|
-
"severity": "WARN",
|
|
7190
|
-
"platform": "ios",
|
|
7191
|
-
"sourceSkill": "ios-guidelines",
|
|
7192
|
-
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
7193
|
-
"confidence": "MEDIUM",
|
|
7194
|
-
"locked": true,
|
|
7195
|
-
"evaluationMode": "DECLARATIVE",
|
|
7171
|
+
"evaluationMode": "AUTO",
|
|
7196
7172
|
"origin": "core"
|
|
7197
7173
|
},
|
|
7198
7174
|
{
|
|
@@ -8239,18 +8215,6 @@
|
|
|
8239
8215
|
"evaluationMode": "DECLARATIVE",
|
|
8240
8216
|
"origin": "core"
|
|
8241
8217
|
},
|
|
8242
|
-
{
|
|
8243
|
-
"id": "skills.ios.guideline.ios.weak-self-en-closures-que-pueden-outlive-self",
|
|
8244
|
-
"description": "[weak self] - En closures que pueden outlive self",
|
|
8245
|
-
"severity": "WARN",
|
|
8246
|
-
"platform": "ios",
|
|
8247
|
-
"sourceSkill": "ios-guidelines",
|
|
8248
|
-
"sourcePath": "vendor/skills/ios-enterprise-rules/SKILL.md",
|
|
8249
|
-
"confidence": "MEDIUM",
|
|
8250
|
-
"locked": true,
|
|
8251
|
-
"evaluationMode": "DECLARATIVE",
|
|
8252
|
-
"origin": "core"
|
|
8253
|
-
},
|
|
8254
8218
|
{
|
|
8255
8219
|
"id": "skills.ios.guideline.ios.xcode-usar-la-u-ltima-versio-n-estable-disponible",
|
|
8256
8220
|
"description": "Xcode: usar la última versión estable disponible",
|