pumuki-ast-hooks 5.6.13 → 5.6.15
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/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 +48 -0
- package/scripts/hooks-system/infrastructure/ast/common/__tests__/ast-common.spec.js +133 -0
- package/scripts/hooks-system/infrastructure/ast/common/ast-common.js +66 -2
- package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki-ast-hooks",
|
|
3
|
-
"version": "5.6.
|
|
3
|
+
"version": "5.6.15",
|
|
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": {
|
|
@@ -9,3 +9,5 @@
|
|
|
9
9
|
{"timestamp":"2026-01-11T18:48:20.329Z","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":{}}
|
|
10
10
|
{"timestamp":"2026-01-11T18:54:50.282Z","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":{}}
|
|
11
11
|
{"timestamp":"2026-01-11T19:08:34.232Z","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":{}}
|
|
12
|
+
{"timestamp":"2026-01-11T20:43:24.310Z","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":{}}
|
|
13
|
+
{"timestamp":"2026-01-11T21:27:16.722Z","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":{}}
|
|
@@ -42,3 +42,11 @@
|
|
|
42
42
|
{"timestamp":"2026-01-11T19:08:34.083Z","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":{}}
|
|
43
43
|
{"timestamp":"2026-01-11T19:08:34.083Z","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":{}}
|
|
44
44
|
{"timestamp":"2026-01-11T19:08:34.083Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
45
|
+
{"timestamp":"2026-01-11T20:43:24.451Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
|
|
46
|
+
{"timestamp":"2026-01-11T20:43:24.460Z","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":{}}
|
|
47
|
+
{"timestamp":"2026-01-11T20:43:24.461Z","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":{}}
|
|
48
|
+
{"timestamp":"2026-01-11T20:43:24.461Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
49
|
+
{"timestamp":"2026-01-11T21:27:16.554Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
|
|
50
|
+
{"timestamp":"2026-01-11T21:27:16.569Z","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":{}}
|
|
51
|
+
{"timestamp":"2026-01-11T21:27:16.571Z","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":{}}
|
|
52
|
+
{"timestamp":"2026-01-11T21:27:16.572Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
|
|
@@ -506,3 +506,51 @@
|
|
|
506
506
|
{"timestamp":1768162663136,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
507
507
|
{"timestamp":1768162663136,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
508
508
|
{"timestamp":1768162663136,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
509
|
+
{"timestamp":1768164204308,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
510
|
+
{"timestamp":1768164204309,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
511
|
+
{"timestamp":1768164204309,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
512
|
+
{"timestamp":1768164204309,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
513
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
514
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
515
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
516
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
517
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
518
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
519
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
520
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
521
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
522
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
523
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
524
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
525
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
526
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
527
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
528
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
529
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
530
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
531
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
532
|
+
{"timestamp":1768164204310,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
533
|
+
{"timestamp":1768166836716,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
534
|
+
{"timestamp":1768166836720,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
535
|
+
{"timestamp":1768166836720,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
536
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
537
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
538
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
539
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
540
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
541
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
542
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
543
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
544
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
545
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
546
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
547
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
548
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
549
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
550
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
551
|
+
{"timestamp":1768166836721,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
552
|
+
{"timestamp":1768166836722,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
553
|
+
{"timestamp":1768166836722,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
554
|
+
{"timestamp":1768166836722,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
|
|
555
|
+
{"timestamp":1768166836722,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
|
|
556
|
+
{"timestamp":1768166836722,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
|
|
@@ -87,6 +87,139 @@ describe('AST Common Module', () => {
|
|
|
87
87
|
expect(findings.some(f => f.ruleId === 'common.testing.missing_makesut')).toBe(false);
|
|
88
88
|
expect(findings.some(f => f.ruleId === 'common.testing.missing_track_for_memory_leaks')).toBe(false);
|
|
89
89
|
});
|
|
90
|
+
|
|
91
|
+
it('does report missing_makesut/missing_track_for_memory_leaks for value type tests unless explicitly ignored (Ruralgo case)', () => {
|
|
92
|
+
const project = new Project({
|
|
93
|
+
useInMemoryFileSystem: true,
|
|
94
|
+
skipAddingFilesFromTsConfig: true,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const swiftPath = '/tmp/DomainAPIEndpointTests.spec.swift';
|
|
98
|
+
const simpleValueTypeTest = `import Domain
|
|
99
|
+
import XCTest
|
|
100
|
+
|
|
101
|
+
final class DomainAPIEndpointTests: XCTestCase {
|
|
102
|
+
func test_givenCustomInit_whenAccessingProperties_thenReturnsExpectedValues() {
|
|
103
|
+
let body = Data([0x01, 0x02])
|
|
104
|
+
let queryItems = [URLQueryItem(name: "page", value: "1")]
|
|
105
|
+
|
|
106
|
+
let endpointPatch = APIEndpoint(
|
|
107
|
+
path: "/any", method: .patch, body: body, queryItems: queryItems)
|
|
108
|
+
|
|
109
|
+
XCTAssertEqual(endpointPatch.path, "/any")
|
|
110
|
+
XCTAssertEqual(endpointPatch.method, .patch)
|
|
111
|
+
XCTAssertEqual(endpointPatch.body, body)
|
|
112
|
+
XCTAssertEqual(endpointPatch.queryItems, queryItems)
|
|
113
|
+
}
|
|
114
|
+
}`;
|
|
115
|
+
|
|
116
|
+
const sf = project.createSourceFile(swiftPath, simpleValueTypeTest);
|
|
117
|
+
jest.spyOn(fs, 'readFileSync').mockReturnValue(simpleValueTypeTest);
|
|
118
|
+
|
|
119
|
+
const findings = [];
|
|
120
|
+
runCommonIntelligence(project, findings);
|
|
121
|
+
|
|
122
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_makesut')).toBe(true);
|
|
123
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_track_for_memory_leaks')).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('does apply rules to complex tests with async/classes', () => {
|
|
127
|
+
const project = new Project({
|
|
128
|
+
useInMemoryFileSystem: true,
|
|
129
|
+
skipAddingFilesFromTsConfig: true,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const swiftPath = '/tmp/NetworkClientTests.spec.swift';
|
|
133
|
+
const complexTest = `import XCTest
|
|
134
|
+
|
|
135
|
+
final class NetworkClientTests: XCTestCase {
|
|
136
|
+
override func setUp() {
|
|
137
|
+
super.setUp()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
func test_load_deliversErrorOnClientError() async {
|
|
141
|
+
let client = HTTPClient()
|
|
142
|
+
let result = await client.load()
|
|
143
|
+
XCTAssertNotNil(result)
|
|
144
|
+
}
|
|
145
|
+
}`;
|
|
146
|
+
|
|
147
|
+
const sf = project.createSourceFile(swiftPath, complexTest);
|
|
148
|
+
jest.spyOn(fs, 'readFileSync').mockReturnValue(complexTest);
|
|
149
|
+
|
|
150
|
+
const findings = [];
|
|
151
|
+
runCommonIntelligence(project, findings);
|
|
152
|
+
|
|
153
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_makesut')).toBe(true);
|
|
154
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_track_for_memory_leaks')).toBe(true);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('respects ast-ignore comments', () => {
|
|
158
|
+
const project = new Project({
|
|
159
|
+
useInMemoryFileSystem: true,
|
|
160
|
+
skipAddingFilesFromTsConfig: true,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const swiftPath = '/tmp/SomeTests.spec.swift';
|
|
164
|
+
const testWithIgnore = `import XCTest
|
|
165
|
+
// ast-ignore: missing_makesut, missing_track_for_memory_leaks
|
|
166
|
+
|
|
167
|
+
final class SomeTests: XCTestCase {
|
|
168
|
+
override func setUp() {
|
|
169
|
+
super.setUp()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
func test_something() async {
|
|
173
|
+
let result = await someAsyncCall()
|
|
174
|
+
XCTAssertNotNil(result)
|
|
175
|
+
}
|
|
176
|
+
}`;
|
|
177
|
+
|
|
178
|
+
const sf = project.createSourceFile(swiftPath, testWithIgnore);
|
|
179
|
+
jest.spyOn(fs, 'readFileSync').mockReturnValue(testWithIgnore);
|
|
180
|
+
|
|
181
|
+
const findings = [];
|
|
182
|
+
runCommonIntelligence(project, findings);
|
|
183
|
+
|
|
184
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_makesut')).toBe(false);
|
|
185
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_track_for_memory_leaks')).toBe(false);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('allows explicit ignore for Ruralgo value type tests via ast-ignore comment', () => {
|
|
189
|
+
const project = new Project({
|
|
190
|
+
useInMemoryFileSystem: true,
|
|
191
|
+
skipAddingFilesFromTsConfig: true,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const swiftPath = '/tmp/DomainAPIEndpointTests.spec.swift';
|
|
195
|
+
const ignoredValueTypeTest = `import Domain
|
|
196
|
+
import XCTest
|
|
197
|
+
// ast-ignore: missing_makesut, missing_track_for_memory_leaks
|
|
198
|
+
|
|
199
|
+
final class DomainAPIEndpointTests: XCTestCase {
|
|
200
|
+
func test_givenCustomInit_whenAccessingProperties_thenReturnsExpectedValues() {
|
|
201
|
+
let body = Data([0x01, 0x02])
|
|
202
|
+
let queryItems = [URLQueryItem(name: "page", value: "1")]
|
|
203
|
+
|
|
204
|
+
let endpointPatch = APIEndpoint(
|
|
205
|
+
path: "/any", method: .patch, body: body, queryItems: queryItems)
|
|
206
|
+
|
|
207
|
+
XCTAssertEqual(endpointPatch.path, "/any")
|
|
208
|
+
XCTAssertEqual(endpointPatch.method, .patch)
|
|
209
|
+
XCTAssertEqual(endpointPatch.body, body)
|
|
210
|
+
XCTAssertEqual(endpointPatch.queryItems, queryItems)
|
|
211
|
+
}
|
|
212
|
+
}`;
|
|
213
|
+
|
|
214
|
+
const sf = project.createSourceFile(swiftPath, ignoredValueTypeTest);
|
|
215
|
+
jest.spyOn(fs, 'readFileSync').mockReturnValue(ignoredValueTypeTest);
|
|
216
|
+
|
|
217
|
+
const findings = [];
|
|
218
|
+
runCommonIntelligence(project, findings);
|
|
219
|
+
|
|
220
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_makesut')).toBe(false);
|
|
221
|
+
expect(findings.some(f => f.ruleId === 'common.testing.missing_track_for_memory_leaks')).toBe(false);
|
|
222
|
+
});
|
|
90
223
|
});
|
|
91
224
|
|
|
92
225
|
describe('exports', () => {
|
|
@@ -71,6 +71,66 @@ function hasTrackForMemoryLeaksEvidence(content) {
|
|
|
71
71
|
return hasTrackForMemoryLeaks(content) || hasMakeSUT(content);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Detect if a test file is a simple value type test that doesn't need makeSUT/trackForMemoryLeaks.
|
|
76
|
+
* Simple tests typically:
|
|
77
|
+
* - Have no async/await or closures capturing self
|
|
78
|
+
* - Have no class instantiation patterns (reference types)
|
|
79
|
+
* - Test only property access or simple assertions
|
|
80
|
+
* - Have no setUp/tearDown methods
|
|
81
|
+
*/
|
|
82
|
+
function isSimpleValueTypeTest(content) {
|
|
83
|
+
// If it has setUp/tearDown, it's not simple - needs proper patterns
|
|
84
|
+
if (/\boverride\s+func\s+(setUp|tearDown)/.test(content)) return false;
|
|
85
|
+
|
|
86
|
+
// If it has async/await, needs memory tracking
|
|
87
|
+
if (/\basync\b|\bawait\b|\bexpectation\(|\bwaitForExpectations\b/.test(content)) return false;
|
|
88
|
+
|
|
89
|
+
// If it has closures that might capture self, needs tracking
|
|
90
|
+
if (/\[\s*(weak|unowned)?\s*self\s*\]/.test(content)) return false;
|
|
91
|
+
|
|
92
|
+
// If it has completion handlers or callbacks, needs tracking
|
|
93
|
+
if (/completion\s*:|\@escaping|\bresult\s*in\b/i.test(content)) return false;
|
|
94
|
+
|
|
95
|
+
// If it creates classes (not structs), needs makeSUT pattern
|
|
96
|
+
// Look for "= ClassName(" but not "= StructName(" - heuristic: classes often have "Client", "Service", "Manager", "Repository"
|
|
97
|
+
if (/=\s*\w*(Client|Service|Manager|Repository|UseCase|Interactor|Presenter|ViewModel|Controller)\s*\(/.test(content)) return false;
|
|
98
|
+
|
|
99
|
+
// If it's a very short test (likely simple property test), skip rules
|
|
100
|
+
const lines = content.split('\n').filter(l => l.trim().length > 0);
|
|
101
|
+
if (lines.length <= 40) return true;
|
|
102
|
+
|
|
103
|
+
// If it only has XCTAssertEqual for properties, it's likely a simple value type test
|
|
104
|
+
const testMethods = content.match(/func\s+test_[^{]+\{[^}]+\}/gs) || [];
|
|
105
|
+
if (testMethods.length > 0) {
|
|
106
|
+
const allSimple = testMethods.every(method => {
|
|
107
|
+
// Simple test: mostly XCTAssert* calls, no complex setup
|
|
108
|
+
const hasOnlyAsserts = /XCTAssert(Equal|True|False|Nil|NotNil)/.test(method);
|
|
109
|
+
const hasNoComplexSetup = !/\bsut\b|makeSUT|\bawait\b|completion/.test(method);
|
|
110
|
+
return hasOnlyAsserts && hasNoComplexSetup;
|
|
111
|
+
});
|
|
112
|
+
if (allSimple && testMethods.length <= 3) return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Check for ast-ignore comments in content
|
|
120
|
+
* Supports: // ast-ignore: rule_name or // ast-ignore: rule1, rule2
|
|
121
|
+
*/
|
|
122
|
+
function hasAstIgnoreComment(content, ruleId) {
|
|
123
|
+
const ignorePattern = /\/\/\s*ast-ignore:\s*([^\n]+)/gi;
|
|
124
|
+
let match;
|
|
125
|
+
while ((match = ignorePattern.exec(content)) !== null) {
|
|
126
|
+
const rules = match[1].split(',').map(r => r.trim().toLowerCase());
|
|
127
|
+
if (rules.includes(ruleId.toLowerCase()) || rules.includes('all')) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
74
134
|
function detectMockSignals(content) {
|
|
75
135
|
const signals = [
|
|
76
136
|
/\bjest\.mock\s*\(/,
|
|
@@ -228,7 +288,9 @@ function runCommonIntelligence(project, findings) {
|
|
|
228
288
|
}
|
|
229
289
|
|
|
230
290
|
if (isSwiftOrKotlinTest) {
|
|
231
|
-
if (!shouldSkipMakeSUTRule(filePath) &&
|
|
291
|
+
if (!shouldSkipMakeSUTRule(filePath) &&
|
|
292
|
+
!hasMakeSUT(content) &&
|
|
293
|
+
!hasAstIgnoreComment(content, 'missing_makesut')) {
|
|
232
294
|
pushFinding(
|
|
233
295
|
'common.testing.missing_makesut',
|
|
234
296
|
'high',
|
|
@@ -239,7 +301,9 @@ function runCommonIntelligence(project, findings) {
|
|
|
239
301
|
);
|
|
240
302
|
}
|
|
241
303
|
|
|
242
|
-
if (!shouldSkipTrackForMemoryLeaksRule(filePath) &&
|
|
304
|
+
if (!shouldSkipTrackForMemoryLeaksRule(filePath) &&
|
|
305
|
+
!hasTrackForMemoryLeaksEvidence(content) &&
|
|
306
|
+
!hasAstIgnoreComment(content, 'missing_track_for_memory_leaks')) {
|
|
243
307
|
pushFinding(
|
|
244
308
|
'common.testing.missing_track_for_memory_leaks',
|
|
245
309
|
'critical',
|
package/scripts/hooks-system/infrastructure/watchdog/__tests__/.audit-reports/token-monitor.log
CHANGED
|
@@ -25,3 +25,9 @@
|
|
|
25
25
|
{"timestamp":"2026-01-11T19:08:37.452Z","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"}}
|
|
26
26
|
{"timestamp":"2026-01-11T19:08:37.467Z","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"}}
|
|
27
27
|
{"timestamp":"2026-01-11T19:08:37.468Z","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)"}}
|
|
28
|
+
{"timestamp":"2026-01-11T20:43:25.680Z","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"}}
|
|
29
|
+
{"timestamp":"2026-01-11T20:43:25.683Z","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"}}
|
|
30
|
+
{"timestamp":"2026-01-11T20:43:25.683Z","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)"}}
|
|
31
|
+
{"timestamp":"2026-01-11T21:27:20.297Z","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"}}
|
|
32
|
+
{"timestamp":"2026-01-11T21:27:20.301Z","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"}}
|
|
33
|
+
{"timestamp":"2026-01-11T21:27:20.301Z","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)"}}
|