pumuki-ast-hooks 6.1.10 → 6.1.11

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 CHANGED
@@ -13,7 +13,7 @@ Portable, project‑agnostic, multi‑platform enterprise framework to govern AI
13
13
 
14
14
  ---
15
15
 
16
- ## Quick Start (30–60s)
16
+ ## Inicio rápido (30–60s)
17
17
 
18
18
  ```bash
19
19
  git init
@@ -22,9 +22,9 @@ npx ast-install
22
22
  npx ast-hooks audit
23
23
  ```
24
24
 
25
- Default installation mode is `npm-runtime`.
25
+ Modo de instalación por defecto: `npm-runtime`.
26
26
 
27
- To opt into an embedded runtime copy (`vendored` mode):
27
+ Para usar runtime embebido (modo `vendored`):
28
28
 
29
29
  ```bash
30
30
  HOOK_INSTALL_MODE=vendored npx ast-install
@@ -360,58 +360,61 @@ The Git Flow cycle includes branch validation, commits, push, PR, merge (by poli
360
360
 
361
361
  ---
362
362
 
363
- ## 9. Commands Section (MANDATORYDO NOT CHANGE)
363
+ ## 9. Sección de comandos (OBLIGATORIONO CAMBIAR)
364
364
 
365
- ### Install (dev)
365
+ ### Instalación (dev)
366
366
 
367
367
  ```bash
368
368
  npm install --save-dev pumuki-ast-hooks
369
+ npx ast-install
369
370
  ```
370
371
 
371
- ### Legacy install
372
+ ### Instalación (legacy)
372
373
 
373
374
  ```bash
374
375
  npm install --save-dev pumuki-ast-hooks
376
+ npx ast-install
375
377
  ```
376
378
 
377
- ### Update
379
+ ### Actualización
378
380
 
379
381
  ```bash
380
382
  npm install --save-dev pumuki-ast-hooks@latest
381
- npm run install-hooks
383
+ npx ast-install
382
384
  ```
383
385
 
384
- ### Uninstall
386
+ ### Desinstalación
385
387
 
386
388
  ```bash
389
+ npx ast-uninstall
387
390
  npm uninstall pumuki-ast-hooks
388
391
  ```
389
392
 
390
- ### Install hooks
393
+ ### Instalar hooks
391
394
 
392
395
  ```bash
393
396
  npm run install-hooks
394
397
  ```
395
398
 
396
- ### Run interactive menu
399
+ ### Menú interactivo
397
400
 
398
401
  ```bash
399
402
  npx ast-hooks
400
403
  ```
401
404
 
402
- ### Version check
405
+ ### Verificación de versión
403
406
 
404
407
  ```bash
405
408
  npm run ast:check-version
406
409
  ```
407
410
 
408
- ### Audit
411
+ ### Auditoría
409
412
 
410
413
  ```bash
411
414
  npm run audit
412
415
  ```
413
416
 
414
- ### Git flow
417
+ ### Git Flow
415
418
 
416
419
  ```bash
417
420
  npm run ast:gitflow
@@ -432,7 +435,7 @@ npm run ast:guard:status
432
435
  npm run ast:guard:logs
433
436
  ```
434
437
 
435
- ### Evidence refresh
438
+ ### Refresco de evidencia
436
439
 
437
440
  ```bash
438
441
  npm run ast:refresh
@@ -626,7 +626,7 @@ To update:
626
626
  npm install --save-dev pumuki-ast-hooks@latest
627
627
 
628
628
  2. Re-install hooks (to get latest features):
629
- npm run install-hooks
629
+ npx ast-install
630
630
 
631
631
  What's new in 5.3.1:
632
632
  Check CHANGELOG.md: https://github.com/...
@@ -651,7 +651,7 @@ npm install --save-dev pumuki-ast-hooks@5.3.1
651
651
  **⚠️ IMPORTANT:** After updating, you MUST re-run the installer to get the latest hooks and configurations:
652
652
 
653
653
  ```bash
654
- npm run install-hooks
654
+ npx ast-install
655
655
  ```
656
656
 
657
657
  This ensures:
@@ -745,6 +745,7 @@ npm view pumuki-ast-hooks version
745
745
 
746
746
  ```bash
747
747
  # Uninstall
748
+ npx ast-uninstall
748
749
  npm uninstall pumuki-ast-hooks
749
750
 
750
751
  # Remove hooks (optional)
@@ -0,0 +1,16 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ describe('pre-tool-use-evidence-validator', () => {
5
+ const filePath = path.join(__dirname, '..', 'pre-tool-use-evidence-validator.ts');
6
+
7
+ it('should exist', () => {
8
+ expect(fs.existsSync(filePath)).toBe(true);
9
+ });
10
+
11
+ it('should include auto-refresh execution of update-evidence', () => {
12
+ const content = fs.readFileSync(filePath, 'utf8');
13
+ expect(content).toMatch(/update-evidence\.sh/);
14
+ expect(content).toMatch(/--auto/);
15
+ });
16
+ });
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFileSync, existsSync } from 'fs';
3
3
  import { join } from 'path';
4
+ import { execSync } from 'child_process';
4
5
  import { sendMacOSNotification } from './notify-macos.js';
5
6
 
6
7
  interface ToolInput {
@@ -34,6 +35,8 @@ interface Violation {
34
35
 
35
36
  const MAX_AGE_SECONDS = 180;
36
37
 
38
+ type ValidationResult = { valid: boolean; code?: string; error?: string };
39
+
37
40
  function utcToEpoch(timestamp: string): number {
38
41
  try {
39
42
  return Math.floor(new Date(timestamp).getTime() / 1000);
@@ -42,10 +45,11 @@ function utcToEpoch(timestamp: string): number {
42
45
  }
43
46
  }
44
47
 
45
- function validateEvidence(evidencePath: string): { valid: boolean; error?: string } {
48
+ function validateEvidence(evidencePath: string): ValidationResult {
46
49
  if (!existsSync(evidencePath)) {
47
50
  return {
48
51
  valid: false,
52
+ code: 'missing',
49
53
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Missing
50
54
 
51
55
  📋 VIOLATION:
@@ -69,6 +73,7 @@ This is enforced by pre-commit hooks and PreToolUse validation`
69
73
  } catch {
70
74
  return {
71
75
  valid: false,
76
+ code: 'invalid_json',
72
77
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Invalid JSON
73
78
 
74
79
  📋 VIOLATION:
@@ -86,6 +91,7 @@ This is enforced by pre-commit hooks and PreToolUse validation`
86
91
  if (!timestamp || typeof timestamp !== 'string') {
87
92
  return {
88
93
  valid: false,
94
+ code: 'missing_timestamp',
89
95
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Missing Timestamp
90
96
 
91
97
  📋 VIOLATION:
@@ -102,6 +108,7 @@ This is enforced by pre-commit hooks and PreToolUse validation`
102
108
  if (evidenceEpoch === 0) {
103
109
  return {
104
110
  valid: false,
111
+ code: 'invalid_timestamp',
105
112
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Invalid Timestamp Format
106
113
 
107
114
  📋 VIOLATION:
@@ -119,6 +126,7 @@ This is enforced by pre-commit hooks and PreToolUse validation`
119
126
  if (ageSeconds > MAX_AGE_SECONDS) {
120
127
  return {
121
128
  valid: false,
129
+ code: 'stale',
122
130
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Too Old
123
131
 
124
132
  📋 VIOLATION:
@@ -139,6 +147,7 @@ Evidence must be fresh to ensure rules were read and questions answered`
139
147
  if (!rulesRead || (Array.isArray(rulesRead) && rulesRead.length === 0)) {
140
148
  return {
141
149
  valid: false,
150
+ code: 'missing_rules',
142
151
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Missing Rules Read
143
152
 
144
153
  📋 VIOLATION:
@@ -155,6 +164,7 @@ Evidence must be fresh to ensure rules were read and questions answered`
155
164
  if (questionsAnswered !== true) {
156
165
  return {
157
166
  valid: false,
167
+ code: 'questions_unanswered',
158
168
  error: `⚠️ BLOCKED - .AI_EVIDENCE.json Protocol Questions Not Answered
159
169
 
160
170
  📋 VIOLATION:
@@ -181,6 +191,7 @@ Evidence must be fresh to ensure rules were read and questions answered`
181
191
 
182
192
  return {
183
193
  valid: false,
194
+ code: 'gate_blocked',
184
195
  error: `🚫 BLOCKED - AI Gate Status: BLOCKED
185
196
 
186
197
  📋 VIOLATION:
@@ -205,6 +216,45 @@ This ensures code quality standards are maintained`
205
216
  return { valid: true };
206
217
  }
207
218
 
219
+ function resolveUpdateEvidenceScript(projectDir: string): string | null {
220
+ const candidates = [
221
+ join(projectDir, 'scripts', 'hooks-system', 'bin', 'update-evidence.sh'),
222
+ join(projectDir, 'node_modules', 'pumuki-ast-hooks', 'scripts', 'hooks-system', 'bin', 'update-evidence.sh'),
223
+ join(projectDir, 'node_modules', 'pumuki-ast-hooks', 'bin', 'update-evidence.sh'),
224
+ join(projectDir, 'bin', 'update-evidence.sh')
225
+ ];
226
+
227
+ for (const candidate of candidates) {
228
+ if (existsSync(candidate)) {
229
+ return candidate;
230
+ }
231
+ }
232
+
233
+ return null;
234
+ }
235
+
236
+ function autoRefreshEvidence(projectDir: string): boolean {
237
+ const flag = String(process.env.AI_START_AUTO_REFRESH || '').trim().toLowerCase();
238
+ if (flag === '0' || flag === 'false' || flag === 'no') {
239
+ return false;
240
+ }
241
+
242
+ const scriptPath = resolveUpdateEvidenceScript(projectDir);
243
+ if (!scriptPath) {
244
+ return false;
245
+ }
246
+
247
+ try {
248
+ execSync(`bash "${scriptPath}" --auto`, {
249
+ cwd: projectDir,
250
+ stdio: 'ignore'
251
+ });
252
+ return true;
253
+ } catch {
254
+ return false;
255
+ }
256
+ }
257
+
208
258
  async function readStdin(): Promise<string> {
209
259
  return new Promise((resolve) => {
210
260
  let data = '';
@@ -225,7 +275,12 @@ async function main() {
225
275
  const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
226
276
  const evidencePath = join(projectDir, '.AI_EVIDENCE.json');
227
277
 
228
- const validation = validateEvidence(evidencePath);
278
+ let validation = validateEvidence(evidencePath);
279
+ if (!validation.valid && validation.code !== 'gate_blocked') {
280
+ if (autoRefreshEvidence(projectDir)) {
281
+ validation = validateEvidence(evidencePath);
282
+ }
283
+ }
229
284
  if (!validation.valid) {
230
285
  try {
231
286
  sendMacOSNotification({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki-ast-hooks",
3
- "version": "6.1.10",
3
+ "version": "6.1.11",
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": {
@@ -136,4 +136,4 @@
136
136
  "./skills": "./skills/skill-rules.json",
137
137
  "./hooks": "./hooks/index.js"
138
138
  }
139
- }
139
+ }
@@ -41,3 +41,8 @@
41
41
  {"timestamp":"2026-01-15T07:49:00.777Z","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
42
  {"timestamp":"2026-01-15T09:57:40.478Z","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":{}}
43
43
  {"timestamp":"2026-01-15T14:53:23.342Z","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":{}}
44
+ {"timestamp":"2026-01-21T12:12:12.268Z","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":{}}
45
+ {"timestamp":"2026-01-21T13:01:11.530Z","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":{}}
46
+ {"timestamp":"2026-01-21T13:16:57.700Z","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":{}}
47
+ {"timestamp":"2026-01-21T14:08:08.597Z","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":{}}
48
+ {"timestamp":"2026-01-21T14:14:43.580Z","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":{}}
@@ -174,3 +174,23 @@
174
174
  {"timestamp":"2026-01-15T14:53:23.414Z","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":{}}
175
175
  {"timestamp":"2026-01-15T14:53:23.415Z","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":{}}
176
176
  {"timestamp":"2026-01-15T14:53:23.415Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
177
+ {"timestamp":"2026-01-21T12:12:11.691Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
178
+ {"timestamp":"2026-01-21T12:12:11.709Z","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":{}}
179
+ {"timestamp":"2026-01-21T12:12:11.710Z","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":{}}
180
+ {"timestamp":"2026-01-21T12:12:11.710Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
181
+ {"timestamp":"2026-01-21T13:01:11.637Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
182
+ {"timestamp":"2026-01-21T13:01:11.652Z","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":{}}
183
+ {"timestamp":"2026-01-21T13:01:11.652Z","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":{}}
184
+ {"timestamp":"2026-01-21T13:01:11.653Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
185
+ {"timestamp":"2026-01-21T13:16:58.626Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
186
+ {"timestamp":"2026-01-21T13:16:58.641Z","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":{}}
187
+ {"timestamp":"2026-01-21T13:16:58.642Z","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":{}}
188
+ {"timestamp":"2026-01-21T13:16:58.642Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
189
+ {"timestamp":"2026-01-21T14:08:09.347Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
190
+ {"timestamp":"2026-01-21T14:08:09.372Z","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":{}}
191
+ {"timestamp":"2026-01-21T14:08:09.374Z","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":{}}
192
+ {"timestamp":"2026-01-21T14:08:09.374Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
193
+ {"timestamp":"2026-01-21T14:14:44.270Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
194
+ {"timestamp":"2026-01-21T14:14:44.277Z","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":{}}
195
+ {"timestamp":"2026-01-21T14:14:44.277Z","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":{}}
196
+ {"timestamp":"2026-01-21T14:14:44.277Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
@@ -1298,3 +1298,155 @@
1298
1298
  {"timestamp":1768488803342,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1299
1299
  {"timestamp":1768488803342,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1300
1300
  {"timestamp":1768488803342,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1301
+ {"timestamp":1768996398842,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1302
+ {"timestamp":1768996398842,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1303
+ {"timestamp":1768996398842,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1304
+ {"timestamp":1768996398842,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1305
+ {"timestamp":1768997532262,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1306
+ {"timestamp":1768997532263,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1307
+ {"timestamp":1768997532264,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1308
+ {"timestamp":1768997532264,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1309
+ {"timestamp":1768997532264,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1310
+ {"timestamp":1768997532264,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1311
+ {"timestamp":1768997532264,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1312
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1313
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1314
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1315
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1316
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1317
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1318
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1319
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1320
+ {"timestamp":1768997532265,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1321
+ {"timestamp":1768997532266,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1322
+ {"timestamp":1768997532266,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1323
+ {"timestamp":1768997532266,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1324
+ {"timestamp":1768997532266,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1325
+ {"timestamp":1768997532266,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1326
+ {"timestamp":1768997532266,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1327
+ {"timestamp":1768997532267,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1328
+ {"timestamp":1768997532267,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1329
+ {"timestamp":1768997567514,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1330
+ {"timestamp":1768997567515,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1331
+ {"timestamp":1768997567515,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1332
+ {"timestamp":1768997567515,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1333
+ {"timestamp":1769000347952,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1334
+ {"timestamp":1769000347953,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1335
+ {"timestamp":1769000347953,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1336
+ {"timestamp":1769000347953,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1337
+ {"timestamp":1769000471526,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1338
+ {"timestamp":1769000471527,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1339
+ {"timestamp":1769000471527,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1340
+ {"timestamp":1769000471527,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1341
+ {"timestamp":1769000471527,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1342
+ {"timestamp":1769000471528,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1343
+ {"timestamp":1769000471528,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1344
+ {"timestamp":1769000471528,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1345
+ {"timestamp":1769000471528,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1346
+ {"timestamp":1769000471528,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1347
+ {"timestamp":1769000471528,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1348
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1349
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1350
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1351
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1352
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1353
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1354
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1355
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1356
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1357
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1358
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1359
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1360
+ {"timestamp":1769000471529,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1361
+ {"timestamp":1769000515929,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1362
+ {"timestamp":1769000515929,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1363
+ {"timestamp":1769000515929,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1364
+ {"timestamp":1769000515929,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1365
+ {"timestamp":1769001417697,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1366
+ {"timestamp":1769001417698,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1367
+ {"timestamp":1769001417698,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1368
+ {"timestamp":1769001417698,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1369
+ {"timestamp":1769001417698,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1370
+ {"timestamp":1769001417698,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1371
+ {"timestamp":1769001417698,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1372
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1373
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1374
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1375
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1376
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1377
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1378
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1379
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1380
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1381
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1382
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1383
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1384
+ {"timestamp":1769001417699,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1385
+ {"timestamp":1769001417700,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1386
+ {"timestamp":1769001417700,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1387
+ {"timestamp":1769001417700,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1388
+ {"timestamp":1769001417700,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1389
+ {"timestamp":1769001466654,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1390
+ {"timestamp":1769001466654,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1391
+ {"timestamp":1769001466654,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1392
+ {"timestamp":1769001466654,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1393
+ {"timestamp":1769002218266,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1394
+ {"timestamp":1769002218266,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1395
+ {"timestamp":1769002218266,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1396
+ {"timestamp":1769002218266,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1397
+ {"timestamp":1769002828740,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1398
+ {"timestamp":1769002828740,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1399
+ {"timestamp":1769002828740,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1400
+ {"timestamp":1769002828740,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1401
+ {"timestamp":1769004488587,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1402
+ {"timestamp":1769004488588,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1403
+ {"timestamp":1769004488588,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1404
+ {"timestamp":1769004488588,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1405
+ {"timestamp":1769004488588,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1406
+ {"timestamp":1769004488588,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1407
+ {"timestamp":1769004488589,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1408
+ {"timestamp":1769004488589,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1409
+ {"timestamp":1769004488589,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1410
+ {"timestamp":1769004488589,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1411
+ {"timestamp":1769004488589,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1412
+ {"timestamp":1769004488592,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1413
+ {"timestamp":1769004488592,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1414
+ {"timestamp":1769004488595,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1415
+ {"timestamp":1769004488595,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1416
+ {"timestamp":1769004488595,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1417
+ {"timestamp":1769004488595,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1418
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1419
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1420
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1421
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1422
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1423
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1424
+ {"timestamp":1769004488596,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1425
+ {"timestamp":1769004883578,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1426
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1427
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1428
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1429
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1430
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1431
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1432
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1433
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1434
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1435
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1436
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1437
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1438
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1439
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1440
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1441
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1442
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1443
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1444
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1445
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1446
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1447
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1448
+ {"timestamp":1769004883579,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1449
+ {"timestamp":1769004905775,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1450
+ {"timestamp":1769004905775,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1451
+ {"timestamp":1769004905775,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1452
+ {"timestamp":1769004905775,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
@@ -65,5 +65,65 @@ describe('Text Scanner Module', () => {
65
65
  const typeSafety = findings.find(f => f.ruleId === 'ios.optionals.type_safety');
66
66
  expect(typeSafety).toBeUndefined();
67
67
  });
68
+
69
+ it('flags switch-based message provider mapping to string literals', () => {
70
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ast-text-'));
71
+ const filePath = path.join(root, 'SupportMessageProvider.swift');
72
+ const content = [
73
+ 'enum SupportStatus {',
74
+ ' case active',
75
+ ' case inactive',
76
+ '}',
77
+ '',
78
+ 'struct SupportMessageProvider {',
79
+ ' func message(for status: SupportStatus) -> String {',
80
+ ' switch status {',
81
+ ' case .active:',
82
+ ' return "support.active"',
83
+ ' case .inactive:',
84
+ ' return "support.inactive"',
85
+ ' }',
86
+ ' }',
87
+ '}'
88
+ ].join('\n');
89
+
90
+ fs.writeFileSync(filePath, content, 'utf8');
91
+
92
+ const findings = [];
93
+ runTextScanner(root, findings);
94
+
95
+ const ocpFinding = findings.find(f => f.ruleId === 'ios.solid.ocp_switch_to_string');
96
+ expect(ocpFinding).toBeDefined();
97
+ });
98
+ });
99
+
100
+ describe('android rules', () => {
101
+ it('flags when-based message provider mapping to string literals', () => {
102
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ast-text-'));
103
+ const filePath = path.join(root, 'SupportMessageProvider.kt');
104
+ const content = [
105
+ 'enum class SupportStatus {',
106
+ ' ACTIVE,',
107
+ ' INACTIVE',
108
+ '}',
109
+ '',
110
+ 'class SupportMessageProvider {',
111
+ ' fun message(status: SupportStatus): String {',
112
+ ' return when (status) {',
113
+ ' SupportStatus.ACTIVE -> "support.active"',
114
+ ' SupportStatus.INACTIVE -> "support.inactive"',
115
+ ' }',
116
+ ' }',
117
+ '}'
118
+ ].join('\n');
119
+
120
+ fs.writeFileSync(filePath, content, 'utf8');
121
+
122
+ const findings = [];
123
+ runTextScanner(root, findings);
124
+
125
+ const ocpFinding = findings.find(f => f.ruleId === 'android.solid.ocp_switch_to_string');
126
+ expect(ocpFinding).toBeDefined();
127
+ });
68
128
  });
69
129
  });
@@ -15,6 +15,58 @@ function walk(dir, acc) {
15
15
  }
16
16
  }
17
17
 
18
+ function hasProviderNameHint(content, filePath) {
19
+ const providerNamePattern = /\b(class|struct|object)\s+[A-Za-z_][A-Za-z0-9_]*(Message|Notice|Localization|Provider|Presenter|Mapper)[A-Za-z0-9_]*\b/i;
20
+ if (providerNamePattern.test(content)) return true;
21
+ const baseName = path.basename(filePath, path.extname(filePath));
22
+ return /Message|Notice|Localization|Provider|Presenter|Mapper/i.test(baseName);
23
+ }
24
+
25
+ function hasSwiftMappingHint(content) {
26
+ return /\brawValue\b/.test(content) || /\bDictionary<[^>]*String\b/.test(content) || /\[[A-Za-z_][A-Za-z0-9_]*\s*:\s*String\]/.test(content);
27
+ }
28
+
29
+ function hasKotlinMappingHint(content) {
30
+ return /\bmapOf\s*\(|\bmutableMapOf\s*\(|\bMap<[^>]*String\b/.test(content);
31
+ }
32
+
33
+ function hasSwiftSwitchToString(content) {
34
+ const switchPattern = /switch\s+[A-Za-z_][A-Za-z0-9_]*\s*\{[^}]*\}/g;
35
+ let match;
36
+ while ((match = switchPattern.exec(content)) !== null) {
37
+ const block = match[0];
38
+ if (!/\bcase\b/.test(block)) continue;
39
+ if (!/\"[^\"]+\"/.test(block)) continue;
40
+ if (!/case\s+(\.|[A-Za-z_][A-Za-z0-9_]*\.)[A-Za-z_][A-Za-z0-9_]*\s*:/.test(block)) continue;
41
+ if (/\breturn\b/.test(block) || /case\s+[^\n:]+:\s*\"[^\"]+\"/.test(block)) return true;
42
+ }
43
+ return false;
44
+ }
45
+
46
+ function hasKotlinWhenToString(content) {
47
+ const whenPattern = /when\s*\([^)]*\)\s*\{[^}]*\}/g;
48
+ let match;
49
+ while ((match = whenPattern.exec(content)) !== null) {
50
+ const block = match[0];
51
+ if (!/[A-Za-z_][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*\s*->\s*\"[^\"]+\"/.test(block)) continue;
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+
57
+ function shouldFlagMessageProviderSwitch(content, filePath, language) {
58
+ if (!hasProviderNameHint(content, filePath)) return false;
59
+ if (language === 'swift') {
60
+ if (hasSwiftMappingHint(content)) return false;
61
+ return hasSwiftSwitchToString(content);
62
+ }
63
+ if (language === 'kotlin') {
64
+ if (hasKotlinMappingHint(content)) return false;
65
+ return hasKotlinWhenToString(content);
66
+ }
67
+ return false;
68
+ }
69
+
18
70
  function runTextScanner(root, findings) {
19
71
  const files = [];
20
72
  let iosAnchorFile = null;
@@ -541,6 +593,11 @@ function runTextScanner(root, findings) {
541
593
  if (/Handler\(\)\.post/.test(content) && !/@SuppressLint\("HandlerLeak"\)/.test(content)) {
542
594
  pushFileFinding('android.antipattern.handler_leak', 'high', file, 1, 1, 'Handler without weak reference - potential memory leak', findings);
543
595
  }
596
+ const isAnalyzer = /infrastructure\/ast\/|analyzers\/|detectors\/|scanner|analyzer|detector/i.test(file);
597
+ const isTestFile = /\.(spec|test)\.(js|ts|kt|kts)$/i.test(file);
598
+ if ((ext === '.kt' || ext === '.kts') && !isAnalyzer && !isTestFile && shouldFlagMessageProviderSwitch(content, file, 'kotlin')) {
599
+ pushFileFinding('android.solid.ocp_switch_to_string', 'medium', file, 1, 1, 'OCP warning: switch-to-string mapping in message/localization provider - prefer injected map or enum raw values', findings);
600
+ }
544
601
  }
545
602
 
546
603
  if (plat === 'ios') {
@@ -636,6 +693,9 @@ function runTextScanner(root, findings) {
636
693
  if (/Text\(\s*\"[^\"]+\"\s*\)/.test(content) && !/NSLocalizedString|\.localized/.test(content)) {
637
694
  pushFileFinding('ios.i18n.hardcoded_strings', 'medium', file, 1, 1, 'Hardcoded string in Text() without localization', findings);
638
695
  }
696
+ if (!isAnalyzer && !isTestFile && shouldFlagMessageProviderSwitch(content, file, 'swift')) {
697
+ pushFileFinding('ios.solid.ocp_switch_to_string', 'medium', file, 1, 1, 'OCP warning: switch-to-string mapping in message/localization provider - prefer RawRepresentable or injected map', findings);
698
+ }
639
699
  if (/Date\(/.test(content) && !/DateFormatter/.test(content)) {
640
700
  pushFileFinding('ios.i18n.missing_date_formatter', 'medium', file, 1, 1, 'Date rendered without DateFormatter', findings);
641
701
  }
@@ -129,6 +129,46 @@ describe('intelligent-audit', () => {
129
129
  expect(updated.timestamp).toBeDefined();
130
130
  expect(updated.timestamp).not.toBe(previous.timestamp);
131
131
  });
132
+
133
+ it('should include medium and low violations in ai_gate output when critical or high exist', async () => {
134
+ const evidencePath = path.join(process.cwd(), '.AI_EVIDENCE.json');
135
+ const original = fs.existsSync(evidencePath) ? fs.readFileSync(evidencePath, 'utf8') : null;
136
+ const minimal = {
137
+ timestamp: new Date().toISOString(),
138
+ severity_metrics: {
139
+ last_updated: new Date().toISOString(),
140
+ total_violations: 0,
141
+ by_severity: { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 }
142
+ },
143
+ ai_gate: { status: 'ALLOWED', scope: 'staging', last_check: new Date().toISOString(), violations: [], instruction: 'x', mandatory: true }
144
+ };
145
+
146
+ try {
147
+ fs.writeFileSync(evidencePath, JSON.stringify(minimal, null, 2));
148
+
149
+ const mod = require('../intelligent-audit');
150
+ const violations = [
151
+ { severity: 'CRITICAL', ruleId: 'rule.critical', filePath: 'apps/a.ts', line: 1, message: 'c' },
152
+ { severity: 'HIGH', ruleId: 'rule.high', filePath: 'apps/b.ts', line: 2, message: 'h' },
153
+ { severity: 'MEDIUM', ruleId: 'rule.medium', filePath: 'apps/c.ts', line: 3, message: 'm' },
154
+ { severity: 'LOW', ruleId: 'rule.low', filePath: 'apps/d.ts', line: 4, message: 'l' }
155
+ ];
156
+
157
+ await mod.updateAIEvidence(violations, { passed: false, blockedBy: 'critical' }, { estimated: 1, percentUsed: 0, remaining: 1 });
158
+
159
+ const updated = JSON.parse(fs.readFileSync(evidencePath, 'utf8'));
160
+ const severities = updated.ai_gate.violations.map(v => v.severity);
161
+ expect(severities).toEqual(expect.arrayContaining(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']));
162
+ } finally {
163
+ if (original === null) {
164
+ if (fs.existsSync(evidencePath)) {
165
+ fs.unlinkSync(evidencePath);
166
+ }
167
+ } else {
168
+ fs.writeFileSync(evidencePath, original);
169
+ }
170
+ }
171
+ });
132
172
  });
133
173
 
134
174
  describe('AI_EVIDENCE.json structure validation', () => {
@@ -736,11 +736,10 @@ async function updateAIEvidence(violations, gateResult, tokenUsage) {
736
736
  const mediumViolations = violations.filter(v => v.severity === 'MEDIUM');
737
737
  const lowViolations = violations.filter(v => v.severity === 'LOW');
738
738
 
739
- let gateViolations = [...criticalViolations, ...highViolations];
740
- if (gateViolations.length === 0) {
741
- gateViolations = [...mediumViolations, ...lowViolations];
742
- }
743
- const blockingViolations = gateViolations.slice(0, 50);
739
+ const maxGateViolations = env.getNumber('AI_GATE_MAX_VIOLATIONS', 200);
740
+ const gateViolationsLimit = Number.isFinite(maxGateViolations) && maxGateViolations > 0 ? maxGateViolations : 200;
741
+ const gateViolations = [...criticalViolations, ...highViolations, ...mediumViolations, ...lowViolations];
742
+ const blockingViolations = gateViolations.slice(0, gateViolationsLimit);
744
743
 
745
744
  const gateScope = String(env.get('AI_GATE_SCOPE', 'staging') || 'staging').trim().toLowerCase();
746
745
 
@@ -0,0 +1,17 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ describe('gitflow-enforcer', () => {
5
+ const scriptPath = path.join(__dirname, '..', 'gitflow-enforcer.sh');
6
+
7
+ test('debe ignorar xcuserdata en atomicidad', () => {
8
+ const script = fs.readFileSync(scriptPath, 'utf8');
9
+ expect(script).toMatch(/xcuserdata/);
10
+ });
11
+
12
+ test('debe omitir lint:hooks si no esta configurado', () => {
13
+ const script = fs.readFileSync(scriptPath, 'utf8');
14
+ expect(script).toMatch(/lint:hooks/);
15
+ expect(script).toMatch(/no configurado/);
16
+ });
17
+ });
@@ -93,11 +93,24 @@ refresh_evidence() {
93
93
  printf "${GREEN}✅ Evidencia renovada (${reason}).${NC}\n"
94
94
  }
95
95
 
96
+ has_lint_hooks_script() {
97
+ local pkg="$1"
98
+ if [[ ! -f "$pkg" ]]; then
99
+ return 1
100
+ fi
101
+ if node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));process.exit(p&&p.scripts&&p.scripts['lint:hooks']?0:1);" "$pkg" >/dev/null 2>&1; then
102
+ return 0
103
+ fi
104
+ return 1
105
+ }
106
+
96
107
  lint_hooks_system() {
97
108
  local repo_pkg="${REPO_ROOT}/package.json"
98
109
  local hooks_pkg="${REPO_ROOT}/scripts/hooks-system/package.json"
110
+ local ran=0
99
111
 
100
- if [[ -f "${repo_pkg}" ]]; then
112
+ if has_lint_hooks_script "${repo_pkg}"; then
113
+ ran=1
101
114
  printf "${CYAN}🔎 Ejecutando lint (repo root)...${NC}\n"
102
115
  if npm --prefix "${REPO_ROOT}" run lint:hooks; then
103
116
  printf "${GREEN}✅ Lint hooks-system OK.${NC}\n"
@@ -105,7 +118,8 @@ lint_hooks_system() {
105
118
  fi
106
119
  fi
107
120
 
108
- if [[ -f "${hooks_pkg}" ]]; then
121
+ if has_lint_hooks_script "${hooks_pkg}"; then
122
+ ran=1
109
123
  printf "${CYAN}🔎 Ejecutando lint (scripts/hooks-system)...${NC}\n"
110
124
  if npm --prefix "${REPO_ROOT}/scripts/hooks-system" run lint:hooks; then
111
125
  printf "${GREEN}✅ Lint hooks-system OK.${NC}\n"
@@ -113,6 +127,11 @@ lint_hooks_system() {
113
127
  fi
114
128
  fi
115
129
 
130
+ if [[ "$ran" -eq 0 ]]; then
131
+ printf "${YELLOW}ℹ️ lint:hooks no configurado; se omite.${NC}\n"
132
+ return 0
133
+ fi
134
+
116
135
  printf "${RED}❌ Lint hooks-system falló.${NC}\n"
117
136
  return 1
118
137
  }
@@ -178,12 +197,17 @@ verify_atomic_commit() {
178
197
  local roots_list=""
179
198
  local root_count=0
180
199
  for file in "${files[@]}"; do
200
+ case "$file" in
201
+ */xcuserdata/*|*/xcuserdatad/*)
202
+ continue
203
+ ;;
204
+ esac
181
205
  local root="${file%%/*}"
182
206
  if [[ "$root" == "$file" ]]; then
183
207
  root="(root)"
184
208
  fi
185
209
  case "$root" in
186
- .AI_EVIDENCE.json|README.md|CHANGELOG.md|docs )
210
+ .AI_EVIDENCE.json|README.md|CHANGELOG.md|docs|.audit_tmp|.audit-reports|.cursor|.windsurf|xcuserdata|xcuserdatad )
187
211
  continue
188
212
  ;;
189
213
  "" )
@@ -127,3 +127,18 @@
127
127
  {"timestamp":"2026-01-15T14:53:25.770Z","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"}}
128
128
  {"timestamp":"2026-01-15T14:53:25.772Z","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"}}
129
129
  {"timestamp":"2026-01-15T14:53:25.772Z","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)"}}
130
+ {"timestamp":"2026-01-21T12:12:08.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"}}
131
+ {"timestamp":"2026-01-21T12:12:08.681Z","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"}}
132
+ {"timestamp":"2026-01-21T12:12:08.681Z","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)"}}
133
+ {"timestamp":"2026-01-21T13:01:16.348Z","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"}}
134
+ {"timestamp":"2026-01-21T13:01:16.349Z","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"}}
135
+ {"timestamp":"2026-01-21T13:01:16.350Z","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)"}}
136
+ {"timestamp":"2026-01-21T13:17:08.086Z","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"}}
137
+ {"timestamp":"2026-01-21T13:17:08.088Z","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"}}
138
+ {"timestamp":"2026-01-21T13:17:08.089Z","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)"}}
139
+ {"timestamp":"2026-01-21T14:08:15.939Z","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"}}
140
+ {"timestamp":"2026-01-21T14:08:15.943Z","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"}}
141
+ {"timestamp":"2026-01-21T14:08:15.945Z","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)"}}
142
+ {"timestamp":"2026-01-21T14:14:45.047Z","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"}}
143
+ {"timestamp":"2026-01-21T14:14:45.048Z","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"}}
144
+ {"timestamp":"2026-01-21T14:14:45.048Z","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)"}}