pumuki 6.3.163 → 6.3.165
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 +13 -0
- package/VERSION +1 -1
- package/core/facts/detectors/text/ios.test.ts +36 -0
- package/core/facts/detectors/text/ios.ts +24 -0
- package/integrations/config/coreSkillsLock.ts +11 -1
- package/integrations/config/skillsRuleSet.ts +0 -1
- package/integrations/mcp/evidenceStdioServer.cli.ts +19 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [6.3.165] - 2026-05-06
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **MCP evidence stdio PRE_PUSH:** los defaults de host, ruta, puerto y timeout quedan nombrados como constantes para cumplir reglas backend de configuración y evitar bloqueos del hook al publicar ramas de release.
|
|
14
|
+
|
|
15
|
+
## [6.3.164] - 2026-05-06
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **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`.
|
|
20
|
+
- **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.
|
|
21
|
+
|
|
9
22
|
## [6.3.143] - 2026-05-05
|
|
10
23
|
|
|
11
24
|
### Fixed
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v6.3.
|
|
1
|
+
v6.3.165
|
|
@@ -683,10 +683,46 @@ func trackForMemoryLeaks(_ instance: AnyObject, file: StaticString = #filePath,
|
|
|
683
683
|
addTeardownBlock { _ = instance }
|
|
684
684
|
}
|
|
685
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
|
+
`;
|
|
686
718
|
|
|
687
719
|
assert.equal(hasSwiftLegacyXCTestImportUsage(helperSource), false);
|
|
688
720
|
assert.equal(hasSwiftModernizableXCTestSuiteUsage(helperSource), false);
|
|
689
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);
|
|
690
726
|
});
|
|
691
727
|
|
|
692
728
|
test('hasSwiftXCTUnwrapUsage detecta XCTUnwrap real y evita strings', () => {
|
|
@@ -840,6 +840,14 @@ 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;
|
|
@@ -885,6 +893,10 @@ export const hasSwiftXCTestAssertionUsage = (source: string): boolean => {
|
|
|
885
893
|
return false;
|
|
886
894
|
}
|
|
887
895
|
|
|
896
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
899
|
+
|
|
888
900
|
if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
|
|
889
901
|
return false;
|
|
890
902
|
}
|
|
@@ -900,6 +912,10 @@ export const hasSwiftXCTUnwrapUsage = (source: string): boolean => {
|
|
|
900
912
|
return false;
|
|
901
913
|
}
|
|
902
914
|
|
|
915
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
916
|
+
return false;
|
|
917
|
+
}
|
|
918
|
+
|
|
903
919
|
if (hasSwiftXCTestOnlyBrownfieldSuiteUsage(source)) {
|
|
904
920
|
return false;
|
|
905
921
|
}
|
|
@@ -916,6 +932,10 @@ const hasSwiftConfirmationUsage = (source: string): boolean => {
|
|
|
916
932
|
};
|
|
917
933
|
|
|
918
934
|
export const hasSwiftWaitForExpectationsUsage = (source: string): boolean => {
|
|
935
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
936
|
+
return false;
|
|
937
|
+
}
|
|
938
|
+
|
|
919
939
|
const legacyWaitPattern = /\bwait\s*\(\s*for\s*:|\bwaitForExpectations\s*\(/;
|
|
920
940
|
return collectSwiftFunctionDeclarations(source).some((declaration) => {
|
|
921
941
|
if (!/\basync\b/.test(declaration.signature)) {
|
|
@@ -927,6 +947,10 @@ export const hasSwiftWaitForExpectationsUsage = (source: string): boolean => {
|
|
|
927
947
|
};
|
|
928
948
|
|
|
929
949
|
export const hasSwiftLegacyExpectationDescriptionUsage = (source: string): boolean => {
|
|
950
|
+
if (hasSwiftXCTestHelperOrFactoryUsage(source)) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
|
|
930
954
|
return collectSwiftFunctionDeclarations(source).some((declaration) => {
|
|
931
955
|
if (!/\basync\b/.test(declaration.signature)) {
|
|
932
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);
|
|
@@ -21,6 +21,10 @@ type JsonRpcResponse = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
24
|
+
const DEFAULT_EVIDENCE_HOST = '127.0.0.1';
|
|
25
|
+
const DEFAULT_EVIDENCE_ROUTE = '/ai-evidence';
|
|
26
|
+
const DEFAULT_EVIDENCE_PORT = 7341;
|
|
27
|
+
const PORT_PROBE_TIMEOUT_MS = 600;
|
|
24
28
|
|
|
25
29
|
const toJsonRpcId = (value: unknown): JsonRpcId => {
|
|
26
30
|
if (typeof value === 'string' || typeof value === 'number' || value === null) {
|
|
@@ -55,7 +59,7 @@ const sendError = (id: JsonRpcId, code: number, message: string): void => {
|
|
|
55
59
|
const isPortInUse = async (host: string, port: number): Promise<boolean> =>
|
|
56
60
|
await new Promise((resolve) => {
|
|
57
61
|
const socket = new Socket();
|
|
58
|
-
socket.setTimeout(
|
|
62
|
+
socket.setTimeout(PORT_PROBE_TIMEOUT_MS);
|
|
59
63
|
socket.once('connect', () => {
|
|
60
64
|
socket.destroy();
|
|
61
65
|
resolve(true);
|
|
@@ -91,15 +95,24 @@ const fetchJson = async (url: string): Promise<unknown> => {
|
|
|
91
95
|
return JSON.parse(text) as unknown;
|
|
92
96
|
};
|
|
93
97
|
|
|
98
|
+
const writeDebugHealthProbeFailure = (error: unknown): void => {
|
|
99
|
+
if (process.env.PUMUKI_DEBUG !== '1') {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
104
|
+
process.stderr.write(`[pumuki-mcp-evidence-stdio] health probe fallback: ${message}\n`);
|
|
105
|
+
};
|
|
106
|
+
|
|
94
107
|
const startOrReuseEvidenceHttp = async (): Promise<{
|
|
95
108
|
host: string;
|
|
96
109
|
port: number;
|
|
97
110
|
route: string;
|
|
98
111
|
}> => {
|
|
99
|
-
const host = process.env.PUMUKI_EVIDENCE_HOST ??
|
|
100
|
-
const route = process.env.PUMUKI_EVIDENCE_ROUTE ??
|
|
112
|
+
const host = process.env.PUMUKI_EVIDENCE_HOST ?? DEFAULT_EVIDENCE_HOST;
|
|
113
|
+
const route = process.env.PUMUKI_EVIDENCE_ROUTE ?? DEFAULT_EVIDENCE_ROUTE;
|
|
101
114
|
const parsedPort = Number.parseInt(process.env.PUMUKI_EVIDENCE_PORT ?? '', 10);
|
|
102
|
-
const preferredPort = Number.isFinite(parsedPort) ? parsedPort :
|
|
115
|
+
const preferredPort = Number.isFinite(parsedPort) ? parsedPort : DEFAULT_EVIDENCE_PORT;
|
|
103
116
|
const requestedPort = preferredPort > 0 ? preferredPort : await findEphemeralPort(host);
|
|
104
117
|
const healthUrl = `http://${host}:${requestedPort}/health`;
|
|
105
118
|
|
|
@@ -108,8 +121,8 @@ const startOrReuseEvidenceHttp = async (): Promise<{
|
|
|
108
121
|
if (health.status === 'ok') {
|
|
109
122
|
return { host, port: requestedPort, route };
|
|
110
123
|
}
|
|
111
|
-
} catch {
|
|
112
|
-
|
|
124
|
+
} catch (error) {
|
|
125
|
+
writeDebugHealthProbeFailure(error);
|
|
113
126
|
}
|
|
114
127
|
|
|
115
128
|
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.165",
|
|
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": {
|