@almadar/std 2.1.1 → 2.4.1

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 (86) hide show
  1. package/dist/behaviors/async.d.ts +12 -7
  2. package/dist/behaviors/async.js +1085 -312
  3. package/dist/behaviors/async.js.map +1 -1
  4. package/dist/behaviors/data-management.d.ts +27 -13
  5. package/dist/behaviors/data-management.js +600 -244
  6. package/dist/behaviors/data-management.js.map +1 -1
  7. package/dist/behaviors/domain/commerce.d.ts +51 -0
  8. package/dist/behaviors/domain/commerce.js +1093 -0
  9. package/dist/behaviors/domain/commerce.js.map +1 -0
  10. package/dist/behaviors/domain/content.d.ts +51 -0
  11. package/dist/behaviors/domain/content.js +1294 -0
  12. package/dist/behaviors/domain/content.js.map +1 -0
  13. package/dist/behaviors/domain/dashboard.d.ts +45 -0
  14. package/dist/behaviors/domain/dashboard.js +783 -0
  15. package/dist/behaviors/domain/dashboard.js.map +1 -0
  16. package/dist/behaviors/domain/education.d.ts +41 -0
  17. package/dist/behaviors/domain/education.js +738 -0
  18. package/dist/behaviors/domain/education.js.map +1 -0
  19. package/dist/behaviors/domain/finance.d.ts +49 -0
  20. package/dist/behaviors/domain/finance.js +660 -0
  21. package/dist/behaviors/domain/finance.js.map +1 -0
  22. package/dist/behaviors/domain/game-2d-platformer.d.ts +50 -0
  23. package/dist/behaviors/domain/game-2d-platformer.js +810 -0
  24. package/dist/behaviors/domain/game-2d-platformer.js.map +1 -0
  25. package/dist/behaviors/domain/game-2d-puzzle.d.ts +42 -0
  26. package/dist/behaviors/domain/game-2d-puzzle.js +622 -0
  27. package/dist/behaviors/domain/game-2d-puzzle.js.map +1 -0
  28. package/dist/behaviors/domain/game-2d-rpg.d.ts +48 -0
  29. package/dist/behaviors/domain/game-2d-rpg.js +860 -0
  30. package/dist/behaviors/domain/game-2d-rpg.js.map +1 -0
  31. package/dist/behaviors/domain/game-2d-strategy.d.ts +48 -0
  32. package/dist/behaviors/domain/game-2d-strategy.js +692 -0
  33. package/dist/behaviors/domain/game-2d-strategy.js.map +1 -0
  34. package/dist/behaviors/domain/geospatial.d.ts +35 -0
  35. package/dist/behaviors/domain/geospatial.js +634 -0
  36. package/dist/behaviors/domain/geospatial.js.map +1 -0
  37. package/dist/behaviors/domain/healthcare.d.ts +36 -0
  38. package/dist/behaviors/domain/healthcare.js +1068 -0
  39. package/dist/behaviors/domain/healthcare.js.map +1 -0
  40. package/dist/behaviors/domain/iot.d.ts +45 -0
  41. package/dist/behaviors/domain/iot.js +589 -0
  42. package/dist/behaviors/domain/iot.js.map +1 -0
  43. package/dist/behaviors/domain/media.d.ts +41 -0
  44. package/dist/behaviors/domain/media.js +771 -0
  45. package/dist/behaviors/domain/media.js.map +1 -0
  46. package/dist/behaviors/domain/scheduling.d.ts +41 -0
  47. package/dist/behaviors/domain/scheduling.js +930 -0
  48. package/dist/behaviors/domain/scheduling.js.map +1 -0
  49. package/dist/behaviors/domain/simulation.d.ts +36 -0
  50. package/dist/behaviors/domain/simulation.js +706 -0
  51. package/dist/behaviors/domain/simulation.js.map +1 -0
  52. package/dist/behaviors/domain/social.d.ts +41 -0
  53. package/dist/behaviors/domain/social.js +840 -0
  54. package/dist/behaviors/domain/social.js.map +1 -0
  55. package/dist/behaviors/domain/workflow.d.ts +41 -0
  56. package/dist/behaviors/domain/workflow.js +879 -0
  57. package/dist/behaviors/domain/workflow.js.map +1 -0
  58. package/dist/behaviors/feedback.d.ts +10 -5
  59. package/dist/behaviors/feedback.js +279 -194
  60. package/dist/behaviors/feedback.js.map +1 -1
  61. package/dist/behaviors/game-core.d.ts +15 -8
  62. package/dist/behaviors/game-core.js +412 -80
  63. package/dist/behaviors/game-core.js.map +1 -1
  64. package/dist/behaviors/game-entity.d.ts +17 -10
  65. package/dist/behaviors/game-entity.js +544 -237
  66. package/dist/behaviors/game-entity.js.map +1 -1
  67. package/dist/behaviors/game-ui.d.ts +16 -8
  68. package/dist/behaviors/game-ui.js +451 -316
  69. package/dist/behaviors/game-ui.js.map +1 -1
  70. package/dist/behaviors/index.d.ts +18 -1
  71. package/dist/behaviors/index.js +18905 -2140
  72. package/dist/behaviors/index.js.map +1 -1
  73. package/dist/behaviors/infrastructure.d.ts +9 -8
  74. package/dist/behaviors/infrastructure.js +597 -169
  75. package/dist/behaviors/infrastructure.js.map +1 -1
  76. package/dist/behaviors/registry.d.ts +11 -11
  77. package/dist/behaviors/registry.js +18904 -2139
  78. package/dist/behaviors/registry.js.map +1 -1
  79. package/dist/behaviors/types.d.ts +19 -2
  80. package/dist/behaviors/types.js.map +1 -1
  81. package/dist/behaviors/ui-interaction.d.ts +20 -14
  82. package/dist/behaviors/ui-interaction.js +928 -518
  83. package/dist/behaviors/ui-interaction.js.map +1 -1
  84. package/dist/index.js +18906 -2141
  85. package/dist/index.js.map +1 -1
  86. package/package.json +1 -1
@@ -1,4 +1,251 @@
1
1
  // behaviors/infrastructure.ts
2
+ var INFRA_THEME = {
3
+ name: "infra-stone",
4
+ tokens: {
5
+ colors: {
6
+ primary: "#57534e",
7
+ "primary-hover": "#44403c",
8
+ "primary-foreground": "#ffffff",
9
+ accent: "#78716c",
10
+ "accent-foreground": "#ffffff",
11
+ success: "#22c55e",
12
+ warning: "#f59e0b",
13
+ error: "#ef4444"
14
+ }
15
+ }
16
+ };
17
+ var circuitBreakerMainView = ["render-ui", "main", {
18
+ type: "stack",
19
+ direction: "vertical",
20
+ gap: "lg",
21
+ children: [
22
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
23
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
24
+ { type: "icon", name: "shield-check", size: "lg" },
25
+ { type: "typography", content: "Circuit Breaker", variant: "h2" }
26
+ ] },
27
+ { type: "badge", label: "@entity.circuitState", icon: "circle-dot", variant: "success" }
28
+ ] },
29
+ { type: "divider" },
30
+ { type: "progress-bar", value: "@entity.errorCount", max: "@entity.errorThreshold", label: "Error Rate" },
31
+ { type: "stack", direction: "horizontal", gap: "md", children: [
32
+ { type: "stat-card", label: "Errors", value: "@entity.errorCount", icon: "x-circle" },
33
+ { type: "stat-card", label: "Successes", value: "@entity.successCount", icon: "check-circle" },
34
+ { type: "stat-card", label: "Total", value: "@entity.totalCount", icon: "hash" },
35
+ { type: "stat-card", label: "Threshold", value: "@entity.errorThreshold", icon: "alert-triangle" }
36
+ ] },
37
+ { type: "divider" },
38
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
39
+ { type: "button", label: "Simulate Success", action: "SUCCESS", icon: "check", variant: "primary" },
40
+ { type: "button", label: "Simulate Failure", action: "FAILURE", icon: "x", variant: "secondary" },
41
+ { type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
42
+ ] }
43
+ ]
44
+ }];
45
+ var circuitBreakerOpenView = ["render-ui", "main", {
46
+ type: "stack",
47
+ direction: "vertical",
48
+ gap: "lg",
49
+ children: [
50
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
51
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
52
+ { type: "icon", name: "shield-alert", size: "lg" },
53
+ { type: "typography", content: "Circuit Breaker - OPEN", variant: "h2" }
54
+ ] },
55
+ { type: "badge", label: "OPEN", icon: "alert-circle", variant: "danger" }
56
+ ] },
57
+ { type: "divider" },
58
+ { type: "progress-bar", value: "@entity.errorCount", max: "@entity.errorThreshold", label: "Errors" },
59
+ { type: "stack", direction: "horizontal", gap: "md", children: [
60
+ { type: "stat-card", label: "Errors", value: "@entity.errorCount", icon: "x-circle" },
61
+ { type: "stat-card", label: "Successes", value: "@entity.successCount", icon: "check-circle" },
62
+ { type: "stat-card", label: "Total", value: "@entity.totalCount", icon: "hash" },
63
+ { type: "stat-card", label: "Error Rate", value: "@entity.errorRate", icon: "percent" }
64
+ ] },
65
+ { type: "divider" },
66
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
67
+ { type: "button", label: "Try Half-Open", action: "HALF_OPEN", icon: "shield-question", variant: "primary" },
68
+ { type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
69
+ ] }
70
+ ]
71
+ }];
72
+ var circuitBreakerHalfOpenView = ["render-ui", "main", {
73
+ type: "stack",
74
+ direction: "vertical",
75
+ gap: "lg",
76
+ children: [
77
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
78
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
79
+ { type: "icon", name: "shield-question", size: "lg" },
80
+ { type: "typography", content: "Circuit Breaker - Half Open", variant: "h2" }
81
+ ] },
82
+ { type: "badge", label: "HALF-OPEN", icon: "alert-triangle", variant: "warning" }
83
+ ] },
84
+ { type: "divider" },
85
+ { type: "stack", direction: "horizontal", gap: "md", children: [
86
+ { type: "stat-card", label: "Errors", value: "@entity.errorCount", icon: "x-circle" },
87
+ { type: "stat-card", label: "Successes", value: "@entity.successCount", icon: "check-circle" },
88
+ { type: "stat-card", label: "Attempts", value: "@entity.halfOpenAttempts", icon: "rotate-cw" },
89
+ { type: "stat-card", label: "Error Rate", value: "@entity.errorRate", icon: "percent" }
90
+ ] },
91
+ { type: "divider" },
92
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
93
+ { type: "button", label: "Test Success", action: "SUCCESS", icon: "check", variant: "primary" },
94
+ { type: "button", label: "Test Failure", action: "FAILURE", icon: "x", variant: "secondary" }
95
+ ] }
96
+ ]
97
+ }];
98
+ var healthCheckView = (title, statusVariant) => ["render-ui", "main", {
99
+ type: "stack",
100
+ direction: "vertical",
101
+ gap: "lg",
102
+ children: [
103
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
104
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
105
+ { type: "icon", name: "activity", size: "lg" },
106
+ { type: "typography", content: title, variant: "h2" }
107
+ ] },
108
+ { type: "badge", label: "@entity.healthStatus", icon: "heart-pulse", variant: statusVariant }
109
+ ] },
110
+ { type: "divider" },
111
+ { type: "progress-bar", value: "@entity.consecutiveFailures", max: "@entity.unhealthyThreshold", label: "Failure Threshold" },
112
+ { type: "stack", direction: "horizontal", gap: "md", children: [
113
+ { type: "stat-card", label: "Failures", value: "@entity.consecutiveFailures", icon: "x-circle" },
114
+ { type: "stat-card", label: "Successes", value: "@entity.consecutiveSuccesses", icon: "check-circle" },
115
+ { type: "stat-card", label: "Total Checks", value: "@entity.totalChecks", icon: "clipboard-check" },
116
+ { type: "stat-card", label: "Total Failures", value: "@entity.totalFailures", icon: "alert-triangle" }
117
+ ] },
118
+ { type: "divider" },
119
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
120
+ { type: "button", label: "Check Success", action: "CHECK_SUCCESS", icon: "check", variant: "primary" },
121
+ { type: "button", label: "Check Failure", action: "CHECK_FAILURE", icon: "x", variant: "secondary" },
122
+ { type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
123
+ ] }
124
+ ]
125
+ }];
126
+ var rateLimiterView = (title) => ["render-ui", "main", {
127
+ type: "stack",
128
+ direction: "vertical",
129
+ gap: "lg",
130
+ children: [
131
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
132
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
133
+ { type: "icon", name: "gauge", size: "lg" },
134
+ { type: "typography", content: title, variant: "h2" }
135
+ ] }
136
+ ] },
137
+ { type: "divider" },
138
+ { type: "progress-bar", value: "@entity.requestCount", max: "@entity.rateLimit", label: "Rate Usage" },
139
+ { type: "stack", direction: "horizontal", gap: "md", children: [
140
+ { type: "stat-card", label: "Requests", value: "@entity.requestCount", icon: "arrow-up-right" },
141
+ { type: "stat-card", label: "Limit", value: "@entity.rateLimit", icon: "shield" },
142
+ { type: "stat-card", label: "Total", value: "@entity.totalRequests", icon: "hash" },
143
+ { type: "stat-card", label: "Rejected", value: "@entity.rejectedRequests", icon: "ban" }
144
+ ] },
145
+ { type: "divider" },
146
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
147
+ { type: "button", label: "Send Request", action: "REQUEST", icon: "send", variant: "primary" },
148
+ { type: "button", label: "Reset Window", action: "RESET_WINDOW", icon: "refresh-cw", variant: "secondary" }
149
+ ] }
150
+ ]
151
+ }];
152
+ var cacheStatsView = (title) => ["render-ui", "main", {
153
+ type: "stack",
154
+ direction: "vertical",
155
+ gap: "lg",
156
+ children: [
157
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
158
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
159
+ { type: "icon", name: "database", size: "lg" },
160
+ { type: "typography", content: title, variant: "h2" }
161
+ ] },
162
+ { type: "badge", label: "@entity.isFresh", icon: "check-circle", variant: "outline" }
163
+ ] },
164
+ { type: "divider" },
165
+ { type: "stack", direction: "horizontal", gap: "md", children: [
166
+ { type: "stat-card", label: "Key", value: "@entity.cacheKey", icon: "key" },
167
+ { type: "stat-card", label: "Hits", value: "@entity.cacheHits", icon: "check" },
168
+ { type: "stat-card", label: "Misses", value: "@entity.cacheMisses", icon: "x" },
169
+ { type: "stat-card", label: "TTL (ms)", value: "@entity.ttlMs", icon: "clock" }
170
+ ] },
171
+ { type: "divider" },
172
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
173
+ { type: "button", label: "Get", action: "GET", icon: "download", variant: "primary" },
174
+ { type: "button", label: "Invalidate", action: "INVALIDATE", icon: "trash-2", variant: "secondary" }
175
+ ] }
176
+ ]
177
+ }];
178
+ var cacheEmptyView = (title) => ["render-ui", "main", {
179
+ type: "stack",
180
+ direction: "vertical",
181
+ gap: "lg",
182
+ children: [
183
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
184
+ { type: "icon", name: "database", size: "lg" },
185
+ { type: "typography", content: title, variant: "h2" }
186
+ ] },
187
+ { type: "divider" },
188
+ { type: "empty-state", icon: "inbox", title: "Cache is empty", description: "No cached data available" },
189
+ { type: "stack", direction: "horizontal", gap: "md", children: [
190
+ { type: "stat-card", label: "Hits", value: "@entity.cacheHits", icon: "check" },
191
+ { type: "stat-card", label: "Misses", value: "@entity.cacheMisses", icon: "x" }
192
+ ] },
193
+ { type: "divider" },
194
+ { type: "button", label: "Fetch Data", action: "SET", icon: "download", variant: "primary" }
195
+ ]
196
+ }];
197
+ var sagaView = (title) => ["render-ui", "main", {
198
+ type: "stack",
199
+ direction: "vertical",
200
+ gap: "lg",
201
+ children: [
202
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
203
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
204
+ { type: "icon", name: "workflow", size: "lg" },
205
+ { type: "typography", content: title, variant: "h2" }
206
+ ] },
207
+ { type: "badge", label: "@entity.sagaStatus", icon: "flag", variant: "outline" }
208
+ ] },
209
+ { type: "divider" },
210
+ { type: "progress-bar", value: "@entity.currentStep", max: "@entity.totalSteps", label: "Progress" },
211
+ { type: "stack", direction: "horizontal", gap: "md", children: [
212
+ { type: "stat-card", label: "Current Step", value: "@entity.currentStep", icon: "footprints" },
213
+ { type: "stat-card", label: "Total Steps", value: "@entity.totalSteps", icon: "list-ordered" },
214
+ { type: "stat-card", label: "Failed Step", value: "@entity.failedStep", icon: "alert-circle" },
215
+ { type: "stat-card", label: "Status", value: "@entity.sagaStatus", icon: "flag" }
216
+ ] },
217
+ { type: "divider" },
218
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
219
+ { type: "button", label: "Execute", action: "EXECUTE", icon: "play", variant: "primary" },
220
+ { type: "button", label: "Compensate", action: "COMPENSATE", icon: "undo-2", variant: "secondary" },
221
+ { type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
222
+ ] }
223
+ ]
224
+ }];
225
+ var metricsView = (title) => ["render-ui", "main", {
226
+ type: "stack",
227
+ direction: "vertical",
228
+ gap: "lg",
229
+ children: [
230
+ { type: "stack", direction: "horizontal", justify: "space-between", children: [
231
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
232
+ { type: "icon", name: "bar-chart-3", size: "lg" },
233
+ { type: "typography", content: title, variant: "h2" }
234
+ ] }
235
+ ] },
236
+ { type: "divider" },
237
+ { type: "stack", direction: "horizontal", gap: "md", children: [
238
+ { type: "stat-card", label: "Recorded", value: "@entity.totalRecorded", icon: "database" },
239
+ { type: "stat-card", label: "Flushes", value: "@entity.totalFlushes", icon: "upload" },
240
+ { type: "stat-card", label: "Last Flush", value: "@entity.lastFlush", icon: "clock" }
241
+ ] },
242
+ { type: "divider" },
243
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
244
+ { type: "button", label: "Record", action: "RECORD", icon: "plus", variant: "primary" },
245
+ { type: "button", label: "Flush", action: "FLUSH", icon: "upload", variant: "secondary" }
246
+ ] }
247
+ ]
248
+ }];
2
249
  var CIRCUIT_BREAKER_BEHAVIOR = {
3
250
  name: "std-circuit-breaker",
4
251
  version: "1.0.0",
@@ -6,6 +253,7 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
6
253
  orbitals: [
7
254
  {
8
255
  name: "CircuitBreakerOrbital",
256
+ theme: INFRA_THEME,
9
257
  entity: {
10
258
  name: "CircuitBreakerState",
11
259
  persistence: "runtime",
@@ -16,8 +264,8 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
16
264
  { name: "errorRate", type: "number", default: 0 },
17
265
  { name: "successCount", type: "number", default: 0 },
18
266
  { name: "totalCount", type: "number", default: 0 },
19
- { name: "lastFailure", type: "number", default: null },
20
- { name: "lastSuccess", type: "number", default: null },
267
+ { name: "lastFailure", type: "number", default: 0 },
268
+ { name: "lastSuccess", type: "number", default: 0 },
21
269
  { name: "errorThreshold", type: "number", default: 5 },
22
270
  { name: "errorRateThreshold", type: "number", default: 0.5 },
23
271
  { name: "resetAfterMs", type: "number", default: 6e4 },
@@ -29,12 +277,7 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
29
277
  {
30
278
  name: "CircuitBreaker",
31
279
  linkedEntity: "CircuitBreakerState",
32
- category: "lifecycle",
33
- emits: [
34
- { event: "CIRCUIT_OPENED", scope: "external" },
35
- { event: "CIRCUIT_CLOSED", scope: "external" },
36
- { event: "CIRCUIT_HALF_OPEN", scope: "external" }
37
- ],
280
+ category: "interaction",
38
281
  stateMachine: {
39
282
  states: [
40
283
  { name: "Closed", isInitial: true },
@@ -42,22 +285,35 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
42
285
  { name: "HalfOpen" }
43
286
  ],
44
287
  events: [
288
+ { key: "INIT", name: "Initialize" },
45
289
  { key: "RECORD_SUCCESS", name: "Record Success" },
46
290
  { key: "RECORD_FAILURE", name: "Record Failure" },
47
291
  { key: "PROBE", name: "Probe" },
48
292
  { key: "RESET", name: "Reset" }
49
293
  ],
50
294
  transitions: [
295
+ // INIT: render dashboard
296
+ {
297
+ from: "Closed",
298
+ to: "Closed",
299
+ event: "INIT",
300
+ effects: [
301
+ ["fetch", "CircuitBreakerState"],
302
+ circuitBreakerMainView
303
+ ]
304
+ },
51
305
  // Closed: record success
52
306
  {
53
307
  from: "Closed",
54
308
  to: "Closed",
55
309
  event: "RECORD_SUCCESS",
56
310
  effects: [
311
+ ["fetch", "CircuitBreakerState"],
57
312
  ["set", "@entity.successCount", ["+", "@entity.successCount", 1]],
58
313
  ["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
59
314
  ["set", "@entity.lastSuccess", ["time/now"]],
60
- ["set", "@entity.errorRate", ["/", "@entity.errorCount", ["math/max", "@entity.totalCount", 1]]]
315
+ ["set", "@entity.errorRate", ["/", "@entity.errorCount", ["math/max", "@entity.totalCount", 1]]],
316
+ circuitBreakerMainView
61
317
  ]
62
318
  },
63
319
  // Closed: record failure, stay closed if under threshold
@@ -67,10 +323,12 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
67
323
  event: "RECORD_FAILURE",
68
324
  guard: ["<", ["+", "@entity.errorCount", 1], "@entity.errorThreshold"],
69
325
  effects: [
326
+ ["fetch", "CircuitBreakerState"],
70
327
  ["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
71
328
  ["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
72
329
  ["set", "@entity.lastFailure", ["time/now"]],
73
- ["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]]
330
+ ["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]],
331
+ circuitBreakerMainView
74
332
  ]
75
333
  },
76
334
  // Closed -> Open: threshold exceeded
@@ -80,11 +338,13 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
80
338
  event: "RECORD_FAILURE",
81
339
  guard: [">=", ["+", "@entity.errorCount", 1], "@entity.errorThreshold"],
82
340
  effects: [
341
+ ["fetch", "CircuitBreakerState"],
83
342
  ["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
84
343
  ["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
85
344
  ["set", "@entity.lastFailure", ["time/now"]],
86
345
  ["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]],
87
- ["emit", "CIRCUIT_OPENED", { errorCount: "@entity.errorCount", errorRate: "@entity.errorRate" }]
346
+ ["set", "@entity.circuitState", "open"],
347
+ circuitBreakerOpenView
88
348
  ]
89
349
  },
90
350
  // Open -> HalfOpen: probe after reset timeout
@@ -94,8 +354,10 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
94
354
  event: "PROBE",
95
355
  guard: [">", ["-", ["time/now"], "@entity.lastFailure"], "@entity.resetAfterMs"],
96
356
  effects: [
357
+ ["fetch", "CircuitBreakerState"],
97
358
  ["set", "@entity.halfOpenAttempts", 0],
98
- ["emit", "CIRCUIT_HALF_OPEN", {}]
359
+ ["set", "@entity.circuitState", "halfOpen"],
360
+ circuitBreakerHalfOpenView
99
361
  ]
100
362
  },
101
363
  // HalfOpen: success -> close
@@ -104,12 +366,14 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
104
366
  to: "Closed",
105
367
  event: "RECORD_SUCCESS",
106
368
  effects: [
369
+ ["fetch", "CircuitBreakerState"],
107
370
  ["set", "@entity.errorCount", 0],
108
371
  ["set", "@entity.errorRate", 0],
109
372
  ["set", "@entity.halfOpenAttempts", 0],
110
373
  ["set", "@entity.successCount", ["+", "@entity.successCount", 1]],
111
374
  ["set", "@entity.lastSuccess", ["time/now"]],
112
- ["emit", "CIRCUIT_CLOSED", {}]
375
+ ["set", "@entity.circuitState", "closed"],
376
+ circuitBreakerMainView
113
377
  ]
114
378
  },
115
379
  // HalfOpen: failure -> back to open
@@ -118,23 +382,59 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
118
382
  to: "Open",
119
383
  event: "RECORD_FAILURE",
120
384
  effects: [
385
+ ["fetch", "CircuitBreakerState"],
121
386
  ["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
122
387
  ["set", "@entity.lastFailure", ["time/now"]],
123
- ["emit", "CIRCUIT_OPENED", { errorCount: "@entity.errorCount" }]
388
+ ["set", "@entity.circuitState", "open"],
389
+ circuitBreakerOpenView
124
390
  ]
125
391
  },
126
- // Reset from any state
392
+ // Reset from Closed
127
393
  {
128
- from: ["Closed", "Open", "HalfOpen"],
394
+ from: "Closed",
395
+ to: "Closed",
396
+ event: "RESET",
397
+ effects: [
398
+ ["fetch", "CircuitBreakerState"],
399
+ ["set", "@entity.errorCount", 0],
400
+ ["set", "@entity.successCount", 0],
401
+ ["set", "@entity.totalCount", 0],
402
+ ["set", "@entity.errorRate", 0],
403
+ ["set", "@entity.halfOpenAttempts", 0],
404
+ ["set", "@entity.circuitState", "closed"],
405
+ circuitBreakerMainView
406
+ ]
407
+ },
408
+ // Reset from Open
409
+ {
410
+ from: "Open",
129
411
  to: "Closed",
130
412
  event: "RESET",
131
413
  effects: [
414
+ ["fetch", "CircuitBreakerState"],
132
415
  ["set", "@entity.errorCount", 0],
133
416
  ["set", "@entity.successCount", 0],
134
417
  ["set", "@entity.totalCount", 0],
135
418
  ["set", "@entity.errorRate", 0],
136
419
  ["set", "@entity.halfOpenAttempts", 0],
137
- ["set", "@entity.circuitState", "closed"]
420
+ ["set", "@entity.circuitState", "closed"],
421
+ circuitBreakerMainView
422
+ ]
423
+ },
424
+ // Reset from HalfOpen
425
+ {
426
+ from: "HalfOpen",
427
+ to: "Closed",
428
+ event: "RESET",
429
+ effects: [
430
+ ["fetch", "CircuitBreakerState"],
431
+ ["set", "@entity.errorCount", 0],
432
+ ["set", "@entity.successCount", 0],
433
+ ["set", "@entity.totalCount", 0],
434
+ ["set", "@entity.errorRate", 0],
435
+ ["set", "@entity.halfOpenAttempts", 0],
436
+ ["set", "@entity.circuitState", "closed"],
437
+ circuitBreakerMainView
138
438
  ]
139
439
  }
140
440
  ]
@@ -142,15 +442,14 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
142
442
  ticks: [
143
443
  {
144
444
  name: "probe_half_open",
145
- interval: "30000",
445
+ interval: 3e4,
146
446
  guard: ["=", "@entity.circuitState", "open"],
147
- effects: [["emit", "PROBE"]],
148
- description: "Periodically probe to transition from Open to HalfOpen"
447
+ effects: []
149
448
  }
150
449
  ]
151
450
  }
152
451
  ],
153
- pages: []
452
+ pages: [{ name: "CircuitBreakerPage", path: "/circuit-breaker", isInitial: true, traits: [{ ref: "CircuitBreaker" }] }]
154
453
  }
155
454
  ]
156
455
  };
@@ -161,17 +460,17 @@ var HEALTH_CHECK_BEHAVIOR = {
161
460
  orbitals: [
162
461
  {
163
462
  name: "HealthCheckOrbital",
463
+ theme: INFRA_THEME,
164
464
  entity: {
165
465
  name: "HealthCheckState",
166
466
  persistence: "runtime",
167
467
  fields: [
168
468
  { name: "id", type: "string", required: true },
169
469
  { name: "healthStatus", type: "string", default: "unknown" },
170
- { name: "lastCheck", type: "number", default: null },
171
- { name: "lastHealthy", type: "number", default: null },
470
+ { name: "lastCheck", type: "number", default: 0 },
471
+ { name: "lastHealthy", type: "number", default: 0 },
172
472
  { name: "consecutiveFailures", type: "number", default: 0 },
173
473
  { name: "consecutiveSuccesses", type: "number", default: 0 },
174
- { name: "checkIntervalMs", type: "number", default: 3e4 },
175
474
  { name: "degradedThreshold", type: "number", default: 2 },
176
475
  { name: "unhealthyThreshold", type: "number", default: 5 },
177
476
  { name: "recoveryThreshold", type: "number", default: 3 },
@@ -183,12 +482,7 @@ var HEALTH_CHECK_BEHAVIOR = {
183
482
  {
184
483
  name: "HealthCheck",
185
484
  linkedEntity: "HealthCheckState",
186
- category: "lifecycle",
187
- emits: [
188
- { event: "SERVICE_HEALTHY", scope: "external" },
189
- { event: "SERVICE_DEGRADED", scope: "external" },
190
- { event: "SERVICE_UNHEALTHY", scope: "external" }
191
- ],
485
+ category: "interaction",
192
486
  stateMachine: {
193
487
  states: [
194
488
  { name: "Unknown", isInitial: true },
@@ -197,25 +491,36 @@ var HEALTH_CHECK_BEHAVIOR = {
197
491
  { name: "Unhealthy" }
198
492
  ],
199
493
  events: [
494
+ { key: "INIT", name: "Initialize" },
200
495
  { key: "CHECK_SUCCESS", name: "Check Success" },
201
496
  { key: "CHECK_FAILURE", name: "Check Failure" },
202
- { key: "HEALTH_TICK", name: "Health Tick" },
203
497
  { key: "RESET", name: "Reset" }
204
498
  ],
205
499
  transitions: [
500
+ // INIT
501
+ {
502
+ from: "Unknown",
503
+ to: "Unknown",
504
+ event: "INIT",
505
+ effects: [
506
+ ["fetch", "HealthCheckState"],
507
+ healthCheckView("Health Check", "outline")
508
+ ]
509
+ },
206
510
  // Unknown -> Healthy on first success
207
511
  {
208
512
  from: "Unknown",
209
513
  to: "Healthy",
210
514
  event: "CHECK_SUCCESS",
211
515
  effects: [
516
+ ["fetch", "HealthCheckState"],
212
517
  ["set", "@entity.healthStatus", "healthy"],
213
518
  ["set", "@entity.consecutiveSuccesses", 1],
214
519
  ["set", "@entity.consecutiveFailures", 0],
215
520
  ["set", "@entity.lastCheck", ["time/now"]],
216
521
  ["set", "@entity.lastHealthy", ["time/now"]],
217
522
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
218
- ["emit", "SERVICE_HEALTHY", {}]
523
+ healthCheckView("Health Check - Healthy", "success")
219
524
  ]
220
525
  },
221
526
  // Unknown -> Degraded on first failure
@@ -224,13 +529,14 @@ var HEALTH_CHECK_BEHAVIOR = {
224
529
  to: "Degraded",
225
530
  event: "CHECK_FAILURE",
226
531
  effects: [
532
+ ["fetch", "HealthCheckState"],
227
533
  ["set", "@entity.healthStatus", "degraded"],
228
534
  ["set", "@entity.consecutiveFailures", 1],
229
535
  ["set", "@entity.consecutiveSuccesses", 0],
230
536
  ["set", "@entity.lastCheck", ["time/now"]],
231
537
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
232
538
  ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
233
- ["emit", "SERVICE_DEGRADED", { consecutiveFailures: 1 }]
539
+ healthCheckView("Health Check - Degraded", "warning")
234
540
  ]
235
541
  },
236
542
  // Healthy: stay healthy on success
@@ -239,11 +545,13 @@ var HEALTH_CHECK_BEHAVIOR = {
239
545
  to: "Healthy",
240
546
  event: "CHECK_SUCCESS",
241
547
  effects: [
548
+ ["fetch", "HealthCheckState"],
242
549
  ["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
243
550
  ["set", "@entity.consecutiveFailures", 0],
244
551
  ["set", "@entity.lastCheck", ["time/now"]],
245
552
  ["set", "@entity.lastHealthy", ["time/now"]],
246
- ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]]
553
+ ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
554
+ healthCheckView("Health Check - Healthy", "success")
247
555
  ]
248
556
  },
249
557
  // Healthy -> Degraded on failure
@@ -252,13 +560,14 @@ var HEALTH_CHECK_BEHAVIOR = {
252
560
  to: "Degraded",
253
561
  event: "CHECK_FAILURE",
254
562
  effects: [
563
+ ["fetch", "HealthCheckState"],
255
564
  ["set", "@entity.healthStatus", "degraded"],
256
565
  ["set", "@entity.consecutiveFailures", 1],
257
566
  ["set", "@entity.consecutiveSuccesses", 0],
258
567
  ["set", "@entity.lastCheck", ["time/now"]],
259
568
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
260
569
  ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
261
- ["emit", "SERVICE_DEGRADED", { consecutiveFailures: 1 }]
570
+ healthCheckView("Health Check - Degraded", "warning")
262
571
  ]
263
572
  },
264
573
  // Degraded: stay degraded on failure (below unhealthy threshold)
@@ -268,11 +577,13 @@ var HEALTH_CHECK_BEHAVIOR = {
268
577
  event: "CHECK_FAILURE",
269
578
  guard: ["<", ["+", "@entity.consecutiveFailures", 1], "@entity.unhealthyThreshold"],
270
579
  effects: [
580
+ ["fetch", "HealthCheckState"],
271
581
  ["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
272
582
  ["set", "@entity.consecutiveSuccesses", 0],
273
583
  ["set", "@entity.lastCheck", ["time/now"]],
274
584
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
275
- ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]]
585
+ ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
586
+ healthCheckView("Health Check - Degraded", "warning")
276
587
  ]
277
588
  },
278
589
  // Degraded -> Unhealthy when threshold exceeded
@@ -282,12 +593,13 @@ var HEALTH_CHECK_BEHAVIOR = {
282
593
  event: "CHECK_FAILURE",
283
594
  guard: [">=", ["+", "@entity.consecutiveFailures", 1], "@entity.unhealthyThreshold"],
284
595
  effects: [
596
+ ["fetch", "HealthCheckState"],
285
597
  ["set", "@entity.healthStatus", "unhealthy"],
286
598
  ["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
287
599
  ["set", "@entity.lastCheck", ["time/now"]],
288
600
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
289
601
  ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
290
- ["emit", "SERVICE_UNHEALTHY", { consecutiveFailures: ["+", "@entity.consecutiveFailures", 1] }]
602
+ healthCheckView("Health Check - Unhealthy", "danger")
291
603
  ]
292
604
  },
293
605
  // Degraded -> Healthy on enough successes
@@ -297,13 +609,14 @@ var HEALTH_CHECK_BEHAVIOR = {
297
609
  event: "CHECK_SUCCESS",
298
610
  guard: [">=", ["+", "@entity.consecutiveSuccesses", 1], "@entity.recoveryThreshold"],
299
611
  effects: [
612
+ ["fetch", "HealthCheckState"],
300
613
  ["set", "@entity.healthStatus", "healthy"],
301
614
  ["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
302
615
  ["set", "@entity.consecutiveFailures", 0],
303
616
  ["set", "@entity.lastCheck", ["time/now"]],
304
617
  ["set", "@entity.lastHealthy", ["time/now"]],
305
618
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
306
- ["emit", "SERVICE_HEALTHY", {}]
619
+ healthCheckView("Health Check - Healthy", "success")
307
620
  ]
308
621
  },
309
622
  // Degraded: stay degraded on success (not enough to recover)
@@ -313,10 +626,12 @@ var HEALTH_CHECK_BEHAVIOR = {
313
626
  event: "CHECK_SUCCESS",
314
627
  guard: ["<", ["+", "@entity.consecutiveSuccesses", 1], "@entity.recoveryThreshold"],
315
628
  effects: [
629
+ ["fetch", "HealthCheckState"],
316
630
  ["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
317
631
  ["set", "@entity.consecutiveFailures", 0],
318
632
  ["set", "@entity.lastCheck", ["time/now"]],
319
- ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]]
633
+ ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
634
+ healthCheckView("Health Check - Degraded", "warning")
320
635
  ]
321
636
  },
322
637
  // Unhealthy: stay unhealthy on failure
@@ -325,10 +640,12 @@ var HEALTH_CHECK_BEHAVIOR = {
325
640
  to: "Unhealthy",
326
641
  event: "CHECK_FAILURE",
327
642
  effects: [
643
+ ["fetch", "HealthCheckState"],
328
644
  ["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
329
645
  ["set", "@entity.lastCheck", ["time/now"]],
330
646
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
331
- ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]]
647
+ ["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
648
+ healthCheckView("Health Check - Unhealthy", "danger")
332
649
  ]
333
650
  },
334
651
  // Unhealthy -> Degraded on first success (recovery begins)
@@ -337,25 +654,73 @@ var HEALTH_CHECK_BEHAVIOR = {
337
654
  to: "Degraded",
338
655
  event: "CHECK_SUCCESS",
339
656
  effects: [
657
+ ["fetch", "HealthCheckState"],
340
658
  ["set", "@entity.healthStatus", "degraded"],
341
659
  ["set", "@entity.consecutiveSuccesses", 1],
342
660
  ["set", "@entity.consecutiveFailures", 0],
343
661
  ["set", "@entity.lastCheck", ["time/now"]],
344
662
  ["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
345
- ["emit", "SERVICE_DEGRADED", { recovering: true }]
663
+ healthCheckView("Health Check - Degraded", "warning")
664
+ ]
665
+ },
666
+ // Reset from Unknown
667
+ {
668
+ from: "Unknown",
669
+ to: "Unknown",
670
+ event: "RESET",
671
+ effects: [
672
+ ["fetch", "HealthCheckState"],
673
+ ["set", "@entity.healthStatus", "unknown"],
674
+ ["set", "@entity.consecutiveFailures", 0],
675
+ ["set", "@entity.consecutiveSuccesses", 0],
676
+ ["set", "@entity.totalChecks", 0],
677
+ ["set", "@entity.totalFailures", 0],
678
+ healthCheckView("Health Check", "outline")
679
+ ]
680
+ },
681
+ // Reset from Healthy
682
+ {
683
+ from: "Healthy",
684
+ to: "Unknown",
685
+ event: "RESET",
686
+ effects: [
687
+ ["fetch", "HealthCheckState"],
688
+ ["set", "@entity.healthStatus", "unknown"],
689
+ ["set", "@entity.consecutiveFailures", 0],
690
+ ["set", "@entity.consecutiveSuccesses", 0],
691
+ ["set", "@entity.totalChecks", 0],
692
+ ["set", "@entity.totalFailures", 0],
693
+ healthCheckView("Health Check", "outline")
694
+ ]
695
+ },
696
+ // Reset from Degraded
697
+ {
698
+ from: "Degraded",
699
+ to: "Unknown",
700
+ event: "RESET",
701
+ effects: [
702
+ ["fetch", "HealthCheckState"],
703
+ ["set", "@entity.healthStatus", "unknown"],
704
+ ["set", "@entity.consecutiveFailures", 0],
705
+ ["set", "@entity.consecutiveSuccesses", 0],
706
+ ["set", "@entity.totalChecks", 0],
707
+ ["set", "@entity.totalFailures", 0],
708
+ healthCheckView("Health Check", "outline")
346
709
  ]
347
710
  },
348
- // Reset from any state
711
+ // Reset from Unhealthy
349
712
  {
350
- from: ["Unknown", "Healthy", "Degraded", "Unhealthy"],
713
+ from: "Unhealthy",
351
714
  to: "Unknown",
352
715
  event: "RESET",
353
716
  effects: [
717
+ ["fetch", "HealthCheckState"],
354
718
  ["set", "@entity.healthStatus", "unknown"],
355
719
  ["set", "@entity.consecutiveFailures", 0],
356
720
  ["set", "@entity.consecutiveSuccesses", 0],
357
721
  ["set", "@entity.totalChecks", 0],
358
- ["set", "@entity.totalFailures", 0]
722
+ ["set", "@entity.totalFailures", 0],
723
+ healthCheckView("Health Check", "outline")
359
724
  ]
360
725
  }
361
726
  ]
@@ -363,14 +728,13 @@ var HEALTH_CHECK_BEHAVIOR = {
363
728
  ticks: [
364
729
  {
365
730
  name: "periodic_health_check",
366
- interval: "@entity.checkIntervalMs",
367
- effects: [["emit", "HEALTH_TICK"]],
368
- description: "Periodically trigger health check"
731
+ interval: 3e4,
732
+ effects: []
369
733
  }
370
734
  ]
371
735
  }
372
736
  ],
373
- pages: []
737
+ pages: [{ name: "HealthCheckPage", path: "/health-check", isInitial: true, traits: [{ ref: "HealthCheck" }] }]
374
738
  }
375
739
  ]
376
740
  };
@@ -381,6 +745,7 @@ var RATE_LIMITER_BEHAVIOR = {
381
745
  orbitals: [
382
746
  {
383
747
  name: "RateLimiterOrbital",
748
+ theme: INFRA_THEME,
384
749
  entity: {
385
750
  name: "RateLimiterState",
386
751
  persistence: "runtime",
@@ -398,21 +763,28 @@ var RATE_LIMITER_BEHAVIOR = {
398
763
  {
399
764
  name: "RateLimiter",
400
765
  linkedEntity: "RateLimiterState",
401
- category: "lifecycle",
402
- emits: [
403
- { event: "RATE_LIMIT_EXCEEDED", scope: "external" }
404
- ],
766
+ category: "interaction",
405
767
  stateMachine: {
406
768
  states: [
407
769
  { name: "Active", isInitial: true }
408
770
  ],
409
771
  events: [
772
+ { key: "INIT", name: "Initialize" },
410
773
  { key: "REQUEST", name: "Record Request" },
411
- { key: "REQUEST_REJECTED", name: "Request Rejected" },
412
774
  { key: "WINDOW_RESET", name: "Window Reset" },
413
775
  { key: "RESET", name: "Full Reset" }
414
776
  ],
415
777
  transitions: [
778
+ // INIT
779
+ {
780
+ from: "Active",
781
+ to: "Active",
782
+ event: "INIT",
783
+ effects: [
784
+ ["fetch", "RateLimiterState"],
785
+ rateLimiterView("Rate Limiter")
786
+ ]
787
+ },
416
788
  // Request allowed
417
789
  {
418
790
  from: "Active",
@@ -420,22 +792,22 @@ var RATE_LIMITER_BEHAVIOR = {
420
792
  event: "REQUEST",
421
793
  guard: ["<", "@entity.requestCount", "@entity.rateLimit"],
422
794
  effects: [
795
+ ["fetch", "RateLimiterState"],
423
796
  ["set", "@entity.requestCount", ["+", "@entity.requestCount", 1]],
424
- ["set", "@entity.totalRequests", ["+", "@entity.totalRequests", 1]]
797
+ ["set", "@entity.totalRequests", ["+", "@entity.totalRequests", 1]],
798
+ rateLimiterView("Rate Limiter")
425
799
  ]
426
800
  },
427
- // Request rejected — over limit
801
+ // Request rejected
428
802
  {
429
803
  from: "Active",
430
804
  to: "Active",
431
805
  event: "REQUEST",
432
806
  guard: [">=", "@entity.requestCount", "@entity.rateLimit"],
433
807
  effects: [
808
+ ["fetch", "RateLimiterState"],
434
809
  ["set", "@entity.rejectedRequests", ["+", "@entity.rejectedRequests", 1]],
435
- ["emit", "RATE_LIMIT_EXCEEDED", {
436
- requestCount: "@entity.requestCount",
437
- rateLimit: "@entity.rateLimit"
438
- }]
810
+ rateLimiterView("Rate Limiter - Limit Exceeded")
439
811
  ]
440
812
  },
441
813
  // Sliding window reset
@@ -444,8 +816,10 @@ var RATE_LIMITER_BEHAVIOR = {
444
816
  to: "Active",
445
817
  event: "WINDOW_RESET",
446
818
  effects: [
819
+ ["fetch", "RateLimiterState"],
447
820
  ["set", "@entity.requestCount", 0],
448
- ["set", "@entity.windowStart", ["time/now"]]
821
+ ["set", "@entity.windowStart", ["time/now"]],
822
+ rateLimiterView("Rate Limiter")
449
823
  ]
450
824
  },
451
825
  // Full counter reset
@@ -454,10 +828,12 @@ var RATE_LIMITER_BEHAVIOR = {
454
828
  to: "Active",
455
829
  event: "RESET",
456
830
  effects: [
831
+ ["fetch", "RateLimiterState"],
457
832
  ["set", "@entity.requestCount", 0],
458
833
  ["set", "@entity.totalRequests", 0],
459
834
  ["set", "@entity.rejectedRequests", 0],
460
- ["set", "@entity.windowStart", ["time/now"]]
835
+ ["set", "@entity.windowStart", ["time/now"]],
836
+ rateLimiterView("Rate Limiter")
461
837
  ]
462
838
  }
463
839
  ]
@@ -465,14 +841,13 @@ var RATE_LIMITER_BEHAVIOR = {
465
841
  ticks: [
466
842
  {
467
843
  name: "window_reset",
468
- interval: "@entity.windowMs",
469
- effects: [["emit", "WINDOW_RESET"]],
470
- description: "Reset request counter on sliding window expiry"
844
+ interval: 6e4,
845
+ effects: []
471
846
  }
472
847
  ]
473
848
  }
474
849
  ],
475
- pages: []
850
+ pages: [{ name: "RateLimiterPage", path: "/rate-limiter", isInitial: true, traits: [{ ref: "RateLimiter" }] }]
476
851
  }
477
852
  ]
478
853
  };
@@ -483,13 +858,14 @@ var CACHE_ASIDE_BEHAVIOR = {
483
858
  orbitals: [
484
859
  {
485
860
  name: "CacheAsideOrbital",
861
+ theme: INFRA_THEME,
486
862
  entity: {
487
863
  name: "CacheEntry",
488
864
  persistence: "runtime",
489
865
  fields: [
490
866
  { name: "id", type: "string", required: true },
491
867
  { name: "cacheKey", type: "string", default: "" },
492
- { name: "cachedValue", type: "object", default: null },
868
+ { name: "cachedValue", type: "string", default: "" },
493
869
  { name: "cachedAt", type: "number", default: 0 },
494
870
  { name: "ttlMs", type: "number", default: 3e5 },
495
871
  { name: "cacheHits", type: "number", default: 0 },
@@ -502,12 +878,7 @@ var CACHE_ASIDE_BEHAVIOR = {
502
878
  {
503
879
  name: "CacheAside",
504
880
  linkedEntity: "CacheEntry",
505
- category: "lifecycle",
506
- emits: [
507
- { event: "CACHE_HIT", scope: "internal" },
508
- { event: "CACHE_MISS", scope: "internal" },
509
- { event: "CACHE_EVICTED", scope: "internal" }
510
- ],
881
+ category: "interaction",
511
882
  stateMachine: {
512
883
  states: [
513
884
  { name: "Empty", isInitial: true },
@@ -515,34 +886,50 @@ var CACHE_ASIDE_BEHAVIOR = {
515
886
  { name: "Stale" }
516
887
  ],
517
888
  events: [
889
+ { key: "INIT", name: "Initialize" },
518
890
  { key: "LOOKUP", name: "Cache Lookup" },
519
- { key: "POPULATE", name: "Populate Cache" },
891
+ { key: "POPULATE", name: "Populate Cache", payloadSchema: [
892
+ { name: "value", type: "string", required: true },
893
+ { name: "key", type: "string", required: true }
894
+ ] },
520
895
  { key: "INVALIDATE", name: "Invalidate" },
521
- { key: "EVICT", name: "Evict" },
522
- { key: "EVICTION_TICK", name: "Eviction Tick" }
896
+ { key: "EVICT", name: "Evict" }
523
897
  ],
524
898
  transitions: [
899
+ // INIT
900
+ {
901
+ from: "Empty",
902
+ to: "Empty",
903
+ event: "INIT",
904
+ effects: [
905
+ ["fetch", "CacheEntry"],
906
+ cacheEmptyView("Cache")
907
+ ]
908
+ },
525
909
  // Empty: lookup is a miss
526
910
  {
527
911
  from: "Empty",
528
912
  to: "Empty",
529
913
  event: "LOOKUP",
530
914
  effects: [
915
+ ["fetch", "CacheEntry"],
531
916
  ["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
532
917
  ["set", "@entity.lastAccessed", ["time/now"]],
533
- ["emit", "CACHE_MISS", { key: "@entity.cacheKey" }]
918
+ cacheEmptyView("Cache - Miss")
534
919
  ]
535
920
  },
536
- // Empty Fresh: populate after fetch
921
+ // Empty -> Fresh: populate after fetch
537
922
  {
538
923
  from: "Empty",
539
924
  to: "Fresh",
540
925
  event: "POPULATE",
541
926
  effects: [
927
+ ["fetch", "CacheEntry"],
542
928
  ["set", "@entity.cachedValue", "@payload.value"],
543
929
  ["set", "@entity.cacheKey", "@payload.key"],
544
930
  ["set", "@entity.cachedAt", ["time/now"]],
545
- ["set", "@entity.isFresh", true]
931
+ ["set", "@entity.isFresh", true],
932
+ cacheStatsView("Cache - Fresh")
546
933
  ]
547
934
  },
548
935
  // Fresh: lookup is a hit
@@ -552,22 +939,36 @@ var CACHE_ASIDE_BEHAVIOR = {
552
939
  event: "LOOKUP",
553
940
  guard: ["<", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"],
554
941
  effects: [
942
+ ["fetch", "CacheEntry"],
555
943
  ["set", "@entity.cacheHits", ["+", "@entity.cacheHits", 1]],
556
944
  ["set", "@entity.lastAccessed", ["time/now"]],
557
- ["emit", "CACHE_HIT", { key: "@entity.cacheKey" }]
945
+ cacheStatsView("Cache - Hit")
558
946
  ]
559
947
  },
560
- // Fresh Stale: TTL expired on lookup
948
+ // Fresh -> Stale: TTL expired on lookup
561
949
  {
562
950
  from: "Fresh",
563
951
  to: "Stale",
564
952
  event: "LOOKUP",
565
953
  guard: [">=", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"],
566
954
  effects: [
955
+ ["fetch", "CacheEntry"],
567
956
  ["set", "@entity.isFresh", false],
568
957
  ["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
569
958
  ["set", "@entity.lastAccessed", ["time/now"]],
570
- ["emit", "CACHE_MISS", { key: "@entity.cacheKey", reason: "ttl_expired" }]
959
+ cacheStatsView("Cache - Stale")
960
+ ]
961
+ },
962
+ // Fresh -> Fresh: update cache
963
+ {
964
+ from: "Fresh",
965
+ to: "Fresh",
966
+ event: "POPULATE",
967
+ effects: [
968
+ ["fetch", "CacheEntry"],
969
+ ["set", "@entity.cachedValue", "@payload.value"],
970
+ ["set", "@entity.cachedAt", ["time/now"]],
971
+ cacheStatsView("Cache - Fresh")
571
972
  ]
572
973
  },
573
974
  // Stale: lookup is a miss
@@ -576,65 +977,75 @@ var CACHE_ASIDE_BEHAVIOR = {
576
977
  to: "Stale",
577
978
  event: "LOOKUP",
578
979
  effects: [
980
+ ["fetch", "CacheEntry"],
579
981
  ["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
580
982
  ["set", "@entity.lastAccessed", ["time/now"]],
581
- ["emit", "CACHE_MISS", { key: "@entity.cacheKey", reason: "stale" }]
983
+ cacheStatsView("Cache - Stale")
582
984
  ]
583
985
  },
584
- // Stale Fresh: re-populate
986
+ // Stale -> Fresh: re-populate
585
987
  {
586
988
  from: "Stale",
587
989
  to: "Fresh",
588
990
  event: "POPULATE",
589
991
  effects: [
992
+ ["fetch", "CacheEntry"],
590
993
  ["set", "@entity.cachedValue", "@payload.value"],
591
994
  ["set", "@entity.cachedAt", ["time/now"]],
592
- ["set", "@entity.isFresh", true]
995
+ ["set", "@entity.isFresh", true],
996
+ cacheStatsView("Cache - Fresh")
593
997
  ]
594
998
  },
595
- // Fresh Fresh: update cache
999
+ // Invalidate from Fresh
596
1000
  {
597
1001
  from: "Fresh",
598
- to: "Fresh",
599
- event: "POPULATE",
1002
+ to: "Empty",
1003
+ event: "INVALIDATE",
600
1004
  effects: [
601
- ["set", "@entity.cachedValue", "@payload.value"],
602
- ["set", "@entity.cachedAt", ["time/now"]]
1005
+ ["fetch", "CacheEntry"],
1006
+ ["set", "@entity.cachedValue", ""],
1007
+ ["set", "@entity.isFresh", false],
1008
+ ["set", "@entity.cachedAt", 0],
1009
+ cacheEmptyView("Cache")
603
1010
  ]
604
1011
  },
605
- // Invalidate from any cached state
1012
+ // Invalidate from Stale
606
1013
  {
607
- from: ["Fresh", "Stale"],
1014
+ from: "Stale",
608
1015
  to: "Empty",
609
1016
  event: "INVALIDATE",
610
1017
  effects: [
611
- ["set", "@entity.cachedValue", null],
1018
+ ["fetch", "CacheEntry"],
1019
+ ["set", "@entity.cachedValue", ""],
612
1020
  ["set", "@entity.isFresh", false],
613
- ["set", "@entity.cachedAt", 0]
1021
+ ["set", "@entity.cachedAt", 0],
1022
+ cacheEmptyView("Cache")
614
1023
  ]
615
1024
  },
616
- // Evict (with event)
1025
+ // Evict from Fresh
617
1026
  {
618
- from: ["Fresh", "Stale"],
1027
+ from: "Fresh",
619
1028
  to: "Empty",
620
1029
  event: "EVICT",
621
1030
  effects: [
622
- ["set", "@entity.cachedValue", null],
1031
+ ["fetch", "CacheEntry"],
1032
+ ["set", "@entity.cachedValue", ""],
623
1033
  ["set", "@entity.isFresh", false],
624
1034
  ["set", "@entity.cachedAt", 0],
625
- ["emit", "CACHE_EVICTED", { key: "@entity.cacheKey" }]
1035
+ cacheEmptyView("Cache")
626
1036
  ]
627
1037
  },
628
- // Eviction tick: evict if stale
1038
+ // Evict from Stale
629
1039
  {
630
1040
  from: "Stale",
631
1041
  to: "Empty",
632
- event: "EVICTION_TICK",
1042
+ event: "EVICT",
633
1043
  effects: [
634
- ["set", "@entity.cachedValue", null],
1044
+ ["fetch", "CacheEntry"],
1045
+ ["set", "@entity.cachedValue", ""],
635
1046
  ["set", "@entity.isFresh", false],
636
1047
  ["set", "@entity.cachedAt", 0],
637
- ["emit", "CACHE_EVICTED", { key: "@entity.cacheKey", reason: "ttl_eviction" }]
1048
+ cacheEmptyView("Cache")
638
1049
  ]
639
1050
  }
640
1051
  ]
@@ -642,15 +1053,14 @@ var CACHE_ASIDE_BEHAVIOR = {
642
1053
  ticks: [
643
1054
  {
644
1055
  name: "eviction_sweep",
645
- interval: "60000",
1056
+ interval: 6e4,
646
1057
  guard: ["and", ["!=", "@entity.cachedAt", 0], [">=", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"]],
647
- effects: [["emit", "EVICTION_TICK"]],
648
- description: "Periodically evict stale cache entries"
1058
+ effects: []
649
1059
  }
650
1060
  ]
651
1061
  }
652
1062
  ],
653
- pages: []
1063
+ pages: [{ name: "CachePage", path: "/cache", isInitial: true, traits: [{ ref: "CacheAside" }] }]
654
1064
  }
655
1065
  ]
656
1066
  };
@@ -661,6 +1071,7 @@ var SAGA_BEHAVIOR = {
661
1071
  orbitals: [
662
1072
  {
663
1073
  name: "SagaOrbital",
1074
+ theme: INFRA_THEME,
664
1075
  entity: {
665
1076
  name: "SagaState",
666
1077
  persistence: "runtime",
@@ -670,8 +1081,6 @@ var SAGA_BEHAVIOR = {
670
1081
  { name: "currentStep", type: "number", default: 0 },
671
1082
  { name: "totalSteps", type: "number", default: 0 },
672
1083
  { name: "sagaStatus", type: "string", default: "idle" },
673
- { name: "completedSteps", type: "array", default: [] },
674
- { name: "compensatedSteps", type: "array", default: [] },
675
1084
  { name: "failedStep", type: "number", default: -1 },
676
1085
  { name: "failureReason", type: "string", default: "" },
677
1086
  { name: "startedAt", type: "number", default: 0 },
@@ -682,15 +1091,7 @@ var SAGA_BEHAVIOR = {
682
1091
  {
683
1092
  name: "Saga",
684
1093
  linkedEntity: "SagaState",
685
- category: "lifecycle",
686
- emits: [
687
- { event: "SAGA_STARTED", scope: "external" },
688
- { event: "SAGA_STEP_COMPLETED", scope: "external" },
689
- { event: "SAGA_COMPLETED", scope: "external" },
690
- { event: "SAGA_COMPENSATING", scope: "external" },
691
- { event: "SAGA_COMPENSATION_DONE", scope: "external" },
692
- { event: "SAGA_FAILED", scope: "external" }
693
- ],
1094
+ category: "interaction",
694
1095
  stateMachine: {
695
1096
  states: [
696
1097
  { name: "Idle", isInitial: true },
@@ -700,6 +1101,7 @@ var SAGA_BEHAVIOR = {
700
1101
  { name: "Failed" }
701
1102
  ],
702
1103
  events: [
1104
+ { key: "INIT", name: "Initialize" },
703
1105
  { key: "START_SAGA", name: "Start Saga" },
704
1106
  { key: "STEP_SUCCESS", name: "Step Success" },
705
1107
  { key: "STEP_FAILURE", name: "Step Failure" },
@@ -708,20 +1110,29 @@ var SAGA_BEHAVIOR = {
708
1110
  { key: "RESET", name: "Reset" }
709
1111
  ],
710
1112
  transitions: [
711
- // Idle → Running: start the saga
1113
+ // INIT
1114
+ {
1115
+ from: "Idle",
1116
+ to: "Idle",
1117
+ event: "INIT",
1118
+ effects: [
1119
+ ["fetch", "SagaState"],
1120
+ sagaView("Saga")
1121
+ ]
1122
+ },
1123
+ // Idle -> Running: start the saga
712
1124
  {
713
1125
  from: "Idle",
714
1126
  to: "Running",
715
1127
  event: "START_SAGA",
716
1128
  effects: [
1129
+ ["fetch", "SagaState"],
717
1130
  ["set", "@entity.sagaStatus", "running"],
718
1131
  ["set", "@entity.currentStep", 0],
719
- ["set", "@entity.completedSteps", []],
720
- ["set", "@entity.compensatedSteps", []],
721
1132
  ["set", "@entity.failedStep", -1],
722
1133
  ["set", "@entity.failureReason", ""],
723
1134
  ["set", "@entity.startedAt", ["time/now"]],
724
- ["emit", "SAGA_STARTED", { sagaName: "@entity.sagaName" }]
1135
+ sagaView("Saga - Running")
725
1136
  ]
726
1137
  },
727
1138
  // Running: step success, more steps remaining
@@ -731,37 +1142,34 @@ var SAGA_BEHAVIOR = {
731
1142
  event: "STEP_SUCCESS",
732
1143
  guard: ["<", ["+", "@entity.currentStep", 1], "@entity.totalSteps"],
733
1144
  effects: [
1145
+ ["fetch", "SagaState"],
734
1146
  ["set", "@entity.currentStep", ["+", "@entity.currentStep", 1]],
735
- ["emit", "SAGA_STEP_COMPLETED", {
736
- step: "@entity.currentStep",
737
- totalSteps: "@entity.totalSteps"
738
- }]
1147
+ sagaView("Saga - Running")
739
1148
  ]
740
1149
  },
741
- // Running Completed: last step succeeded
1150
+ // Running -> Completed: last step succeeded
742
1151
  {
743
1152
  from: "Running",
744
1153
  to: "Completed",
745
1154
  event: "STEP_SUCCESS",
746
1155
  guard: [">=", ["+", "@entity.currentStep", 1], "@entity.totalSteps"],
747
1156
  effects: [
1157
+ ["fetch", "SagaState"],
748
1158
  ["set", "@entity.sagaStatus", "completed"],
749
1159
  ["set", "@entity.completedAt", ["time/now"]],
750
- ["emit", "SAGA_COMPLETED", { sagaName: "@entity.sagaName" }]
1160
+ sagaView("Saga - Completed")
751
1161
  ]
752
1162
  },
753
- // Running Compensating: a step failed
1163
+ // Running -> Compensating: a step failed
754
1164
  {
755
1165
  from: "Running",
756
1166
  to: "Compensating",
757
1167
  event: "STEP_FAILURE",
758
1168
  effects: [
1169
+ ["fetch", "SagaState"],
759
1170
  ["set", "@entity.sagaStatus", "compensating"],
760
1171
  ["set", "@entity.failedStep", "@entity.currentStep"],
761
- ["emit", "SAGA_COMPENSATING", {
762
- failedStep: "@entity.currentStep",
763
- sagaName: "@entity.sagaName"
764
- }]
1172
+ sagaView("Saga - Compensating")
765
1173
  ]
766
1174
  },
767
1175
  // Compensating: compensation step succeeded, more to undo
@@ -771,47 +1179,62 @@ var SAGA_BEHAVIOR = {
771
1179
  event: "COMPENSATE_SUCCESS",
772
1180
  guard: [">", "@entity.currentStep", 0],
773
1181
  effects: [
774
- ["set", "@entity.currentStep", ["-", "@entity.currentStep", 1]]
1182
+ ["fetch", "SagaState"],
1183
+ ["set", "@entity.currentStep", ["-", "@entity.currentStep", 1]],
1184
+ sagaView("Saga - Compensating")
775
1185
  ]
776
1186
  },
777
- // Compensating Failed: all compensations done (reached step 0)
1187
+ // Compensating -> Failed: all compensations done (reached step 0)
778
1188
  {
779
1189
  from: "Compensating",
780
1190
  to: "Failed",
781
1191
  event: "COMPENSATE_SUCCESS",
782
1192
  guard: ["<=", "@entity.currentStep", 0],
783
1193
  effects: [
1194
+ ["fetch", "SagaState"],
784
1195
  ["set", "@entity.sagaStatus", "failed"],
785
1196
  ["set", "@entity.completedAt", ["time/now"]],
786
- ["emit", "SAGA_COMPENSATION_DONE", { sagaName: "@entity.sagaName" }]
1197
+ sagaView("Saga - Failed")
787
1198
  ]
788
1199
  },
789
- // Compensating Failed: compensation itself failed
1200
+ // Compensating -> Failed: compensation itself failed
790
1201
  {
791
1202
  from: "Compensating",
792
1203
  to: "Failed",
793
1204
  event: "COMPENSATE_FAILURE",
794
1205
  effects: [
1206
+ ["fetch", "SagaState"],
795
1207
  ["set", "@entity.sagaStatus", "failed"],
796
1208
  ["set", "@entity.completedAt", ["time/now"]],
797
- ["emit", "SAGA_FAILED", {
798
- sagaName: "@entity.sagaName",
799
- reason: "Compensation failed"
800
- }]
1209
+ sagaView("Saga - Failed")
801
1210
  ]
802
1211
  },
803
- // Reset from terminal states
1212
+ // Reset from Completed
804
1213
  {
805
- from: ["Completed", "Failed"],
1214
+ from: "Completed",
806
1215
  to: "Idle",
807
1216
  event: "RESET",
808
1217
  effects: [
1218
+ ["fetch", "SagaState"],
809
1219
  ["set", "@entity.sagaStatus", "idle"],
810
1220
  ["set", "@entity.currentStep", 0],
811
- ["set", "@entity.completedSteps", []],
812
- ["set", "@entity.compensatedSteps", []],
813
1221
  ["set", "@entity.failedStep", -1],
814
- ["set", "@entity.failureReason", ""]
1222
+ ["set", "@entity.failureReason", ""],
1223
+ sagaView("Saga")
1224
+ ]
1225
+ },
1226
+ // Reset from Failed
1227
+ {
1228
+ from: "Failed",
1229
+ to: "Idle",
1230
+ event: "RESET",
1231
+ effects: [
1232
+ ["fetch", "SagaState"],
1233
+ ["set", "@entity.sagaStatus", "idle"],
1234
+ ["set", "@entity.currentStep", 0],
1235
+ ["set", "@entity.failedStep", -1],
1236
+ ["set", "@entity.failureReason", ""],
1237
+ sagaView("Saga")
815
1238
  ]
816
1239
  }
817
1240
  ]
@@ -819,7 +1242,7 @@ var SAGA_BEHAVIOR = {
819
1242
  ticks: []
820
1243
  }
821
1244
  ],
822
- pages: []
1245
+ pages: [{ name: "SagaPage", path: "/saga", isInitial: true, traits: [{ ref: "Saga" }] }]
823
1246
  }
824
1247
  ]
825
1248
  };
@@ -830,15 +1253,13 @@ var METRICS_COLLECTOR_BEHAVIOR = {
830
1253
  orbitals: [
831
1254
  {
832
1255
  name: "MetricsCollectorOrbital",
1256
+ theme: INFRA_THEME,
833
1257
  entity: {
834
1258
  name: "MetricsState",
835
1259
  persistence: "runtime",
836
1260
  fields: [
837
1261
  { name: "id", type: "string", required: true },
838
- { name: "counters", type: "object", default: {} },
839
- { name: "gauges", type: "object", default: {} },
840
1262
  { name: "lastFlush", type: "number", default: 0 },
841
- { name: "flushIntervalMs", type: "number", default: 6e4 },
842
1263
  { name: "totalFlushes", type: "number", default: 0 },
843
1264
  { name: "totalRecorded", type: "number", default: 0 }
844
1265
  ]
@@ -847,28 +1268,38 @@ var METRICS_COLLECTOR_BEHAVIOR = {
847
1268
  {
848
1269
  name: "MetricsCollector",
849
1270
  linkedEntity: "MetricsState",
850
- category: "lifecycle",
851
- emits: [
852
- { event: "METRICS_REPORT", scope: "external" }
853
- ],
1271
+ category: "interaction",
854
1272
  stateMachine: {
855
1273
  states: [
856
1274
  { name: "Collecting", isInitial: true }
857
1275
  ],
858
1276
  events: [
1277
+ { key: "INIT", name: "Initialize" },
859
1278
  { key: "RECORD_COUNTER", name: "Record Counter" },
860
1279
  { key: "RECORD_GAUGE", name: "Record Gauge" },
861
1280
  { key: "FLUSH", name: "Flush Metrics" },
862
1281
  { key: "RESET", name: "Reset All" }
863
1282
  ],
864
1283
  transitions: [
1284
+ // INIT
1285
+ {
1286
+ from: "Collecting",
1287
+ to: "Collecting",
1288
+ event: "INIT",
1289
+ effects: [
1290
+ ["fetch", "MetricsState"],
1291
+ metricsView("Metrics Collector")
1292
+ ]
1293
+ },
865
1294
  // Record a counter increment
866
1295
  {
867
1296
  from: "Collecting",
868
1297
  to: "Collecting",
869
1298
  event: "RECORD_COUNTER",
870
1299
  effects: [
871
- ["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]]
1300
+ ["fetch", "MetricsState"],
1301
+ ["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]],
1302
+ metricsView("Metrics Collector")
872
1303
  ]
873
1304
  },
874
1305
  // Record a gauge value
@@ -877,23 +1308,21 @@ var METRICS_COLLECTOR_BEHAVIOR = {
877
1308
  to: "Collecting",
878
1309
  event: "RECORD_GAUGE",
879
1310
  effects: [
880
- ["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]]
1311
+ ["fetch", "MetricsState"],
1312
+ ["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]],
1313
+ metricsView("Metrics Collector")
881
1314
  ]
882
1315
  },
883
- // Flush: emit report and reset counters
1316
+ // Flush: reset counters
884
1317
  {
885
1318
  from: "Collecting",
886
1319
  to: "Collecting",
887
1320
  event: "FLUSH",
888
1321
  effects: [
889
- ["emit", "METRICS_REPORT", {
890
- counters: "@entity.counters",
891
- gauges: "@entity.gauges",
892
- totalRecorded: "@entity.totalRecorded"
893
- }],
894
- ["set", "@entity.counters", {}],
1322
+ ["fetch", "MetricsState"],
895
1323
  ["set", "@entity.lastFlush", ["time/now"]],
896
- ["set", "@entity.totalFlushes", ["+", "@entity.totalFlushes", 1]]
1324
+ ["set", "@entity.totalFlushes", ["+", "@entity.totalFlushes", 1]],
1325
+ metricsView("Metrics Collector")
897
1326
  ]
898
1327
  },
899
1328
  // Full reset
@@ -902,11 +1331,11 @@ var METRICS_COLLECTOR_BEHAVIOR = {
902
1331
  to: "Collecting",
903
1332
  event: "RESET",
904
1333
  effects: [
905
- ["set", "@entity.counters", {}],
906
- ["set", "@entity.gauges", {}],
1334
+ ["fetch", "MetricsState"],
907
1335
  ["set", "@entity.totalRecorded", 0],
908
1336
  ["set", "@entity.totalFlushes", 0],
909
- ["set", "@entity.lastFlush", 0]
1337
+ ["set", "@entity.lastFlush", 0],
1338
+ metricsView("Metrics Collector")
910
1339
  ]
911
1340
  }
912
1341
  ]
@@ -914,15 +1343,14 @@ var METRICS_COLLECTOR_BEHAVIOR = {
914
1343
  ticks: [
915
1344
  {
916
1345
  name: "periodic_flush",
917
- interval: "@entity.flushIntervalMs",
1346
+ interval: 6e4,
918
1347
  guard: [">", "@entity.totalRecorded", 0],
919
- effects: [["emit", "FLUSH"]],
920
- description: "Periodically flush accumulated metrics"
1348
+ effects: []
921
1349
  }
922
1350
  ]
923
1351
  }
924
1352
  ],
925
- pages: []
1353
+ pages: [{ name: "MetricsPage", path: "/metrics", isInitial: true, traits: [{ ref: "MetricsCollector" }] }]
926
1354
  }
927
1355
  ]
928
1356
  };