pumuki-ast-hooks 6.3.2 → 6.3.3

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
@@ -11,6 +11,8 @@ Portable, project‑agnostic, multi‑platform enterprise framework to govern AI
11
11
  ![platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Backend%20%7C%20Frontend-blue)
12
12
  ![license](https://img.shields.io/badge/license-MIT-black)
13
13
 
14
+ Latest release: 6.3.3 (2026-01-28)
15
+
14
16
  ---
15
17
 
16
18
  ## Quick start (30–60s)
@@ -1,3 +1,23 @@
1
+ # Release Notes - v6.3.3
2
+
3
+ **Release Date**: January 28, 2026
4
+ **Type**: Patch Release
5
+ **Compatibility**: Fully backward compatible with 6.3.x
6
+
7
+ ---
8
+
9
+ ## ✅ Fixes
10
+
11
+ - **iOS false positives**: `ios.weak_self` ahora detecta capture lists con `weak/unowned self`.
12
+ - **Task cancellation**: `ios.concurrency.task_cancellation` reconoce `Task.isCancelled` y `Task.checkCancellation` (incl. `try?`).
13
+ - **BDD triad**: `workflow.triad.tests_without_implementation` respeta la cabecera `Implementation:` en `.feature`.
14
+ - **Gate evidence**: `ai_gate` no bloquea por violaciones solo MEDIUM/LOW en la evidencia.
15
+ - **Protocol Q2**: la respuesta incluye referencia a commits recientes.
16
+ - **Backend config**: `backend.config.missing_validation` se aplica solo a apps backend reales.
17
+ - **WorkflowRules**: `AUDIT_LIBRARY_SELF` se valida con `env.getBool`.
18
+
19
+ ---
20
+
1
21
  # Release Notes - v6.0.16
2
22
 
3
23
  **Release Date**: January 13, 2026
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki-ast-hooks",
3
- "version": "6.3.2",
3
+ "version": "6.3.3",
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": {
@@ -62,3 +62,8 @@
62
62
  {"timestamp":"2026-01-26T16:02:19.123Z","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":{}}
63
63
  {"timestamp":"2026-01-26T16:20:32.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":{}}
64
64
  {"timestamp":"2026-01-26T19:01:57.880Z","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":{}}
65
+ {"timestamp":"2026-01-28T18:12:43.061Z","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
+ {"timestamp":"2026-01-28T18:37:05.469Z","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":{}}
67
+ {"timestamp":"2026-01-28T18:48:21.937Z","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":{}}
68
+ {"timestamp":"2026-01-28T18:51:11.719Z","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":{}}
69
+ {"timestamp":"2026-01-28T18:59:57.949Z","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":{}}
@@ -258,3 +258,23 @@
258
258
  {"timestamp":"2026-01-26T19:01:57.651Z","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":{}}
259
259
  {"timestamp":"2026-01-26T19:01:57.651Z","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":{}}
260
260
  {"timestamp":"2026-01-26T19:01:57.651Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
261
+ {"timestamp":"2026-01-28T18:12:42.463Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
262
+ {"timestamp":"2026-01-28T18:12:42.468Z","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":{}}
263
+ {"timestamp":"2026-01-28T18:12:42.468Z","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":{}}
264
+ {"timestamp":"2026-01-28T18:12:42.468Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
265
+ {"timestamp":"2026-01-28T18:37:05.512Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
266
+ {"timestamp":"2026-01-28T18:37:05.516Z","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":{}}
267
+ {"timestamp":"2026-01-28T18:37:05.517Z","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":{}}
268
+ {"timestamp":"2026-01-28T18:37:05.517Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
269
+ {"timestamp":"2026-01-28T18:48:22.127Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
270
+ {"timestamp":"2026-01-28T18:48:22.132Z","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":{}}
271
+ {"timestamp":"2026-01-28T18:48:22.132Z","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":{}}
272
+ {"timestamp":"2026-01-28T18:48:22.132Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
273
+ {"timestamp":"2026-01-28T18:51:11.902Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
274
+ {"timestamp":"2026-01-28T18:51:11.906Z","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":{}}
275
+ {"timestamp":"2026-01-28T18:51:11.907Z","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":{}}
276
+ {"timestamp":"2026-01-28T18:51:11.907Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
277
+ {"timestamp":"2026-01-28T18:59:57.992Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_START","data":{"repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"},"context":{}}
278
+ {"timestamp":"2026-01-28T18:59:57.996Z","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":{}}
279
+ {"timestamp":"2026-01-28T18:59:57.996Z","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":{}}
280
+ {"timestamp":"2026-01-28T18:59:57.996Z","level":"info","component":"InstallWizard","event":"INSTALL_WIZARD_COMPLETED","data":{},"context":{}}
@@ -1922,3 +1922,135 @@
1922
1922
  {"timestamp":1769454140085,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1923
1923
  {"timestamp":1769454140085,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1924
1924
  {"timestamp":1769454140085,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1925
+ {"timestamp":1769622061973,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1926
+ {"timestamp":1769622061974,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1927
+ {"timestamp":1769622061974,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1928
+ {"timestamp":1769622061974,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1929
+ {"timestamp":1769623963059,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1930
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1931
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1932
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1933
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1934
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1935
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1936
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1937
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1938
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1939
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1940
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1941
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1942
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1943
+ {"timestamp":1769623963060,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1944
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1945
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1946
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1947
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1948
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1949
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1950
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1951
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1952
+ {"timestamp":1769623963061,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1953
+ {"timestamp":1769625425468,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1954
+ {"timestamp":1769625425468,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1955
+ {"timestamp":1769625425468,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1956
+ {"timestamp":1769625425468,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1957
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1958
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1959
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1960
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1961
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1962
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1963
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1964
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1965
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1966
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1967
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1968
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1969
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1970
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1971
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1972
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1973
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1974
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1975
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1976
+ {"timestamp":1769625425469,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1977
+ {"timestamp":1769625560836,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1978
+ {"timestamp":1769625560836,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1979
+ {"timestamp":1769625560836,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1980
+ {"timestamp":1769625560836,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1981
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1982
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1983
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1984
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1985
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1986
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1987
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1988
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1989
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1990
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1991
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1992
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1993
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1994
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1995
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
1996
+ {"timestamp":1769626101936,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1997
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
1998
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
1999
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2000
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2001
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2002
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2003
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2004
+ {"timestamp":1769626101937,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2005
+ {"timestamp":1769626271718,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2006
+ {"timestamp":1769626271718,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2007
+ {"timestamp":1769626271718,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2008
+ {"timestamp":1769626271718,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2009
+ {"timestamp":1769626271718,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2010
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2011
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2012
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2013
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2014
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2015
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2016
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2017
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2018
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2019
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2020
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2021
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2022
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2023
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2024
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2025
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2026
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2027
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2028
+ {"timestamp":1769626271719,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2029
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2030
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2031
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2032
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2033
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2034
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2035
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2036
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2037
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2038
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2039
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2040
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2041
+ {"timestamp":1769626797948,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2042
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2043
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2044
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2045
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2046
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2047
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2048
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2049
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2050
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2051
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2052
+ {"timestamp":1769626797949,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2053
+ {"timestamp":1769627021261,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
2054
+ {"timestamp":1769627021261,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
2055
+ {"timestamp":1769627021261,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
2056
+ {"timestamp":1769627021261,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
@@ -1,12 +1,3 @@
1
- jest.mock('../../infrastructure/adapters/MacOSNotificationAdapter');
2
- jest.mock('../../infrastructure/adapters/FileEvidenceAdapter');
3
- jest.mock('../../infrastructure/adapters/GitQueryAdapter');
4
- jest.mock('../../infrastructure/adapters/GitCommandAdapter');
5
- jest.mock('../../infrastructure/adapters/GitHubCliAdapter');
6
- jest.mock('../../infrastructure/adapters/AstAnalyzerAdapter');
7
- jest.mock('../services/AutonomousOrchestrator');
8
- jest.mock('../services/ContextDetectionEngine');
9
-
10
1
  const CompositionRoot = require('../CompositionRoot');
11
2
 
12
3
  describe('CompositionRoot', () => {
@@ -1,9 +1,8 @@
1
- jest.mock('child_process', () => ({
2
- execSync: jest.fn(),
3
- }));
4
-
5
1
  const childProcess = require('child_process');
6
- const { getGitTreeState, isTreeBeyondLimit, summarizeTreeState } = require('../GitTreeState');
2
+ let getGitTreeState;
3
+ let isTreeBeyondLimit;
4
+ let summarizeTreeState;
5
+ let execSyncSpy;
7
6
 
8
7
  function makeMockGitStatus(stagedFiles = [], workingFiles = [], untrackedFiles = []) {
9
8
  const lines = [];
@@ -21,11 +20,14 @@ function makeMockGitStatus(stagedFiles = [], workingFiles = [], untrackedFiles =
21
20
 
22
21
  describe('GitTreeState', () => {
23
22
  beforeEach(() => {
24
- childProcess.execSync.mockReset();
23
+ jest.resetModules();
24
+ execSyncSpy = jest.spyOn(childProcess, 'execSync');
25
+ execSyncSpy.mockReset();
26
+ ({ getGitTreeState, isTreeBeyondLimit, summarizeTreeState } = require('../GitTreeState'));
25
27
  });
26
28
 
27
29
  afterEach(() => {
28
- jest.clearAllMocks();
30
+ execSyncSpy.mockRestore();
29
31
  });
30
32
 
31
33
  describe('getGitTreeState', () => {
@@ -166,4 +168,3 @@ describe('GitTreeState', () => {
166
168
  });
167
169
  });
168
170
  });
169
-
@@ -1,21 +1,14 @@
1
- jest.mock('../GitTreeState', () => ({
2
- getGitTreeState: jest.fn(),
3
- }));
4
-
5
- jest.mock('../logging/AuditLogger', () => {
6
- return jest.fn().mockImplementation(() => ({
7
- record: jest.fn(),
8
- info: jest.fn(),
9
- warn: jest.fn(),
10
- error: jest.fn(),
11
- }));
12
- });
13
-
14
- jest.mock('../IntelligentCommitAnalyzer');
15
-
16
- const IntelligentGitTreeMonitor = require('../IntelligentGitTreeMonitor');
17
- const IntelligentCommitAnalyzer = require('../IntelligentCommitAnalyzer');
18
- const { getGitTreeState } = require('../GitTreeState');
1
+ const childProcess = require('child_process');
2
+
3
+ let AuditLogger;
4
+ let IntelligentGitTreeMonitor;
5
+ let IntelligentCommitAnalyzer;
6
+ let execSyncSpy;
7
+ let analyzeAndSuggestCommitsSpy;
8
+ let getReadyCommitsSpy;
9
+ let getNeedsAttentionSpy;
10
+ let ensureDirSpy;
11
+ let recordSpy;
19
12
 
20
13
  function makeSUT(options = {}) {
21
14
  const defaultOptions = {
@@ -28,17 +21,38 @@ function makeSUT(options = {}) {
28
21
  return new IntelligentGitTreeMonitor(defaultOptions);
29
22
  }
30
23
 
24
+ function buildGitStatusOutput({ staged = [], working = [], untracked = [] } = {}) {
25
+ const stagedLines = staged.map(file => `A ${file}`);
26
+ const workingLines = working.map(file => ` M ${file}`);
27
+ const untrackedLines = untracked.map(file => `?? ${file}`);
28
+ return [...stagedLines, ...workingLines, ...untrackedLines].join('\n');
29
+ }
30
+
31
31
  describe('IntelligentGitTreeMonitor', () => {
32
32
  beforeEach(() => {
33
- jest.clearAllMocks();
34
- getGitTreeState.mockReset();
35
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits = jest.fn();
36
- IntelligentCommitAnalyzer.prototype.getReadyCommits = jest.fn();
37
- IntelligentCommitAnalyzer.prototype.getNeedsAttention = jest.fn();
33
+ jest.resetModules();
34
+ execSyncSpy = jest.spyOn(childProcess, 'execSync');
35
+ execSyncSpy.mockReset();
36
+ AuditLogger = require('../logging/AuditLogger');
37
+ IntelligentCommitAnalyzer = require('../IntelligentCommitAnalyzer');
38
+ IntelligentGitTreeMonitor = require('../IntelligentGitTreeMonitor');
39
+ analyzeAndSuggestCommitsSpy = jest.spyOn(IntelligentCommitAnalyzer.prototype, 'analyzeAndSuggestCommits');
40
+ getReadyCommitsSpy = jest.spyOn(IntelligentCommitAnalyzer.prototype, 'getReadyCommits');
41
+ getNeedsAttentionSpy = jest.spyOn(IntelligentCommitAnalyzer.prototype, 'getNeedsAttention');
42
+ ensureDirSpy = jest.spyOn(AuditLogger.prototype, 'ensureDir').mockImplementation(() => {});
43
+ recordSpy = jest.spyOn(AuditLogger.prototype, 'record').mockImplementation(() => {});
44
+ analyzeAndSuggestCommitsSpy.mockResolvedValue([]);
45
+ getReadyCommitsSpy.mockReturnValue([]);
46
+ getNeedsAttentionSpy.mockReturnValue([]);
38
47
  });
39
48
 
40
49
  afterEach(() => {
41
- jest.clearAllMocks();
50
+ execSyncSpy.mockRestore();
51
+ analyzeAndSuggestCommitsSpy.mockRestore();
52
+ getReadyCommitsSpy.mockRestore();
53
+ getNeedsAttentionSpy.mockRestore();
54
+ ensureDirSpy.mockRestore();
55
+ recordSpy.mockRestore();
42
56
  });
43
57
 
44
58
  describe('constructor', () => {
@@ -65,14 +79,7 @@ describe('IntelligentGitTreeMonitor', () => {
65
79
 
66
80
  describe('analyze', () => {
67
81
  it('should return clean action when git tree is clean', async () => {
68
- getGitTreeState.mockReturnValue({
69
- uniqueCount: 0,
70
- stagedFiles: [],
71
- workingFiles: [],
72
- });
73
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits.mockResolvedValue([]);
74
- IntelligentCommitAnalyzer.prototype.getReadyCommits.mockReturnValue([]);
75
- IntelligentCommitAnalyzer.prototype.getNeedsAttention.mockReturnValue([]);
82
+ execSyncSpy.mockReturnValue('');
76
83
  const monitor = makeSUT();
77
84
  const result = await monitor.analyze();
78
85
  expect(result.action).toBe('clean');
@@ -89,15 +96,13 @@ describe('IntelligentGitTreeMonitor', () => {
89
96
  platform: 'backend',
90
97
  },
91
98
  ];
92
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits.mockResolvedValue([]);
93
- IntelligentCommitAnalyzer.prototype.getReadyCommits.mockReturnValue(mockReadyCommits);
94
- IntelligentCommitAnalyzer.prototype.getNeedsAttention.mockReturnValue([]);
99
+ analyzeAndSuggestCommitsSpy.mockResolvedValue([]);
100
+ getReadyCommitsSpy.mockReturnValue(mockReadyCommits);
101
+ getNeedsAttentionSpy.mockReturnValue([]);
95
102
 
96
- getGitTreeState.mockReturnValue({
97
- uniqueCount: 2,
98
- stagedFiles: ['file1.ts'],
99
- workingFiles: ['file2.ts'],
100
- });
103
+ execSyncSpy.mockReturnValue(
104
+ buildGitStatusOutput({ staged: ['file1.ts'], working: ['file2.ts'] })
105
+ );
101
106
 
102
107
  const monitor = makeSUT();
103
108
  const result = await monitor.analyze();
@@ -113,15 +118,13 @@ describe('IntelligentGitTreeMonitor', () => {
113
118
  files: [`file${i}.ts`],
114
119
  fileCount: 1,
115
120
  }));
116
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits.mockResolvedValue(manySuggestions);
117
- IntelligentCommitAnalyzer.prototype.getReadyCommits.mockReturnValue([]);
118
- IntelligentCommitAnalyzer.prototype.getNeedsAttention.mockReturnValue([]);
121
+ analyzeAndSuggestCommitsSpy.mockResolvedValue(manySuggestions);
122
+ getReadyCommitsSpy.mockReturnValue([]);
123
+ getNeedsAttentionSpy.mockReturnValue([]);
119
124
 
120
- getGitTreeState.mockReturnValue({
121
- uniqueCount: 15,
122
- stagedFiles: [],
123
- workingFiles: Array.from({ length: 15 }, (_, i) => `file${i}.ts`),
124
- });
125
+ execSyncSpy.mockReturnValue(
126
+ buildGitStatusOutput({ working: Array.from({ length: 15 }, (_, i) => `file${i}.ts`) })
127
+ );
125
128
 
126
129
  const monitor = makeSUT();
127
130
  const result = await monitor.analyze();
@@ -135,15 +138,13 @@ describe('IntelligentGitTreeMonitor', () => {
135
138
  { feature: 'feature-a', files: ['file1.ts'], fileCount: 1 },
136
139
  { feature: 'feature-b', files: ['file2.ts'], fileCount: 1 },
137
140
  ];
138
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits.mockResolvedValue(suggestions);
139
- IntelligentCommitAnalyzer.prototype.getReadyCommits.mockReturnValue([]);
140
- IntelligentCommitAnalyzer.prototype.getNeedsAttention.mockReturnValue([]);
141
+ analyzeAndSuggestCommitsSpy.mockResolvedValue(suggestions);
142
+ getReadyCommitsSpy.mockReturnValue([]);
143
+ getNeedsAttentionSpy.mockReturnValue([]);
141
144
 
142
- getGitTreeState.mockReturnValue({
143
- uniqueCount: 2,
144
- stagedFiles: ['file1.ts'],
145
- workingFiles: ['file2.ts'],
146
- });
145
+ execSyncSpy.mockReturnValue(
146
+ buildGitStatusOutput({ staged: ['file1.ts'], working: ['file2.ts'] })
147
+ );
147
148
 
148
149
  const monitor = makeSUT();
149
150
  const result = await monitor.analyze();
@@ -155,14 +156,7 @@ describe('IntelligentGitTreeMonitor', () => {
155
156
 
156
157
  describe('notify', () => {
157
158
  it('should not notify when git tree is clean', async () => {
158
- getGitTreeState.mockReturnValue({
159
- uniqueCount: 0,
160
- stagedFiles: [],
161
- workingFiles: [],
162
- });
163
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits.mockResolvedValue([]);
164
- IntelligentCommitAnalyzer.prototype.getReadyCommits.mockReturnValue([]);
165
- IntelligentCommitAnalyzer.prototype.getNeedsAttention.mockReturnValue([]);
159
+ execSyncSpy.mockReturnValue('');
166
160
  const notifier = jest.fn();
167
161
  const monitor = makeSUT({ notifier });
168
162
  await monitor.notify();
@@ -178,15 +172,13 @@ describe('IntelligentGitTreeMonitor', () => {
178
172
  fileCount: 1,
179
173
  },
180
174
  ];
181
- IntelligentCommitAnalyzer.prototype.analyzeAndSuggestCommits.mockResolvedValue([]);
182
- IntelligentCommitAnalyzer.prototype.getReadyCommits.mockReturnValue(mockReadyCommits);
183
- IntelligentCommitAnalyzer.prototype.getNeedsAttention.mockReturnValue([]);
175
+ analyzeAndSuggestCommitsSpy.mockResolvedValue([]);
176
+ getReadyCommitsSpy.mockReturnValue(mockReadyCommits);
177
+ getNeedsAttentionSpy.mockReturnValue([]);
184
178
 
185
- getGitTreeState.mockReturnValue({
186
- uniqueCount: 1,
187
- stagedFiles: ['file1.ts'],
188
- workingFiles: [],
189
- });
179
+ execSyncSpy.mockReturnValue(
180
+ buildGitStatusOutput({ staged: ['file1.ts'] })
181
+ );
190
182
 
191
183
  const notifier = jest.fn();
192
184
  const monitor = makeSUT({ notifier });
@@ -199,4 +191,3 @@ describe('IntelligentGitTreeMonitor', () => {
199
191
  });
200
192
  });
201
193
  });
202
-
@@ -1,13 +1,8 @@
1
- jest.mock('child_process', () => ({
2
- spawnSync: jest.fn(),
3
- }));
4
-
5
1
  const childProcess = require('child_process');
6
- const PlaybookRunner = require('../PlaybookRunner');
7
2
  const fs = require('fs');
8
3
  const path = require('path');
9
-
10
- const { spawnSync } = childProcess;
4
+ let PlaybookRunner;
5
+ let spawnSyncSpy;
11
6
 
12
7
  function makeSUT(options = {}) {
13
8
  return new PlaybookRunner(options);
@@ -32,11 +27,15 @@ function cleanupPlaybooksFile() {
32
27
  describe('PlaybookRunner', () => {
33
28
  beforeEach(() => {
34
29
  cleanupPlaybooksFile();
35
- jest.clearAllMocks();
30
+ jest.resetModules();
31
+ spawnSyncSpy = jest.spyOn(childProcess, 'spawnSync');
32
+ spawnSyncSpy.mockReset();
33
+ PlaybookRunner = require('../PlaybookRunner');
36
34
  });
37
35
 
38
36
  afterEach(() => {
39
37
  cleanupPlaybooksFile();
38
+ spawnSyncSpy.mockRestore();
40
39
  });
41
40
 
42
41
  describe('constructor', () => {
@@ -98,10 +97,10 @@ describe('PlaybookRunner', () => {
98
97
  },
99
98
  };
100
99
  createMockPlaybooksFile(playbooks);
101
- spawnSync.mockReturnValue({ status: 0 });
100
+ spawnSyncSpy.mockReturnValue({ status: 0 });
102
101
  const runner = makeSUT();
103
102
  runner.run('test');
104
- expect(spawnSync).toHaveBeenCalledTimes(2);
103
+ expect(spawnSyncSpy).toHaveBeenCalledTimes(2);
105
104
  });
106
105
 
107
106
  it('should throw error when playbook not found', () => {
@@ -119,7 +118,7 @@ describe('PlaybookRunner', () => {
119
118
  },
120
119
  };
121
120
  createMockPlaybooksFile(playbooks);
122
- spawnSync.mockReturnValue({ status: 1 });
121
+ spawnSyncSpy.mockReturnValue({ status: 1 });
123
122
  const runner = makeSUT();
124
123
  expect(() => {
125
124
  runner.run('test');
@@ -134,14 +133,13 @@ describe('PlaybookRunner', () => {
134
133
  },
135
134
  };
136
135
  createMockPlaybooksFile(playbooks);
137
- spawnSync.mockReturnValue({ status: 0 });
136
+ spawnSyncSpy.mockReturnValue({ status: 0 });
138
137
  const runner = makeSUT({ cwd: customCwd });
139
138
  runner.run('test');
140
- expect(spawnSync).toHaveBeenCalledWith(
139
+ expect(spawnSyncSpy).toHaveBeenCalledWith(
141
140
  expect.any(String),
142
141
  expect.objectContaining({ cwd: customCwd })
143
142
  );
144
143
  });
145
144
  });
146
145
  });
147
-
@@ -301,11 +301,13 @@ class SwiftAnalyzer {
301
301
  checkWeakSelf(ast, filePath, content) {
302
302
  const lines = content.split('\n');
303
303
  let inClosure = false;
304
+ let closureHasWeakSelf = false;
304
305
  lines.forEach((line, index) => {
305
306
  if (line.includes('{') && (line.includes('->') || line.includes('in'))) {
306
307
  inClosure = true;
308
+ closureHasWeakSelf = /\b(weak|unowned)\s+self\b/.test(line);
307
309
  }
308
- if (inClosure && line.includes('self.') && !line.includes('[weak self]') && !line.includes('[unowned self]')) {
310
+ if (inClosure && line.includes('self.') && !closureHasWeakSelf) {
309
311
  this.addFinding({
310
312
  rule: 'ios.weak_self',
311
313
  severity: 'medium',
@@ -316,6 +318,7 @@ class SwiftAnalyzer {
316
318
  }
317
319
  if (line.includes('}')) {
318
320
  inClosure = false;
321
+ closureHasWeakSelf = false;
319
322
  }
320
323
  });
321
324
  }
@@ -303,13 +303,6 @@ function runBackendIntelligence(project, findings, platform) {
303
303
  pushFinding("backend.config.missing_env_separation", "info", sf, sf, "Missing environment-specific configuration - consider NODE_ENV or ConfigService", findings);
304
304
  }
305
305
 
306
- const hasConfigValidation = sf.getFullText().includes("joi") ||
307
- sf.getFullText().includes("class-validator") ||
308
- sf.getFullText().includes("@nestjs/config");
309
- if (!hasConfigValidation && sf.getFullText().includes("process.env")) {
310
- pushFinding("backend.config.missing_validation", "warning", sf, sf, "Environment variables without validation - consider Joi or class-validator", findings);
311
- }
312
-
313
306
  const hardMaxLines = env.getNumber('AST_GODCLASS_HARD_MAX_LINES', 0);
314
307
  const softMaxLines = env.getNumber('AST_GODCLASS_SOFT_MAX_LINES', 500);
315
308
  const absoluteGodLines = env.getNumber('AST_GODCLASS_ABSOLUTE_LINES', 1000);
@@ -328,6 +321,13 @@ function runBackendIntelligence(project, findings, platform) {
328
321
  return;
329
322
  }
330
323
 
324
+ const hasConfigValidation = sf.getFullText().includes("joi") ||
325
+ sf.getFullText().includes("class-validator") ||
326
+ sf.getFullText().includes("@nestjs/config");
327
+ if (!hasConfigValidation && sf.getFullText().includes("process.env")) {
328
+ pushFinding("backend.config.missing_validation", "warning", sf, sf, "Environment variables without validation - consider Joi or class-validator", findings);
329
+ }
330
+
331
331
  sf.getDescendantsOfKind(SyntaxKind.ClassDeclaration).forEach((cls) => {
332
332
  const name = cls.getName();
333
333
  if (name && /Entity|Model|Domain/.test(name)) {
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const glob = require('glob');
3
+ const env = require('../../../../config/env');
3
4
  const { pushFileFinding } = require('../../ast-core');
4
5
 
5
6
  class WorkflowRules {
@@ -21,7 +22,7 @@ class WorkflowRules {
21
22
  absolute: true
22
23
  });
23
24
 
24
- const isLibrarySelfAudit = process.env.AUDIT_LIBRARY_SELF === 'true' ||
25
+ const isLibrarySelfAudit = env.getBool('AUDIT_LIBRARY_SELF', false) ||
25
26
  this.projectRoot.includes('ast-intelligence-hooks');
26
27
  if (isLibrarySelfAudit) {
27
28
  return;
@@ -74,6 +75,7 @@ class WorkflowRules {
74
75
  featureFiles.forEach(featureFile => {
75
76
  const content = fs.readFileSync(featureFile, 'utf-8');
76
77
  const featureName = this.extractFeatureName(content);
78
+ const hasImplementationHint = /^\s*Implementation\s*:/m.test(content);
77
79
 
78
80
  if (featureName) {
79
81
  let testFiles = glob.sync(`**/*${featureName}*.{test,spec}.{ts,tsx,swift,kt}`, {
@@ -112,7 +114,7 @@ class WorkflowRules {
112
114
  );
113
115
  }
114
116
 
115
- if (implFiles.length === 0 && testFiles.length > 0) {
117
+ if (implFiles.length === 0 && testFiles.length > 0 && !hasImplementationHint) {
116
118
  pushFileFinding(
117
119
  'workflow.triad.tests_without_implementation',
118
120
  'low',
@@ -646,7 +646,8 @@ function runTextScanner(root, findings) {
646
646
  if (hasForceUnwrap && !hasLogicalNegation && !/@IBOutlet\b/.test(content) && !usesModernLocalization) {
647
647
  pushFileFinding('ios.force_unwrapping', 'high', file, 1, 1, 'Force unwrapping detected', findings);
648
648
  }
649
- if (/\[[ ]*(weak|unowned)[ ]+self[ ]*\]/.test(content) === false && /self\./.test(content) && /\{[^\n]*in/.test(content)) {
649
+ const hasWeakSelfCapture = /\[[^\]]*\b(weak|unowned)\s+self\b[^\]]*\]/.test(content);
650
+ if (!hasWeakSelfCapture && /self\./.test(content) && /\{[^\n]*in/.test(content)) {
650
651
  pushFileFinding('ios.weak_self', 'medium', file, 1, 1, 'Closure referencing self without [weak self]', findings);
651
652
  }
652
653
  if (/\[\s*unowned\s+self\s*\]/.test(content)) {
@@ -673,7 +674,8 @@ function runTextScanner(root, findings) {
673
674
  if (/\.sink\s*\(|\.assign\s*\(/.test(content) && !/store\s*\(in\s*:\s*/.test(content)) {
674
675
  pushFileFinding('ios.combine.memory_management', 'medium', file, 1, 1, 'Combine subscription without store(in:)', findings);
675
676
  }
676
- if (/\bTask\s*\{/.test(content) && !/withTaskCancellationHandler\s*\(/.test(content)) {
677
+ const hasTaskCancellationHandling = /withTaskCancellationHandler\s*\(|\bTask\.isCancelled\b|\bTask\.checkCancellation\s*\(/.test(content);
678
+ if (/\bTask\s*\{/.test(content) && !hasTaskCancellationHandling) {
677
679
  pushFileFinding('ios.concurrency.task_cancellation', 'low', file, 1, 1, 'Task without cancellation handling', findings);
678
680
  }
679
681
  iosTaskCount += (content.match(/\bTask\s*\{/g) || []).length;
@@ -1,11 +1,6 @@
1
- jest.mock('child_process', () => ({
2
- execSync: jest.fn(),
3
- }));
4
-
5
1
  const childProcess = require('child_process');
6
- const { GitOperations } = require('../GitOperations');
7
-
8
- const { execSync } = childProcess;
2
+ let GitOperations;
3
+ let execSyncSpy;
9
4
 
10
5
  function makeMockGitOutput(files) {
11
6
  return files.join('\n') + (files.length > 0 ? '\n' : '');
@@ -13,35 +8,42 @@ function makeMockGitOutput(files) {
13
8
 
14
9
  describe('GitOperations', () => {
15
10
  beforeEach(() => {
16
- jest.clearAllMocks();
11
+ jest.resetModules();
12
+ execSyncSpy = jest.spyOn(childProcess, 'execSync');
13
+ execSyncSpy.mockReset();
14
+ ({ GitOperations } = require('../GitOperations'));
15
+ });
16
+
17
+ afterEach(() => {
18
+ execSyncSpy.mockRestore();
17
19
  });
18
20
 
19
21
  describe('getStagedFiles', () => {
20
22
  it('should return array of staged files', () => {
21
23
  const mockFiles = ['file1.ts', 'file2.ts', 'file3.ts'];
22
- execSync.mockReturnValue(makeMockGitOutput(mockFiles));
24
+ execSyncSpy.mockReturnValue(makeMockGitOutput(mockFiles));
23
25
  const files = GitOperations.getStagedFiles();
24
26
  expect(files).toEqual(mockFiles);
25
- expect(execSync).toHaveBeenCalledWith(
27
+ expect(execSyncSpy).toHaveBeenCalledWith(
26
28
  'git diff --cached --name-only --diff-filter=ACM',
27
29
  { encoding: 'utf8' }
28
30
  );
29
31
  });
30
32
 
31
33
  it('should return empty array when no staged files', () => {
32
- execSync.mockReturnValue('');
34
+ execSyncSpy.mockReturnValue('');
33
35
  const files = GitOperations.getStagedFiles();
34
36
  expect(files).toEqual([]);
35
37
  });
36
38
 
37
39
  it('should filter out empty lines', () => {
38
- execSync.mockReturnValue('file1.ts\n\nfile2.ts\n');
40
+ execSyncSpy.mockReturnValue('file1.ts\n\nfile2.ts\n');
39
41
  const files = GitOperations.getStagedFiles();
40
42
  expect(files).toEqual(['file1.ts', 'file2.ts']);
41
43
  });
42
44
 
43
45
  it('should return empty array on git error', () => {
44
- execSync.mockImplementation(() => {
46
+ execSyncSpy.mockImplementation(() => {
45
47
  throw new Error('Not a git repository');
46
48
  });
47
49
  const files = GitOperations.getStagedFiles();
@@ -52,23 +54,23 @@ describe('GitOperations', () => {
52
54
  describe('getWorkingDirectoryFiles', () => {
53
55
  it('should return array of working directory files', () => {
54
56
  const mockFiles = ['file1.ts', 'file2.ts'];
55
- execSync.mockReturnValue(makeMockGitOutput(mockFiles));
57
+ execSyncSpy.mockReturnValue(makeMockGitOutput(mockFiles));
56
58
  const files = GitOperations.getWorkingDirectoryFiles();
57
59
  expect(files).toEqual(mockFiles);
58
- expect(execSync).toHaveBeenCalledWith(
60
+ expect(execSyncSpy).toHaveBeenCalledWith(
59
61
  'git diff --name-only --diff-filter=ACM',
60
62
  { encoding: 'utf8' }
61
63
  );
62
64
  });
63
65
 
64
66
  it('should return empty array when no working files', () => {
65
- execSync.mockReturnValue('');
67
+ execSyncSpy.mockReturnValue('');
66
68
  const files = GitOperations.getWorkingDirectoryFiles();
67
69
  expect(files).toEqual([]);
68
70
  });
69
71
 
70
72
  it('should return empty array on git error', () => {
71
- execSync.mockImplementation(() => {
73
+ execSyncSpy.mockImplementation(() => {
72
74
  throw new Error('Git error');
73
75
  });
74
76
  const files = GitOperations.getWorkingDirectoryFiles();
@@ -79,20 +81,20 @@ describe('GitOperations', () => {
79
81
  describe('getAllChangedFiles', () => {
80
82
  it('should return array of all changed files', () => {
81
83
  const mockFiles = ['staged1.ts', 'staged2.ts', 'working1.ts'];
82
- execSync.mockReturnValue(makeMockGitOutput(mockFiles));
84
+ execSyncSpy.mockReturnValue(makeMockGitOutput(mockFiles));
83
85
  const files = GitOperations.getAllChangedFiles();
84
86
  expect(files).toEqual(mockFiles);
85
87
  });
86
88
 
87
89
  it('should combine staged and working files', () => {
88
- execSync.mockReturnValue('staged.ts\nworking.ts\n');
90
+ execSyncSpy.mockReturnValue('staged.ts\nworking.ts\n');
89
91
  const files = GitOperations.getAllChangedFiles();
90
92
  expect(files).toContain('staged.ts');
91
93
  expect(files).toContain('working.ts');
92
94
  });
93
95
 
94
96
  it('should return empty array on git error', () => {
95
- execSync.mockImplementation(() => {
97
+ execSyncSpy.mockImplementation(() => {
96
98
  throw new Error('Git error');
97
99
  });
98
100
  const files = GitOperations.getAllChangedFiles();
@@ -102,17 +104,17 @@ describe('GitOperations', () => {
102
104
 
103
105
  describe('isInGitRepository', () => {
104
106
  it('should return true when in git repository', () => {
105
- execSync.mockReturnValue('.git');
107
+ execSyncSpy.mockReturnValue('.git');
106
108
  const isGit = GitOperations.isInGitRepository();
107
109
  expect(isGit).toBe(true);
108
- expect(execSync).toHaveBeenCalledWith(
110
+ expect(execSyncSpy).toHaveBeenCalledWith(
109
111
  'git rev-parse --git-dir',
110
112
  { stdio: 'ignore' }
111
113
  );
112
114
  });
113
115
 
114
116
  it('should return false when not in git repository', () => {
115
- execSync.mockImplementation(() => {
117
+ execSyncSpy.mockImplementation(() => {
116
118
  throw new Error('Not a git repository');
117
119
  });
118
120
  const isGit = GitOperations.isInGitRepository();
@@ -123,17 +125,17 @@ describe('GitOperations', () => {
123
125
  describe('getRepositoryRoot', () => {
124
126
  it('should return repository root path', () => {
125
127
  const mockRoot = '/path/to/repo';
126
- execSync.mockReturnValue(mockRoot + '\n');
128
+ execSyncSpy.mockReturnValue(mockRoot + '\n');
127
129
  const root = GitOperations.getRepositoryRoot();
128
130
  expect(root).toBe(mockRoot);
129
- expect(execSync).toHaveBeenCalledWith(
131
+ expect(execSyncSpy).toHaveBeenCalledWith(
130
132
  'git rev-parse --show-toplevel',
131
133
  { encoding: 'utf8' }
132
134
  );
133
135
  });
134
136
 
135
137
  it('should return current working directory on error', () => {
136
- execSync.mockImplementation(() => {
138
+ execSyncSpy.mockImplementation(() => {
137
139
  throw new Error('Not a git repository');
138
140
  });
139
141
  const root = GitOperations.getRepositoryRoot();
@@ -141,10 +143,9 @@ describe('GitOperations', () => {
141
143
  });
142
144
 
143
145
  it('should trim whitespace from root path', () => {
144
- execSync.mockReturnValue(' /path/to/repo \n');
146
+ execSyncSpy.mockReturnValue(' /path/to/repo \n');
145
147
  const root = GitOperations.getRepositoryRoot();
146
148
  expect(root).toBe('/path/to/repo');
147
149
  });
148
150
  });
149
151
  });
150
-
@@ -825,8 +825,10 @@ async function updateAIEvidence(violations, gateResult, tokenUsage) {
825
825
  }
826
826
  }
827
827
 
828
+ const hasBlockingSeverities = criticalViolations.length > 0 || highViolations.length > 0;
829
+ const evidenceGateStatus = gateResult.passed || !hasBlockingSeverities ? 'ALLOWED' : 'BLOCKED';
828
830
  const nextGate = {
829
- status: gateResult.passed ? 'ALLOWED' : 'BLOCKED',
831
+ status: evidenceGateStatus,
830
832
  scope: gateScope === 'repo' || gateScope === 'repository' ? 'repo' : 'staging',
831
833
  last_check: formatLocalTimestamp(),
832
834
  severity_summary: {
@@ -874,8 +876,8 @@ async function updateAIEvidence(violations, gateResult, tokenUsage) {
874
876
  ? `Staged files analyzed: ${stagedFilesList.length}. Platforms detected: ${detectedPlatformsForQuestions.join(', ') || 'none'}.`
875
877
  : 'No staged files detected for analysis.',
876
878
  question_2_similar_exists: violations.length > 0
877
- ? `Detected ${violations.length} rule violations; review existing patterns and rule matches.`
878
- : 'No rule violations detected; no similar patterns flagged.',
879
+ ? `Detected ${violations.length} rule violations; review recent commits and similar patterns flagged by rules.`
880
+ : 'No rule violations detected; no similar patterns flagged in recent commits.',
879
881
  question_3_clean_architecture: architectureViolations.length > 0
880
882
  ? `Found ${architectureViolations.length} Clean Architecture/SOLID-related violations that require review.`
881
883
  : 'No Clean Architecture or SOLID violations detected.',
@@ -190,3 +190,15 @@
190
190
  {"timestamp":"2026-01-26T19:01:58.968Z","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"}}
191
191
  {"timestamp":"2026-01-26T19:01:58.970Z","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"}}
192
192
  {"timestamp":"2026-01-26T19:01:58.971Z","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)"}}
193
+ {"timestamp":"2026-01-28T18:12:39.899Z","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"}}
194
+ {"timestamp":"2026-01-28T18:12:39.900Z","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"}}
195
+ {"timestamp":"2026-01-28T18:12:39.901Z","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)"}}
196
+ {"timestamp":"2026-01-28T18:37:07.882Z","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"}}
197
+ {"timestamp":"2026-01-28T18:37:07.883Z","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"}}
198
+ {"timestamp":"2026-01-28T18:37:07.884Z","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)"}}
199
+ {"timestamp":"2026-01-28T18:51:14.085Z","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"}}
200
+ {"timestamp":"2026-01-28T18:51:14.087Z","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"}}
201
+ {"timestamp":"2026-01-28T18:51:14.088Z","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)"}}
202
+ {"timestamp":"2026-01-28T18:59:59.378Z","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"}}
203
+ {"timestamp":"2026-01-28T18:59:59.380Z","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"}}
204
+ {"timestamp":"2026-01-28T18:59:59.380Z","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)"}}