pumuki-ast-hooks 5.3.30 → 5.4.0
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/docs/VIOLATIONS_RESOLUTION_PLAN.md +10 -10
- package/package.json +2 -2
- package/scripts/hooks-system/application/CompositionRoot.js +57 -282
- package/scripts/hooks-system/application/factories/AdapterFactory.js +58 -0
- package/scripts/hooks-system/application/factories/MonitorFactory.js +104 -0
- package/scripts/hooks-system/application/factories/ServiceFactory.js +153 -0
- package/scripts/hooks-system/application/services/RealtimeGuardService.js +49 -246
- package/scripts/hooks-system/application/services/guard/EvidenceManager.js +153 -0
- package/scripts/hooks-system/application/services/guard/GitTreeManager.js +129 -0
- package/scripts/hooks-system/application/services/guard/GuardNotifier.js +54 -0
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +3 -2
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +33 -29
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +80 -10
- package/scripts/hooks-system/infrastructure/ast/ios/ast-ios.js +45 -11
- package/scripts/hooks-system/infrastructure/ast/ios/native-bridge.js +39 -2
- package/scripts/hooks-system/.hook-system/config.json +0 -8
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const glob = require('glob');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
const env = require('../../config/env');
|
|
4
6
|
const { pushFinding, mapToLevel, SyntaxKind, isTestFile, platformOf, getRepoRoot } = require(path.join(__dirname, '../ast-core'));
|
|
5
7
|
const { iOSEnterpriseAnalyzer } = require(path.join(__dirname, 'analyzers/iOSEnterpriseAnalyzer'));
|
|
6
8
|
const { iOSArchitectureDetector } = require(path.join(__dirname, 'analyzers/iOSArchitectureDetector'));
|
|
@@ -27,14 +29,40 @@ async function runIOSIntelligence(project, findings, platform) {
|
|
|
27
29
|
console.error(`[iOS AST Intelligence] Running SourceKitten-based analysis...`);
|
|
28
30
|
const astAnalyzer = new iOSASTIntelligentAnalyzer(findings);
|
|
29
31
|
const root = getRepoRoot();
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const stagingOnly = env.get('STAGING_ONLY_MODE', '0') === '1';
|
|
33
|
+
let stagedRelSwift = [];
|
|
34
|
+
if (stagingOnly) {
|
|
35
|
+
try {
|
|
36
|
+
stagedRelSwift = execSync('git diff --cached --name-only --diff-filter=ACM', {
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
cwd: root,
|
|
39
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
40
|
+
})
|
|
41
|
+
.trim()
|
|
42
|
+
.split('\n')
|
|
43
|
+
.map(s => s.trim())
|
|
44
|
+
.filter(Boolean)
|
|
45
|
+
.filter(p => p.endsWith('.swift'));
|
|
46
|
+
} catch {
|
|
47
|
+
stagedRelSwift = [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const swiftFilesForAST = stagingOnly
|
|
52
|
+
? stagedRelSwift.map(rel => path.join(root, rel))
|
|
53
|
+
: glob.sync('**/*.swift', {
|
|
54
|
+
cwd: root,
|
|
55
|
+
ignore: ['**/node_modules/**', '**/build/**', '**/Pods/**', '**/.build/**', '**/CustomLintRules/**'],
|
|
56
|
+
absolute: true,
|
|
57
|
+
});
|
|
35
58
|
|
|
36
59
|
for (const swiftFile of swiftFilesForAST) {
|
|
37
|
-
|
|
60
|
+
const rel = stagingOnly ? path.relative(root, swiftFile).replace(/\\/g, '/') : null;
|
|
61
|
+
astAnalyzer.analyzeFile(swiftFile, {
|
|
62
|
+
repoRoot: root,
|
|
63
|
+
displayPath: swiftFile,
|
|
64
|
+
stagedRelPath: stagingOnly ? rel : null
|
|
65
|
+
});
|
|
38
66
|
}
|
|
39
67
|
|
|
40
68
|
astAnalyzer.finalizeGodClassDetection();
|
|
@@ -42,6 +70,10 @@ async function runIOSIntelligence(project, findings, platform) {
|
|
|
42
70
|
|
|
43
71
|
await runSwiftLintNative(findings);
|
|
44
72
|
|
|
73
|
+
if (stagingOnly) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
45
77
|
project.getSourceFiles().forEach((sf) => {
|
|
46
78
|
if (!sf || typeof sf.getFilePath !== 'function') return;
|
|
47
79
|
const filePath = sf.getFilePath();
|
|
@@ -87,11 +119,13 @@ async function runIOSIntelligence(project, findings, platform) {
|
|
|
87
119
|
|
|
88
120
|
try {
|
|
89
121
|
const root = getRepoRoot();
|
|
90
|
-
const swiftFiles =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
122
|
+
const swiftFiles = stagingOnly
|
|
123
|
+
? stagedRelSwift.map(rel => path.join(root, rel))
|
|
124
|
+
: glob.sync('**/*.swift', {
|
|
125
|
+
cwd: root,
|
|
126
|
+
ignore: ['**/node_modules/**', '**/build/**', '**/Pods/**', '**/.build/**'],
|
|
127
|
+
absolute: true,
|
|
128
|
+
});
|
|
95
129
|
|
|
96
130
|
if (swiftFiles.length > 0) {
|
|
97
131
|
console.error(`[iOS Enterprise] Analyzing ${swiftFiles.length} Swift files with SourceKitten...`);
|
|
@@ -2,12 +2,32 @@ const { execSync } = require('child_process');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const { pushFileFinding } = require('../ast-core');
|
|
5
|
+
const env = require('../../config/env');
|
|
6
|
+
|
|
7
|
+
function getStagedSwiftFiles(repoRoot) {
|
|
8
|
+
try {
|
|
9
|
+
return execSync('git diff --cached --name-only --diff-filter=ACM', {
|
|
10
|
+
encoding: 'utf8',
|
|
11
|
+
cwd: repoRoot,
|
|
12
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
13
|
+
})
|
|
14
|
+
.trim()
|
|
15
|
+
.split('\n')
|
|
16
|
+
.map(s => s.trim())
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.filter(p => p.endsWith('.swift'));
|
|
19
|
+
} catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
5
23
|
|
|
6
24
|
async function runSwiftLintNative(findings) {
|
|
7
25
|
try {
|
|
8
26
|
const { getRepoRoot } = require('../ast-core');
|
|
9
27
|
const projectRoot = getRepoRoot();
|
|
10
28
|
const customRulesPath = path.join(projectRoot, 'CustomLintRules');
|
|
29
|
+
const stagingOnly = env.get('STAGING_ONLY_MODE', '0') === '1';
|
|
30
|
+
const stagedSwiftRel = stagingOnly ? getStagedSwiftFiles(projectRoot) : null;
|
|
11
31
|
|
|
12
32
|
if (!fs.existsSync(customRulesPath)) {
|
|
13
33
|
console.log('[SwiftLint Native] CustomLintRules package not found - skipping');
|
|
@@ -35,7 +55,10 @@ async function runSwiftLintNative(findings) {
|
|
|
35
55
|
timeout: 60000
|
|
36
56
|
});
|
|
37
57
|
|
|
38
|
-
parseSwiftLintOutput(result, findings
|
|
58
|
+
parseSwiftLintOutput(result, findings, {
|
|
59
|
+
repoRoot: projectRoot,
|
|
60
|
+
stagedSwiftRel
|
|
61
|
+
});
|
|
39
62
|
|
|
40
63
|
console.log('[SwiftLint Native] ✅ Custom rules executed');
|
|
41
64
|
|
|
@@ -44,7 +67,13 @@ async function runSwiftLintNative(findings) {
|
|
|
44
67
|
}
|
|
45
68
|
}
|
|
46
69
|
|
|
47
|
-
function parseSwiftLintOutput(output, findings) {
|
|
70
|
+
function parseSwiftLintOutput(output, findings, options = {}) {
|
|
71
|
+
const { repoRoot, stagedSwiftRel } = options;
|
|
72
|
+
const stagingOnly = Array.isArray(stagedSwiftRel);
|
|
73
|
+
const stagedAbs = stagingOnly && repoRoot
|
|
74
|
+
? new Set(stagedSwiftRel.map(rel => path.join(repoRoot, rel)))
|
|
75
|
+
: null;
|
|
76
|
+
|
|
48
77
|
const lines = output.split('\n');
|
|
49
78
|
|
|
50
79
|
for (const line of lines) {
|
|
@@ -53,6 +82,14 @@ function parseSwiftLintOutput(output, findings) {
|
|
|
53
82
|
if (match) {
|
|
54
83
|
const [, filePath, lineNum, col, severity, message] = match;
|
|
55
84
|
|
|
85
|
+
if (stagingOnly && stagedAbs) {
|
|
86
|
+
const normalized = String(filePath || '');
|
|
87
|
+
const isStaged = stagedAbs.has(normalized) || Array.from(stagedAbs).some(p => normalized.endsWith(p));
|
|
88
|
+
if (!isStaged) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
56
93
|
const level = severity === 'error' ? 'high' : 'medium';
|
|
57
94
|
const ruleId = extractRuleId(message);
|
|
58
95
|
|