claude-flow-novice 1.6.1 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/.claude/agents/cfn-loop/product-owner.md +54 -4
  2. package/.claude/commands/cfn-claude-sync.md +303 -0
  3. package/.claude/commands/cfn-loop-epic.md +290 -0
  4. package/.claude/commands/cfn-loop-single.md +168 -0
  5. package/.claude/commands/cfn-loop-sprints.md +384 -0
  6. package/.claude/commands/cfn-loop.md +180 -0
  7. package/.claude/commands/metrics-summary.md +58 -0
  8. package/.claude/commands/parse-epic.md +357 -0
  9. package/.claude/settings.json +4 -4
  10. package/.claude/settings.local.json +9 -2
  11. package/.claude-flow-novice/.claude/agents/cfn-loop/product-owner.md +792 -0
  12. package/.claude-flow-novice/dist/mcp/server.js +21 -2
  13. package/.claude-flow-novice/dist/src/api/claude-client.js +138 -3
  14. package/.claude-flow-novice/dist/src/api/claude-client.js.map +1 -1
  15. package/.claude-flow-novice/dist/src/cfn-loop/phase-orchestrator-example.js +1 -1
  16. package/.claude-flow-novice/dist/src/cfn-loop/scope-control.js +247 -0
  17. package/.claude-flow-novice/dist/src/cfn-loop/scope-control.js.map +1 -0
  18. package/.claude-flow-novice/dist/src/cli/commands/swarm.js +32 -15
  19. package/.claude-flow-novice/dist/src/cli/commands/swarm.js.map +1 -1
  20. package/.claude-flow-novice/dist/src/cli/commands/transparency.js +455 -0
  21. package/.claude-flow-novice/dist/src/cli/commands/transparency.js.map +1 -0
  22. package/.claude-flow-novice/dist/src/cli/simple-commands/init/templates/CLAUDE.md +129 -13
  23. package/.claude-flow-novice/dist/src/components/visualizations/index.js +9 -0
  24. package/.claude-flow-novice/dist/src/components/visualizations/index.js.map +1 -0
  25. package/.claude-flow-novice/dist/src/coordination/adapters/v1-coordinator-adapter.js +462 -0
  26. package/.claude-flow-novice/dist/src/coordination/adapters/v1-coordinator-adapter.js.map +1 -0
  27. package/.claude-flow-novice/dist/src/coordination/config-translator.js +248 -0
  28. package/.claude-flow-novice/dist/src/coordination/config-translator.js.map +1 -0
  29. package/.claude-flow-novice/dist/src/coordination/coordination-toggle.js +287 -0
  30. package/.claude-flow-novice/dist/src/coordination/coordination-toggle.js.map +1 -0
  31. package/.claude-flow-novice/dist/src/coordination/distributed-consensus.js +68 -9
  32. package/.claude-flow-novice/dist/src/coordination/distributed-consensus.js.map +1 -1
  33. package/.claude-flow-novice/dist/src/coordination/feature-flags.js +166 -0
  34. package/.claude-flow-novice/dist/src/coordination/feature-flags.js.map +1 -0
  35. package/.claude-flow-novice/dist/src/coordination/queen-agent.js +18 -4
  36. package/.claude-flow-novice/dist/src/coordination/queen-agent.js.map +1 -1
  37. package/.claude-flow-novice/dist/src/coordination/role-assignment.js +6 -110
  38. package/.claude-flow-novice/dist/src/coordination/role-assignment.js.map +1 -1
  39. package/.claude-flow-novice/dist/src/coordination/v2/cache/artifact-cache-optimizer.js +632 -0
  40. package/.claude-flow-novice/dist/src/coordination/v2/cache/artifact-cache-optimizer.js.map +1 -0
  41. package/.claude-flow-novice/dist/src/coordination/v2/cache/index.js +11 -0
  42. package/.claude-flow-novice/dist/src/coordination/v2/cache/index.js.map +1 -0
  43. package/.claude-flow-novice/dist/src/coordination/v2/checkpoints/checkpoint-compressor.js +318 -0
  44. package/.claude-flow-novice/dist/src/coordination/v2/checkpoints/checkpoint-compressor.js.map +1 -0
  45. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.example.js +364 -0
  46. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.example.js.map +1 -0
  47. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.js +492 -0
  48. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/cascading-shutdown.js.map +1 -0
  49. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/hierarchical-coordinator.js +786 -0
  50. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/hierarchical-coordinator.js.map +1 -0
  51. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/index.js +16 -0
  52. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/index.js.map +1 -0
  53. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/parent-child-manager.js +342 -0
  54. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/parent-child-manager.js.map +1 -0
  55. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/swarm-coordinator-v2.js +601 -0
  56. package/.claude-flow-novice/dist/src/coordination/v2/coordinators/swarm-coordinator-v2.js.map +1 -0
  57. package/.claude-flow-novice/dist/src/coordination/v2/core/help-request-metrics.js +211 -0
  58. package/.claude-flow-novice/dist/src/coordination/v2/core/help-request-metrics.js.map +1 -0
  59. package/.claude-flow-novice/dist/src/coordination/v2/core/index.js +1 -0
  60. package/.claude-flow-novice/dist/src/coordination/v2/core/index.js.map +1 -1
  61. package/.claude-flow-novice/dist/src/coordination/v2/core/message-broker.js +365 -6
  62. package/.claude-flow-novice/dist/src/coordination/v2/core/message-broker.js.map +1 -1
  63. package/.claude-flow-novice/dist/src/coordination/v2/core/resource-manager-safe.js +478 -0
  64. package/.claude-flow-novice/dist/src/coordination/v2/core/resource-manager-safe.js.map +1 -0
  65. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine-config.js +5 -2
  66. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine-config.js.map +1 -1
  67. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine.js +189 -0
  68. package/.claude-flow-novice/dist/src/coordination/v2/core/state-machine.js.map +1 -1
  69. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/deadlock-detector.js +424 -0
  70. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/deadlock-detector.js.map +1 -0
  71. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/index.js +9 -0
  72. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/index.js.map +1 -0
  73. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/resource-manager.js +669 -0
  74. package/.claude-flow-novice/dist/src/coordination/v2/deadlock/resource-manager.js.map +1 -0
  75. package/.claude-flow-novice/dist/src/coordination/v2/dependency/artifact-storage.js +451 -0
  76. package/.claude-flow-novice/dist/src/coordination/v2/dependency/artifact-storage.js.map +1 -0
  77. package/.claude-flow-novice/dist/src/coordination/v2/dependency/cycle-detector.js +271 -0
  78. package/.claude-flow-novice/dist/src/coordination/v2/dependency/cycle-detector.js.map +1 -0
  79. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-graph.js +335 -0
  80. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-graph.js.map +1 -0
  81. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-manager.js +439 -0
  82. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-manager.js.map +1 -0
  83. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-request.js +92 -0
  84. package/.claude-flow-novice/dist/src/coordination/v2/dependency/dependency-request.js.map +1 -0
  85. package/.claude-flow-novice/dist/src/coordination/v2/dependency/index.js +21 -0
  86. package/.claude-flow-novice/dist/src/coordination/v2/dependency/index.js.map +1 -0
  87. package/.claude-flow-novice/dist/src/coordination/v2/dependency/topological-sort.js +223 -0
  88. package/.claude-flow-novice/dist/src/coordination/v2/dependency/topological-sort.js.map +1 -0
  89. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-coordinator.js +436 -0
  90. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-coordinator.js.map +1 -0
  91. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-matcher.js +278 -0
  92. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-matcher.js.map +1 -0
  93. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request-handler.js +317 -0
  94. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request-handler.js.map +1 -0
  95. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request.js +273 -0
  96. package/.claude-flow-novice/dist/src/coordination/v2/help-system/help-request.js.map +1 -0
  97. package/.claude-flow-novice/dist/src/coordination/v2/help-system/index.js +15 -0
  98. package/.claude-flow-novice/dist/src/coordination/v2/help-system/index.js.map +1 -0
  99. package/.claude-flow-novice/dist/src/coordination/v2/help-system/waiting-agent-pool.js +512 -0
  100. package/.claude-flow-novice/dist/src/coordination/v2/help-system/waiting-agent-pool.js.map +1 -0
  101. package/.claude-flow-novice/dist/src/coordination/v2/index.js +6 -0
  102. package/.claude-flow-novice/dist/src/coordination/v2/index.js.map +1 -1
  103. package/.claude-flow-novice/dist/src/coordination/v2/integration/help-deadlock-integration.js +557 -0
  104. package/.claude-flow-novice/dist/src/coordination/v2/integration/help-deadlock-integration.js.map +1 -0
  105. package/.claude-flow-novice/dist/src/coordination/v2/integration/index.js +14 -0
  106. package/.claude-flow-novice/dist/src/coordination/v2/integration/index.js.map +1 -0
  107. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.example.js +212 -0
  108. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.example.js.map +1 -0
  109. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.js +552 -0
  110. package/.claude-flow-novice/dist/src/coordination/v2/integration/message-bus-completion-integration.js.map +1 -0
  111. package/.claude-flow-novice/dist/src/coordination/v2/memory/dependency-storage.js +367 -0
  112. package/.claude-flow-novice/dist/src/coordination/v2/memory/dependency-storage.js.map +1 -0
  113. package/.claude-flow-novice/dist/src/coordination/v2/memory/index.js +1 -0
  114. package/.claude-flow-novice/dist/src/coordination/v2/memory/index.js.map +1 -1
  115. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channel.js +371 -0
  116. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channel.js.map +1 -0
  117. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/dependency-channel.js +355 -0
  118. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/dependency-channel.js.map +1 -0
  119. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/help-channel.js +424 -0
  120. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/help-channel.js.map +1 -0
  121. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/index.js +16 -0
  122. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/index.js.map +1 -0
  123. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/state-channel.js +295 -0
  124. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/state-channel.js.map +1 -0
  125. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/task-channel.js +411 -0
  126. package/.claude-flow-novice/dist/src/coordination/v2/messaging/channels/task-channel.js.map +1 -0
  127. package/.claude-flow-novice/dist/src/coordination/v2/messaging/index.js +14 -0
  128. package/.claude-flow-novice/dist/src/coordination/v2/messaging/index.js.map +1 -0
  129. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-bus.js +387 -0
  130. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-bus.js.map +1 -0
  131. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-persistence.js +589 -0
  132. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-persistence.js.map +1 -0
  133. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-router.js +444 -0
  134. package/.claude-flow-novice/dist/src/coordination/v2/messaging/message-router.js.map +1 -0
  135. package/.claude-flow-novice/dist/src/coordination/v2/sdk/checkpoint-manager.js +29 -8
  136. package/.claude-flow-novice/dist/src/coordination/v2/sdk/checkpoint-manager.js.map +1 -1
  137. package/.claude-flow-novice/dist/src/coordination/v2/sdk/help-coordinator.js +470 -0
  138. package/.claude-flow-novice/dist/src/coordination/v2/sdk/help-coordinator.js.map +1 -0
  139. package/.claude-flow-novice/dist/src/coordination/v2/sdk/hierarchical-background-integration.js +450 -0
  140. package/.claude-flow-novice/dist/src/coordination/v2/sdk/hierarchical-background-integration.js.map +1 -0
  141. package/.claude-flow-novice/dist/src/coordination/v2/sdk/index.js +5 -0
  142. package/.claude-flow-novice/dist/src/coordination/v2/sdk/index.js.map +1 -1
  143. package/.claude-flow-novice/dist/src/coordination/v2/sdk/multi-level-control.js +545 -0
  144. package/.claude-flow-novice/dist/src/coordination/v2/sdk/multi-level-control.js.map +1 -0
  145. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-controller.js +44 -0
  146. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-controller.js.map +1 -1
  147. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-message-integration.js +415 -0
  148. package/.claude-flow-novice/dist/src/coordination/v2/sdk/query-message-integration.js.map +1 -0
  149. package/.claude-flow-novice/dist/src/coordination/v2/sdk/session-pool-optimizer.js +615 -0
  150. package/.claude-flow-novice/dist/src/coordination/v2/sdk/session-pool-optimizer.js.map +1 -0
  151. package/.claude-flow-novice/dist/src/coordination/v2/security/payload-validator.js +259 -0
  152. package/.claude-flow-novice/dist/src/coordination/v2/security/payload-validator.js.map +1 -0
  153. package/.claude-flow-novice/dist/src/coordination/v2/transparency/index.js +17 -0
  154. package/.claude-flow-novice/dist/src/coordination/v2/transparency/index.js.map +1 -0
  155. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-integration.js +357 -0
  156. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-integration.js.map +1 -0
  157. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-system.js +679 -0
  158. package/.claude-flow-novice/dist/src/coordination/v2/transparency/transparency-system.js.map +1 -0
  159. package/.claude-flow-novice/dist/src/core/agent-manager.js +30 -0
  160. package/.claude-flow-novice/dist/src/core/agent-manager.js.map +1 -1
  161. package/.claude-flow-novice/dist/src/mcp/server.js +21 -2
  162. package/.claude-flow-novice/dist/src/mcp/server.js.map +1 -1
  163. package/.claude-flow-novice/dist/src/observability/metrics-counter.js +268 -0
  164. package/.claude-flow-novice/dist/src/observability/metrics-counter.js.map +1 -0
  165. package/.claude-flow-novice/dist/src/observability/metrics-storage.js +265 -0
  166. package/.claude-flow-novice/dist/src/observability/metrics-storage.js.map +1 -0
  167. package/.claude-flow-novice/dist/src/observability/telemetry.js +26 -0
  168. package/.claude-flow-novice/dist/src/observability/telemetry.js.map +1 -1
  169. package/.claude-flow-novice/dist/src/providers/tiered-router.js +64 -10
  170. package/.claude-flow-novice/dist/src/providers/tiered-router.js.map +1 -1
  171. package/.claude-flow-novice/dist/src/providers/zai-provider.js +196 -97
  172. package/.claude-flow-novice/dist/src/providers/zai-provider.js.map +1 -1
  173. package/.claude-flow-novice/dist/src/slash-commands/cfn-claude-sync.js +533 -0
  174. package/.claude-flow-novice/dist/src/slash-commands/index.js +5 -0
  175. package/.claude-flow-novice/dist/src/slash-commands/metrics-summary-class.js +74 -0
  176. package/.claude-flow-novice/dist/src/slash-commands/metrics-summary.js +335 -0
  177. package/.claude-flow-novice/dist/src/slash-commands/register-all-commands.js +12 -0
  178. package/.claude-flow-novice/dist/src/verification/checkpoint-compression-demo.js +96 -0
  179. package/.claude-flow-novice/dist/src/verification/checkpoint-compression-demo.js.map +1 -0
  180. package/.claude-flow-novice/dist/src/verification/checkpoint-compression.js +406 -0
  181. package/.claude-flow-novice/dist/src/verification/checkpoint-compression.js.map +1 -0
  182. package/.claude-flow-novice/dist/src/verification/checkpoint-manager.js +35 -5
  183. package/.claude-flow-novice/dist/src/verification/checkpoint-manager.js.map +1 -1
  184. package/.claude-flow-novice/dist/src/web/api/config/api-config.js +186 -0
  185. package/.claude-flow-novice/dist/src/web/api/config/api-config.js.map +1 -0
  186. package/.claude-flow-novice/dist/src/web/api/middleware/auth.js +205 -0
  187. package/.claude-flow-novice/dist/src/web/api/middleware/auth.js.map +1 -0
  188. package/.claude-flow-novice/dist/src/web/api/middleware/cache.js +262 -0
  189. package/.claude-flow-novice/dist/src/web/api/middleware/cache.js.map +1 -0
  190. package/.claude-flow-novice/dist/src/web/api/middleware/error-handler.js +250 -0
  191. package/.claude-flow-novice/dist/src/web/api/middleware/error-handler.js.map +1 -0
  192. package/.claude-flow-novice/dist/src/web/api/middleware/request-logger.js +217 -0
  193. package/.claude-flow-novice/dist/src/web/api/middleware/request-logger.js.map +1 -0
  194. package/.claude-flow-novice/dist/src/web/api/middleware/validation.js +325 -0
  195. package/.claude-flow-novice/dist/src/web/api/middleware/validation.js.map +1 -0
  196. package/.claude-flow-novice/dist/src/web/api/routes/events.js +465 -0
  197. package/.claude-flow-novice/dist/src/web/api/routes/events.js.map +1 -0
  198. package/.claude-flow-novice/dist/src/web/api/routes/hierarchy.js +302 -0
  199. package/.claude-flow-novice/dist/src/web/api/routes/hierarchy.js.map +1 -0
  200. package/.claude-flow-novice/dist/src/web/api/routes/index.js +14 -0
  201. package/.claude-flow-novice/dist/src/web/api/routes/index.js.map +1 -0
  202. package/.claude-flow-novice/dist/src/web/api/routes/metrics.js +561 -0
  203. package/.claude-flow-novice/dist/src/web/api/routes/metrics.js.map +1 -0
  204. package/.claude-flow-novice/dist/src/web/api/routes/status.js +450 -0
  205. package/.claude-flow-novice/dist/src/web/api/routes/status.js.map +1 -0
  206. package/.claude-flow-novice/dist/src/web/api/server.js +451 -0
  207. package/.claude-flow-novice/dist/src/web/api/server.js.map +1 -0
  208. package/.claude-flow-novice/dist/src/web/dashboard/hooks/useWebSocket.js +385 -0
  209. package/.claude-flow-novice/dist/src/web/dashboard/hooks/useWebSocket.js.map +1 -0
  210. package/.claude-flow-novice/dist/src/web/dashboard/index.js +87 -0
  211. package/.claude-flow-novice/dist/src/web/dashboard/index.js.map +1 -0
  212. package/.claude-flow-novice/dist/src/web/dashboard/types.js +6 -0
  213. package/.claude-flow-novice/dist/src/web/dashboard/types.js.map +1 -0
  214. package/.claude-flow-novice/metrics.db +0 -0
  215. package/.claude-flow-novice/metrics.db-shm +0 -0
  216. package/.claude-flow-novice/metrics.db-wal +0 -0
  217. package/CLAUDE.md +29 -0
  218. package/README.md +27 -0
  219. package/config/hooks/post-edit-pipeline.js +36 -2
  220. package/examples/metrics-counter-demo.ts +106 -0
  221. package/examples/persistent-metrics-demo.ts +83 -0
  222. package/examples/phase-5-multi-level-control.ts +282 -0
  223. package/examples/session-pool-optimizer-example.ts +311 -0
  224. package/package.json +15 -3
  225. package/scripts/check-routing-stats.cjs +122 -0
  226. package/scripts/pre-publish-validation.cjs +212 -0
  227. package/scripts/test-provider-routing.cjs +228 -0
  228. package/scripts/test-routing-telemetry.cjs +147 -0
  229. package/scripts/test-zai-10k.cjs +81 -0
  230. package/scripts/test-zai-api.cjs +191 -0
  231. package/scripts/test-zai-diagnostic.cjs +151 -0
  232. package/scripts/test-zai-final.cjs +128 -0
  233. package/scripts/test-zai-with-env.cjs +85 -0
  234. package/scripts/validate-coordination-cli.js +69 -0
  235. package/scripts/validate-coordination-toggle-integration.cjs +501 -0
  236. package/src/cli/simple-commands/init/templates/CLAUDE.md +29 -0
  237. package/src/observability/metrics-counter.ts +347 -0
  238. package/src/observability/metrics-storage.ts +356 -0
  239. package/src/observability/telemetry.ts +658 -0
  240. package/src/slash-commands/cfn-claude-sync.js +533 -0
  241. package/src/slash-commands/index.js +5 -0
  242. package/src/slash-commands/metrics-summary-class.js +74 -0
  243. package/src/slash-commands/metrics-summary.js +335 -0
  244. package/src/slash-commands/register-all-commands.js +12 -0
@@ -0,0 +1,658 @@
1
+ /**
2
+ * Observability Infrastructure for Hierarchical Orchestration
3
+ *
4
+ * Provides distributed tracing, structured logging, and metrics collection
5
+ * for agent coordination and task delegation.
6
+ *
7
+ * @module observability/telemetry
8
+ */
9
+
10
+ import { EventEmitter } from 'node:events';
11
+ import { Logger } from '../core/logger.js';
12
+ import { generateId } from '../utils/helpers.js';
13
+ import { getGlobalMetricsStorage, type MetricsStorage } from './metrics-storage.js';
14
+
15
+ // ============================================================================
16
+ // Types & Interfaces
17
+ // ============================================================================
18
+
19
+ export interface TraceContext {
20
+ traceId: string;
21
+ spanId: string;
22
+ parentSpanId?: string;
23
+ startTime: Date;
24
+ endTime?: Date;
25
+ duration?: number;
26
+ tags: Record<string, string | number | boolean>;
27
+ logs: TraceLog[];
28
+ status: 'active' | 'completed' | 'failed';
29
+ }
30
+
31
+ export interface TraceLog {
32
+ timestamp: Date;
33
+ level: 'debug' | 'info' | 'warn' | 'error';
34
+ message: string;
35
+ fields: Record<string, any>;
36
+ }
37
+
38
+ export interface MetricPoint {
39
+ name: string;
40
+ value: number;
41
+ timestamp: Date;
42
+ tags: Record<string, string>;
43
+ type: 'counter' | 'gauge' | 'histogram' | 'timer';
44
+ }
45
+
46
+ export interface StructuredLogEntry {
47
+ timestamp: Date;
48
+ level: 'debug' | 'info' | 'warn' | 'error';
49
+ message: string;
50
+ correlationId: string;
51
+ traceId?: string;
52
+ workerId?: string;
53
+ taskId?: string;
54
+ fields: Record<string, any>;
55
+ }
56
+
57
+ export interface LatencyMetrics {
58
+ p50: number;
59
+ p90: number;
60
+ p95: number;
61
+ p99: number;
62
+ mean: number;
63
+ min: number;
64
+ max: number;
65
+ count: number;
66
+ }
67
+
68
+ export interface ThroughputMetrics {
69
+ totalRequests: number;
70
+ successfulRequests: number;
71
+ failedRequests: number;
72
+ requestsPerSecond: number;
73
+ successRate: number;
74
+ failureRate: number;
75
+ }
76
+
77
+ export interface TelemetryConfig {
78
+ enableTracing: boolean;
79
+ enableMetrics: boolean;
80
+ enableStructuredLogging: boolean;
81
+ enablePersistence: boolean; // Store metrics to SQLite
82
+ metricsFlushInterval: number; // ms
83
+ traceSamplingRate: number; // 0-1
84
+ maxTraceHistory: number;
85
+ maxMetricHistory: number;
86
+ }
87
+
88
+ // ============================================================================
89
+ // Telemetry System
90
+ // ============================================================================
91
+
92
+ export class TelemetrySystem extends EventEmitter {
93
+ private logger: Logger;
94
+ private config: TelemetryConfig;
95
+ private storage?: MetricsStorage;
96
+
97
+ // Tracing
98
+ private activeTraces: Map<string, TraceContext> = new Map();
99
+ private completedTraces: TraceContext[] = [];
100
+
101
+ // Metrics
102
+ private metrics: Map<string, MetricPoint[]> = new Map();
103
+ private latencyBuffer: Map<string, number[]> = new Map();
104
+ private metricsFlushTimer?: NodeJS.Timeout;
105
+
106
+ // Structured Logging
107
+ private logBuffer: StructuredLogEntry[] = [];
108
+ private readonly maxLogBuffer = 1000;
109
+
110
+ constructor(config: Partial<TelemetryConfig> = {}) {
111
+ super();
112
+
113
+ this.config = {
114
+ enableTracing: config.enableTracing ?? true,
115
+ enableMetrics: config.enableMetrics ?? true,
116
+ enableStructuredLogging: config.enableStructuredLogging ?? true,
117
+ enablePersistence: config.enablePersistence ?? true, // Default: persist to SQLite
118
+ metricsFlushInterval: config.metricsFlushInterval ?? 60000, // 1 minute
119
+ traceSamplingRate: config.traceSamplingRate ?? 1.0,
120
+ maxTraceHistory: config.maxTraceHistory ?? 100,
121
+ maxMetricHistory: config.maxMetricHistory ?? 1000,
122
+ };
123
+
124
+ this.logger = new Logger(
125
+ { level: 'info', format: 'json', destination: 'console' },
126
+ { component: 'TelemetrySystem' }
127
+ );
128
+
129
+ // Initialize persistent storage if enabled
130
+ if (this.config.enablePersistence) {
131
+ try {
132
+ this.storage = getGlobalMetricsStorage();
133
+ } catch (error) {
134
+ this.logger.warn('Failed to initialize metrics storage, persistence disabled', { error });
135
+ this.config.enablePersistence = false;
136
+ }
137
+ }
138
+ }
139
+
140
+ // ============================================================================
141
+ // Distributed Tracing
142
+ // ============================================================================
143
+
144
+ /**
145
+ * Start a new trace span
146
+ */
147
+ startSpan(
148
+ operation: string,
149
+ parentSpanId?: string,
150
+ tags: Record<string, string | number | boolean> = {}
151
+ ): TraceContext {
152
+ if (!this.config.enableTracing) {
153
+ return this.createNoOpTrace();
154
+ }
155
+
156
+ // Sampling decision
157
+ if (Math.random() > this.config.traceSamplingRate) {
158
+ return this.createNoOpTrace();
159
+ }
160
+
161
+ const traceId = generateId('trace');
162
+ const spanId = generateId('span');
163
+
164
+ const trace: TraceContext = {
165
+ traceId,
166
+ spanId,
167
+ parentSpanId,
168
+ startTime: new Date(),
169
+ tags: {
170
+ operation,
171
+ ...tags,
172
+ },
173
+ logs: [],
174
+ status: 'active',
175
+ };
176
+
177
+ this.activeTraces.set(spanId, trace);
178
+
179
+ this.emit('trace:started', trace);
180
+ this.logger.debug('Trace span started', {
181
+ traceId,
182
+ spanId,
183
+ operation,
184
+ parentSpanId,
185
+ });
186
+
187
+ return trace;
188
+ }
189
+
190
+ /**
191
+ * End a trace span
192
+ */
193
+ endSpan(spanId: string, status: 'completed' | 'failed' = 'completed'): void {
194
+ if (!this.config.enableTracing) {
195
+ return;
196
+ }
197
+
198
+ const trace = this.activeTraces.get(spanId);
199
+ if (!trace) {
200
+ this.logger.warn('Attempted to end non-existent trace span', { spanId });
201
+ return;
202
+ }
203
+
204
+ trace.endTime = new Date();
205
+ trace.duration = trace.endTime.getTime() - trace.startTime.getTime();
206
+ trace.status = status;
207
+
208
+ this.activeTraces.delete(spanId);
209
+ this.completedTraces.push(trace);
210
+
211
+ // Maintain history limit
212
+ if (this.completedTraces.length > this.config.maxTraceHistory) {
213
+ this.completedTraces.shift();
214
+ }
215
+
216
+ this.emit('trace:ended', trace);
217
+ this.logger.debug('Trace span ended', {
218
+ traceId: trace.traceId,
219
+ spanId,
220
+ duration: trace.duration,
221
+ status,
222
+ });
223
+ }
224
+
225
+ /**
226
+ * Add log to trace span
227
+ */
228
+ addTraceLog(
229
+ spanId: string,
230
+ level: TraceLog['level'],
231
+ message: string,
232
+ fields: Record<string, any> = {}
233
+ ): void {
234
+ const trace = this.activeTraces.get(spanId);
235
+ if (!trace) {
236
+ return;
237
+ }
238
+
239
+ trace.logs.push({
240
+ timestamp: new Date(),
241
+ level,
242
+ message,
243
+ fields,
244
+ });
245
+ }
246
+
247
+ /**
248
+ * Add tags to trace span
249
+ */
250
+ addTraceTags(spanId: string, tags: Record<string, string | number | boolean>): void {
251
+ const trace = this.activeTraces.get(spanId);
252
+ if (!trace) {
253
+ return;
254
+ }
255
+
256
+ Object.assign(trace.tags, tags);
257
+ }
258
+
259
+ /**
260
+ * Get trace by ID
261
+ */
262
+ getTrace(traceId: string): TraceContext | undefined {
263
+ // Check active traces
264
+ for (const trace of this.activeTraces.values()) {
265
+ if (trace.traceId === traceId) {
266
+ return trace;
267
+ }
268
+ }
269
+
270
+ // Check completed traces
271
+ return this.completedTraces.find(t => t.traceId === traceId);
272
+ }
273
+
274
+ /**
275
+ * Get all traces for correlation ID
276
+ */
277
+ getTracesByCorrelation(correlationId: string): TraceContext[] {
278
+ return this.completedTraces.filter(
279
+ t => t.tags.correlationId === correlationId
280
+ );
281
+ }
282
+
283
+ // ============================================================================
284
+ // Metrics Collection
285
+ // ============================================================================
286
+
287
+ /**
288
+ * Record a counter metric (increments)
289
+ */
290
+ recordCounter(name: string, value: number = 1, tags: Record<string, string> = {}): void {
291
+ if (!this.config.enableMetrics) {
292
+ return;
293
+ }
294
+
295
+ const metric: MetricPoint = {
296
+ name,
297
+ value,
298
+ timestamp: new Date(),
299
+ tags,
300
+ type: 'counter',
301
+ };
302
+
303
+ this.storeMetric(name, metric);
304
+ this.emit('metric:counter', metric);
305
+ }
306
+
307
+ /**
308
+ * Record a gauge metric (point-in-time value)
309
+ */
310
+ recordGauge(name: string, value: number, tags: Record<string, string> = {}): void {
311
+ if (!this.config.enableMetrics) {
312
+ return;
313
+ }
314
+
315
+ const metric: MetricPoint = {
316
+ name,
317
+ value,
318
+ timestamp: new Date(),
319
+ tags,
320
+ type: 'gauge',
321
+ };
322
+
323
+ this.storeMetric(name, metric);
324
+ this.emit('metric:gauge', metric);
325
+ }
326
+
327
+ /**
328
+ * Record a timer metric (duration)
329
+ */
330
+ recordTimer(name: string, durationMs: number, tags: Record<string, string> = {}): void {
331
+ if (!this.config.enableMetrics) {
332
+ return;
333
+ }
334
+
335
+ const metric: MetricPoint = {
336
+ name,
337
+ value: durationMs,
338
+ timestamp: new Date(),
339
+ tags,
340
+ type: 'timer',
341
+ };
342
+
343
+ this.storeMetric(name, metric);
344
+
345
+ // Add to latency buffer for percentile calculations
346
+ if (!this.latencyBuffer.has(name)) {
347
+ this.latencyBuffer.set(name, []);
348
+ }
349
+ this.latencyBuffer.get(name)!.push(durationMs);
350
+
351
+ this.emit('metric:timer', metric);
352
+ }
353
+
354
+ /**
355
+ * Record a histogram metric
356
+ */
357
+ recordHistogram(name: string, value: number, tags: Record<string, string> = {}): void {
358
+ if (!this.config.enableMetrics) {
359
+ return;
360
+ }
361
+
362
+ const metric: MetricPoint = {
363
+ name,
364
+ value,
365
+ timestamp: new Date(),
366
+ tags,
367
+ type: 'histogram',
368
+ };
369
+
370
+ this.storeMetric(name, metric);
371
+ this.emit('metric:histogram', metric);
372
+ }
373
+
374
+ /**
375
+ * Get latency metrics for operation
376
+ */
377
+ getLatencyMetrics(operationName: string): LatencyMetrics | null {
378
+ const latencies = this.latencyBuffer.get(operationName);
379
+ if (!latencies || latencies.length === 0) {
380
+ return null;
381
+ }
382
+
383
+ const sorted = [...latencies].sort((a, b) => a - b);
384
+ const count = sorted.length;
385
+
386
+ return {
387
+ p50: this.percentile(sorted, 0.5),
388
+ p90: this.percentile(sorted, 0.9),
389
+ p95: this.percentile(sorted, 0.95),
390
+ p99: this.percentile(sorted, 0.99),
391
+ mean: sorted.reduce((sum, val) => sum + val, 0) / count,
392
+ min: sorted[0],
393
+ max: sorted[count - 1],
394
+ count,
395
+ };
396
+ }
397
+
398
+ /**
399
+ * Get throughput metrics for operation
400
+ */
401
+ getThroughputMetrics(operationName: string, windowMs: number = 60000): ThroughputMetrics {
402
+ const now = Date.now();
403
+ const windowStart = now - windowMs;
404
+
405
+ const metrics = this.metrics.get(operationName) || [];
406
+ const recentMetrics = metrics.filter(
407
+ m => m.timestamp.getTime() >= windowStart
408
+ );
409
+
410
+ const totalRequests = recentMetrics.length;
411
+ const successfulRequests = recentMetrics.filter(
412
+ m => m.tags.status === 'success'
413
+ ).length;
414
+ const failedRequests = totalRequests - successfulRequests;
415
+
416
+ const requestsPerSecond = (totalRequests / windowMs) * 1000;
417
+ const successRate = totalRequests > 0 ? successfulRequests / totalRequests : 0;
418
+ const failureRate = totalRequests > 0 ? failedRequests / totalRequests : 0;
419
+
420
+ return {
421
+ totalRequests,
422
+ successfulRequests,
423
+ failedRequests,
424
+ requestsPerSecond,
425
+ successRate,
426
+ failureRate,
427
+ };
428
+ }
429
+
430
+ /**
431
+ * Get all metrics for a name
432
+ */
433
+ getMetrics(name: string, windowMs?: number): MetricPoint[] {
434
+ const metrics = this.metrics.get(name) || [];
435
+
436
+ if (!windowMs) {
437
+ return metrics;
438
+ }
439
+
440
+ const now = Date.now();
441
+ const windowStart = now - windowMs;
442
+
443
+ return metrics.filter(m => m.timestamp.getTime() >= windowStart);
444
+ }
445
+
446
+ // ============================================================================
447
+ // Structured Logging
448
+ // ============================================================================
449
+
450
+ /**
451
+ * Write structured log entry
452
+ */
453
+ log(
454
+ level: StructuredLogEntry['level'],
455
+ message: string,
456
+ correlationId: string,
457
+ fields: Record<string, any> = {}
458
+ ): void {
459
+ if (!this.config.enableStructuredLogging) {
460
+ return;
461
+ }
462
+
463
+ const entry: StructuredLogEntry = {
464
+ timestamp: new Date(),
465
+ level,
466
+ message,
467
+ correlationId,
468
+ traceId: fields.traceId,
469
+ workerId: fields.workerId,
470
+ taskId: fields.taskId,
471
+ fields,
472
+ };
473
+
474
+ this.logBuffer.push(entry);
475
+
476
+ // Maintain buffer limit
477
+ if (this.logBuffer.length > this.maxLogBuffer) {
478
+ this.logBuffer.shift();
479
+ }
480
+
481
+ this.emit('log:entry', entry);
482
+
483
+ // Also log to standard logger
484
+ this.logger[level](message, fields);
485
+ }
486
+
487
+ /**
488
+ * Get recent log entries
489
+ */
490
+ getRecentLogs(count: number = 100, level?: StructuredLogEntry['level']): StructuredLogEntry[] {
491
+ let logs = this.logBuffer;
492
+
493
+ if (level) {
494
+ logs = logs.filter(l => l.level === level);
495
+ }
496
+
497
+ return logs.slice(-count);
498
+ }
499
+
500
+ /**
501
+ * Get logs by correlation ID
502
+ */
503
+ getLogsByCorrelation(correlationId: string): StructuredLogEntry[] {
504
+ return this.logBuffer.filter(l => l.correlationId === correlationId);
505
+ }
506
+
507
+ // ============================================================================
508
+ // Lifecycle Management
509
+ // ============================================================================
510
+
511
+ /**
512
+ * Initialize telemetry system
513
+ */
514
+ initialize(): void {
515
+ this.logger.info('Initializing telemetry system', {
516
+ config: this.config,
517
+ });
518
+
519
+ if (this.config.enableMetrics) {
520
+ this.startMetricsFlush();
521
+ }
522
+
523
+ this.emit('telemetry:initialized');
524
+ }
525
+
526
+ /**
527
+ * Shutdown telemetry system
528
+ */
529
+ shutdown(): void {
530
+ this.logger.info('Shutting down telemetry system');
531
+
532
+ if (this.metricsFlushTimer) {
533
+ clearInterval(this.metricsFlushTimer);
534
+ this.metricsFlushTimer = undefined;
535
+ }
536
+
537
+ // Flush final metrics
538
+ this.flushMetrics();
539
+
540
+ // Clear buffers
541
+ this.activeTraces.clear();
542
+ this.completedTraces.length = 0;
543
+ this.metrics.clear();
544
+ this.latencyBuffer.clear();
545
+ this.logBuffer.length = 0;
546
+
547
+ // Clean up event listeners
548
+ this.removeAllListeners();
549
+
550
+ this.emit('telemetry:shutdown');
551
+ }
552
+
553
+ // ============================================================================
554
+ // Internal Helpers
555
+ // ============================================================================
556
+
557
+ private storeMetric(name: string, metric: MetricPoint): void {
558
+ // Store in memory buffer
559
+ if (!this.metrics.has(name)) {
560
+ this.metrics.set(name, []);
561
+ }
562
+
563
+ const metricsList = this.metrics.get(name)!;
564
+ metricsList.push(metric);
565
+
566
+ // Maintain history limit
567
+ if (metricsList.length > this.config.maxMetricHistory) {
568
+ metricsList.shift();
569
+ }
570
+
571
+ // Persist to SQLite if enabled
572
+ if (this.config.enablePersistence && this.storage) {
573
+ try {
574
+ this.storage.store(metric);
575
+ } catch (error) {
576
+ this.logger.error('Failed to persist metric', { metric: name, error });
577
+ }
578
+ }
579
+ }
580
+
581
+ private startMetricsFlush(): void {
582
+ this.metricsFlushTimer = setInterval(() => {
583
+ this.flushMetrics();
584
+ }, this.config.metricsFlushInterval);
585
+ }
586
+
587
+ private flushMetrics(): void {
588
+ const summary = this.getMetricsSummary();
589
+
590
+ this.emit('metrics:flush', summary);
591
+
592
+ this.logger.debug('Metrics flushed', {
593
+ totalMetrics: summary.totalMetrics,
594
+ metricNames: summary.metricNames,
595
+ });
596
+ }
597
+
598
+ private getMetricsSummary(): {
599
+ totalMetrics: number;
600
+ metricNames: string[];
601
+ byType: Record<string, number>;
602
+ } {
603
+ let totalMetrics = 0;
604
+ const byType: Record<string, number> = {
605
+ counter: 0,
606
+ gauge: 0,
607
+ timer: 0,
608
+ histogram: 0,
609
+ };
610
+
611
+ for (const metricsList of this.metrics.values()) {
612
+ totalMetrics += metricsList.length;
613
+ for (const metric of metricsList) {
614
+ byType[metric.type]++;
615
+ }
616
+ }
617
+
618
+ return {
619
+ totalMetrics,
620
+ metricNames: Array.from(this.metrics.keys()),
621
+ byType,
622
+ };
623
+ }
624
+
625
+ private percentile(sorted: number[], p: number): number {
626
+ const index = Math.ceil(sorted.length * p) - 1;
627
+ return sorted[Math.max(0, index)];
628
+ }
629
+
630
+ private createNoOpTrace(): TraceContext {
631
+ return {
632
+ traceId: 'noop',
633
+ spanId: 'noop',
634
+ startTime: new Date(),
635
+ tags: {},
636
+ logs: [],
637
+ status: 'active',
638
+ };
639
+ }
640
+ }
641
+
642
+ // ============================================================================
643
+ // Global Telemetry Instance
644
+ // ============================================================================
645
+
646
+ let globalTelemetry: TelemetrySystem | undefined;
647
+
648
+ export function getGlobalTelemetry(): TelemetrySystem {
649
+ if (!globalTelemetry) {
650
+ globalTelemetry = new TelemetrySystem();
651
+ globalTelemetry.initialize();
652
+ }
653
+ return globalTelemetry;
654
+ }
655
+
656
+ export function setGlobalTelemetry(telemetry: TelemetrySystem): void {
657
+ globalTelemetry = telemetry;
658
+ }