pumuki 6.3.162 → 6.3.164
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 +7 -0
- package/VERSION +1 -1
- package/core/facts/detectors/text/ios.test.ts +56 -0
- package/core/facts/detectors/text/ios.ts +28 -0
- package/integrations/config/coreSkillsLock.ts +11 -1
- package/integrations/config/skillsRuleSet.ts +0 -1
- package/integrations/git/runPlatformGate.ts +10 -0
- package/integrations/mcp/evidenceStdioServer.cli.ts +11 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [6.3.164] - 2026-05-06
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **PUMUKI-INC-130 XCTest helpers brownfield:** `trackForMemoryLeaks`/factory helpers that import `XCTest` but do not define `XCTestCase` suites or `test...` methods no longer trigger `skills.ios.critical-test-quality`.
|
|
14
|
+
- **Skills runtime enforcement:** declarative skill registry rules stay visible in coverage metadata without being counted as missing runtime AST detectors; AUTO rules without detector mapping still fail closed.
|
|
15
|
+
|
|
9
16
|
## [6.3.143] - 2026-05-05
|
|
10
17
|
|
|
11
18
|
### Fixed
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v6.3.
|
|
1
|
+
v6.3.164
|
|
@@ -669,6 +669,62 @@ final class LoginModelTests: XCTestCase {
|
|
|
669
669
|
assert.equal(hasSwiftModernizableXCTestSuiteUsage(missingQualityContract), false);
|
|
670
670
|
});
|
|
671
671
|
|
|
672
|
+
test('detectores Swift Testing excluyen helpers y factories XCTest brownfield sin XCTestCase', () => {
|
|
673
|
+
const helperSource = `
|
|
674
|
+
import XCTest
|
|
675
|
+
|
|
676
|
+
final class AuthTestFactories {
|
|
677
|
+
static func makeToken() -> String {
|
|
678
|
+
"token"
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
func trackForMemoryLeaks(_ instance: AnyObject, file: StaticString = #filePath, line: UInt = #line) {
|
|
683
|
+
addTeardownBlock { _ = instance }
|
|
684
|
+
}
|
|
685
|
+
`;
|
|
686
|
+
const ruralGoHelperSource = `
|
|
687
|
+
import XCTest
|
|
688
|
+
|
|
689
|
+
final class WeakReference<T: AnyObject> {
|
|
690
|
+
weak var value: T?
|
|
691
|
+
|
|
692
|
+
init(_ value: T) {
|
|
693
|
+
self.value = value
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
func trackForMemoryLeaks(
|
|
698
|
+
_ instance: AnyObject,
|
|
699
|
+
testCase: XCTestCase,
|
|
700
|
+
file: StaticString = #filePath,
|
|
701
|
+
line: UInt = #line
|
|
702
|
+
) {
|
|
703
|
+
nonisolated(unsafe) let reference = makeSUT(instance)
|
|
704
|
+
testCase.addTeardownBlock {
|
|
705
|
+
XCTAssertNil(
|
|
706
|
+
reference.value,
|
|
707
|
+
"Instance should have been deallocated. Potential memory leak.",
|
|
708
|
+
file: file,
|
|
709
|
+
line: line
|
|
710
|
+
)
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
private func makeSUT<T: AnyObject>(_ instance: T) -> WeakReference<T> {
|
|
715
|
+
WeakReference(instance)
|
|
716
|
+
}
|
|
717
|
+
`;
|
|
718
|
+
|
|
719
|
+
assert.equal(hasSwiftLegacyXCTestImportUsage(helperSource), false);
|
|
720
|
+
assert.equal(hasSwiftModernizableXCTestSuiteUsage(helperSource), false);
|
|
721
|
+
assert.equal(hasSwiftXCTestAssertionUsage(helperSource), false);
|
|
722
|
+
assert.equal(hasSwiftLegacyXCTestImportUsage(ruralGoHelperSource), false);
|
|
723
|
+
assert.equal(hasSwiftModernizableXCTestSuiteUsage(ruralGoHelperSource), false);
|
|
724
|
+
assert.equal(hasSwiftXCTestAssertionUsage(ruralGoHelperSource), false);
|
|
725
|
+
assert.equal(hasSwiftXCTUnwrapUsage(ruralGoHelperSource), false);
|
|
726
|
+
});
|
|
727
|
+
|
|
672
728
|
test('hasSwiftXCTUnwrapUsage detecta XCTUnwrap real y evita strings', () => {
|
|
673
729
|
const source = `
|
|
674
730
|
let value = try XCTUnwrap(optionalValue)
|
|
@@ -840,11 +840,23 @@ const hasSwiftXCTestOnlyBrownfieldSuiteUsage = (source: string): boolean => {
|
|
|
840
840
|
return !hasSwiftTestingImportUsage(source) && !hasSwiftTestingSuiteAttributeUsage(source);
|
|
841
841
|
};
|
|
842
842
|
|
|
843
|
+
const hasSwiftXCTestHelperOrFactoryUsage = (source: string): boolean => {
|
|
844
|
+
return (
|
|
845
|
+
hasSwiftXCTestImportUsage(source) &&
|
|
846
|
+
!hasSwiftXCTestCaseSubclassUsage(source) &&
|
|
847
|
+
!hasSwiftLegacyXCTestMethodUsage(source)
|
|
848
|
+
);
|
|
849
|
+
};
|
|
850
|
+
|
|
843
851
|
export const hasSwiftLegacyXCTestImportUsage = (source: string): boolean => {
|
|
844
852
|
if (!hasSwiftXCTestImportUsage(source)) {
|
|
845
853
|
return false;
|
|
846
854
|
}
|
|
847
855
|
|
|
856
|
+
if (!hasSwiftXCTestCaseSubclassUsage(source) || !hasSwiftLegacyXCTestMethodUsage(source)) {
|
|
857
|
+
return false;
|
|
858
|
+
}
|
|
859
|
+
|
|
848
860
|
if (hasSwiftLegacyXCTestUiOrPerformanceUsage(source)) {
|
|
849
861
|
return false;
|
|
850
862
|
}
|
|
@@ -881,6 +893,10 @@ export const hasSwiftXCTestAssertionUsage = (source: string): boolean => {
|
|
|
881
893
|
return false;
|
|
882
894
|
}
|
|
883
895
|
|
|
896
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
899
|
+
|
|
884
900
|
if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
|
|
885
901
|
return false;
|
|
886
902
|
}
|
|
@@ -896,6 +912,10 @@ export const hasSwiftXCTUnwrapUsage = (source: string): boolean => {
|
|
|
896
912
|
return false;
|
|
897
913
|
}
|
|
898
914
|
|
|
915
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
916
|
+
return false;
|
|
917
|
+
}
|
|
918
|
+
|
|
899
919
|
if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
|
|
900
920
|
return false;
|
|
901
921
|
}
|
|
@@ -912,6 +932,10 @@ const hasSwiftConfirmationUsage = (source: string): boolean => {
|
|
|
912
932
|
};
|
|
913
933
|
|
|
914
934
|
export const hasSwiftWaitForExpectationsUsage = (source: string): boolean => {
|
|
935
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
936
|
+
return false;
|
|
937
|
+
}
|
|
938
|
+
|
|
915
939
|
const legacyWaitPattern = /\bwait\s*\(\s*for\s*:|\bwaitForExpectations\s*\(/;
|
|
916
940
|
return collectSwiftFunctionDeclarations(source).some((declaration) => {
|
|
917
941
|
if (!/\basync\b/.test(declaration.signature)) {
|
|
@@ -923,6 +947,10 @@ export const hasSwiftWaitForExpectationsUsage = (source: string): boolean => {
|
|
|
923
947
|
};
|
|
924
948
|
|
|
925
949
|
export const hasSwiftLegacyExpectationDescriptionUsage = (source: string): boolean => {
|
|
950
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
|
|
926
954
|
return collectSwiftFunctionDeclarations(source).some((declaration) => {
|
|
927
955
|
if (!/\basync\b/.test(declaration.signature)) {
|
|
928
956
|
return false;
|
|
@@ -8,6 +8,15 @@ const PACKAGE_ROOT = resolve(__dirname, '..', '..');
|
|
|
8
8
|
|
|
9
9
|
let cachedCoreSkillsLock: SkillsLockV1 | undefined;
|
|
10
10
|
|
|
11
|
+
const writeDebugFallback = (error: unknown): void => {
|
|
12
|
+
if (process.env.PUMUKI_DEBUG !== '1') {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17
|
+
process.stderr.write(`[pumuki][skills-lock] compile fallback: ${message}\n`);
|
|
18
|
+
};
|
|
19
|
+
|
|
11
20
|
export const resolveCoreSkillsLockForPackageRoot = (
|
|
12
21
|
packageRoot: string
|
|
13
22
|
): SkillsLockV1 | undefined => {
|
|
@@ -20,7 +29,8 @@ export const resolveCoreSkillsLockForPackageRoot = (
|
|
|
20
29
|
if (compiledLock.bundles.length > 0) {
|
|
21
30
|
return compiledLock;
|
|
22
31
|
}
|
|
23
|
-
} catch {
|
|
32
|
+
} catch (error) {
|
|
33
|
+
writeDebugFallback(error);
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
return loadSkillsLock(packageRoot);
|
|
@@ -655,6 +655,13 @@ const isXCTestSource = (content: string): boolean => {
|
|
|
655
655
|
return /\bimport\s+XCTest\b/.test(content) || /\bXCTestCase\b/.test(content);
|
|
656
656
|
};
|
|
657
657
|
|
|
658
|
+
const isXCTestSuiteSource = (content: string): boolean => {
|
|
659
|
+
return (
|
|
660
|
+
/\bclass\s+[A-Za-z_][A-Za-z0-9_]*\s*:\s*XCTestCase\b/.test(content) &&
|
|
661
|
+
/^\s*(?:override\s+)?func\s+test[A-Za-z0-9_]*\s*\(/m.test(content)
|
|
662
|
+
);
|
|
663
|
+
};
|
|
664
|
+
|
|
658
665
|
const isXCTestUiOrPerformanceCompatibilitySource = (content: string): boolean => {
|
|
659
666
|
return /\bXCUIApplication\b|\bXCTMetric\b|\bmeasure\s*(?:\(|\{)/.test(content);
|
|
660
667
|
};
|
|
@@ -678,6 +685,9 @@ const toIosTestsQualityBlockingFinding = (params: {
|
|
|
678
685
|
if (!isXCTestSource(testFile.content)) {
|
|
679
686
|
continue;
|
|
680
687
|
}
|
|
688
|
+
if (!isXCTestSuiteSource(testFile.content)) {
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
681
691
|
if (isXCTestUiOrPerformanceCompatibilitySource(testFile.content)) {
|
|
682
692
|
continue;
|
|
683
693
|
}
|
|
@@ -91,6 +91,15 @@ const fetchJson = async (url: string): Promise<unknown> => {
|
|
|
91
91
|
return JSON.parse(text) as unknown;
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
+
const writeDebugHealthProbeFailure = (error: unknown): void => {
|
|
95
|
+
if (process.env.PUMUKI_DEBUG !== '1') {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
+
process.stderr.write(`[pumuki-mcp-evidence-stdio] health probe fallback: ${message}\n`);
|
|
101
|
+
};
|
|
102
|
+
|
|
94
103
|
const startOrReuseEvidenceHttp = async (): Promise<{
|
|
95
104
|
host: string;
|
|
96
105
|
port: number;
|
|
@@ -108,8 +117,8 @@ const startOrReuseEvidenceHttp = async (): Promise<{
|
|
|
108
117
|
if (health.status === 'ok') {
|
|
109
118
|
return { host, port: requestedPort, route };
|
|
110
119
|
}
|
|
111
|
-
} catch {
|
|
112
|
-
|
|
120
|
+
} catch (error) {
|
|
121
|
+
writeDebugHealthProbeFailure(error);
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
const portInUse = await isPortInUse(host, requestedPort);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.164",
|
|
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": {
|