pumuki-ast-hooks 6.0.0 → 6.0.2
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/README.md +9 -9
- package/package.json +1 -1
- package/scripts/hooks-system/.audit-reports/auto-recovery.log +2 -0
- package/scripts/hooks-system/.audit-reports/install-wizard.log +8 -0
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +56 -0
- package/scripts/hooks-system/config/project.config.json +1 -1
- package/scripts/hooks-system/infrastructure/ast/common/__tests__/network-resilience-analyzer.spec.js +12 -0
- package/scripts/hooks-system/infrastructure/ast/common/network-resilience-analyzer.js +2 -1
- package/scripts/hooks-system/infrastructure/ast/ios/detectors/__tests__/ios-unused-imports.spec.js +14 -0
- package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-ast-intelligent-strategies.js +6 -1
- package/scripts/hooks-system/infrastructure/ast/text/__tests__/text-scanner.spec.js +49 -0
- package/scripts/hooks-system/infrastructure/ast/text/text-scanner.js +6 -2
- package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log +6 -0
package/README.md
CHANGED
|
@@ -27,19 +27,19 @@ npx ast-hooks
|
|
|
27
27
|
|
|
28
28
|
### Pre‑write enforcement (block before writing)
|
|
29
29
|
|
|
30
|
-

|
|
31
31
|
|
|
32
32
|
### AI Gate (blocked example)
|
|
33
33
|
|
|
34
|
-

|
|
35
35
|
|
|
36
36
|
### ai-start (bootstrap + evidence refresh)
|
|
37
37
|
|
|
38
|
-

|
|
39
39
|
|
|
40
40
|
### Pre-flight check (in-memory validation)
|
|
41
41
|
|
|
42
|
-

|
|
43
43
|
|
|
44
44
|
### Interactive menu (orchestrator overview)
|
|
45
45
|
|
|
@@ -58,15 +58,15 @@ Documentation:
|
|
|
58
58
|
|
|
59
59
|
## Visual Overview
|
|
60
60
|
|
|
61
|
-

|
|
62
62
|
|
|
63
|
-

|
|
64
64
|
|
|
65
|
-

|
|
66
66
|
|
|
67
|
-

|
|
68
68
|
|
|
69
|
-

|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki-ast-hooks",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
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": {
|
|
@@ -14,3 +14,5 @@
|
|
|
14
14
|
{"timestamp":"2026-01-11T21:44:57.015Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
15
15
|
{"timestamp":"2026-01-12T08:29:42.539Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
16
16
|
{"timestamp":"2026-01-12T08:44:03.829Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
17
|
+
{"timestamp":"2026-01-12T18:40:40.786Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
18
|
+
{"timestamp":"2026-01-12T19:29:17.037Z","level":"info","component":"AutoRecovery","event":"NotificationCenterService shutdown","data":{"totalEnqueued":0,"totalSent":0,"totalDeduplicated":0,"totalCooldownSkipped":0,"totalFailed":0,"totalRetries":0,"queueSize":0,"deduplication":{"size":0},"cooldowns":{"activeCooldowns":0}},"context":{}}
|
|
@@ -66,3 +66,11 @@
|
|
|
66
66
|
{"timestamp":"2026-01-12T08:44:03.895Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_CONFIG_EXISTS","data":{"configPath":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.hook-system/config.json"},"context":{}}
|
|
67
67
|
{"timestamp":"2026-01-12T08:44:03.895Z","level":"error","component":"InstallWizard","event":"INSTALL_WIZARD_SYMLINK_FAILED","data":{"error":"EEXIST: file already exists, symlink '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/scripts/hooks-system/bin/guard-supervisor.js' -> '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.git/hooks/guard-supervisor'"},"context":{}}
|
|
68
68
|
{"timestamp":"2026-01-12T08:44:03.895Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
69
|
+
{"timestamp":"2026-01-12T18:40:40.839Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
|
|
70
|
+
{"timestamp":"2026-01-12T18:40:40.845Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_CONFIG_EXISTS","data":{"configPath":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.hook-system/config.json"},"context":{}}
|
|
71
|
+
{"timestamp":"2026-01-12T18:40:40.846Z","level":"error","component":"InstallWizard","event":"INSTALL_WIZARD_SYMLINK_FAILED","data":{"error":"EEXIST: file already exists, symlink '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/scripts/hooks-system/bin/guard-supervisor.js' -> '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.git/hooks/guard-supervisor'"},"context":{}}
|
|
72
|
+
{"timestamp":"2026-01-12T18:40:40.846Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
73
|
+
{"timestamp":"2026-01-12T19:29:17.091Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
|
|
74
|
+
{"timestamp":"2026-01-12T19:29:17.097Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_CONFIG_EXISTS","data":{"configPath":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.hook-system/config.json"},"context":{}}
|
|
75
|
+
{"timestamp":"2026-01-12T19:29:17.098Z","level":"error","component":"InstallWizard","event":"INSTALL_WIZARD_SYMLINK_FAILED","data":{"error":"EEXIST: file already exists, symlink '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/scripts/hooks-system/bin/guard-supervisor.js' -> '/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system/.git/hooks/guard-supervisor'"},"context":{}}
|
|
76
|
+
{"timestamp":"2026-01-12T19:29:17.098Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
@@ -626,3 +626,59 @@
|
|
|
626
626
|
{"timestamp":1768207443829,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
627
627
|
{"timestamp":1768207443829,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
628
628
|
{"timestamp":1768207443829,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
629
|
+
{"timestamp":1768243240785,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
630
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
631
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
632
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
633
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
634
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
635
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
636
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
637
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
638
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
639
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
640
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
641
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
642
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
643
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
644
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
645
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
646
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
647
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
648
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
649
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
650
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
651
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
652
|
+
{"timestamp":1768243240786,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
653
|
+
{"timestamp":1768246157036,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
654
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
655
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
656
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
657
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
658
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
659
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
660
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
661
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
662
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
663
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
664
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
665
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
666
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
667
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
668
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
669
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
670
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
671
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
672
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
673
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
674
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
675
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
676
|
+
{"timestamp":1768246157037,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
677
|
+
{"timestamp":1768247437287,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
678
|
+
{"timestamp":1768247437287,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
679
|
+
{"timestamp":1768247437287,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
680
|
+
{"timestamp":1768247437287,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
681
|
+
{"timestamp":1768247690240,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
682
|
+
{"timestamp":1768247690240,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
683
|
+
{"timestamp":1768247690240,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
684
|
+
{"timestamp":1768247690241,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
package/scripts/hooks-system/infrastructure/ast/common/__tests__/network-resilience-analyzer.spec.js
CHANGED
|
@@ -176,5 +176,17 @@ describe('network-resilience-analyzer', () => {
|
|
|
176
176
|
|
|
177
177
|
expect(findings.filter(f => f.ruleId === 'common.network.missing_connection_pooling')).toHaveLength(0);
|
|
178
178
|
});
|
|
179
|
+
|
|
180
|
+
it('should ignore non-js sources', () => {
|
|
181
|
+
const project = createMockProject([{
|
|
182
|
+
path: '/app/services/KeychainHelper.swift',
|
|
183
|
+
content: 'struct KeychainHelper { }'
|
|
184
|
+
}]);
|
|
185
|
+
const findings = [];
|
|
186
|
+
|
|
187
|
+
analyzeNetworkResilience(project, findings);
|
|
188
|
+
|
|
189
|
+
expect(findings.filter(f => f.ruleId === 'common.network.missing_connection_pooling')).toHaveLength(0);
|
|
190
|
+
});
|
|
179
191
|
});
|
|
180
192
|
});
|
|
@@ -149,7 +149,8 @@ function checkConnectionPooling(sf, content, findings) {
|
|
|
149
149
|
const filePath = sf.getFilePath();
|
|
150
150
|
const isAnalyzer = /infrastructure\/ast\/|analyzers\/|detectors\/|scanner|analyzer|detector/i.test(filePath);
|
|
151
151
|
const isTestFile = /\.(spec|test)\.(js|ts)$/i.test(filePath);
|
|
152
|
-
|
|
152
|
+
const isSupportedSource = /\.(jsx?|tsx?)$/i.test(filePath);
|
|
153
|
+
if (isAnalyzer || isTestFile || !isSupportedSource) {
|
|
153
154
|
return;
|
|
154
155
|
}
|
|
155
156
|
|
package/scripts/hooks-system/infrastructure/ast/ios/detectors/__tests__/ios-unused-imports.spec.js
CHANGED
|
@@ -31,4 +31,18 @@ describe('ios.imports.unused', () => {
|
|
|
31
31
|
|
|
32
32
|
expect(analyzer.findings.find(f => f.ruleId === 'ios.imports.unused')).toBeUndefined();
|
|
33
33
|
});
|
|
34
|
+
|
|
35
|
+
it('does not report unused Foundation when Foundation types are used in file content', () => {
|
|
36
|
+
const filePath = '/tmp/Bar.swift';
|
|
37
|
+
const analyzer = makeAnalyzer({
|
|
38
|
+
fileContent: 'import Foundation\n\nstruct Bar { let createdAt: Date }',
|
|
39
|
+
allNodes: []
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
analyzer.imports = [{ name: 'Foundation', line: 1 }];
|
|
43
|
+
|
|
44
|
+
analyzeImportsAST(analyzer, filePath);
|
|
45
|
+
|
|
46
|
+
expect(analyzer.findings.find(f => f.ruleId === 'ios.imports.unused')).toBeUndefined();
|
|
47
|
+
});
|
|
34
48
|
});
|
package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-ast-intelligent-strategies.js
CHANGED
|
@@ -87,6 +87,7 @@ function analyzeImportsAST(analyzer, filePath) {
|
|
|
87
87
|
if (filePath.includes('Tests')) {
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
+
const content = analyzer.fileContent || '';
|
|
90
91
|
const importNames = analyzer.imports.map((i) => i.name);
|
|
91
92
|
|
|
92
93
|
const hasUIKit = importNames.includes('UIKit');
|
|
@@ -117,14 +118,18 @@ function analyzeImportsAST(analyzer, filePath) {
|
|
|
117
118
|
|
|
118
119
|
const unusedImportAllowlist = new Set(['Foundation', 'SwiftUI', 'UIKit', 'Combine']);
|
|
119
120
|
|
|
121
|
+
const foundationTypeUsage = /\b(Data|Date|URL|UUID|Decimal|NSNumber|NSDecimalNumber|NSSet|NSDictionary|NSArray|IndexPath|Notification|FileManager|Bundle|Locale|TimeZone|Calendar|DateComponents|URLRequest|URLSession)\b/;
|
|
120
122
|
for (const imp of analyzer.imports) {
|
|
121
123
|
if (!unusedImportAllowlist.has(imp.name)) continue;
|
|
122
124
|
|
|
123
|
-
|
|
125
|
+
let isUsed = analyzer.allNodes.some((n) => {
|
|
124
126
|
const typename = n['key.typename'] || '';
|
|
125
127
|
const name = n['key.name'] || '';
|
|
126
128
|
return typename.includes(imp.name) || name.includes(imp.name);
|
|
127
129
|
});
|
|
130
|
+
if (!isUsed && imp.name === 'Foundation') {
|
|
131
|
+
isUsed = foundationTypeUsage.test(content);
|
|
132
|
+
}
|
|
128
133
|
|
|
129
134
|
if (!isUsed) {
|
|
130
135
|
analyzer.pushFinding('ios.imports.unused', 'low', filePath, imp.line, `Unused import: ${imp.name}`);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const { runTextScanner } = require('../text-scanner');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const path = require('path');
|
|
2
5
|
|
|
3
6
|
describe('Text Scanner Module', () => {
|
|
4
7
|
describe('runTextScanner', () => {
|
|
@@ -17,4 +20,50 @@ describe('Text Scanner Module', () => {
|
|
|
17
20
|
expect(mod.runTextScanner).toBeDefined();
|
|
18
21
|
});
|
|
19
22
|
});
|
|
23
|
+
|
|
24
|
+
describe('ios rules', () => {
|
|
25
|
+
it('does not flag missing DI when Package.swift has empty dependencies', () => {
|
|
26
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ast-text-'));
|
|
27
|
+
const packagePath = path.join(root, 'Package.swift');
|
|
28
|
+
const content = [
|
|
29
|
+
'// swift-tools-version: 5.9',
|
|
30
|
+
'import PackageDescription',
|
|
31
|
+
'',
|
|
32
|
+
'let package = Package(',
|
|
33
|
+
' name: "Demo",',
|
|
34
|
+
' dependencies: [],',
|
|
35
|
+
' targets: [',
|
|
36
|
+
' .target(name: "Demo")',
|
|
37
|
+
' ]',
|
|
38
|
+
')'
|
|
39
|
+
].join('\n');
|
|
40
|
+
|
|
41
|
+
fs.writeFileSync(packagePath, content, 'utf8');
|
|
42
|
+
|
|
43
|
+
const findings = [];
|
|
44
|
+
runTextScanner(root, findings);
|
|
45
|
+
|
|
46
|
+
const diFinding = findings.find(f => f.ruleId === 'ios.spm.dependency_injection');
|
|
47
|
+
expect(diFinding).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('does not flag Any usage when Security context is present', () => {
|
|
51
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ast-text-'));
|
|
52
|
+
const filePath = path.join(root, 'KeychainHelper.swift');
|
|
53
|
+
const content = [
|
|
54
|
+
'import Security',
|
|
55
|
+
'struct KeychainHelper {',
|
|
56
|
+
' func baseQuery() -> [String: Any] { [:] }',
|
|
57
|
+
'}'
|
|
58
|
+
].join('\n');
|
|
59
|
+
|
|
60
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
61
|
+
|
|
62
|
+
const findings = [];
|
|
63
|
+
runTextScanner(root, findings);
|
|
64
|
+
|
|
65
|
+
const typeSafety = findings.find(f => f.ruleId === 'ios.optionals.type_safety');
|
|
66
|
+
expect(typeSafety).toBeUndefined();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
20
69
|
});
|
|
@@ -561,7 +561,8 @@ function runTextScanner(root, findings) {
|
|
|
561
561
|
if (targetCount < 2) {
|
|
562
562
|
pushFileFinding('ios.spm.modular_architecture', 'low', file, 1, 1, 'Package.swift without multiple targets (weak modular architecture)', findings);
|
|
563
563
|
}
|
|
564
|
-
|
|
564
|
+
const hasEmptyDependencies = /dependencies\s*:\s*\[\s*\]/.test(content);
|
|
565
|
+
if (!hasEmptyDependencies && !/Swinject|Needle|Resolver|Factory\b/.test(content)) {
|
|
565
566
|
pushFileFinding('ios.spm.dependency_injection', 'low', file, 1, 1, 'No DI library hint found in Package.swift', findings);
|
|
566
567
|
}
|
|
567
568
|
}
|
|
@@ -601,7 +602,10 @@ function runTextScanner(root, findings) {
|
|
|
601
602
|
pushFileFinding('ios.optionals.optional_binding', 'medium', file, 1, 1, 'Optional check != nil (prefer optional binding)', findings);
|
|
602
603
|
}
|
|
603
604
|
if (/:\s*Any\b|\bas\s*Any\b/.test(content)) {
|
|
604
|
-
|
|
605
|
+
const hasSecurityContext = /import\s+Security\b/.test(content) || /\bkSec[A-Za-z0-9_]+\b/.test(content);
|
|
606
|
+
if (!hasSecurityContext) {
|
|
607
|
+
pushFileFinding('ios.optionals.type_safety', 'medium', file, 1, 1, 'Usage of Any reduces type safety', findings);
|
|
608
|
+
}
|
|
605
609
|
}
|
|
606
610
|
if (/\.sink\s*\(/.test(content) && !/receiveCompletion\s*:\s*/.test(content)) {
|
|
607
611
|
pushFileFinding('ios.combine.error_handling', 'medium', file, 1, 1, 'Combine sink without receiveCompletion handler', findings);
|
package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log
CHANGED
|
@@ -43,3 +43,9 @@
|
|
|
43
43
|
{"timestamp":"2026-01-12T08:44:05.598Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
|
|
44
44
|
{"timestamp":"2026-01-12T08:44:05.599Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
|
|
45
45
|
{"timestamp":"2026-01-12T08:44:05.600Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
|
|
46
|
+
{"timestamp":"2026-01-12T18:40:42.667Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
|
|
47
|
+
{"timestamp":"2026-01-12T18:40:42.668Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
|
|
48
|
+
{"timestamp":"2026-01-12T18:40:42.669Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
|
|
49
|
+
{"timestamp":"2026-01-12T19:29:18.617Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":10,"tokensUsed":100000,"maxTokens":1000000,"source":"realtime","stale":false},"context":{"message":"Result level=ok percent=10% used=100000/1000000 source=realtime"}}
|
|
50
|
+
{"timestamp":"2026-01-12T19:29:18.618Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"warning","percentUsed":91,"tokensUsed":910000,"maxTokens":1000000,"source":"fallback","stale":false},"context":{"message":"Result level=warning percent=91% used=910000/1000000 source=fallback"}}
|
|
51
|
+
{"timestamp":"2026-01-12T19:29:18.618Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"critical","percentUsed":98,"tokensUsed":980000,"maxTokens":1000000,"source":"realtime","stale":true},"context":{"message":"Result level=critical percent=98% used=980000/1000000 source=realtime (stale)"}}
|