pumuki-ast-hooks 5.3.17 → 5.3.18

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.
Files changed (36) hide show
  1. package/docs/VIOLATIONS_RESOLUTION_PLAN.md +9 -9
  2. package/docs/alerting-system.md +51 -0
  3. package/docs/observability.md +36 -0
  4. package/docs/type-safety.md +8 -0
  5. package/package.json +1 -1
  6. package/scripts/hooks-system/.AI_TOKEN_STATUS.txt +1 -1
  7. package/scripts/hooks-system/.audit-reports/notifications.log +11 -0
  8. package/scripts/hooks-system/.audit-reports/token-monitor.log +72 -0
  9. package/scripts/hooks-system/application/CompositionRoot.js +73 -24
  10. package/scripts/hooks-system/application/services/DynamicRulesLoader.js +2 -1
  11. package/scripts/hooks-system/application/services/RealtimeGuardService.js +85 -15
  12. package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +31 -2
  13. package/scripts/hooks-system/application/services/guard/GuardConfig.js +17 -9
  14. package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +6 -9
  15. package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +29 -0
  16. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +3 -0
  17. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +2 -1
  18. package/scripts/hooks-system/application/services/logging/AuditLogger.js +88 -0
  19. package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +13 -4
  20. package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +7 -3
  21. package/scripts/hooks-system/application/services/token/TokenMetricsService.js +14 -1
  22. package/scripts/hooks-system/config/env.js +33 -0
  23. package/scripts/hooks-system/domain/events/__tests__/EventBus.spec.js +33 -0
  24. package/scripts/hooks-system/domain/events/index.js +16 -0
  25. package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +3 -2
  26. package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -20
  27. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +8 -18
  28. package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +2 -1
  29. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +10 -8
  30. package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
  31. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +3 -2
  32. package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +3 -2
  33. package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +35 -5
  34. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +86 -16
  35. package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +51 -2
  36. package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +6 -8
@@ -50,22 +50,22 @@ gantt
50
50
  | Estado | Violación | Cant. | Responsable | DOD (Definition of Done) | Doc |
51
51
  |--------|-----------|-------|-------------|--------------------------|-----|
52
52
  | ✅ | backend.error.custom_exceptions | 105 | BE | CustomError base + reemplazo de `Error` genérico en BE; tests pasando | [Guía de excepciones](../docs/error-handling.md) |
53
- | 🚧 | backend.config.missing_env_separation | 80 | BE | Config por entorno (dev/stg/prod), sin secretos hardcode | [Config entornos](../docs/env-configuration.md) |
54
- | | backend.security.missing_audit_logging | 69 | BE | Audit trail en operaciones sensibles + logs estructurados | [Audit logging](../docs/security-auditing.md) |
55
- | | backend.metrics.missing_prometheus | 64 | BE | Endpoints /metrics, instrumentación clave y dashboard base | [Prometheus](../docs/metrics-monitoring.md) |
56
- | | backend.reliability.missing_bulkhead | 40 | BE | Limitadores/aislamiento en puntos críticos + pruebas de carga | [Reliability](../docs/reliability-patterns.md) |
53
+ | | backend.config.missing_env_separation | 80 | BE | Config por entorno (dev/stg/prod), sin secretos hardcode | [Config entornos](../docs/env-configuration.md) |
54
+ | | backend.security.missing_audit_logging | 69 | BE | Audit trail en operaciones sensibles + logs estructurados | [Audit logging](../docs/security-auditing.md) |
55
+ | | backend.metrics.missing_prometheus | 64 | BE | Endpoints /metrics, instrumentación clave y dashboard base | [Prometheus](../docs/metrics-monitoring.md) |
56
+ | | backend.reliability.missing_bulkhead | 40 | BE | Limitadores/aislamiento en puntos críticos + pruebas de carga | [Reliability](../docs/reliability-patterns.md) |
57
57
 
58
58
  ---
59
59
 
60
60
  ## 🟠 Fase 2: Violaciones HIGH + MEDIUM (118)
61
61
  | Estado | Violación | Cant. | Responsable | DOD | Doc |
62
62
  |--------|-----------|-------|-------------|-----|-----|
63
- | | HIGH (1) | 1 | BE | Tipado estricto sin `any`; tests verdes | [Type safety](../docs/type-safety.md) |
64
- | | backend.testing.mocks | 40 | QA/BE | Mocks revisados; cobertura > 80% en módulos afectados | [Testing](../docs/testing-strategies.md) |
65
- | | backend.event.handler | 26 | BE | Handlers idempotentes + tests de eventos | [Eventos](../docs/event-handling.md) |
63
+ | | HIGH (1) | 1 | BE | No aplica (repo JS puro sin TS); se documenta enfoque de seguridad de tipos | [Type safety](../docs/type-safety.md) |
64
+ | | backend.testing.mocks | 40 | QA/BE | Mocks revisados; cobertura > 80% en módulos afectados | [Testing](../docs/testing-strategies.md) |
65
+ | | backend.event.handler | 26 | BE | Handlers idempotentes + tests de eventos | [Eventos](../docs/event-handling.md) |
66
66
  | ⏳ | backend.observability.missing_prometheus | 24 | BE | Métricas por handler; dashboards mínimos | [Observabilidad](../docs/observability.md) |
67
- | | backend.auth.missing_cors | 17 | BE | Política CORS por entorno; tests e2e básicos | [CORS](../docs/cors-configuration.md) |
68
- | | backend.observability.missing_alerting | 10 | SRE | Alertas en métricas críticas; umbrales definidos | [Alerting](../docs/alerting-system.md) |
67
+ | | backend.auth.missing_cors | 17 | BE | No aplica al hook-system (no expone servidor HTTP); la detección queda en proyectos auditados | [CORS](../docs/cors-configuration.md) |
68
+ | | backend.observability.missing_alerting | 10 | SRE | Alertas en métricas críticas; umbrales definidos | [Alerting](../docs/alerting-system.md) |
69
69
 
70
70
  ---
71
71
 
@@ -0,0 +1,51 @@
1
+ # Alerting system (hook-system)
2
+
3
+ This repo does not expose its own HTTP server; metrics are published via `/metrics` in `metrics-server.js`, reading `.audit_tmp/hook-metrics.jsonl`. Alerts rely on `recordMetric` events from critical services (guards, scheduler).
4
+
5
+ ## Key metrics
6
+ - `hook_events_total{hook="guard_auto_manager",status="lock_fail|start|stop"}`
7
+ - `hook_events_total{hook="realtime_guard",status="start|stop"}`
8
+ - `hook_events_total{hook="git_tree",status="dirty|clean"}`
9
+ - `hook_events_total{hook="token_monitor",status="start|fail"}`
10
+ - `hook_events_total{hook="gitflow_autosync",status="enabled|sync_success"}`
11
+ - `hook_events_total{hook="evidence",status="stale|auto_refresh_success"}`
12
+
13
+ ## Alert examples (Prometheus)
14
+ ```yaml
15
+ - alert: GuardLockFailure
16
+ expr: increase(hook_events_total{hook="guard_auto_manager",status="lock_fail"}[5m]) > 0
17
+ for: 5m
18
+ labels: { severity: critical }
19
+ annotations:
20
+ summary: "Guard auto manager could not acquire lock"
21
+ description: "Check duplicate instance or orphan PID file"
22
+
23
+ - alert: GitTreeDirtyPersistent
24
+ expr: increase(hook_events_total{hook="git_tree",status="dirty"}[15m]) >= 3
25
+ for: 0m
26
+ labels: { severity: warning }
27
+ annotations:
28
+ summary: "Repo dirty repeatedly"
29
+ description: "More than 3 dirty detections in 15m"
30
+
31
+ - alert: EvidenceStale
32
+ expr: increase(hook_events_total{hook="evidence",status="stale"}[30m]) > 0
33
+ for: 0m
34
+ labels: { severity: warning }
35
+ annotations:
36
+ summary: "Evidence is stale"
37
+ description: "Guard detected evidence outside SLA"
38
+
39
+ - alert: TokenMonitorFail
40
+ expr: increase(hook_events_total{hook="token_monitor",status="fail"}[10m]) > 0
41
+ for: 0m
42
+ labels: { severity: warning }
43
+ annotations:
44
+ summary: "Token monitor failed to start"
45
+ description: "Check script/token monitor availability"
46
+ ```
47
+
48
+ ## Operations
49
+ - Run `metrics-server.js` (port `HOOK_METRICS_PORT`, default 9464) to expose `/metrics`.
50
+ - Scrape Prometheus apuntando a `http://<host>:<port>/metrics`.
51
+ - Ajustar umbrales/ventanas según ruido y frecuencia de uso.
@@ -0,0 +1,36 @@
1
+ # Observability (Prometheus) - hook-system
2
+
3
+ The hook-system exposes plaintext metrics via `/metrics` (`infrastructure/telemetry/metrics-server.js`). Metrics are based on `hook_events_total` emitted by `recordMetric` from critical services (GuardAutoManager, RealtimeGuardService, HookSystemScheduler, etc.).
4
+
5
+ ## Exposure
6
+ - Run `metrics-server.js` (port `HOOK_METRICS_PORT`, default 9464).
7
+ - Data source: `.audit_tmp/hook-metrics.jsonl` (append-only).
8
+ - Endpoint: `http://<host>:<port>/metrics`.
9
+
10
+ ## Available metrics (main)
11
+ - `hook_events_total{hook="guard_auto_manager",status="lock_fail|start|stop"}`
12
+ - `hook_events_total{hook="realtime_guard",status="start|stop"}`
13
+ - `hook_events_total{hook="git_tree",status="dirty|clean"}`
14
+ - `hook_events_total{hook="token_monitor",status="start|fail"}`
15
+ - `hook_events_total{hook="gitflow_autosync",status="enabled|sync_success"}`
16
+ - `hook_events_total{hook="evidence",status="stale|auto_refresh_success"}`
17
+ - `hook_events_total{hook="autonomous-orchestrator",status="success|failure"}`
18
+
19
+ ## Prometheus scrape (example)
20
+ ```yaml
21
+ scrape_configs:
22
+ - job_name: 'hook-system'
23
+ metrics_path: /metrics
24
+ static_configs:
25
+ - targets: ['localhost:9464']
26
+ ```
27
+
28
+ ## Base dashboard (Grafana example)
29
+ - Panel 1: "Guard status" -> `increase(hook_events_total{hook="guard_auto_manager"}[5m])`
30
+ - Panel 2: "Git tree dirty" -> `increase(hook_events_total{hook="git_tree",status="dirty"}[15m])`
31
+ - Panel 3: "Evidence stale" -> `increase(hook_events_total{hook="evidence",status="stale"}[30m])`
32
+ - Panel 4: "Token monitor fails" -> `increase(hook_events_total{hook="token_monitor",status="fail"}[10m])`
33
+
34
+ ## Notes
35
+ - Adjust window sizes `[]` based on noise/usage.
36
+ - `.audit_tmp/hook-metrics.jsonl` can be rotated externally if it grows too much; `/metrics` recomputes from the current file.
@@ -0,0 +1,8 @@
1
+ # Type safety (hook-system)
2
+
3
+ The hook-system is 100% JavaScript (no TS build), so strict TypeScript “no-any” migration does not apply here. Type safety is enforced through:
4
+ - Unit/critical tests (guards, event bus, scheduler) and implicit contracts in services.
5
+ - Input validation in events (DomainEvent and derivatives) and defensive checks in services.
6
+ - No TS transpilation/bundle in this repo; CORS/AST analyses run on audited projects that may use TS.
7
+
8
+ For audited projects (outside this repo), use strict TS and avoid `any`; here we only document non-applicability.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki-ast-hooks",
3
- "version": "5.3.17",
3
+ "version": "5.3.18",
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": {
@@ -12,5 +12,5 @@ Source: file
12
12
 
13
13
  ℹ️ Data is stale. Ensure guards are running and refreshing token usage.
14
14
 
15
- Last updated: 2025-12-30T08:25:20.984Z
15
+ Last updated: 2025-12-30T08:58:22.226Z
16
16
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -849,3 +849,14 @@
849
849
  {"timestamp":"2025-12-30T08:19:20.750Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"aea6dbae-9f29-476f-aae0-eb0baed57b63","type":"token_ok"},"context":{}}
850
850
  {"timestamp":"2025-12-30T08:22:20.864Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"9b5ff199-4e82-4c52-ac48-63c3f113bce8","type":"token_ok"},"context":{}}
851
851
  {"timestamp":"2025-12-30T08:25:20.986Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"c997c7e1-df65-444b-9f83-256def74479f","type":"token_ok"},"context":{}}
852
+ {"timestamp":"2025-12-30T08:28:21.114Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"c0ff8c81-b221-41e5-b794-47f531c4695c","type":"token_ok"},"context":{}}
853
+ {"timestamp":"2025-12-30T08:31:21.232Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"f1fd65fe-8c97-4cf7-9e69-e78adcee7f6a","type":"token_ok"},"context":{}}
854
+ {"timestamp":"2025-12-30T08:34:21.331Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"813aa1ac-d446-409a-9073-b8926977e1e3","type":"token_ok"},"context":{}}
855
+ {"timestamp":"2025-12-30T08:37:21.446Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"3302369a-dfd0-412f-9371-0f42e2d38c43","type":"token_ok"},"context":{}}
856
+ {"timestamp":"2025-12-30T08:40:21.564Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"99b37ef1-a097-4813-a549-f5397704155e","type":"token_ok"},"context":{}}
857
+ {"timestamp":"2025-12-30T08:43:21.675Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"a4910417-b3c5-44cb-bbaf-17a058951161","type":"token_ok"},"context":{}}
858
+ {"timestamp":"2025-12-30T08:46:21.788Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"d354de41-d835-44da-868f-0ee4b6f446b0","type":"token_ok"},"context":{}}
859
+ {"timestamp":"2025-12-30T08:49:21.901Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"b8d841eb-439a-4ea8-b90f-25555315f26d","type":"token_ok"},"context":{}}
860
+ {"timestamp":"2025-12-30T08:52:22.017Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"9c11c1b3-3816-4a02-b776-7298606a33f1","type":"token_ok"},"context":{}}
861
+ {"timestamp":"2025-12-30T08:55:22.116Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"5440bbb5-a069-4be6-a84f-1a8e525e2ebe","type":"token_ok"},"context":{}}
862
+ {"timestamp":"2025-12-30T08:58:22.227Z","level":"debug","component":"NotificationCenter","event":"Notification enqueued","data":{"id":"22a08362-af10-4d6d-8e4d-011afe460c7d","type":"token_ok"},"context":{}}
@@ -2551,3 +2551,75 @@
2551
2551
  {"timestamp":"2025-12-30T08:25:20.975Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2552
2552
  {"timestamp":"2025-12-30T08:25:20.976Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2553
2553
  {"timestamp":"2025-12-30T08:25:20.986Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2554
+ {"timestamp":"2025-12-30T08:28:21.102Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2555
+ {"timestamp":"2025-12-30T08:28:21.104Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2556
+ {"timestamp":"2025-12-30T08:28:21.114Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2557
+ {"timestamp":"2025-12-30T08:31:21.222Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2558
+ {"timestamp":"2025-12-30T08:31:21.223Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2559
+ {"timestamp":"2025-12-30T08:31:21.232Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2560
+ {"timestamp":"2025-12-30T08:34:21.319Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2561
+ {"timestamp":"2025-12-30T08:34:21.321Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2562
+ {"timestamp":"2025-12-30T08:34:21.331Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2563
+ {"timestamp":"2025-12-30T08:37:21.435Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2564
+ {"timestamp":"2025-12-30T08:37:21.437Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2565
+ {"timestamp":"2025-12-30T08:37:21.447Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2566
+ {"timestamp":"2025-12-30T08:40:21.554Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2567
+ {"timestamp":"2025-12-30T08:40:21.555Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2568
+ {"timestamp":"2025-12-30T08:40:21.564Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2569
+ {"timestamp":"2025-12-30T08:43:21.664Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2570
+ {"timestamp":"2025-12-30T08:43:21.665Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2571
+ {"timestamp":"2025-12-30T08:43:21.676Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2572
+ {"timestamp":"2025-12-30T08:46:21.778Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2573
+ {"timestamp":"2025-12-30T08:46:21.779Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2574
+ {"timestamp":"2025-12-30T08:46:21.788Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2575
+ {"timestamp":"2025-12-30T08:49:21.891Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2576
+ {"timestamp":"2025-12-30T08:49:21.892Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2577
+ {"timestamp":"2025-12-30T08:49:21.901Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2578
+ {"timestamp":"2025-12-30T08:52:22.006Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2579
+ {"timestamp":"2025-12-30T08:52:22.008Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2580
+ {"timestamp":"2025-12-30T08:52:22.017Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2581
+ {"timestamp":"2025-12-30T08:55:22.104Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2582
+ {"timestamp":"2025-12-30T08:55:22.106Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2583
+ {"timestamp":"2025-12-30T08:55:22.117Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2584
+ {"timestamp":"2025-12-30T08:58:22.216Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2585
+ {"timestamp":"2025-12-30T08:58:22.217Z","level":"debug","component":"TokenMonitor","event":"TOKEN_MONITOR_METRICS","data":{"timestamp":"2025-12-29T15:38:11.174Z","tokensUsed":0,"maxTokens":1000000,"percentUsed":0,"remainingTokens":1000000,"level":"ok","source":"file","stale":true,"untrusted":false},"context":{}}
2586
+ {"timestamp":"2025-12-30T08:58:22.227Z","level":"info","component":"TokenMonitor","event":"TOKEN_MONITOR_RESULT","data":{"level":"ok","percentUsed":0,"tokensUsed":0,"maxTokens":1000000,"source":"file","stale":true,"untrusted":false},"context":{"message":"Result level=ok percent=0% used=0/1000000 source=file (stale)"}}
2587
+ {"timestamp":"2025-12-30T09:01:22.338Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2588
+ {"timestamp":"2025-12-30T09:04:22.455Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2589
+ {"timestamp":"2025-12-30T09:07:22.567Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2590
+ {"timestamp":"2025-12-30T09:10:22.674Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2591
+ {"timestamp":"2025-12-30T09:13:22.769Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2592
+ {"timestamp":"2025-12-30T09:16:22.893Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2593
+ {"timestamp":"2025-12-30T09:19:23.006Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2594
+ {"timestamp":"2025-12-30T09:22:23.112Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2595
+ {"timestamp":"2025-12-30T09:25:23.225Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2596
+ {"timestamp":"2025-12-30T09:28:23.340Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2597
+ {"timestamp":"2025-12-30T09:31:23.437Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2598
+ {"timestamp":"2025-12-30T09:34:23.547Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2599
+ {"timestamp":"2025-12-30T09:37:23.640Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2600
+ {"timestamp":"2025-12-30T09:40:23.752Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2601
+ {"timestamp":"2025-12-30T09:43:23.845Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2602
+ {"timestamp":"2025-12-30T09:46:23.937Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2603
+ {"timestamp":"2025-12-30T09:49:24.042Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2604
+ {"timestamp":"2025-12-30T09:52:24.136Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2605
+ {"timestamp":"2025-12-30T09:55:24.231Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2606
+ {"timestamp":"2025-12-30T09:58:24.330Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2607
+ {"timestamp":"2025-12-30T10:01:24.438Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2608
+ {"timestamp":"2025-12-30T10:04:24.542Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2609
+ {"timestamp":"2025-12-30T10:07:24.654Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2610
+ {"timestamp":"2025-12-30T10:10:24.769Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2611
+ {"timestamp":"2025-12-30T10:13:24.886Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2612
+ {"timestamp":"2025-12-30T10:16:24.995Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2613
+ {"timestamp":"2025-12-30T10:19:25.098Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2614
+ {"timestamp":"2025-12-30T10:22:25.205Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2615
+ {"timestamp":"2025-12-30T10:25:25.296Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2616
+ {"timestamp":"2025-12-30T10:28:25.400Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2617
+ {"timestamp":"2025-12-30T10:31:25.497Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2618
+ {"timestamp":"2025-12-30T10:34:25.602Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2619
+ {"timestamp":"2025-12-30T10:37:25.690Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2620
+ {"timestamp":"2025-12-30T10:40:25.786Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2621
+ {"timestamp":"2025-12-30T10:43:25.876Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2622
+ {"timestamp":"2025-12-30T10:46:25.978Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2623
+ {"timestamp":"2025-12-30T10:49:26.076Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2624
+ {"timestamp":"2025-12-30T10:52:26.168Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
2625
+ {"timestamp":"2025-12-30T10:55:26.256Z","level":"debug","component":"TokenMonitor","event":"CURSOR_SERVICE_USING_FILE","data":{"usage":{"tokensUsed":0,"maxTokens":1000000,"percentUsed":72.36585,"timestamp":"2025-12-29T15:38:11.174Z","source":"file","untrusted":false}},"context":{}}
@@ -21,19 +21,54 @@ const TokenMonitor = require('./services/monitoring/TokenMonitor');
21
21
  const ActivityMonitor = require('./services/monitoring/ActivityMonitor');
22
22
  const DevDocsMonitor = require('./services/monitoring/DevDocsMonitor');
23
23
  const AstMonitor = require('./services/monitoring/AstMonitor');
24
+ const AuditLogger = require('./services/logging/AuditLogger');
24
25
 
25
26
  const path = require('path');
26
27
  const fs = require('fs');
28
+ const env = require('../config/env');
29
+
30
+ // Import recordMetric for prometheus metrics
31
+ const { recordMetric } = require('../infrastructure/telemetry/metrics-logger');
27
32
 
28
33
  class CompositionRoot {
29
34
  constructor(repoRoot) {
30
35
  this.repoRoot = repoRoot;
31
36
  this.instances = new Map();
32
37
 
38
+ this._initializeInfrastructure();
39
+ this._initializeServices();
40
+ this._initializeMonitors();
41
+ }
42
+
43
+ _initializeInfrastructure() {
33
44
  // Ensure audit directories exist
34
- this.auditDir = path.join(repoRoot, '.audit-reports');
35
- this.tempDir = path.join(repoRoot, '.audit_tmp');
45
+ this.auditDir = path.join(this.repoRoot, '.audit-reports');
46
+ this.tempDir = path.join(this.repoRoot, '.audit_tmp');
36
47
  this._ensureDirectories([this.auditDir, this.tempDir]);
48
+
49
+ // Audit log composition root creation
50
+ const auditLogger = this.getAuditLogger();
51
+ auditLogger.log({
52
+ action: 'composition_root_created',
53
+ category: 'system',
54
+ severity: 'info',
55
+ message: 'CompositionRoot initialized for dependency injection',
56
+ metadata: {
57
+ repoRoot: this.repoRoot,
58
+ auditDir: this.auditDir,
59
+ tempDir: this.tempDir
60
+ }
61
+ });
62
+ }
63
+
64
+ _initializeServices() {
65
+ // Services are created lazily when requested
66
+ // This reduces the initialization load
67
+ }
68
+
69
+ _initializeMonitors() {
70
+ // Monitors are created lazily when requested
71
+ // This reduces the initialization load
37
72
  }
38
73
 
39
74
  _ensureDirectories(dirs) {
@@ -51,7 +86,7 @@ class CompositionRoot {
51
86
  file: {
52
87
  enabled: true,
53
88
  path: path.join(this.auditDir, 'guard-audit.jsonl'),
54
- level: process.env.HOOK_LOG_LEVEL || 'info'
89
+ level: env.get('HOOK_LOG_LEVEL', env.isProd ? 'warn' : 'info')
55
90
  },
56
91
  console: {
57
92
  enabled: false,
@@ -73,6 +108,18 @@ class CompositionRoot {
73
108
  return this.instances.get('notificationService');
74
109
  }
75
110
 
111
+ getAuditLogger() {
112
+ if (!this.instances.has('auditLogger')) {
113
+ const logger = this.getLogger();
114
+ this.instances.set('auditLogger', new AuditLogger({
115
+ repoRoot: this.repoRoot,
116
+ filename: path.join('.audit_tmp', 'audit.log'),
117
+ logger
118
+ }));
119
+ }
120
+ return this.instances.get('auditLogger');
121
+ }
122
+
76
123
  // --- Infrastructure Adapters ---
77
124
 
78
125
  getNotificationAdapter() {
@@ -183,9 +230,9 @@ class CompositionRoot {
183
230
  getEvidenceMonitor() {
184
231
  if (!this.instances.has('evidenceMonitor')) {
185
232
  this.instances.set('evidenceMonitor', new EvidenceMonitor(this.repoRoot, {
186
- staleThresholdMs: Number(process.env.HOOK_GUARD_EVIDENCE_STALE_THRESHOLD || 180000),
187
- pollIntervalMs: Number(process.env.HOOK_GUARD_EVIDENCE_POLL_INTERVAL || 30000),
188
- reminderIntervalMs: Number(process.env.HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL || 60000)
233
+ staleThresholdMs: env.getNumber('HOOK_GUARD_EVIDENCE_STALE_THRESHOLD', 180000),
234
+ pollIntervalMs: env.getNumber('HOOK_GUARD_EVIDENCE_POLL_INTERVAL', 30000),
235
+ reminderIntervalMs: env.getNumber('HOOK_GUARD_EVIDENCE_REMINDER_INTERVAL', 60000)
189
236
  }));
190
237
  }
191
238
  return this.instances.get('evidenceMonitor');
@@ -194,11 +241,11 @@ class CompositionRoot {
194
241
  getGitTreeMonitor() {
195
242
  if (!this.instances.has('gitTreeMonitor')) {
196
243
  this.instances.set('gitTreeMonitor', new GitTreeMonitor(this.repoRoot, {
197
- stagedThreshold: Number(process.env.HOOK_GUARD_DIRTY_TREE_STAGED_LIMIT || 10),
198
- unstagedThreshold: Number(process.env.HOOK_GUARD_DIRTY_TREE_UNSTAGED_LIMIT || 15),
199
- totalThreshold: Number(process.env.HOOK_GUARD_DIRTY_TREE_TOTAL_LIMIT || 20),
200
- checkIntervalMs: Number(process.env.HOOK_GUARD_DIRTY_TREE_INTERVAL || 60000),
201
- reminderMs: Number(process.env.HOOK_GUARD_DIRTY_TREE_REMINDER || 300000)
244
+ stagedThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_STAGED_LIMIT', 10),
245
+ unstagedThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_UNSTAGED_LIMIT', 15),
246
+ totalThreshold: env.getNumber('HOOK_GUARD_DIRTY_TREE_TOTAL_LIMIT', 20),
247
+ checkIntervalMs: env.getNumber('HOOK_GUARD_DIRTY_TREE_INTERVAL', 60000),
248
+ reminderMs: env.getNumber('HOOK_GUARD_DIRTY_TREE_REMINDER', 300000)
202
249
  }));
203
250
  }
204
251
  return this.instances.get('gitTreeMonitor');
@@ -219,11 +266,11 @@ class CompositionRoot {
219
266
  const github = this.getGitHubAdapter();
220
267
 
221
268
  this.instances.set('gitFlowService', new GitFlowService(this.repoRoot, {
222
- developBranch: process.env.HOOK_GUARD_GITFLOW_DEVELOP_BRANCH || 'develop',
223
- mainBranch: process.env.HOOK_GUARD_GITFLOW_MAIN_BRANCH || 'main',
224
- autoSyncEnabled: process.env.HOOK_GUARD_GITFLOW_AUTOSYNC !== 'false',
225
- autoCleanEnabled: process.env.HOOK_GUARD_GITFLOW_AUTOCLEAN !== 'false',
226
- requireClean: process.env.HOOK_GUARD_GITFLOW_REQUIRE_CLEAN !== 'false'
269
+ developBranch: env.get('HOOK_GUARD_GITFLOW_DEVELOP_BRANCH', 'develop'),
270
+ mainBranch: env.get('HOOK_GUARD_GITFLOW_MAIN_BRANCH', 'main'),
271
+ autoSyncEnabled: env.getBool('HOOK_GUARD_GITFLOW_AUTOSYNC', true),
272
+ autoCleanEnabled: env.getBool('HOOK_GUARD_GITFLOW_AUTOCLEAN', true),
273
+ requireClean: env.getBool('HOOK_GUARD_GITFLOW_REQUIRE_CLEAN', true)
227
274
  }, logger, gitQuery, gitCommand, github));
228
275
  }
229
276
  return this.instances.get('gitFlowService');
@@ -234,7 +281,7 @@ class CompositionRoot {
234
281
  const logger = this.getLogger();
235
282
  this.instances.set('activityMonitor', new ActivityMonitor({
236
283
  repoRoot: this.repoRoot,
237
- inactivityGraceMs: Number(process.env.HOOK_GUARD_INACTIVITY_GRACE_MS || 420000),
284
+ inactivityGraceMs: env.getNumber('HOOK_GUARD_INACTIVITY_GRACE_MS', 420000),
238
285
  logger
239
286
  }));
240
287
  }
@@ -247,9 +294,9 @@ class CompositionRoot {
247
294
  const notificationService = this.getNotificationService();
248
295
  this.instances.set('devDocsMonitor', new DevDocsMonitor({
249
296
  repoRoot: this.repoRoot,
250
- checkIntervalMs: Number(process.env.HOOK_GUARD_DEV_DOCS_CHECK_INTERVAL || 300000),
251
- staleThresholdMs: Number(process.env.HOOK_GUARD_DEV_DOCS_STALE_THRESHOLD || 86400000),
252
- autoRefreshEnabled: process.env.HOOK_GUARD_DEV_DOCS_AUTO_REFRESH !== 'false',
297
+ checkIntervalMs: env.getNumber('HOOK_GUARD_DEV_DOCS_CHECK_INTERVAL', 300000),
298
+ staleThresholdMs: env.getNumber('HOOK_GUARD_DEV_DOCS_STALE_THRESHOLD', 86400000),
299
+ autoRefreshEnabled: env.getBool('HOOK_GUARD_DEV_DOCS_AUTO_REFRESH', true),
253
300
  logger,
254
301
  notificationService
255
302
  }));
@@ -263,9 +310,9 @@ class CompositionRoot {
263
310
  const notificationService = this.getNotificationService();
264
311
  this.instances.set('astMonitor', new AstMonitor({
265
312
  repoRoot: this.repoRoot,
266
- debounceMs: Number(process.env.HOOK_AST_WATCH_DEBOUNCE || 8000),
267
- cooldownMs: Number(process.env.HOOK_AST_WATCH_COOLDOWN || 30000),
268
- enabled: process.env.HOOK_AST_WATCH !== 'false',
313
+ debounceMs: env.getNumber('HOOK_AST_WATCH_DEBOUNCE', 8000),
314
+ cooldownMs: env.getNumber('HOOK_AST_WATCH_COOLDOWN', 30000),
315
+ enabled: env.getBool('HOOK_AST_WATCH', true),
269
316
  logger,
270
317
  notificationService
271
318
  }));
@@ -291,6 +338,7 @@ class CompositionRoot {
291
338
  const notificationService = this.getNotificationService();
292
339
  const monitors = this.getMonitors();
293
340
  const orchestrator = this.getOrchestrator();
341
+ const auditLogger = this.getAuditLogger();
294
342
  const config = {
295
343
  debugLogPath: path.join(this.auditDir, 'guard-debug.log'),
296
344
  repoRoot: this.repoRoot
@@ -301,7 +349,8 @@ class CompositionRoot {
301
349
  notificationService,
302
350
  monitors,
303
351
  orchestration: orchestrator,
304
- config
352
+ config,
353
+ auditLogger
305
354
  }));
306
355
  }
307
356
  return this.instances.get('guardService');
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs').promises;
2
2
  const path = require('path');
3
+ const env = require('../config/env');
3
4
 
4
5
  class DynamicRulesLoader {
5
6
  constructor(rulesDirectory, logger = console) {
@@ -27,7 +28,7 @@ class DynamicRulesLoader {
27
28
  return [this.rulesDirectory];
28
29
  }
29
30
 
30
- const envRaw = process.env.AST_RULES_DIRECTORIES;
31
+ const envRaw = env.get('AST_RULES_DIRECTORIES');
31
32
  if (envRaw && typeof envRaw === 'string' && envRaw.trim().length > 0) {
32
33
  return envRaw
33
34
  .split(',')