pumuki 6.3.294 → 6.3.295
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/CHANGELOG.md +4 -0
- package/core/facts/detectors/text/ios.test.ts +59 -0
- package/core/facts/detectors/text/ios.ts +25 -0
- package/core/facts/detectors/typescript/index.test.ts +569 -0
- package/core/facts/detectors/typescript/index.ts +312 -0
- package/core/facts/extractHeuristicFacts.ts +26 -0
- package/core/rules/presets/heuristics/ios.test.ts +11 -1
- package/core/rules/presets/heuristics/ios.ts +36 -0
- package/core/rules/presets/heuristics/typescript.test.ts +55 -1
- package/core/rules/presets/heuristics/typescript.ts +165 -0
- package/integrations/config/skillsDetectorRegistry.ts +58 -0
- package/integrations/git/runPlatformGate.ts +41 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [6.3.295] - 2026-05-19
|
|
4
|
+
|
|
5
|
+
- `PUMUKI-INC-156`: staged PRE_WRITE/PRE_COMMIT no longer blocks an atomic iOS slice with broad file-level SwiftUI skill findings that expose dozens of lines without a precise AST node introduced by the diff. Precise AST/skills findings still block in every severity when they intersect changed lines; broad brownfield file debt is retained as advisory with remediation demanding line/node-level evidence or a dedicated remediation slice.
|
|
6
|
+
|
|
3
7
|
## [6.3.283] - 2026-05-19
|
|
4
8
|
|
|
5
9
|
- `PUMUKI-INC-150`: brownfield XCTest specs that satisfy `makeSUT()` and `trackForMemoryLeaks()` are also exempt from Swift Testing migration assertion findings (`skills.ios.no-xctassert` / `skills.ios.no-xctunwrap`). These rules remain active for modern Swift Testing suites and XCTest specs without an explicit brownfield quality contract.
|
|
@@ -31,6 +31,10 @@ import {
|
|
|
31
31
|
hasSwiftAdHocLoggingUsage,
|
|
32
32
|
hasSwiftAlamofireUsage,
|
|
33
33
|
hasSwiftEmptyCatchUsage,
|
|
34
|
+
collectSwiftNSErrorThrowLines,
|
|
35
|
+
hasSwiftNSErrorThrowUsage,
|
|
36
|
+
collectSwiftPackageBranchDependencyLines,
|
|
37
|
+
hasSwiftPackageBranchDependencyUsage,
|
|
34
38
|
hasSwiftForEachIndicesUsage,
|
|
35
39
|
hasSwiftForEachSelfIdentityUsage,
|
|
36
40
|
collectSwiftForceCastLines,
|
|
@@ -384,6 +388,61 @@ do {
|
|
|
384
388
|
assert.equal(hasSwiftEmptyCatchUsage(safe), false);
|
|
385
389
|
});
|
|
386
390
|
|
|
391
|
+
test('hasSwiftNSErrorThrowUsage detecta NSError lanzado directamente y preserva errores tipados', () => {
|
|
392
|
+
const source = `
|
|
393
|
+
func map(response: HTTPURLResponse) throws {
|
|
394
|
+
if response.statusCode >= 500 {
|
|
395
|
+
throw NSError(domain: "Network", code: response.statusCode)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
`;
|
|
399
|
+
const safe = `
|
|
400
|
+
enum NetworkError: Error {
|
|
401
|
+
case server(statusCode: Int)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
func map(response: HTTPURLResponse) throws {
|
|
405
|
+
if response.statusCode >= 500 {
|
|
406
|
+
throw NetworkError.server(statusCode: response.statusCode)
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
let sample = "throw NSError(domain: code:)"
|
|
411
|
+
// throw NSError(domain: "Sample", code: 1)
|
|
412
|
+
`;
|
|
413
|
+
|
|
414
|
+
assert.equal(hasSwiftNSErrorThrowUsage(source), true);
|
|
415
|
+
assert.deepEqual(collectSwiftNSErrorThrowLines(source), [4]);
|
|
416
|
+
assert.equal(hasSwiftNSErrorThrowUsage(safe), false);
|
|
417
|
+
assert.deepEqual(collectSwiftNSErrorThrowLines(safe), []);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
test('hasSwiftPackageBranchDependencyUsage detecta dependencias SwiftPM por branch y preserva versiones', () => {
|
|
421
|
+
const source = `
|
|
422
|
+
let package = Package(
|
|
423
|
+
dependencies: [
|
|
424
|
+
.package(url: "https://example.com/ui-kit.git", branch: "main"),
|
|
425
|
+
]
|
|
426
|
+
)
|
|
427
|
+
`;
|
|
428
|
+
const safe = `
|
|
429
|
+
let package = Package(
|
|
430
|
+
dependencies: [
|
|
431
|
+
.package(url: "https://example.com/ui-kit.git", exact: "1.2.3"),
|
|
432
|
+
.package(url: "https://example.com/domain.git", from: "2.0.0"),
|
|
433
|
+
]
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
let sample = ".package(url: branch:)"
|
|
437
|
+
// .package(url: "https://example.com/debug.git", branch: "develop")
|
|
438
|
+
`;
|
|
439
|
+
|
|
440
|
+
assert.equal(hasSwiftPackageBranchDependencyUsage(source), true);
|
|
441
|
+
assert.deepEqual(collectSwiftPackageBranchDependencyLines(source), [4]);
|
|
442
|
+
assert.equal(hasSwiftPackageBranchDependencyUsage(safe), false);
|
|
443
|
+
assert.deepEqual(collectSwiftPackageBranchDependencyLines(safe), []);
|
|
444
|
+
});
|
|
445
|
+
|
|
387
446
|
test('hasSwiftNonLazyScrollForEachUsage detecta ScrollView con stack no lazy y preserva LazyVStack', () => {
|
|
388
447
|
const source = `
|
|
389
448
|
struct FeedView: View {
|
|
@@ -698,6 +698,31 @@ export const hasSwiftEmptyCatchUsage = (source: string): boolean => {
|
|
|
698
698
|
return /\bcatch(?:\s+(?:let|var)\s+[A-Za-z_][A-Za-z0-9_]*)?\s*\{\s*\}/.test(sanitized);
|
|
699
699
|
};
|
|
700
700
|
|
|
701
|
+
export const collectSwiftNSErrorThrowLines = (source: string): readonly number[] => {
|
|
702
|
+
return collectSwiftRegexLines(source, /\bthrow\s+NSError\s*\(/g);
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
export const hasSwiftNSErrorThrowUsage = (source: string): boolean => {
|
|
706
|
+
return collectSwiftNSErrorThrowLines(source).length > 0;
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
export const collectSwiftPackageBranchDependencyLines = (source: string): readonly number[] => {
|
|
710
|
+
const matches: number[] = [];
|
|
711
|
+
source.split(/\r?\n/).forEach((line, index) => {
|
|
712
|
+
const sanitized = line
|
|
713
|
+
.replace(/"(?:\\.|[^"\\])*"/g, '""')
|
|
714
|
+
.replace(/\/\/.*$/, '');
|
|
715
|
+
if (/\.\s*package\s*\([^)]*\bbranch\s*:/.test(sanitized)) {
|
|
716
|
+
matches.push(index + 1);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
return matches;
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
export const hasSwiftPackageBranchDependencyUsage = (source: string): boolean => {
|
|
723
|
+
return collectSwiftPackageBranchDependencyLines(source).length > 0;
|
|
724
|
+
};
|
|
725
|
+
|
|
701
726
|
export const hasSwiftOnAppearTaskUsage = (source: string): boolean => {
|
|
702
727
|
return collectSwiftOnAppearTaskLines(source).length > 0;
|
|
703
728
|
};
|