@winkjs/composer 0.0.2 → 0.4.0

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 (451) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +42 -103
  3. package/package.json +53 -29
  4. package/src/composer.js +75 -0
  5. package/src/core/batch/aoo-encoder.js +148 -0
  6. package/src/core/batch/index.js +12 -0
  7. package/src/core/batch/sliding-window.js +91 -0
  8. package/src/core/codec/index.js +137 -0
  9. package/src/core/emitter-manager/mqtt/constants.js +102 -0
  10. package/src/core/emitter-manager/mqtt/emitter.js +780 -0
  11. package/src/core/emitter-manager/mqtt/index.js +190 -0
  12. package/src/core/emitter-manager/mqtt/mqtt-store.js +538 -0
  13. package/src/core/emitter-manager/terminal/assert-columns.js +98 -0
  14. package/src/core/emitter-manager/terminal/formatters.js +160 -0
  15. package/src/core/emitter-manager/terminal/index.js +341 -0
  16. package/src/core/env-vars.js +245 -0
  17. package/src/core/mqtt-protocol.js +47 -0
  18. package/src/core/partition-manager/index.js +7 -0
  19. package/src/core/partition-manager/init.js +44 -0
  20. package/src/core/partition-manager/introspect.js +15 -0
  21. package/src/core/partition-manager/publish-to.js +6 -0
  22. package/src/core/partition-manager/recompute.js +5 -0
  23. package/src/core/partition-manager/reset.js +5 -0
  24. package/src/core/partition-manager/update.js +264 -0
  25. package/src/core/partition-manager/validate-flow.js +157 -0
  26. package/src/core/semantics/digest.js +128 -0
  27. package/src/core/semantics/index.js +83 -0
  28. package/src/core/semantics/loader.js +571 -0
  29. package/src/core/semantics/schemas/asset-class-schema.js +218 -0
  30. package/src/core/semantics/schemas/column-schema.js +651 -0
  31. package/src/core/semantics/schemas/enum-schema.js +153 -0
  32. package/src/core/semantics/schemas/index.js +51 -0
  33. package/src/core/semantics/warnings.js +141 -0
  34. package/src/core/shutdown-manager/index.js +289 -0
  35. package/src/core/source-manager/csv/index.js +171 -0
  36. package/src/core/source-manager/csv/start.js +456 -0
  37. package/src/core/source-manager/mqtt/client.js +406 -0
  38. package/src/core/source-manager/mqtt/constants.js +147 -0
  39. package/src/core/source-manager/mqtt/dedup.js +244 -0
  40. package/src/core/source-manager/mqtt/index.js +260 -0
  41. package/src/core/source-manager/mqtt/status.js +546 -0
  42. package/src/core/source-manager/test-harness/comparator.js +226 -0
  43. package/src/core/source-manager/test-harness/field-generator.js +85 -0
  44. package/src/core/source-manager/test-harness/fuzz.js +87 -0
  45. package/src/core/source-manager/test-harness/index.js +115 -0
  46. package/src/core/source-manager/test-harness/prng.js +57 -0
  47. package/src/core/source-manager/test-harness/start.js +232 -0
  48. package/src/core/source-manager/test-harness/validate.js +213 -0
  49. package/src/core/storage-manager/questdb/assert-columns.js +120 -0
  50. package/src/core/storage-manager/questdb/ensure-tables.js +187 -0
  51. package/src/core/storage-manager/questdb/index.js +1251 -0
  52. package/src/core/storage-manager/questdb/persist-plan.js +488 -0
  53. package/src/core/storage-manager/questdb/writers.js +142 -0
  54. package/src/core/test-utils/sealed-record.js +80 -0
  55. package/src/core/test-utils/soak-signature.js +149 -0
  56. package/src/core/test-utils/tcp-proxy.js +106 -0
  57. package/src/core/tunable/helpers.js +254 -0
  58. package/src/core/tunable/index.js +87 -0
  59. package/src/core/utils/console-formatter/index.js +207 -0
  60. package/src/core/utils/create-smart-store-as/index.js +98 -0
  61. package/src/core/utils/create-smart-store-as/sanitize-field.js +46 -0
  62. package/src/core/utils/create-smart-store-as/smart-truncate.js +93 -0
  63. package/src/core/utils/flow/index.js +5 -0
  64. package/src/core/utils/flow/make-collision-checker.js +23 -0
  65. package/src/core/utils/flow/to-kebab.js +20 -0
  66. package/src/core/utils/half-life/index.js +111 -0
  67. package/src/core/utils/node/disable.js +11 -0
  68. package/src/core/utils/node/enable.js +11 -0
  69. package/src/core/utils/node/execute-triggers.js +40 -0
  70. package/src/core/utils/node/index.js +10 -0
  71. package/src/core/utils/node/pause.js +11 -0
  72. package/src/core/utils/node/populate-predicate-inputs.js +14 -0
  73. package/src/core/utils/node/publish-nan.js +19 -0
  74. package/src/core/utils/node/reset-predicate-inputs.js +11 -0
  75. package/src/core/utils/node/unpause.js +11 -0
  76. package/src/core/utils/node/validate-spec.js +22 -0
  77. package/src/core/utils/options/resolve-field-keyed.js +115 -0
  78. package/src/core/utils/quantize/index.js +75 -0
  79. package/src/core/utils/stats/formulas.js +67 -0
  80. package/src/core/utils/stats/index.js +3 -0
  81. package/src/core/utils/validate/composer-validators.js +141 -0
  82. package/src/core/utils/validate/helpers.js +206 -0
  83. package/src/core/utils/validate/index.js +12 -0
  84. package/src/core/utils/validate/type-validators.js +538 -0
  85. package/src/core/utils/validate/validate.js +107 -0
  86. package/src/core/utils/validate/validators.js +177 -0
  87. package/src/core/wiring/assert-handle.js +57 -0
  88. package/src/core/wiring/assert-module.js +63 -0
  89. package/src/core/wiring/index.js +5 -0
  90. package/src/core/wiring/node-type-to-module.js +17 -0
  91. package/src/core/wiring/wire-emitters.js +256 -0
  92. package/src/core/wiring/wire-linear-graph.js +25 -0
  93. package/src/core/wiring/wire-node.js +157 -0
  94. package/src/core/wiring/wire-semantics.js +173 -0
  95. package/src/core/wiring/wire-storages.js +344 -0
  96. package/src/flow/check-output-collisions.js +93 -0
  97. package/src/flow/consts.js +9 -0
  98. package/src/flow/deep-clone-spec.js +64 -0
  99. package/src/flow/driver.js +171 -0
  100. package/src/flow/expand-single-input-array.js +76 -0
  101. package/src/flow/expand-template-spec.js +93 -0
  102. package/src/flow/flow-api-schemas.js +300 -0
  103. package/src/flow/flow.js +658 -0
  104. package/src/flow/for-each.js +225 -0
  105. package/src/flow/get-signature-pattern.js +31 -0
  106. package/src/flow/get-target-array.js +46 -0
  107. package/src/flow/inspect.js +67 -0
  108. package/src/flow/load-node-module.js +81 -0
  109. package/src/flow/make-node-method.js +112 -0
  110. package/src/flow/resolve-pick-by-field.js +77 -0
  111. package/src/flow/resolve-tunables.js +76 -0
  112. package/src/flow/run.js +392 -0
  113. package/src/flow/serialize.js +161 -0
  114. package/src/flow/signatures-schema.js +222 -0
  115. package/src/flow/spec-builder.js +65 -0
  116. package/src/flow/validate-triggers.js +250 -0
  117. package/src/flow/validate.js +261 -0
  118. package/src/nodes/accumulate/index.js +21 -0
  119. package/src/nodes/accumulate/init.js +48 -0
  120. package/src/nodes/accumulate/introspect.js +123 -0
  121. package/src/nodes/accumulate/publish-to.js +34 -0
  122. package/src/nodes/accumulate/recompute.js +27 -0
  123. package/src/nodes/accumulate/reset.js +25 -0
  124. package/src/nodes/accumulate/update.js +42 -0
  125. package/src/nodes/appraise/calibrate.js +64 -0
  126. package/src/nodes/appraise/decision.js +66 -0
  127. package/src/nodes/appraise/deviation.js +140 -0
  128. package/src/nodes/appraise/index.js +23 -0
  129. package/src/nodes/appraise/init.js +165 -0
  130. package/src/nodes/appraise/integrate.js +45 -0
  131. package/src/nodes/appraise/introspect.js +352 -0
  132. package/src/nodes/appraise/publish-to.js +93 -0
  133. package/src/nodes/appraise/receptor.js +69 -0
  134. package/src/nodes/appraise/recompute.js +79 -0
  135. package/src/nodes/appraise/reset.js +53 -0
  136. package/src/nodes/appraise/update.js +130 -0
  137. package/src/nodes/archive/csv/index.js +6 -0
  138. package/src/nodes/archive/csv/init.js +36 -0
  139. package/src/nodes/archive/csv/load.js +70 -0
  140. package/src/nodes/archive/csv/reset.js +14 -0
  141. package/src/nodes/archive/csv/simple-parser.js +216 -0
  142. package/src/nodes/archive/csv/test.js +173 -0
  143. package/src/nodes/archive/csv/update.js +63 -0
  144. package/src/nodes/butterworth-filter/index.js +18 -0
  145. package/src/nodes/butterworth-filter/init.js +184 -0
  146. package/src/nodes/butterworth-filter/introspect.js +228 -0
  147. package/src/nodes/butterworth-filter/publish-to.js +21 -0
  148. package/src/nodes/butterworth-filter/recompute.js +13 -0
  149. package/src/nodes/butterworth-filter/reset.js +30 -0
  150. package/src/nodes/butterworth-filter/update.js +38 -0
  151. package/src/nodes/categorize/index.js +19 -0
  152. package/src/nodes/categorize/init.js +58 -0
  153. package/src/nodes/categorize/introspect.js +177 -0
  154. package/src/nodes/categorize/publish-to.js +29 -0
  155. package/src/nodes/categorize/recompute.js +14 -0
  156. package/src/nodes/categorize/reset.js +16 -0
  157. package/src/nodes/categorize/update.js +53 -0
  158. package/src/nodes/controller/index.js +9 -0
  159. package/src/nodes/controller/init.js +55 -0
  160. package/src/nodes/controller/introspect.js +91 -0
  161. package/src/nodes/controller/publish-to.js +8 -0
  162. package/src/nodes/controller/recompute.js +9 -0
  163. package/src/nodes/controller/reset.js +17 -0
  164. package/src/nodes/controller/update.js +63 -0
  165. package/src/nodes/diff/index.js +19 -0
  166. package/src/nodes/diff/init.js +37 -0
  167. package/src/nodes/diff/introspect.js +132 -0
  168. package/src/nodes/diff/publish-to.js +21 -0
  169. package/src/nodes/diff/recompute.js +12 -0
  170. package/src/nodes/diff/reset.js +12 -0
  171. package/src/nodes/diff/update.js +37 -0
  172. package/src/nodes/digest-moments/formulas.js +12 -0
  173. package/src/nodes/digest-moments/index.js +14 -0
  174. package/src/nodes/digest-moments/init.js +67 -0
  175. package/src/nodes/digest-moments/introspect.js +154 -0
  176. package/src/nodes/digest-moments/publish-to.js +34 -0
  177. package/src/nodes/digest-moments/recompute.js +14 -0
  178. package/src/nodes/digest-moments/reset.js +14 -0
  179. package/src/nodes/digest-moments/update.js +120 -0
  180. package/src/nodes/dwell-time-tracker/index.js +14 -0
  181. package/src/nodes/dwell-time-tracker/init.js +59 -0
  182. package/src/nodes/dwell-time-tracker/introspect.js +137 -0
  183. package/src/nodes/dwell-time-tracker/publish-to.js +22 -0
  184. package/src/nodes/dwell-time-tracker/recompute.js +8 -0
  185. package/src/nodes/dwell-time-tracker/reset.js +23 -0
  186. package/src/nodes/dwell-time-tracker/update.js +103 -0
  187. package/src/nodes/emit-if/helpers.js +94 -0
  188. package/src/nodes/emit-if/index.js +16 -0
  189. package/src/nodes/emit-if/init.js +67 -0
  190. package/src/nodes/emit-if/introspect.js +102 -0
  191. package/src/nodes/emit-if/publish-to.js +13 -0
  192. package/src/nodes/emit-if/recompute.js +12 -0
  193. package/src/nodes/emit-if/reset.js +27 -0
  194. package/src/nodes/emit-if/update.js +93 -0
  195. package/src/nodes/es-correlation/index.js +19 -0
  196. package/src/nodes/es-correlation/init.js +73 -0
  197. package/src/nodes/es-correlation/introspect.js +176 -0
  198. package/src/nodes/es-correlation/publish-to.js +32 -0
  199. package/src/nodes/es-correlation/recompute.js +56 -0
  200. package/src/nodes/es-correlation/reset.js +27 -0
  201. package/src/nodes/es-correlation/update.js +110 -0
  202. package/src/nodes/es-mean/index.js +20 -0
  203. package/src/nodes/es-mean/init.js +58 -0
  204. package/src/nodes/es-mean/introspect.js +129 -0
  205. package/src/nodes/es-mean/publish-to.js +19 -0
  206. package/src/nodes/es-mean/recompute.js +16 -0
  207. package/src/nodes/es-mean/reset.js +24 -0
  208. package/src/nodes/es-mean/update.js +69 -0
  209. package/src/nodes/es-pairwise-correlation/index.js +19 -0
  210. package/src/nodes/es-pairwise-correlation/init.js +98 -0
  211. package/src/nodes/es-pairwise-correlation/introspect.js +187 -0
  212. package/src/nodes/es-pairwise-correlation/publish-to.js +31 -0
  213. package/src/nodes/es-pairwise-correlation/recompute.js +69 -0
  214. package/src/nodes/es-pairwise-correlation/reset.js +29 -0
  215. package/src/nodes/es-pairwise-correlation/update.js +89 -0
  216. package/src/nodes/es-stats/index.js +21 -0
  217. package/src/nodes/es-stats/init.js +105 -0
  218. package/src/nodes/es-stats/introspect.js +157 -0
  219. package/src/nodes/es-stats/publish-to.js +42 -0
  220. package/src/nodes/es-stats/recompute.js +74 -0
  221. package/src/nodes/es-stats/reset.js +49 -0
  222. package/src/nodes/es-stats/update-envelope.js +44 -0
  223. package/src/nodes/es-stats/update-welford.js +64 -0
  224. package/src/nodes/es-stats/update.js +59 -0
  225. package/src/nodes/index.js +83 -0
  226. package/src/nodes/invert-flag/index.js +20 -0
  227. package/src/nodes/invert-flag/init.js +36 -0
  228. package/src/nodes/invert-flag/introspect.js +115 -0
  229. package/src/nodes/invert-flag/publish-to.js +23 -0
  230. package/src/nodes/invert-flag/recompute.js +12 -0
  231. package/src/nodes/invert-flag/reset.js +12 -0
  232. package/src/nodes/invert-flag/update.js +32 -0
  233. package/src/nodes/kalman1d/index.js +20 -0
  234. package/src/nodes/kalman1d/init.js +103 -0
  235. package/src/nodes/kalman1d/introspect.js +250 -0
  236. package/src/nodes/kalman1d/publish-to.js +34 -0
  237. package/src/nodes/kalman1d/recompute.js +23 -0
  238. package/src/nodes/kalman1d/reset.js +29 -0
  239. package/src/nodes/kalman1d/update.js +144 -0
  240. package/src/nodes/kernel/index.js +18 -0
  241. package/src/nodes/kernel/init.js +66 -0
  242. package/src/nodes/kernel/introspect.js +163 -0
  243. package/src/nodes/kernel/presets.js +74 -0
  244. package/src/nodes/kernel/publish-to.js +25 -0
  245. package/src/nodes/kernel/recompute.js +14 -0
  246. package/src/nodes/kernel/reset.js +20 -0
  247. package/src/nodes/kernel/update.js +69 -0
  248. package/src/nodes/lag/index.js +21 -0
  249. package/src/nodes/lag/init.js +87 -0
  250. package/src/nodes/lag/introspect.js +202 -0
  251. package/src/nodes/lag/publish-to.js +64 -0
  252. package/src/nodes/lag/recompute.js +33 -0
  253. package/src/nodes/lag/reset.js +49 -0
  254. package/src/nodes/lag/update.js +133 -0
  255. package/src/nodes/median3/index.js +19 -0
  256. package/src/nodes/median3/init.js +40 -0
  257. package/src/nodes/median3/introspect.js +116 -0
  258. package/src/nodes/median3/publish-to.js +21 -0
  259. package/src/nodes/median3/recompute.js +12 -0
  260. package/src/nodes/median3/reset.js +15 -0
  261. package/src/nodes/median3/update.js +58 -0
  262. package/src/nodes/moments-digest/copy-from.js +12 -0
  263. package/src/nodes/moments-digest/flush.js +17 -0
  264. package/src/nodes/moments-digest/index.js +132 -0
  265. package/src/nodes/moments-digest/init.js +84 -0
  266. package/src/nodes/moments-digest/introspect.js +122 -0
  267. package/src/nodes/moments-digest/prelude.js +28 -0
  268. package/src/nodes/moments-digest/publish-to.js +31 -0
  269. package/src/nodes/moments-digest/recompute.js +9 -0
  270. package/src/nodes/moments-digest/reset.js +20 -0
  271. package/src/nodes/moments-digest/update.js +182 -0
  272. package/src/nodes/node-names.js +67 -0
  273. package/src/nodes/page-hinkley/index.js +20 -0
  274. package/src/nodes/page-hinkley/init.js +66 -0
  275. package/src/nodes/page-hinkley/introspect.js +193 -0
  276. package/src/nodes/page-hinkley/publish-to.js +28 -0
  277. package/src/nodes/page-hinkley/recompute.js +14 -0
  278. package/src/nodes/page-hinkley/reset.js +23 -0
  279. package/src/nodes/page-hinkley/update.js +105 -0
  280. package/src/nodes/pass-if/index.js +21 -0
  281. package/src/nodes/pass-if/init.js +37 -0
  282. package/src/nodes/pass-if/introspect.js +93 -0
  283. package/src/nodes/pass-if/publish-to.js +15 -0
  284. package/src/nodes/pass-if/recompute.js +15 -0
  285. package/src/nodes/pass-if/reset.js +18 -0
  286. package/src/nodes/pass-if/update.js +37 -0
  287. package/src/nodes/persist-if/helpers.js +111 -0
  288. package/src/nodes/persist-if/index.js +9 -0
  289. package/src/nodes/persist-if/init.js +98 -0
  290. package/src/nodes/persist-if/introspect.js +106 -0
  291. package/src/nodes/persist-if/publish-to.js +21 -0
  292. package/src/nodes/persist-if/recompute.js +20 -0
  293. package/src/nodes/persist-if/reset.js +35 -0
  294. package/src/nodes/persist-if/update.js +112 -0
  295. package/src/nodes/persistence-check/index.js +14 -0
  296. package/src/nodes/persistence-check/init.js +38 -0
  297. package/src/nodes/persistence-check/introspect.js +144 -0
  298. package/src/nodes/persistence-check/publish-to.js +11 -0
  299. package/src/nodes/persistence-check/recompute.js +7 -0
  300. package/src/nodes/persistence-check/reset.js +12 -0
  301. package/src/nodes/persistence-check/update.js +57 -0
  302. package/src/nodes/process-index/index.js +15 -0
  303. package/src/nodes/process-index/init.js +48 -0
  304. package/src/nodes/process-index/introspect.js +182 -0
  305. package/src/nodes/process-index/publish-to.js +29 -0
  306. package/src/nodes/process-index/recompute.js +8 -0
  307. package/src/nodes/process-index/reset.js +8 -0
  308. package/src/nodes/process-index/update.js +75 -0
  309. package/src/nodes/ratio/index.js +14 -0
  310. package/src/nodes/ratio/init.js +37 -0
  311. package/src/nodes/ratio/introspect.js +155 -0
  312. package/src/nodes/ratio/publish-to.js +15 -0
  313. package/src/nodes/ratio/recompute.js +7 -0
  314. package/src/nodes/ratio/reset.js +7 -0
  315. package/src/nodes/ratio/update.js +47 -0
  316. package/src/nodes/sanitize/index.js +82 -0
  317. package/src/nodes/sanitize/init.js +82 -0
  318. package/src/nodes/sanitize/introspect.js +194 -0
  319. package/src/nodes/sanitize/publish-to.js +15 -0
  320. package/src/nodes/sanitize/recompute.js +8 -0
  321. package/src/nodes/sanitize/reset.js +14 -0
  322. package/src/nodes/sanitize/update.js +102 -0
  323. package/src/nodes/spike-guard/index.js +14 -0
  324. package/src/nodes/spike-guard/init.js +47 -0
  325. package/src/nodes/spike-guard/introspect.js +130 -0
  326. package/src/nodes/spike-guard/publish-to.js +35 -0
  327. package/src/nodes/spike-guard/recompute.js +14 -0
  328. package/src/nodes/spike-guard/reset.js +19 -0
  329. package/src/nodes/spike-guard/update.js +89 -0
  330. package/src/nodes/sse-emitter/index.js +7 -0
  331. package/src/nodes/sse-emitter/init.js +105 -0
  332. package/src/nodes/sse-emitter/introspect.js +134 -0
  333. package/src/nodes/sse-emitter/publish-to.js +6 -0
  334. package/src/nodes/sse-emitter/recompute.js +16 -0
  335. package/src/nodes/sse-emitter/reset.js +19 -0
  336. package/src/nodes/sse-emitter/update.js +69 -0
  337. package/src/nodes/sse-emitter/utils/broadcast-heartbeat.js +36 -0
  338. package/src/nodes/sse-emitter/utils/build-message.js +31 -0
  339. package/src/nodes/sse-emitter/utils/connection-manager.js +45 -0
  340. package/src/nodes/sse-emitter/utils/endpoint-initializer.js +20 -0
  341. package/src/nodes/sse-emitter/utils/health-monitor.js +38 -0
  342. package/src/nodes/sse-emitter/utils/qos-handler.js +41 -0
  343. package/src/nodes/state-change-detector/helpers.js +35 -0
  344. package/src/nodes/state-change-detector/index.js +12 -0
  345. package/src/nodes/state-change-detector/init.js +56 -0
  346. package/src/nodes/state-change-detector/introspect.js +146 -0
  347. package/src/nodes/state-change-detector/publish-to.js +20 -0
  348. package/src/nodes/state-change-detector/recompute.js +6 -0
  349. package/src/nodes/state-change-detector/reset.js +20 -0
  350. package/src/nodes/state-change-detector/update.js +97 -0
  351. package/src/nodes/sw-stats/index.js +14 -0
  352. package/src/nodes/sw-stats/init.js +51 -0
  353. package/src/nodes/sw-stats/introspect.js +131 -0
  354. package/src/nodes/sw-stats/publish-to.js +45 -0
  355. package/src/nodes/sw-stats/recompute.js +33 -0
  356. package/src/nodes/sw-stats/reset.js +15 -0
  357. package/src/nodes/sw-stats/update.js +39 -0
  358. package/src/nodes/swing-watch/index.js +17 -0
  359. package/src/nodes/swing-watch/init.js +144 -0
  360. package/src/nodes/swing-watch/introspect.js +188 -0
  361. package/src/nodes/swing-watch/publish-to.js +53 -0
  362. package/src/nodes/swing-watch/recompute.js +22 -0
  363. package/src/nodes/swing-watch/reset.js +55 -0
  364. package/src/nodes/swing-watch/update.js +767 -0
  365. package/src/nodes/tally/index.js +15 -0
  366. package/src/nodes/tally/init.js +32 -0
  367. package/src/nodes/tally/introspect.js +116 -0
  368. package/src/nodes/tally/publish-to.js +28 -0
  369. package/src/nodes/tally/recompute.js +10 -0
  370. package/src/nodes/tally/reset.js +10 -0
  371. package/src/nodes/tally/update.js +44 -0
  372. package/src/nodes/threshold/index.js +14 -0
  373. package/src/nodes/threshold/init.js +121 -0
  374. package/src/nodes/threshold/introspect.js +192 -0
  375. package/src/nodes/threshold/publish-to.js +11 -0
  376. package/src/nodes/threshold/recompute.js +8 -0
  377. package/src/nodes/threshold/reset.js +14 -0
  378. package/src/nodes/threshold/update.js +54 -0
  379. package/src/nodes/transform/helpers.js +39 -0
  380. package/src/nodes/transform/index.js +15 -0
  381. package/src/nodes/transform/init.js +35 -0
  382. package/src/nodes/transform/introspect.js +118 -0
  383. package/src/nodes/transform/publish-to.js +23 -0
  384. package/src/nodes/transform/recompute.js +12 -0
  385. package/src/nodes/transform/reset.js +11 -0
  386. package/src/nodes/transform/update.js +32 -0
  387. package/src/nodes/trend/compute-confidence.js +112 -0
  388. package/src/nodes/trend/index.js +14 -0
  389. package/src/nodes/trend/init.js +81 -0
  390. package/src/nodes/trend/introspect.js +151 -0
  391. package/src/nodes/trend/publish-to.js +22 -0
  392. package/src/nodes/trend/recompute.js +15 -0
  393. package/src/nodes/trend/reset.js +26 -0
  394. package/src/nodes/trend/update.js +93 -0
  395. package/src/nodes/tw-stats/copy-from.js +16 -0
  396. package/src/nodes/tw-stats/flush.js +12 -0
  397. package/src/nodes/tw-stats/index.js +41 -0
  398. package/src/nodes/tw-stats/init.js +92 -0
  399. package/src/nodes/tw-stats/introspect.js +171 -0
  400. package/src/nodes/tw-stats/publish-to.js +108 -0
  401. package/src/nodes/tw-stats/recompute.js +9 -0
  402. package/src/nodes/tw-stats/reset.js +16 -0
  403. package/src/nodes/tw-stats/update.js +113 -0
  404. package/src/nodes/unbalance/index.js +15 -0
  405. package/src/nodes/unbalance/init.js +59 -0
  406. package/src/nodes/unbalance/introspect.js +167 -0
  407. package/src/nodes/unbalance/publish-to.js +52 -0
  408. package/src/nodes/unbalance/recompute.js +11 -0
  409. package/src/nodes/unbalance/reset.js +10 -0
  410. package/src/nodes/unbalance/update.js +83 -0
  411. package/src/nodes/vector-distance/index.js +14 -0
  412. package/src/nodes/vector-distance/init.js +54 -0
  413. package/src/nodes/vector-distance/introspect.js +149 -0
  414. package/src/nodes/vector-distance/publish-to.js +35 -0
  415. package/src/nodes/vector-distance/recompute.js +11 -0
  416. package/src/nodes/vector-distance/reset.js +20 -0
  417. package/src/nodes/vector-distance/update.js +139 -0
  418. package/src/nodes/winnow/index.js +12 -0
  419. package/src/nodes/winnow/init.js +82 -0
  420. package/src/nodes/winnow/introspect.js +253 -0
  421. package/src/nodes/winnow/publish-to.js +51 -0
  422. package/src/nodes/winnow/recompute.js +14 -0
  423. package/src/nodes/winnow/reset.js +34 -0
  424. package/src/nodes/winnow/update.js +203 -0
  425. package/src/tools/training/features.js +227 -0
  426. package/src/tools/training/index.js +21 -0
  427. package/src/tools/training/logistic.js +238 -0
  428. package/src/tools/training/metrics.js +126 -0
  429. package/src/tools/training/scale.js +239 -0
  430. package/src/tools/training/validate.js +103 -0
  431. package/src/windowing/count-sliding/create.js +16 -0
  432. package/src/windowing/count-sliding/get-reverse-chronological-index.js +19 -0
  433. package/src/windowing/count-sliding/index.js +6 -0
  434. package/src/windowing/count-sliding/is-not-full.js +5 -0
  435. package/src/windowing/count-sliding/push.js +15 -0
  436. package/src/windowing/count-sliding/reset.js +11 -0
  437. package/src/windowing/count-sliding/size.js +5 -0
  438. package/src/windowing/time-sliding/create.js +25 -0
  439. package/src/windowing/time-sliding/push.js +42 -0
  440. package/CODE_OF_CONDUCT.md +0 -46
  441. package/CONTRIBUTING.md +0 -132
  442. package/docs/.nojekyll +0 -0
  443. package/docs/CONTRIBUTING.md +0 -134
  444. package/docs/README.md +0 -132
  445. package/docs/_coverpage.md +0 -26
  446. package/docs/_media/bg.png +0 -0
  447. package/docs/_media/wink-logo.png +0 -0
  448. package/docs/_navbar.md +0 -14
  449. package/docs/_sidebar.md +0 -2
  450. package/docs/index.html +0 -44
  451. package/eslint.config.js +0 -283
@@ -0,0 +1,144 @@
1
+ // @fileoverview
2
+ // init.js — pre-allocates all state for the swingWatch node.
3
+ //
4
+ // Every typed array, ring buffer, and accumulator is allocated here and never
5
+ // again during the hot path (update / publishTo). Total memory per instance
6
+ // at W=100 is ~7.9 KB — fits comfortably in L1 cache.
7
+
8
+ import { validateSpec } from '../../core/utils/node/index.js';
9
+ import * as introspect from './introspect.js';
10
+ import { create } from '../../windowing/count-sliding/index.js';
11
+ import { resolveScalar } from '../../core/utils/options/resolve-field-keyed.js';
12
+ import { asTunable } from '../../core/tunable/index.js';
13
+
14
+ const init = function ( spec ) {
15
+ validateSpec( spec, introspect );
16
+
17
+ const state = Object.create( null );
18
+
19
+ // ── Standard flags ───────────────────────────────────────
20
+ state.inputValidationFailed = false;
21
+ state.disable = false;
22
+ state.pause = false;
23
+
24
+ // ── Configuration from spec ──────────────────────────────
25
+ state.x = spec.from.x;
26
+ state.stats = Object.assign( Object.create( null ), spec.stats );
27
+ state.direction = spec.direction ?? introspect.DEFAULT_OPTIONS.direction;
28
+ state.minAbsoluteThreshold = spec.minAbsoluteThreshold ?? introspect.DEFAULT_OPTIONS.minAbsoluteThreshold;
29
+
30
+ // ── Window size (field-keyed support) ─────────────────────
31
+ const windowSizeSpec = resolveScalar( spec.windowSize, state.x );
32
+ const W = windowSizeSpec ?? introspect.DEFAULT_OPTIONS.windowSize;
33
+ state.windowSize = W;
34
+
35
+ // ── Ring buffer (reuse composer's count-sliding module) ──
36
+ state.ring = create( W );
37
+
38
+ // ── Threshold tunable ────────────────────────────────────
39
+ state.thresholdFn = asTunable( spec.threshold );
40
+ state.currentThreshold = 0;
41
+ state.tunableErrorLogged = false;
42
+
43
+ // ── Pre-allocated typed arrays (zero allocation in hot path) ─
44
+
45
+ // Linearized copy of ring buffer (contiguous for sort)
46
+ state.linear = new Float64Array( W );
47
+
48
+ // Sort workspace: indices [0..W-1] sorted by linear[i]
49
+ state.sortedIndices = new Int32Array( W );
50
+
51
+ // Pre-built comparator — avoids per-tick closure allocation at the
52
+ // .sort() call site. Captures state.linear by reference; its contents
53
+ // are overwritten in place each tick but the binding is stable.
54
+ state.compareIndices = ( a, b ) => {
55
+ const d = state.linear[ a ] - state.linear[ b ];
56
+ if ( d !== 0 ) return d;
57
+ return a - b;
58
+ };
59
+
60
+ // Union-find arrays (reused for both min and max sweeps)
61
+ state.ufParent = new Int32Array( W );
62
+ state.ufBirthVal = new Float64Array( W );
63
+ state.ufBirthIdx = new Int32Array( W );
64
+
65
+ // Processed flags for sweep (cleared between min/max sweeps)
66
+ state.processed = new Uint8Array( W );
67
+
68
+ // Accounted-emission flags, one byte per ring slot per direction
69
+ // (exactly-once rule c in update.js Section 3). A set byte means the
70
+ // sample in that slot has already driven — or been recognized as a
71
+ // duplicate of — a completion emission. Cleared per-slot on overwrite.
72
+ state.minEmitFlag = new Uint8Array( W );
73
+ state.maxEmitFlag = new Uint8Array( W );
74
+
75
+ // Pair storage — parallel typed arrays, max pairs = floor(W/2)
76
+ const maxPairs = Math.floor( W / 2 );
77
+ state.maxPairs = maxPairs;
78
+
79
+ // Current tick's min pairs
80
+ state.minBirthValArr = new Float64Array( maxPairs );
81
+ state.minBirthIdxArr = new Int32Array( maxPairs );
82
+ state.minDeathValArr = new Float64Array( maxPairs );
83
+ state.minDeathIdxArr = new Int32Array( maxPairs );
84
+ state.minPersArr = new Float64Array( maxPairs );
85
+ state.minPairCount = 0;
86
+
87
+ // Current tick's max pairs
88
+ state.maxBirthValArr = new Float64Array( maxPairs );
89
+ state.maxBirthIdxArr = new Int32Array( maxPairs );
90
+ state.maxDeathValArr = new Float64Array( maxPairs );
91
+ state.maxDeathIdxArr = new Int32Array( maxPairs );
92
+ state.maxPersArr = new Float64Array( maxPairs );
93
+ state.maxPairCount = 0;
94
+
95
+ // Previous tick's pairs (for diffing — only need indices to compare)
96
+ state.prevMinBirthIdx = new Int32Array( maxPairs );
97
+ state.prevMinDeathIdx = new Int32Array( maxPairs );
98
+ state.prevMinPairCount = 0;
99
+
100
+ state.prevMaxBirthIdx = new Int32Array( maxPairs );
101
+ state.prevMaxDeathIdx = new Int32Array( maxPairs );
102
+ state.prevMaxPairCount = 0;
103
+
104
+ // ── Completion event slots (Mode A) ──────────────────────
105
+ state.dipCompleted = false;
106
+ state.dipValue = NaN;
107
+ state.dipLag = 0;
108
+ state.dipSize = NaN;
109
+
110
+ state.peakCompleted = false;
111
+ state.peakValue = NaN;
112
+ state.peakLag = 0;
113
+ state.peakSize = NaN;
114
+
115
+ // ── Pre-built field-key maps (zero string-concat in diff hot path) ──
116
+ // diffOneSide writes to state[ keys.completed ] etc. using these
117
+ // pre-built strings instead of runtime concatenation. The min/max keys
118
+ // name the sweep side (signal minima/maxima); the values are the
119
+ // published dip/peak stat fields those sides feed.
120
+ state.fieldKeys = Object.create( null );
121
+ state.fieldKeys.min = Object.create( null );
122
+ state.fieldKeys.min.completed = 'dipCompleted';
123
+ state.fieldKeys.min.birthValue = 'dipValue';
124
+ state.fieldKeys.min.birthLag = 'dipLag';
125
+ state.fieldKeys.min.persistence = 'dipSize';
126
+ state.fieldKeys.max = Object.create( null );
127
+ state.fieldKeys.max.completed = 'peakCompleted';
128
+ state.fieldKeys.max.birthValue = 'peakValue';
129
+ state.fieldKeys.max.birthLag = 'peakLag';
130
+ state.fieldKeys.max.persistence = 'peakSize';
131
+
132
+ // ── Diagnostic counters ──────────────────────────────────
133
+ state.received = 0;
134
+ state.emitted = 0;
135
+ state.swingsThisTick = 0;
136
+ state.swingRate = 0;
137
+
138
+ // ── Metadata ─────────────────────────────────────────────
139
+ state.nodeType = introspect.getNodeType();
140
+
141
+ return state;
142
+ }; // init()
143
+
144
+ export default init;
@@ -0,0 +1,188 @@
1
+ // @fileoverview
2
+ // Introspection metadata for the swingWatch node.
3
+ //
4
+ // swingWatch watches a signal for swings — dips and peaks — over a sliding
5
+ // window and reports the size of each swing when it completes. A swing's
6
+ // size is its topological persistence: how far the value travels between a
7
+ // turning point and the level that closes the round trip. On each tick the
8
+ // node runs a batch persistence sweep (sort by value + union-find, the
9
+ // Huber/Persistence1D algorithm) on the current window and emits completion
10
+ // events for pairs that are new compared to the previous tick.
11
+ //
12
+ // Convention: topological persistence — the global extremum in the window is
13
+ // unpaired (infinite persistence). This matches Persistence1D, not scipy's
14
+ // peak-prominence convention.
15
+ //
16
+ // References:
17
+ // Edelsbrunner, Letscher & Zomorodian (2002). Topological Persistence and
18
+ // Simplification. Discrete & Computational Geometry, 28, 511–533.
19
+ // Huber, S. Persistent Topology for Peak Detection.
20
+ // https://www.sthu.org/blog/13-perstopology-peakdetection/index.html
21
+
22
+ import { validators } from '../../core/utils/validate/index.js';
23
+
24
+ // ── Supported Features ───────────────────────────────────────
25
+ const SUPPORTED_STATS = [
26
+ 'dipCompleted',
27
+ 'dipValue',
28
+ 'dipLag',
29
+ 'dipSize',
30
+ 'peakCompleted',
31
+ 'peakValue',
32
+ 'peakLag',
33
+ 'peakSize',
34
+ 'swingsThisTick',
35
+ 'swingRate'
36
+ ];
37
+
38
+ const STAT_DESCRIPTIONS = {
39
+ dipCompleted: 'True on the tick a significant dip completes (false otherwise)',
40
+ dipValue: 'Signal value at the bottom of the completed dip (undefined when not completing)',
41
+ dipLag: 'Samples back to the bottom of the completed dip within the window (undefined when not completing)',
42
+ dipSize: 'Size (depth) of the completed dip: deathVal - birthVal (undefined when not completing)',
43
+ peakCompleted: 'True on the tick a significant peak completes',
44
+ peakValue: 'Signal value at the top of the completed peak (undefined when not completing)',
45
+ peakLag: 'Samples back to the top of the completed peak within the window (undefined when not completing)',
46
+ peakSize: 'Size (height) of the completed peak: birthVal - deathVal (undefined when not completing)',
47
+ swingsThisTick: 'Number of swings newly accounted this tick; when several finish at once the dip/peak stats detail the largest',
48
+ swingRate: 'Cumulative swings per received sample (emitted / received); can exceed 1.0 with direction "both" when one tick completes both a dip and a peak'
49
+ };
50
+
51
+ const SUPPORTED_CONTROL_METHODS = {
52
+ reset: 'Clears ring buffer and all completion history',
53
+ enable: 'Enables node processing',
54
+ disable: 'Disables node processing',
55
+ pause: 'Pauses update but keeps publishTo outputs visible',
56
+ unpause: 'Resumes update after pause'
57
+ };
58
+
59
+ const NODE_TYPE = 'Swing Watch';
60
+
61
+ const CAPABILITIES = {
62
+ description: 'Watches a signal for swings — dips and peaks — over a sliding window and reports the size of each completed swing',
63
+ features: [
64
+ 'Windowed batch persistence sweep (sort + union-find) per tick',
65
+ 'Topological convention — consistent with Persistence1D and Huber',
66
+ 'Adaptive threshold via tunable pattern (k × σ from upstream stats)',
67
+ 'Configurable minimum absolute threshold floor for quiet signals',
68
+ 'Bidirectional detection (dips, peaks, or both)',
69
+ 'Output scrubbing on non-completion ticks (undefined) per momentsDigest convention',
70
+ 'Zero allocation in hot path — all typed arrays pre-allocated in init',
71
+ 'Exactly-once completion events — flag-based emission suppressing window-boundary artifacts (left-edge eviction re-fires, right-edge provisional extrema)'
72
+ ]
73
+ };
74
+
75
+ // ── Default Options ──────────────────────────────────────────
76
+ export const DEFAULT_OPTIONS = {
77
+ windowSize: 100,
78
+ direction: 'both',
79
+ minAbsoluteThreshold: 0
80
+ };
81
+
82
+ /** Parameters that support tunable (dynamic) values. */
83
+ export const TUNABLE_PARAMS = [ 'threshold' ];
84
+
85
+ // ── Getter Functions (defensive copies) ──────────────────────
86
+ export const getSupportedStats = () => SUPPORTED_STATS.slice();
87
+ export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
88
+ export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
89
+ export const getNodeType = () => NODE_TYPE;
90
+ export const getCapabilities = () => ( {
91
+ ...CAPABILITIES,
92
+ features: CAPABILITIES.features.slice()
93
+ } );
94
+
95
+ // ── DSL Metadata ─────────────────────────────────────────────
96
+ const DSL_METADATA = {
97
+ specSchema: {
98
+ nodeType: {
99
+ type: 'string',
100
+ required: true,
101
+ value: NODE_TYPE
102
+ },
103
+ name: {
104
+ type: 'string',
105
+ required: true,
106
+ validator: validators.identifier,
107
+ error: 'Name must be a valid identifier'
108
+ },
109
+ from: {
110
+ type: 'object',
111
+ required: true,
112
+ properties: {
113
+ x: {
114
+ type: 'string',
115
+ required: true,
116
+ validator: validators.noSpaces,
117
+ error: 'Field name cannot contain spaces'
118
+ }
119
+ }
120
+ },
121
+ threshold: {
122
+ type: 'numberOrFunctionOrFieldKeyed',
123
+ required: true,
124
+ min: 0,
125
+ error: 'threshold must be a non-negative number, function, or per-field map'
126
+ },
127
+ // Upper bound chosen so the two copy loops and the per-tick sort stay
128
+ // in L1 cache. Algorithm is correct for larger W but performance has
129
+ // not been validated beyond 256. integer+min+max are applied per
130
+ // numeric value — including inside a field-keyed object — by the
131
+ // numberOrFieldKeyed type validator. A custom `validator` would run on
132
+ // the outer value (the object itself), which would reject any
133
+ // field-keyed spec.
134
+ windowSize: {
135
+ type: 'numberOrFieldKeyed',
136
+ required: false,
137
+ default: DEFAULT_OPTIONS.windowSize,
138
+ integer: true,
139
+ min: 4,
140
+ max: 256
141
+ },
142
+ direction: {
143
+ type: 'string',
144
+ required: false,
145
+ default: DEFAULT_OPTIONS.direction,
146
+ validator: validators.oneOf( [ 'both', 'dips', 'peaks' ] ),
147
+ error: 'direction must be "both", "dips", or "peaks"'
148
+ },
149
+ minAbsoluteThreshold: {
150
+ type: 'number',
151
+ required: false,
152
+ default: DEFAULT_OPTIONS.minAbsoluteThreshold,
153
+ min: 0,
154
+ error: 'minAbsoluteThreshold must be a non-negative number'
155
+ },
156
+ stats: {
157
+ type: 'object',
158
+ required: true,
159
+ minProperties: 1,
160
+ propertyNames: SUPPORTED_STATS,
161
+ propertySchema: {
162
+ type: 'object',
163
+ required: true,
164
+ properties: {
165
+ storeAs: {
166
+ type: 'string',
167
+ required: true,
168
+ minLength: 1,
169
+ validator: validators.identifier,
170
+ error: 'storeAs must be a valid identifier'
171
+ }
172
+ }
173
+ }
174
+ }
175
+ },
176
+
177
+ crossFieldValidators: [],
178
+
179
+ buildSpec: ( name, x, stats, options ) => ( {
180
+ nodeType: NODE_TYPE,
181
+ name,
182
+ from: { x },
183
+ stats,
184
+ ...( options || {} )
185
+ } )
186
+ };
187
+
188
+ export const getDSLMetadata = () => ( { ...DSL_METADATA } );
@@ -0,0 +1,53 @@
1
+ // @fileoverview
2
+ // publish-to.js — copy computed completion fields to the output message.
3
+ //
4
+ // Follows the momentsDigest output-scrubbing convention: on non-completion
5
+ // ticks, detail fields (birthValue, birthLag, persistence) are explicitly
6
+ // set to `undefined` — not left as stale values from a previous tick. This
7
+ // prevents downstream nodes from acting on outdated event data.
8
+ //
9
+ // The completion booleans (dipCompleted, peakCompleted) are always published
10
+ // so downstream can branch on them. Diagnostic fields (swingsThisTick,
11
+ // swingRate) are always published when the window is full.
12
+ //
13
+ // Guard order (per ADR-004):
14
+ // 1. disable → skip entirely (node invisible downstream)
15
+ // 2. inputValidationFailed → publishNaN for all stats (fault isolation)
16
+ // 3. isNotFull → skip (warmup, no meaningful output yet)
17
+
18
+ import { isNotFull } from '../../windowing/count-sliding/index.js';
19
+ import { publishNaN } from '../../core/utils/node/index.js';
20
+
21
+ const publishTo = function ( state, msg ) {
22
+ if ( state.disable ) return;
23
+
24
+ if ( state.inputValidationFailed ) {
25
+ publishNaN( state, msg );
26
+ return;
27
+ }
28
+
29
+ // Do not publish during warmup (window not yet full)
30
+ if ( isNotFull( state.ring ) ) return;
31
+
32
+ const s = state.stats;
33
+
34
+ // ── Completion booleans (always published) ────────────────
35
+ if ( s.dipCompleted ) msg[ s.dipCompleted.storeAs ] = state.dipCompleted;
36
+ if ( s.peakCompleted ) msg[ s.peakCompleted.storeAs ] = state.peakCompleted;
37
+
38
+ // ── Dip detail fields (scrubbed to undefined on non-completion ticks) ─
39
+ if ( s.dipValue ) msg[ s.dipValue.storeAs ] = state.dipCompleted ? state.dipValue : undefined;
40
+ if ( s.dipLag ) msg[ s.dipLag.storeAs ] = state.dipCompleted ? state.dipLag : undefined;
41
+ if ( s.dipSize ) msg[ s.dipSize.storeAs ] = state.dipCompleted ? state.dipSize : undefined;
42
+
43
+ // ── Peak detail fields (scrubbed to undefined on non-completion ticks) ─
44
+ if ( s.peakValue ) msg[ s.peakValue.storeAs ] = state.peakCompleted ? state.peakValue : undefined;
45
+ if ( s.peakLag ) msg[ s.peakLag.storeAs ] = state.peakCompleted ? state.peakLag : undefined;
46
+ if ( s.peakSize ) msg[ s.peakSize.storeAs ] = state.peakCompleted ? state.peakSize : undefined;
47
+
48
+ // ── Diagnostics (always published when window is full) ───
49
+ if ( s.swingsThisTick ) msg[ s.swingsThisTick.storeAs ] = state.swingsThisTick;
50
+ if ( s.swingRate ) msg[ s.swingRate.storeAs ] = state.swingRate;
51
+ }; // publishTo()
52
+
53
+ export default publishTo;
@@ -0,0 +1,22 @@
1
+ // @fileoverview
2
+ // recompute.js — re-establish numerical ground truth per ADR-004.
3
+ //
4
+ // Unlike incremental-accumulator nodes (esMean, swStats) where floating-point
5
+ // drift can compound over millions of updates, swingWatch recomputes the
6
+ // entire persistence diagram from scratch on every tick (the windowed batch
7
+ // sweep sorts and sweeps the full window). There is no accumulated state that
8
+ // can drift.
9
+ //
10
+ // The only action needed is to clear the previous-tick pair storage, which
11
+ // forces the next tick's diff to re-derive every current pair as unmatched.
12
+ // The accounted-emission flags (exactly-once rule c in update.js) survive
13
+ // recompute deliberately: every re-derived pair's birth vertex is still
14
+ // flagged as accounted, so recompute causes no spurious re-emission burst.
15
+
16
+ const recompute = function ( state ) {
17
+ state.prevMinPairCount = 0;
18
+ state.prevMaxPairCount = 0;
19
+ return true;
20
+ }; // recompute()
21
+
22
+ export default recompute;
@@ -0,0 +1,55 @@
1
+ // @fileoverview
2
+ // reset.js — idempotent reset per ADR-004.
3
+ //
4
+ // Clears the ring buffer, all pair storage (current and previous tick),
5
+ // completion event slots, and diagnostic counters. After reset, the node
6
+ // re-enters the warmup phase (isNotFull returns true) and will not publish
7
+ // until the window fills again.
8
+ //
9
+ // Multiple calls produce the same state as a single call (idempotent).
10
+
11
+ import { reset as resetRing } from '../../windowing/count-sliding/index.js';
12
+
13
+ const reset = function ( state ) {
14
+ // Clear the ring buffer — head, used, and buffer contents all zeroed
15
+ resetRing( state.ring );
16
+
17
+ // Clear current tick's pair counts (typed arrays contents are irrelevant
18
+ // when count is 0 — no need to zero the arrays themselves)
19
+ state.minPairCount = 0;
20
+ state.maxPairCount = 0;
21
+
22
+ // Clear previous tick's pair counts (forces fresh diff on next tick —
23
+ // all pairs in the first full-window tick will appear as "new")
24
+ state.prevMinPairCount = 0;
25
+ state.prevMaxPairCount = 0;
26
+
27
+ // Clear the accounted-emission flags (exactly-once rule c) — after a
28
+ // reset every vertex of the refilled window may emit afresh
29
+ state.minEmitFlag.fill( 0 );
30
+ state.maxEmitFlag.fill( 0 );
31
+
32
+ // Clear completion event slots
33
+ state.dipCompleted = false;
34
+ state.peakCompleted = false;
35
+ state.dipValue = NaN;
36
+ state.peakValue = NaN;
37
+ state.dipLag = 0;
38
+ state.peakLag = 0;
39
+ state.dipSize = NaN;
40
+ state.peakSize = NaN;
41
+
42
+ // Clear diagnostics
43
+ state.received = 0;
44
+ state.emitted = 0;
45
+ state.swingsThisTick = 0;
46
+ state.swingRate = 0;
47
+
48
+ // Clear health and tunable error flags
49
+ state.inputValidationFailed = false;
50
+ state.tunableErrorLogged = false;
51
+
52
+ return true;
53
+ }; // reset()
54
+
55
+ export default reset;