@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,144 @@
1
+ // nodes/persistence-check/introspect.js
2
+
3
+ import { validators, composerValidators } from '../../core/utils/validate/index.js';
4
+
5
+ /** Single source of truth for what this plugin can do */
6
+ const SUPPORTED_STATS = [
7
+ 'persistenceConfirmed'
8
+ ];
9
+
10
+ /** Human-readable descriptions (for introspection) */
11
+ const STAT_DESCRIPTIONS = {
12
+ persistenceConfirmed: 'True if a predicate meets or exceeds the minimum votes out of a given total'
13
+ };
14
+
15
+ /** Control methods available for triggers */
16
+ const SUPPORTED_CONTROL_METHODS = {
17
+ reset: 'Clears accumulated state and restarts computation',
18
+ enable: 'Enables node processing',
19
+ disable: 'Disables node processing',
20
+ pause: 'Pauses node processing while keeping state visible',
21
+ unpause: 'Resumes node processing after pause'
22
+ };
23
+
24
+ /** The type of this node */
25
+ const NODE_TYPE = 'Persistence Check';
26
+
27
+ /** Node capabilities for documentation */
28
+ const CAPABILITIES = {
29
+ description: 'Confirms persistence when a predicate satisfies a minimum threshold within a window',
30
+ features: [
31
+ 'Evaluates predicate with filtered inputs and counter arguments',
32
+ 'Voting mechanism for stability confirmation',
33
+ 'Configurable minimum votes and window size',
34
+ 'Automatic reset after publishing confirmation'
35
+ ]
36
+ };
37
+
38
+ // Export functions for accessing metadata
39
+ export const getSupportedStats = () => SUPPORTED_STATS.slice();
40
+ export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
41
+ export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
42
+ export const getNodeType = () => NODE_TYPE;
43
+ export const getCapabilities = () => ( { ...CAPABILITIES, features: CAPABILITIES.features.slice() } );
44
+
45
+ // Spec default values
46
+ export const DEFAULT_OPTIONS = {
47
+ minVotes: 3,
48
+ outOfTotal: 5
49
+ };
50
+
51
+ // DSL Metadata for transpilation
52
+ const DSL_METADATA = {
53
+ // Spec schema for validation
54
+ specSchema: {
55
+ nodeType: {
56
+ type: 'string',
57
+ required: true,
58
+ value: NODE_TYPE
59
+ },
60
+ name: {
61
+ type: 'string',
62
+ required: true,
63
+ validator: validators.identifier,
64
+ error: 'Name must be a valid identifier'
65
+ },
66
+ predicate: {
67
+ type: 'function',
68
+ required: true,
69
+ arity: 1,
70
+ error: 'Predicate must be a function with exactly one parameters (msg)'
71
+ },
72
+ minVotes: {
73
+ type: 'number',
74
+ required: false,
75
+ default: 3,
76
+ integer: true,
77
+ min: 1,
78
+ validator: validators.positiveInteger,
79
+ error: 'minVotes must be a positive integer'
80
+ },
81
+ outOfTotal: {
82
+ type: 'number',
83
+ required: false,
84
+ default: 5,
85
+ integer: true,
86
+ min: 1,
87
+ validator: validators.positiveInteger,
88
+ error: 'outOfTotal must be a positive integer'
89
+ },
90
+ stats: {
91
+ type: 'object',
92
+ required: true,
93
+ propertyNames: SUPPORTED_STATS,
94
+ propertySchema: {
95
+ type: 'object',
96
+ required: true,
97
+ properties: {
98
+ storeAs: {
99
+ type: 'string',
100
+ required: true,
101
+ minLength: 1,
102
+ validator: validators.identifier,
103
+ error: 'storeAs must be a valid identifier'
104
+ }
105
+ }
106
+ }
107
+ },
108
+ triggers: {
109
+ type: 'array',
110
+ required: false,
111
+ itemSchema: {
112
+ type: 'object',
113
+ validator: composerValidators.trigger,
114
+ error: 'Invalid trigger specification'
115
+ }
116
+ }
117
+ },
118
+
119
+ // Cross-field validators
120
+ crossFieldValidators: [
121
+ {
122
+ fields: [ 'minVotes', 'outOfTotal' ],
123
+ validator: (spec) => {
124
+ const minVotes = spec.minVotes || 3;
125
+ const outOfTotal = spec.outOfTotal || 5;
126
+ return outOfTotal >= minVotes;
127
+ },
128
+ error: 'outOfTotal must be greater than or equal to minVotes'
129
+ },
130
+ composerValidators.noSelfTriggers
131
+ ],
132
+
133
+ // How to build the spec from DSL params
134
+ buildSpec: ( name, predicate, stats, options ) => ( {
135
+ nodeType: NODE_TYPE,
136
+ name,
137
+ predicate,
138
+ stats,
139
+ ...options
140
+ } ),
141
+
142
+ };
143
+
144
+ export const getDSLMetadata = () => ( { ...DSL_METADATA } );
@@ -0,0 +1,11 @@
1
+ // nodes/persistence-check/publish-to.js
2
+
3
+ const publishTo = function ( state, msg ) {
4
+ if ( state.disable ) return;
5
+
6
+ msg[ state.stats.persistenceConfirmed.storeAs ] = state.persistenceConfirmed;
7
+ // Reset immediately after publishing it.
8
+ state.persistenceConfirmed = false;
9
+ }; // publishTo()
10
+
11
+ export default publishTo;
@@ -0,0 +1,7 @@
1
+ // nodes/persistence-check/recompute.js
2
+
3
+ const recompute = function () {
4
+ return true;
5
+ }; // recompute()
6
+
7
+ export default recompute;
@@ -0,0 +1,12 @@
1
+ // nodes/persistence-check/reset.js
2
+
3
+ const reset = function ( state ) {
4
+ state.voteCount = 0;
5
+ state.unvoteCount = 0;
6
+ state.persistenceConfirmed = false;
7
+ // Clear error suppression so next error episode is logged
8
+ state.predicateErrorLogged = false;
9
+ return state;
10
+ }; // reset()
11
+
12
+ export default reset;
@@ -0,0 +1,57 @@
1
+ // nodes/persistence-check/update.js
2
+
3
+ import { executeTriggers } from '../../core/utils/node/index.js';
4
+
5
+ const update = function ( state, msg ) {
6
+ if ( state.disable || state.pause ) return state;
7
+
8
+ let predicateResult;
9
+ try {
10
+ predicateResult = state.predicate( msg );
11
+ // Recovery: clear log-suppression flag on success
12
+ if ( state.predicateErrorLogged ) state.predicateErrorLogged = false;
13
+ } catch ( error ) {
14
+ // Assume it to be a case of predicate evaluating to false
15
+ predicateResult = false;
16
+ // Log first error per episode; suppress subsequent until recovery
17
+ if ( !state.predicateErrorLogged ) {
18
+ state.predicateErrorLogged = true;
19
+ console.error( `WinkComposer/persistenceCheck: predicate threw exception: ${error.message}` );
20
+ }
21
+ }
22
+
23
+ // Update vote counts
24
+ if ( predicateResult ) {
25
+ state.voteCount += 1;
26
+ } else {
27
+ state.unvoteCount += 1;
28
+ }
29
+
30
+ // Check for success
31
+ if ( state.voteCount >= state.minVotes ) {
32
+ state.voteCount = 0;
33
+ state.unvoteCount = 0;
34
+ state.persistenceConfirmed = true;
35
+
36
+ // Trigger controls
37
+ executeTriggers( state );
38
+
39
+ return state; // Early return on success
40
+ }
41
+
42
+ // Check for window completion or mathematical impossibility
43
+ const totalProcessed = state.voteCount + state.unvoteCount;
44
+ const remaining = state.outOfTotal - totalProcessed;
45
+
46
+ if ( totalProcessed >= state.outOfTotal || // Window completition check
47
+ ( state.voteCount + remaining ) < state.minVotes ) { // Mathematical impossibility check
48
+ // Window complete or success impossible - reset
49
+ state.voteCount = 0;
50
+ state.unvoteCount = 0;
51
+ state.persistenceConfirmed = false;
52
+ }
53
+
54
+ return state;
55
+ }; // update()
56
+
57
+ export default update;
@@ -0,0 +1,15 @@
1
+ // nodes/process-index/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';
15
+
@@ -0,0 +1,48 @@
1
+ // nodes/process-index/init.js
2
+
3
+ import { validateSpec } from '../../core/utils/node/index.js';
4
+ import * as introspect from './introspect.js';
5
+ import { DEFAULT_OPTIONS } from './introspect.js';
6
+
7
+ const init = function ( spec ) {
8
+ validateSpec( spec, introspect );
9
+
10
+ const state = Object.create( null );
11
+ // Standard input parameter health flag during update: false means healthy
12
+ state.inputValidationFailed = false;
13
+ // Ensure node is enabled by default
14
+ state.disable = false;
15
+ state.pause = false;
16
+
17
+ // Input fields
18
+ state.x = spec.from.x; // mean field
19
+ state.y = spec.from.y; // stddev field
20
+
21
+ // Spec limits (at least one required, validated by specSchema)
22
+ state.hasUpperSpecLimit = spec.upperSpecLimit !== undefined;
23
+ state.hasLowerSpecLimit = spec.lowerSpecLimit !== undefined;
24
+ state.upperSpecLimit = state.hasUpperSpecLimit ? spec.upperSpecLimit : NaN;
25
+ state.lowerSpecLimit = state.hasLowerSpecLimit ? spec.lowerSpecLimit : NaN;
26
+
27
+ // Options
28
+ state.epsilon = spec.epsilon ?? DEFAULT_OPTIONS.epsilon;
29
+ state.maxIndex = spec.maxIndex ?? DEFAULT_OPTIONS.maxIndex;
30
+ state.capableThreshold = spec.capableThreshold ?? DEFAULT_OPTIONS.capableThreshold;
31
+ state.marginalThreshold = spec.marginalThreshold ?? DEFAULT_OPTIONS.marginalThreshold;
32
+
33
+ // Config copy
34
+ state.stats = spec.stats;
35
+
36
+ // Output values
37
+ state.index = NaN;
38
+ state.upper = NaN;
39
+ state.lower = NaN;
40
+ state.status = 'incapable';
41
+
42
+ state.nodeType = introspect.getNodeType();
43
+
44
+ return state;
45
+ }; // init()
46
+
47
+ export default init;
48
+
@@ -0,0 +1,182 @@
1
+ // nodes/process-index/introspect.js
2
+
3
+ /**
4
+ * @fileoverview Introspection metadata for processIndex node.
5
+ *
6
+ * Computes process capability/performance index from mean and standard deviation
7
+ * with specification limits. Uses neutral terminology since interpretation as
8
+ * Cpk vs Ppk depends on upstream window configuration.
9
+ *
10
+ * Formulas:
11
+ * - upper = (upperSpecLimit - mean) / (3 * stddev)
12
+ * - lower = (mean - lowerSpecLimit) / (3 * stddev)
13
+ * - index = min(upper, lower) for two-sided, or the applicable one for one-sided
14
+ *
15
+ * DSL: .processIndex( 'tempPI', 'tempMean', 'tempStddev', { index: {...} }, { upperSpecLimit, lowerSpecLimit } )
16
+ */
17
+
18
+ import { validators } from '../../core/utils/validate/index.js';
19
+
20
+ /** Single source of truth for what this plugin can do */
21
+ const SUPPORTED_STATS = [
22
+ 'index',
23
+ 'upper',
24
+ 'lower',
25
+ 'status'
26
+ ];
27
+
28
+ /** Human-readable descriptions (for introspection) */
29
+ const STAT_DESCRIPTIONS = {
30
+ index: 'Process index: min(upper, lower) for two-sided specs',
31
+ upper: 'Upper process index: (upperSpecLimit - mean) / (3 * stddev)',
32
+ lower: 'Lower process index: (mean - lowerSpecLimit) / (3 * stddev)',
33
+ status: 'Classification: capable, marginal, or incapable'
34
+ };
35
+
36
+ /** Control methods available for triggers */
37
+ const SUPPORTED_CONTROL_METHODS = {
38
+ reset: 'Clears accumulated state and restarts computation',
39
+ enable: 'Enables node processing',
40
+ disable: 'Disables node processing',
41
+ pause: 'Pauses node processing while keeping state visible',
42
+ unpause: 'Resumes node processing after pause'
43
+ };
44
+
45
+ /** The type of this node */
46
+ const NODE_TYPE = 'Process Index';
47
+
48
+ /** Node capabilities for documentation */
49
+ const CAPABILITIES = {
50
+ description: 'Computes process capability/performance index from mean and stddev',
51
+ features: [
52
+ 'Two-sided specs: index = min(upper, lower)',
53
+ 'One-sided specs: upperSpecLimit only or lowerSpecLimit only supported',
54
+ 'Status classification: capable (>=1.33), marginal (1.0-1.33), incapable (<1.0)',
55
+ 'Configurable thresholds for status classification',
56
+ 'Caps index at maxIndex (default 12) for near-zero stddev'
57
+ ]
58
+ };
59
+
60
+ // Attach static metadata once, from our constants by making a shallow copy.
61
+ export const getSupportedStats = () => SUPPORTED_STATS.slice();
62
+ export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
63
+ export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
64
+ export const getNodeType = () => NODE_TYPE;
65
+ export const getCapabilities = () => ( { ...CAPABILITIES, features: CAPABILITIES.features.slice() } );
66
+
67
+ export const DEFAULT_OPTIONS = {
68
+ epsilon: 1e-12,
69
+ maxIndex: 12,
70
+ capableThreshold: 1.33,
71
+ marginalThreshold: 1.0
72
+ };
73
+
74
+ // DSL Metadata for transpilation
75
+ const DSL_METADATA = {
76
+ // Spec schema for validation
77
+ specSchema: {
78
+ nodeType: {
79
+ type: 'string',
80
+ required: true,
81
+ value: NODE_TYPE
82
+ },
83
+ name: {
84
+ type: 'string',
85
+ required: true,
86
+ validator: validators.identifier,
87
+ error: 'Name must be a valid identifier'
88
+ },
89
+ from: {
90
+ type: 'object',
91
+ required: true,
92
+ properties: {
93
+ x: {
94
+ type: 'string',
95
+ required: true,
96
+ validator: validators.noSpaces,
97
+ error: 'Mean field name cannot contain spaces'
98
+ },
99
+ y: {
100
+ type: 'string',
101
+ required: true,
102
+ validator: validators.noSpaces,
103
+ error: 'Stddev field name cannot contain spaces'
104
+ }
105
+ }
106
+ },
107
+ upperSpecLimit: {
108
+ type: 'number',
109
+ required: false
110
+ },
111
+ lowerSpecLimit: {
112
+ type: 'number',
113
+ required: false
114
+ },
115
+ epsilon: {
116
+ type: 'number',
117
+ required: false,
118
+ default: DEFAULT_OPTIONS.epsilon
119
+ },
120
+ maxIndex: {
121
+ type: 'number',
122
+ required: false,
123
+ default: DEFAULT_OPTIONS.maxIndex
124
+ },
125
+ capableThreshold: {
126
+ type: 'number',
127
+ required: false,
128
+ default: DEFAULT_OPTIONS.capableThreshold
129
+ },
130
+ marginalThreshold: {
131
+ type: 'number',
132
+ required: false,
133
+ default: DEFAULT_OPTIONS.marginalThreshold
134
+ },
135
+ stats: {
136
+ type: 'object',
137
+ required: true,
138
+ propertyNames: SUPPORTED_STATS,
139
+ propertySchema: {
140
+ type: 'object',
141
+ required: true,
142
+ properties: {
143
+ storeAs: {
144
+ type: 'string',
145
+ required: true,
146
+ minLength: 1,
147
+ validator: validators.identifier,
148
+ error: 'storeAs must be a valid identifier'
149
+ }
150
+ }
151
+ }
152
+ }
153
+ },
154
+
155
+ // Cross-field validators
156
+ crossFieldValidators: [
157
+ {
158
+ fields: [ 'upperSpecLimit', 'lowerSpecLimit' ],
159
+ validator: ( spec ) => spec.upperSpecLimit !== undefined || spec.lowerSpecLimit !== undefined,
160
+ error: 'At least one of upperSpecLimit or lowerSpecLimit must be provided'
161
+ },
162
+ {
163
+ fields: [ 'from.x', 'from.y' ],
164
+ validator: ( spec ) => spec.from.x !== spec.from.y,
165
+ error: 'from.x (mean) and from.y (stddev) must be different fields'
166
+ }
167
+ ],
168
+
169
+ // How to build the spec from DSL params
170
+ // DSL: .processIndex( 'tempPI', 'tempMean', 'tempStddev', { index: {...} }, { upperSpecLimit, lowerSpecLimit } )
171
+ buildSpec: ( name, x, y, stats, options ) => ( {
172
+ nodeType: NODE_TYPE,
173
+ name,
174
+ from: { x, y },
175
+ stats,
176
+ ...options
177
+ } ),
178
+
179
+ };
180
+
181
+ export const getDSLMetadata = () => ( { ...DSL_METADATA } );
182
+
@@ -0,0 +1,29 @@
1
+ // nodes/process-index/publish-to.js
2
+
3
+ /**
4
+ * @fileoverview Publish function for processIndex node.
5
+ *
6
+ * Publishes computed index values and status to the message.
7
+ * On inputValidationFailed, publishes NaN for numeric stats and 'incapable' for status.
8
+ */
9
+
10
+ const publishTo = function ( state, msg ) {
11
+ if ( state.disable ) return;
12
+
13
+ if ( state.inputValidationFailed ) {
14
+ // Publish NaN for numeric stats, 'incapable' for status
15
+ if ( state.stats.index ) msg[ state.stats.index.storeAs ] = NaN;
16
+ if ( state.stats.upper ) msg[ state.stats.upper.storeAs ] = NaN;
17
+ if ( state.stats.lower ) msg[ state.stats.lower.storeAs ] = NaN;
18
+ if ( state.stats.status ) msg[ state.stats.status.storeAs ] = 'incapable';
19
+ return;
20
+ }
21
+
22
+ if ( state.stats.index ) msg[ state.stats.index.storeAs ] = state.index;
23
+ if ( state.stats.upper ) msg[ state.stats.upper.storeAs ] = state.upper;
24
+ if ( state.stats.lower ) msg[ state.stats.lower.storeAs ] = state.lower;
25
+ if ( state.stats.status ) msg[ state.stats.status.storeAs ] = state.status;
26
+ }; // publishTo()
27
+
28
+ export default publishTo;
29
+
@@ -0,0 +1,8 @@
1
+ // nodes/process-index/recompute.js
2
+
3
+ const recompute = function () {
4
+ return true;
5
+ }; // recompute()
6
+
7
+ export default recompute;
8
+
@@ -0,0 +1,8 @@
1
+ // nodes/process-index/reset.js
2
+
3
+ const reset = function () {
4
+ return true;
5
+ }; // reset()
6
+
7
+ export default reset;
8
+
@@ -0,0 +1,75 @@
1
+ // nodes/process-index/update.js
2
+
3
+ /**
4
+ * @fileoverview Update function for processIndex node.
5
+ *
6
+ * Computes process capability/performance index from mean and stddev.
7
+ * Supports two-sided specs (upperSpecLimit + lowerSpecLimit) and one-sided specs.
8
+ */
9
+
10
+ /**
11
+ * Clamp a value to [-maxIdx, maxIdx] range.
12
+ * @param {number} value - Raw index value
13
+ * @param {number} maxIdx - Maximum absolute value
14
+ * @returns {number} Clamped value
15
+ */
16
+ const clampIndex = function ( value, maxIdx ) {
17
+ return Math.max( Math.min( value, maxIdx ), -maxIdx );
18
+ }; // clampIndex()
19
+
20
+ const update = function ( state, msg ) {
21
+ if ( state.disable || state.pause ) return state;
22
+
23
+ state.inputValidationFailed = false;
24
+
25
+ const mean = msg[ state.x ];
26
+ const stddev = msg[ state.y ];
27
+
28
+ // Validate inputs: mean must be finite, stddev must be finite and positive
29
+ if ( !Number.isFinite( mean ) || !Number.isFinite( stddev ) || stddev <= 0 ) {
30
+ state.inputValidationFailed = true;
31
+ return state;
32
+ }
33
+
34
+ const maxIdx = state.maxIndex;
35
+ const denominator = 3 * stddev;
36
+
37
+ // Compute upper index (if upperSpecLimit provided)
38
+ if ( state.hasUpperSpecLimit ) {
39
+ const rawUpper = ( state.upperSpecLimit - mean ) / denominator;
40
+ state.upper = clampIndex( rawUpper, maxIdx );
41
+ } else {
42
+ state.upper = NaN;
43
+ }
44
+
45
+ // Compute lower index (if lowerSpecLimit provided)
46
+ if ( state.hasLowerSpecLimit ) {
47
+ const rawLower = ( mean - state.lowerSpecLimit ) / denominator;
48
+ state.lower = clampIndex( rawLower, maxIdx );
49
+ } else {
50
+ state.lower = NaN;
51
+ }
52
+
53
+ // Combined index: explicit handling to avoid Math.min(NaN, value) = NaN
54
+ if ( state.hasUpperSpecLimit && state.hasLowerSpecLimit ) {
55
+ state.index = Math.min( state.upper, state.lower );
56
+ } else if ( state.hasUpperSpecLimit ) {
57
+ state.index = state.upper;
58
+ } else {
59
+ state.index = state.lower;
60
+ }
61
+
62
+ // Status classification based on combined index
63
+ if ( state.index >= state.capableThreshold ) {
64
+ state.status = 'capable';
65
+ } else if ( state.index >= state.marginalThreshold ) {
66
+ state.status = 'marginal';
67
+ } else {
68
+ state.status = 'incapable';
69
+ }
70
+
71
+ return state;
72
+ }; // update()
73
+
74
+ export default update;
75
+
@@ -0,0 +1,14 @@
1
+ // nodes/ratio/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,37 @@
1
+ // nodes/ratio/init.js
2
+
3
+ import { validateSpec } from '../../core/utils/node/index.js';
4
+ import * as introspect from './introspect.js';
5
+
6
+ const init = function ( spec ) {
7
+ validateSpec( spec, introspect );
8
+
9
+ // Create state after validation passes
10
+ const state = Object.create( null );
11
+ // Standard input parameter health flag during update: false means healthy
12
+ state.inputValidationFailed = false;
13
+ // Ensure node is enabled by default
14
+ state.disable = false;
15
+ state.pause = false;
16
+
17
+ // Extract field names - x is numerator, y is denominator.
18
+ state.x = spec.from.x;
19
+ state.y = spec.from.y;
20
+
21
+ // Config copy.
22
+ state.stats = spec.stats;
23
+
24
+ // Apply defaults from introspect (validation doesn't enforce them)
25
+ state.logScale = spec.logScale ?? introspect.DEFAULT_OPTIONS.logScale;
26
+ state.minY = spec.minY ?? introspect.DEFAULT_OPTIONS.minY;
27
+ state.scaleBy = spec.scaleBy ?? introspect.DEFAULT_OPTIONS.scaleBy;
28
+
29
+ // State variables.
30
+ state.ratio = 0;
31
+
32
+ state.nodeType = introspect.getNodeType();
33
+
34
+ return state;
35
+ }; // init()
36
+
37
+ export default init;