@winkjs/composer 0.0.2 → 0.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 (451) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +106 -80
  3. package/package.json +56 -28
  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,146 @@
1
+ import { validators, composerValidators } from '../../core/utils/validate/index.js';
2
+
3
+ /** Single source of truth for what this node can do */
4
+ const SUPPORTED_STATS = [
5
+ 'dwellTime',
6
+ 'dwellSamples'
7
+ ];
8
+
9
+ /** Human-readable descriptions */
10
+ const STAT_DESCRIPTIONS = {
11
+ dwellTime: 'Duration in milliseconds spent in previous state (never negative — a backward clock step reports 0)',
12
+ dwellSamples: 'Number of samples observed in previous state'
13
+ };
14
+
15
+ /** The type of this node */
16
+ const NODE_TYPE = 'State Change Detector';
17
+
18
+ /** Control methods available for triggers */
19
+ const SUPPORTED_CONTROL_METHODS = {
20
+ reset: 'Clears accumulated state and restarts computation',
21
+ enable: 'Enables node processing',
22
+ disable: 'Disables node processing',
23
+ pause: 'Pauses node processing while keeping state visible',
24
+ unpause: 'Resumes node processing after pause'
25
+ };
26
+
27
+ /** Default configuration options */
28
+ const DEFAULT_OPTIONS = {
29
+ debounce: 3,
30
+ changeMode: 'any'
31
+ };
32
+
33
+ /** Node capabilities for documentation */
34
+ const CAPABILITIES = {
35
+ description: 'Detects and confirms transitions between categorical states with debounce filtering',
36
+ features: [
37
+ 'Multi-field state monitoring with any/all logic',
38
+ 'Debounce protection against boundary oscillation',
39
+ 'Dwell time and sample count tracking',
40
+ 'Trigger support for adaptive behavior'
41
+ ]
42
+ };
43
+
44
+ // Export functions for accessing metadata
45
+ export const getSupportedStats = () => SUPPORTED_STATS.slice();
46
+ export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
47
+ export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
48
+ export const getNodeType = () => NODE_TYPE;
49
+ export const getCapabilities = () => ( {
50
+ ...CAPABILITIES,
51
+ features: CAPABILITIES.features.slice()
52
+ } );
53
+ export { DEFAULT_OPTIONS };
54
+
55
+ // DSL Metadata
56
+ const DSL_METADATA = {
57
+ specSchema: {
58
+ nodeType: {
59
+ type: 'string',
60
+ required: true,
61
+ value: NODE_TYPE
62
+ },
63
+ name: {
64
+ type: 'string',
65
+ required: true,
66
+ validator: validators.identifier,
67
+ error: 'Name must be a valid identifier'
68
+ },
69
+ from: {
70
+ type: 'object',
71
+ required: true,
72
+ properties: {
73
+ x: {
74
+ type: 'array',
75
+ required: true,
76
+ minItems: 1,
77
+ itemSchema: {
78
+ type: 'string',
79
+ validator: validators.noSpaces,
80
+ error: 'Field names must not contain spaces'
81
+ }
82
+ }
83
+ }
84
+ },
85
+ debounce: {
86
+ type: 'number',
87
+ required: false,
88
+ default: 3,
89
+ validator: composerValidators.windowSize,
90
+ error: 'Debounce must be a positive integer'
91
+ },
92
+ changeMode: {
93
+ type: 'string',
94
+ required: false,
95
+ default: 'any',
96
+ validator: validators.oneOf( [ 'any', 'all' ] ),
97
+ error: 'changeMode must be "any" or "all"'
98
+ },
99
+ timestampField: {
100
+ type: 'string',
101
+ required: false,
102
+ validator: validators.identifier,
103
+ error: 'timestampField must be a valid identifier'
104
+ },
105
+ stats: {
106
+ type: 'object',
107
+ required: true,
108
+ minProperties: 1,
109
+ propertyNames: SUPPORTED_STATS,
110
+ propertySchema: {
111
+ type: 'object',
112
+ properties: {
113
+ storeAs: {
114
+ type: 'string',
115
+ required: true,
116
+ validator: validators.identifier,
117
+ error: 'storeAs must be a valid identifier'
118
+ }
119
+ }
120
+ }
121
+ },
122
+ triggers: {
123
+ type: 'array',
124
+ required: false,
125
+ itemSchema: {
126
+ type: 'object',
127
+ validator: composerValidators.trigger,
128
+ error: 'Invalid trigger specification'
129
+ }
130
+ }
131
+ },
132
+
133
+ crossFieldValidators: [],
134
+
135
+ // Pattern: NAME_X_OUTPUTS_OPTIONS -> (name, x, stats, options)
136
+ buildSpec: ( name, x, stats, options ) => ( {
137
+ nodeType: NODE_TYPE,
138
+ name,
139
+ from: { x },
140
+ stats,
141
+ ...options
142
+ } ),
143
+
144
+ };
145
+
146
+ export const getDSLMetadata = () => ( { ...DSL_METADATA } );
@@ -0,0 +1,20 @@
1
+ import { publishNaN } from '../../core/utils/node/index.js';
2
+
3
+ const publishTo = function ( state, msg ) {
4
+ if ( state.disable ) return;
5
+ // Propagate NaN if unhealthy
6
+ if ( state.inputValidationFailed ) {
7
+ publishNaN( state, msg );
8
+ return;
9
+ }
10
+
11
+ // Iterate only over configured stats
12
+ const stats = state.stats;
13
+ for ( const statName in stats ) {
14
+ if ( Object.prototype.hasOwnProperty.call(stats, statName ) ) {
15
+ msg[ stats[ statName ].storeAs ] = state[ statName ];
16
+ }
17
+ }
18
+ }; // publishTo()
19
+
20
+ export default publishTo;
@@ -0,0 +1,6 @@
1
+ const recompute = function ( /* state */ ) {
2
+ // No numerical stability concerns for categorical state tracking
3
+ return true;
4
+ }; // recompute()
5
+
6
+ export default recompute;
@@ -0,0 +1,20 @@
1
+ const reset = function ( state ) {
2
+ // Reset all fields to null (forces re-initialization)
3
+ for ( let i = 0; i < state.fieldCount; i += 1 ) {
4
+ const field = state.fieldNames[ i ];
5
+ state.prevValues[ field ] = null;
6
+ }
7
+
8
+ // Reset counters and timing
9
+ state.debounceCount = 0;
10
+ state.stateStartTime = null;
11
+ state.samplesInState = 0;
12
+
13
+
14
+ state.dwellSamples = null;
15
+ state.dwellTime = null;
16
+
17
+ return state;
18
+ }; // reset()
19
+
20
+ export default reset;
@@ -0,0 +1,97 @@
1
+ import { executeTriggers } from '../../core/utils/node/index.js';
2
+ import { validateCategoricalFields } from './helpers.js';
3
+
4
+ const update = function ( state, msg ) {
5
+ if ( state.disable || state.pause ) return state;
6
+ // Reset on each update
7
+ state.inputValidationFailed = false;
8
+ // Validate all required fields are present and categorical
9
+ if ( !validateCategoricalFields( msg, state.fieldNames, state.fieldCount ) ) {
10
+ state.inputValidationFailed = true;
11
+ return state;
12
+ }
13
+
14
+ // These will be set only and only if change is spotted && debounced;
15
+ // otherwise they will remain null.
16
+ state.dwellTime = null;
17
+ state.dwellSamples = null;
18
+
19
+ // Get timestamp once for this message
20
+ const timestamp = state.useTimestampField ? msg[ state.timestampField ] : Date.now();
21
+
22
+ // ADR-004 fault handling: a message-supplied timestamp is a
23
+ // numerical input, so a missing or non-numeric value faults this
24
+ // ONE message and leaves the measurement in progress untouched
25
+ // (same guard as dwellTimeTracker). The device clock never fails
26
+ // this check.
27
+ if ( state.useTimestampField && !Number.isFinite( timestamp ) ) {
28
+ state.inputValidationFailed = true;
29
+ return state;
30
+ }
31
+
32
+ // First message initialization
33
+ if ( state.prevValues[ state.fieldNames[ 0 ] ] === null ) {
34
+ // Initialize prevValues and timing
35
+ for ( let i = 0; i < state.fieldCount; i += 1 ) {
36
+ const field = state.fieldNames[ i ];
37
+ state.prevValues[ field ] = msg[ field ];
38
+ }
39
+ state.stateStartTime = timestamp;
40
+ state.samplesInState = 1;
41
+ return state;
42
+ }
43
+
44
+ // Count fields that differ from last confirmed state
45
+ let changedFieldCount = 0;
46
+ for ( let i = 0; i < state.fieldCount; i += 1 ) {
47
+ const field = state.fieldNames[ i ];
48
+ if ( state.prevValues[ field ] !== msg[ field ] ) {
49
+ changedFieldCount += 1;
50
+ }
51
+ }
52
+
53
+ // Apply changeMode logic
54
+ const changeSpotted = state.changeMode ?
55
+ ( changedFieldCount === state.fieldCount ) : // 'all': every field changed
56
+ ( changedFieldCount > 0 ); // 'any': at least one changed
57
+
58
+ if ( changeSpotted ) {
59
+ // Different from last confirmed state
60
+ state.debounceCount += 1;
61
+
62
+ // Check if debounce threshold reached
63
+ if ( state.debounceCount >= state.debounce ) {
64
+ // Change CONFIRMED!
65
+ // Calculate stats BEFORE updating prevValues
66
+ state.dwellTime = timestamp - state.stateStartTime;
67
+ // A dwell can never be negative. A backward clock step
68
+ // (an NTP correction landing mid-measurement) would make
69
+ // the subtraction negative — publish 0 instead, matching
70
+ // dwellTimeTracker's guard (its update.js:74).
71
+ if ( state.dwellTime < 0 ) state.dwellTime = 0;
72
+ state.dwellSamples = state.samplesInState;
73
+
74
+ // Commit new state - update prevValues
75
+ for ( let i = 0; i < state.fieldCount; i += 1 ) {
76
+ const field = state.fieldNames[ i ];
77
+ state.prevValues[ field ] = msg[ field ];
78
+ }
79
+
80
+ // Reset counters for next transition
81
+ state.debounceCount = 0;
82
+ state.stateStartTime = timestamp;
83
+ state.samplesInState = 1;
84
+
85
+ // Execute triggers
86
+ executeTriggers( state );
87
+ }
88
+ } else {
89
+ // Matches last confirmed state - reset debounce
90
+ state.debounceCount = 0;
91
+ state.samplesInState += 1;
92
+ }
93
+
94
+ return state;
95
+ }; // update()
96
+
97
+ export default update;
@@ -0,0 +1,14 @@
1
+ // nodes/sw-stats/index.js
2
+
3
+ export { default as init } from './init.js';
4
+ export { default as update } from './update.js';
5
+ export { default as reset } from './reset.js';
6
+ export { default as recompute } from './recompute.js';
7
+ export { default as publishTo } from './publish-to.js';
8
+ // Direct imports for common control functions
9
+ export { default as disable } from '../../core/utils/node/disable.js';
10
+ export { default as enable } from '../../core/utils/node/enable.js';
11
+ export { default as pause } from '../../core/utils/node/pause.js';
12
+ export { default as unpause } from '../../core/utils/node/unpause.js';
13
+ // Re-export everything from introspection.js
14
+ export * from './introspect.js';
@@ -0,0 +1,51 @@
1
+ // nodes/sw-stats/init.js
2
+
3
+ import { validateSpec } from '../../core/utils/node/index.js';
4
+ import * as introspect from './introspect.js';
5
+ import { create } from '../../windowing/count-sliding/index.js';
6
+ import { resolveScalar } from '../../core/utils/options/resolve-field-keyed.js';
7
+
8
+ const init = function ( spec ) {
9
+ validateSpec( spec, introspect );
10
+
11
+ // Create state after validation passes
12
+ const state = Object.create( null );
13
+ // Standard input parameter health flag during update: false means healthy
14
+ state.inputValidationFailed = false;
15
+ // Ensure node is enabled by default
16
+ state.disable = false;
17
+ state.pause = false;
18
+
19
+ // Extract field name.
20
+ state.x = spec.from.x;
21
+
22
+ // Apply defaults from introspect (validation doesn't enforce them)
23
+ // Supports both direct and field-keyed specification
24
+ const windowSizeSpec = resolveScalar( spec.windowSize, state.x );
25
+ const windowSize = windowSizeSpec ?? introspect.DEFAULT_OPTIONS.windowSize;
26
+
27
+ // Underlying ring buffer storing the windowed values.
28
+ state.ring = create( windowSize );
29
+
30
+ // Config copy.
31
+ state.stats = Object.assign( Object.create( null ), spec.stats );
32
+
33
+ // Which of the SUPPORTED_STATS the user actually requested.
34
+ const statsList = Object.keys( state.stats );
35
+ // Determine which moments we need to compute and save it as state constants
36
+ state.need2 = statsList.some( ( m ) => [ 'variance', 'stdev', 'skewness', 'kurtosis', 'rms' ].includes( m ) );
37
+ state.need3 = statsList.some( ( m ) => [ 'skewness', 'kurtosis' ].includes( m ) );
38
+ state.need4 = statsList.includes( 'kurtosis' );
39
+
40
+ // State variables for incremental computation (s=sum, n=power).
41
+ state.s1 = 0;
42
+ state.s2 = ( state.need2 ) ? 0 : undefined;
43
+ state.s3 = ( state.need3 ) ? 0 : undefined;
44
+ state.s4 = ( state.need4 ) ? 0 : undefined;
45
+
46
+ state.nodeType = introspect.getNodeType();
47
+
48
+ return state;
49
+ }; // init()
50
+
51
+ export default init;
@@ -0,0 +1,131 @@
1
+ // nodes/sw-stats/introspect.js
2
+
3
+ import { validators } from '../../core/utils/validate/index.js';
4
+
5
+ /** Single source of truth for what this plugin can do */
6
+ const SUPPORTED_STATS = [
7
+ 'mean',
8
+ 'variance',
9
+ 'stdev',
10
+ 'skewness',
11
+ 'kurtosis',
12
+ 'rms'
13
+ ];
14
+
15
+ /** Human-readable descriptions (for introspection) */
16
+ const STAT_DESCRIPTIONS = {
17
+ mean: 'Average of the last N samples',
18
+ variance: 'Sample variance (denominator N–1)',
19
+ stdev: 'Sample standard deviation',
20
+ skewness: 'Normalized third central moment',
21
+ kurtosis: 'Excess kurtosis (μ₄/σ⁴ – 3)',
22
+ rms: 'Root mean square'
23
+ };
24
+
25
+ /** Control methods available for triggers */
26
+ const SUPPORTED_CONTROL_METHODS = {
27
+ reset: 'Clears accumulated state and restarts computation',
28
+ enable: 'Enables node processing',
29
+ disable: 'Disables node processing',
30
+ pause: 'Pauses node processing while keeping state visible',
31
+ unpause: 'Resumes node processing after pause'
32
+ };
33
+
34
+ /** The type of this node */
35
+ const NODE_TYPE = 'SW Stats';
36
+
37
+ /** Node capabilities for documentation */
38
+ const CAPABILITIES = {
39
+ description: 'Computes running statistics over a sliding window',
40
+ features: [
41
+ 'Efficient incremental computation',
42
+ 'Configurable window size',
43
+ 'Multiple statistics in single pass',
44
+ 'Numerically stable algorithms'
45
+ ]
46
+ };
47
+
48
+ // Attach static metadata once, from our constants by making a shallow copy.
49
+ export const getSupportedStats = () => SUPPORTED_STATS.slice();
50
+ export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
51
+ export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
52
+ export const getNodeType = () => NODE_TYPE;
53
+ export const getCapabilities = () => ( { ...CAPABILITIES, features: CAPABILITIES.features.slice() } );
54
+
55
+ export const DEFAULT_OPTIONS = {
56
+ windowSize: 10
57
+ };
58
+
59
+ // DSL Metadata for transpilation
60
+ const DSL_METADATA = {
61
+ // Spec schema for validation
62
+ specSchema: {
63
+ nodeType: {
64
+ type: 'string',
65
+ required: true,
66
+ value: NODE_TYPE
67
+ },
68
+ name: {
69
+ type: 'string',
70
+ required: true,
71
+ validator: validators.identifier,
72
+ error: 'Name must be a valid identifier'
73
+ },
74
+ from: {
75
+ type: 'object',
76
+ required: true,
77
+ properties: {
78
+ x: {
79
+ type: 'string',
80
+ required: true,
81
+ validator: validators.noSpaces,
82
+ error: 'Field name cannot contain spaces'
83
+ }
84
+ }
85
+ },
86
+ windowSize: {
87
+ type: 'numberOrFieldKeyed',
88
+ required: false,
89
+ default: 10,
90
+ integer: true,
91
+ min: 4,
92
+ validator: validators.positiveInteger,
93
+ error: 'Window size must be a positive integer; minimum 4'
94
+ },
95
+ stats: {
96
+ type: 'object',
97
+ required: true,
98
+ minProperties: 1,
99
+ propertyNames: SUPPORTED_STATS,
100
+ propertySchema: {
101
+ type: 'object',
102
+ required: true,
103
+ properties: {
104
+ storeAs: {
105
+ type: 'string',
106
+ required: true,
107
+ minLength: 1,
108
+ validator: validators.identifier,
109
+ error: 'storeAs must be a valid identifier'
110
+ }
111
+ }
112
+ }
113
+ }
114
+ },
115
+
116
+ // Cross-field validators
117
+ crossFieldValidators: [],
118
+
119
+ // How to build the spec from DSL params
120
+ // Pattern: NAME_X_OUTPUTS_OPTIONS -> (name, x, stats, options)
121
+ buildSpec: ( name, x, stats, options ) => ( {
122
+ nodeType: NODE_TYPE,
123
+ name,
124
+ from: { x },
125
+ stats,
126
+ ...options
127
+ } ),
128
+
129
+ };
130
+
131
+ export const getDSLMetadata = () => ( { ...DSL_METADATA } );
@@ -0,0 +1,45 @@
1
+ // nodes/sw-stats/publish-to.js
2
+
3
+ import { isNotFull, size } from '../../windowing/count-sliding/index.js';
4
+ import { publishNaN } from '../../core/utils/node/index.js';
5
+
6
+ const EPS = 1e-9;
7
+
8
+ const publishTo = function ( state, msg ) {
9
+ if ( state.disable ) return;
10
+ // Propagate NaN if unhealthy
11
+ if ( state.inputValidationFailed ) {
12
+ publishNaN( state, msg );
13
+ return;
14
+ }
15
+ // Do not publish partial results.
16
+ if ( isNotFull( state.ring ) ) return;
17
+
18
+ const windowSize = size( state.ring );
19
+ const mean = state.s1 / windowSize;
20
+ if ( state.stats.mean ) msg[ state.stats.mean.storeAs ] = mean;
21
+ if ( state.need2 ) {
22
+ const sumSquaredDeviations = state.s2 - ( state.s1 * mean );
23
+ const m2 = sumSquaredDeviations / windowSize;
24
+ const variance = sumSquaredDeviations / ( windowSize - 1 );
25
+ const safeVariance = ( variance < EPS ) ? 0 : variance;
26
+ // --- Use `stats.variance` in the if statement to check ---------------------
27
+ if ( state.stats.variance ) msg[ state.stats.variance.storeAs ] = safeVariance;
28
+ if ( state.stats.stdev ) msg[ state.stats.stdev.storeAs ] = Math.sqrt( safeVariance );
29
+ if ( state.stats.rms ) msg[ state.stats.rms.storeAs ] = Math.sqrt( state.s2 / windowSize );
30
+ if ( state.need3 ) {
31
+ // Formula: m3 = ( s3 - 3 μ s2 + 2 μ^3 N ) / N
32
+ const m3 = ( state.s3 - (3 * mean * state.s2 ) + ( 2 * mean * mean * mean * windowSize ) ) / windowSize;
33
+ const denom = Math.pow( m2, 1.5 );
34
+ if ( state.stats.skewness ) msg[ state.stats.skewness.storeAs ] = ( denom > EPS ) ? m3 / denom : 0;
35
+ }
36
+ if ( state.need4 ) {
37
+ const m4 = ( state.s4 - ( 4 * ( mean * state.s3 ) ) + ( 6 * mean * mean * state.s2 ) -
38
+ ( 3 * mean * mean * mean * mean * windowSize ) ) / windowSize;
39
+ const denom = m2 * m2;
40
+ if ( state.stats.kurtosis ) msg[ state.stats.kurtosis.storeAs ] = ( denom > EPS ) ? ( ( m4 / denom ) - 3 ) : -3;
41
+ }
42
+ }
43
+ }; // publishTo()
44
+
45
+ export default publishTo;
@@ -0,0 +1,33 @@
1
+ // nodes/sw-stats/recompute.js
2
+
3
+ const recompute = function ( state ) {
4
+ // Reset accumulators first
5
+ state.s1 = 0;
6
+ state.s2 = state.need2 ? 0 : undefined;
7
+ state.s3 = state.need3 ? 0 : undefined;
8
+ state.s4 = state.need4 ? 0 : undefined;
9
+
10
+ const buf = state.ring.buffer;
11
+ // Only process actual values
12
+ const used = state.ring.used;
13
+
14
+ for ( let k = 0; k < used; k += 1 ) {
15
+ const value = buf[ k ];
16
+ state.s1 += value;
17
+ if ( state.need2 || state.need3 || state.need4 ) {
18
+ const value2 = value * value;
19
+ if ( state.need2 ) state.s2 += value2;
20
+ if ( state.need3 || state.need4 ) {
21
+ const value3 = value2 * value;
22
+ if ( state.need3 ) state.s3 += value3;
23
+ if ( state.need4 ) {
24
+ const value4 = value3 * value;
25
+ state.s4 += value4;
26
+ }
27
+ }
28
+ }
29
+ }
30
+ return true;
31
+ }; // recompute()
32
+
33
+ export default recompute;
@@ -0,0 +1,15 @@
1
+ // nodes/sw-stats/reset.js
2
+
3
+ import { reset as resetRing } from '../../windowing/count-sliding/index.js';
4
+ const reset = function ( state ) {
5
+ state.s1 = 0;
6
+ state.s2 = state.need2 ? 0 : undefined;
7
+ state.s3 = state.need3 ? 0 : undefined;
8
+ state.s4 = state.need4 ? 0 : undefined;
9
+
10
+ resetRing( state.ring );
11
+
12
+ return true;
13
+ }; // reset()
14
+
15
+ export default reset;
@@ -0,0 +1,39 @@
1
+ // nodes/sw-stats/update.js
2
+
3
+ import { push } from '../../windowing/count-sliding/index.js';
4
+
5
+ const update = function ( state, msg ) {
6
+ if ( state.disable || state.pause ) return state;
7
+ const xVal = msg[ state.x ];
8
+ // Reset on each update
9
+ state.inputValidationFailed = false;
10
+ // Handle faults gracefully: ensure their isolation
11
+ if ( !Number.isFinite( xVal ) ) {
12
+ // Signals publishing NaN for all demanded `stats` in publishTo.
13
+ state.inputValidationFailed = true;
14
+ return state;
15
+ }
16
+
17
+ const evicted = push( state.ring, xVal ) ?? 0;
18
+
19
+ state.s1 += xVal - evicted;
20
+ if ( state.need2 ) {
21
+ const value2 = xVal * xVal;
22
+ const evicted2 = evicted * evicted;
23
+ state.s2 += value2 - evicted2;
24
+ if ( state.need3 ) {
25
+ const value3 = value2 * xVal;
26
+ const evicted3 = evicted2 * evicted;
27
+ state.s3 += value3 - evicted3;
28
+ if ( state.need4 ) {
29
+ const value4 = value3 * xVal;
30
+ const evicted4 = evicted3 * evicted;
31
+ state.s4 += value4 - evicted4;
32
+ }
33
+ }
34
+ }
35
+
36
+ return state;
37
+ }; // update()
38
+
39
+ export default update;
@@ -0,0 +1,17 @@
1
+ // @fileoverview
2
+ // index.js — standard node exports per ADR-004.
3
+ //
4
+ // Re-exports all lifecycle functions and shared control signals. The
5
+ // introspection metadata (getSupportedStats, getDSLMetadata, etc.) is
6
+ // re-exported via the wildcard export from introspect.js.
7
+
8
+ export { default as init } from './init.js';
9
+ export { default as update } from './update.js';
10
+ export { default as reset } from './reset.js';
11
+ export { default as recompute } from './recompute.js';
12
+ export { default as publishTo } from './publish-to.js';
13
+ export { default as disable } from '../../core/utils/node/disable.js';
14
+ export { default as enable } from '../../core/utils/node/enable.js';
15
+ export { default as pause } from '../../core/utils/node/pause.js';
16
+ export { default as unpause } from '../../core/utils/node/unpause.js';
17
+ export * from './introspect.js';