@winkjs/composer 0.0.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +42 -103
  3. package/package.json +53 -29
  4. package/src/composer.js +75 -0
  5. package/src/core/batch/aoo-encoder.js +148 -0
  6. package/src/core/batch/index.js +12 -0
  7. package/src/core/batch/sliding-window.js +91 -0
  8. package/src/core/codec/index.js +137 -0
  9. package/src/core/emitter-manager/mqtt/constants.js +102 -0
  10. package/src/core/emitter-manager/mqtt/emitter.js +780 -0
  11. package/src/core/emitter-manager/mqtt/index.js +190 -0
  12. package/src/core/emitter-manager/mqtt/mqtt-store.js +538 -0
  13. package/src/core/emitter-manager/terminal/assert-columns.js +98 -0
  14. package/src/core/emitter-manager/terminal/formatters.js +160 -0
  15. package/src/core/emitter-manager/terminal/index.js +341 -0
  16. package/src/core/env-vars.js +245 -0
  17. package/src/core/mqtt-protocol.js +47 -0
  18. package/src/core/partition-manager/index.js +7 -0
  19. package/src/core/partition-manager/init.js +44 -0
  20. package/src/core/partition-manager/introspect.js +15 -0
  21. package/src/core/partition-manager/publish-to.js +6 -0
  22. package/src/core/partition-manager/recompute.js +5 -0
  23. package/src/core/partition-manager/reset.js +5 -0
  24. package/src/core/partition-manager/update.js +264 -0
  25. package/src/core/partition-manager/validate-flow.js +157 -0
  26. package/src/core/semantics/digest.js +128 -0
  27. package/src/core/semantics/index.js +83 -0
  28. package/src/core/semantics/loader.js +571 -0
  29. package/src/core/semantics/schemas/asset-class-schema.js +218 -0
  30. package/src/core/semantics/schemas/column-schema.js +651 -0
  31. package/src/core/semantics/schemas/enum-schema.js +153 -0
  32. package/src/core/semantics/schemas/index.js +51 -0
  33. package/src/core/semantics/warnings.js +141 -0
  34. package/src/core/shutdown-manager/index.js +289 -0
  35. package/src/core/source-manager/csv/index.js +171 -0
  36. package/src/core/source-manager/csv/start.js +456 -0
  37. package/src/core/source-manager/mqtt/client.js +406 -0
  38. package/src/core/source-manager/mqtt/constants.js +147 -0
  39. package/src/core/source-manager/mqtt/dedup.js +244 -0
  40. package/src/core/source-manager/mqtt/index.js +260 -0
  41. package/src/core/source-manager/mqtt/status.js +546 -0
  42. package/src/core/source-manager/test-harness/comparator.js +226 -0
  43. package/src/core/source-manager/test-harness/field-generator.js +85 -0
  44. package/src/core/source-manager/test-harness/fuzz.js +87 -0
  45. package/src/core/source-manager/test-harness/index.js +115 -0
  46. package/src/core/source-manager/test-harness/prng.js +57 -0
  47. package/src/core/source-manager/test-harness/start.js +232 -0
  48. package/src/core/source-manager/test-harness/validate.js +213 -0
  49. package/src/core/storage-manager/questdb/assert-columns.js +120 -0
  50. package/src/core/storage-manager/questdb/ensure-tables.js +187 -0
  51. package/src/core/storage-manager/questdb/index.js +1251 -0
  52. package/src/core/storage-manager/questdb/persist-plan.js +488 -0
  53. package/src/core/storage-manager/questdb/writers.js +142 -0
  54. package/src/core/test-utils/sealed-record.js +80 -0
  55. package/src/core/test-utils/soak-signature.js +149 -0
  56. package/src/core/test-utils/tcp-proxy.js +106 -0
  57. package/src/core/tunable/helpers.js +254 -0
  58. package/src/core/tunable/index.js +87 -0
  59. package/src/core/utils/console-formatter/index.js +207 -0
  60. package/src/core/utils/create-smart-store-as/index.js +98 -0
  61. package/src/core/utils/create-smart-store-as/sanitize-field.js +46 -0
  62. package/src/core/utils/create-smart-store-as/smart-truncate.js +93 -0
  63. package/src/core/utils/flow/index.js +5 -0
  64. package/src/core/utils/flow/make-collision-checker.js +23 -0
  65. package/src/core/utils/flow/to-kebab.js +20 -0
  66. package/src/core/utils/half-life/index.js +111 -0
  67. package/src/core/utils/node/disable.js +11 -0
  68. package/src/core/utils/node/enable.js +11 -0
  69. package/src/core/utils/node/execute-triggers.js +40 -0
  70. package/src/core/utils/node/index.js +10 -0
  71. package/src/core/utils/node/pause.js +11 -0
  72. package/src/core/utils/node/populate-predicate-inputs.js +14 -0
  73. package/src/core/utils/node/publish-nan.js +19 -0
  74. package/src/core/utils/node/reset-predicate-inputs.js +11 -0
  75. package/src/core/utils/node/unpause.js +11 -0
  76. package/src/core/utils/node/validate-spec.js +22 -0
  77. package/src/core/utils/options/resolve-field-keyed.js +115 -0
  78. package/src/core/utils/quantize/index.js +75 -0
  79. package/src/core/utils/stats/formulas.js +67 -0
  80. package/src/core/utils/stats/index.js +3 -0
  81. package/src/core/utils/validate/composer-validators.js +141 -0
  82. package/src/core/utils/validate/helpers.js +206 -0
  83. package/src/core/utils/validate/index.js +12 -0
  84. package/src/core/utils/validate/type-validators.js +538 -0
  85. package/src/core/utils/validate/validate.js +107 -0
  86. package/src/core/utils/validate/validators.js +177 -0
  87. package/src/core/wiring/assert-handle.js +57 -0
  88. package/src/core/wiring/assert-module.js +63 -0
  89. package/src/core/wiring/index.js +5 -0
  90. package/src/core/wiring/node-type-to-module.js +17 -0
  91. package/src/core/wiring/wire-emitters.js +256 -0
  92. package/src/core/wiring/wire-linear-graph.js +25 -0
  93. package/src/core/wiring/wire-node.js +157 -0
  94. package/src/core/wiring/wire-semantics.js +173 -0
  95. package/src/core/wiring/wire-storages.js +344 -0
  96. package/src/flow/check-output-collisions.js +93 -0
  97. package/src/flow/consts.js +9 -0
  98. package/src/flow/deep-clone-spec.js +64 -0
  99. package/src/flow/driver.js +171 -0
  100. package/src/flow/expand-single-input-array.js +76 -0
  101. package/src/flow/expand-template-spec.js +93 -0
  102. package/src/flow/flow-api-schemas.js +300 -0
  103. package/src/flow/flow.js +658 -0
  104. package/src/flow/for-each.js +225 -0
  105. package/src/flow/get-signature-pattern.js +31 -0
  106. package/src/flow/get-target-array.js +46 -0
  107. package/src/flow/inspect.js +67 -0
  108. package/src/flow/load-node-module.js +81 -0
  109. package/src/flow/make-node-method.js +112 -0
  110. package/src/flow/resolve-pick-by-field.js +77 -0
  111. package/src/flow/resolve-tunables.js +76 -0
  112. package/src/flow/run.js +392 -0
  113. package/src/flow/serialize.js +161 -0
  114. package/src/flow/signatures-schema.js +222 -0
  115. package/src/flow/spec-builder.js +65 -0
  116. package/src/flow/validate-triggers.js +250 -0
  117. package/src/flow/validate.js +261 -0
  118. package/src/nodes/accumulate/index.js +21 -0
  119. package/src/nodes/accumulate/init.js +48 -0
  120. package/src/nodes/accumulate/introspect.js +123 -0
  121. package/src/nodes/accumulate/publish-to.js +34 -0
  122. package/src/nodes/accumulate/recompute.js +27 -0
  123. package/src/nodes/accumulate/reset.js +25 -0
  124. package/src/nodes/accumulate/update.js +42 -0
  125. package/src/nodes/appraise/calibrate.js +64 -0
  126. package/src/nodes/appraise/decision.js +66 -0
  127. package/src/nodes/appraise/deviation.js +140 -0
  128. package/src/nodes/appraise/index.js +23 -0
  129. package/src/nodes/appraise/init.js +165 -0
  130. package/src/nodes/appraise/integrate.js +45 -0
  131. package/src/nodes/appraise/introspect.js +352 -0
  132. package/src/nodes/appraise/publish-to.js +93 -0
  133. package/src/nodes/appraise/receptor.js +69 -0
  134. package/src/nodes/appraise/recompute.js +79 -0
  135. package/src/nodes/appraise/reset.js +53 -0
  136. package/src/nodes/appraise/update.js +130 -0
  137. package/src/nodes/archive/csv/index.js +6 -0
  138. package/src/nodes/archive/csv/init.js +36 -0
  139. package/src/nodes/archive/csv/load.js +70 -0
  140. package/src/nodes/archive/csv/reset.js +14 -0
  141. package/src/nodes/archive/csv/simple-parser.js +216 -0
  142. package/src/nodes/archive/csv/test.js +173 -0
  143. package/src/nodes/archive/csv/update.js +63 -0
  144. package/src/nodes/butterworth-filter/index.js +18 -0
  145. package/src/nodes/butterworth-filter/init.js +184 -0
  146. package/src/nodes/butterworth-filter/introspect.js +228 -0
  147. package/src/nodes/butterworth-filter/publish-to.js +21 -0
  148. package/src/nodes/butterworth-filter/recompute.js +13 -0
  149. package/src/nodes/butterworth-filter/reset.js +30 -0
  150. package/src/nodes/butterworth-filter/update.js +38 -0
  151. package/src/nodes/categorize/index.js +19 -0
  152. package/src/nodes/categorize/init.js +58 -0
  153. package/src/nodes/categorize/introspect.js +177 -0
  154. package/src/nodes/categorize/publish-to.js +29 -0
  155. package/src/nodes/categorize/recompute.js +14 -0
  156. package/src/nodes/categorize/reset.js +16 -0
  157. package/src/nodes/categorize/update.js +53 -0
  158. package/src/nodes/controller/index.js +9 -0
  159. package/src/nodes/controller/init.js +55 -0
  160. package/src/nodes/controller/introspect.js +91 -0
  161. package/src/nodes/controller/publish-to.js +8 -0
  162. package/src/nodes/controller/recompute.js +9 -0
  163. package/src/nodes/controller/reset.js +17 -0
  164. package/src/nodes/controller/update.js +63 -0
  165. package/src/nodes/diff/index.js +19 -0
  166. package/src/nodes/diff/init.js +37 -0
  167. package/src/nodes/diff/introspect.js +132 -0
  168. package/src/nodes/diff/publish-to.js +21 -0
  169. package/src/nodes/diff/recompute.js +12 -0
  170. package/src/nodes/diff/reset.js +12 -0
  171. package/src/nodes/diff/update.js +37 -0
  172. package/src/nodes/digest-moments/formulas.js +12 -0
  173. package/src/nodes/digest-moments/index.js +14 -0
  174. package/src/nodes/digest-moments/init.js +67 -0
  175. package/src/nodes/digest-moments/introspect.js +154 -0
  176. package/src/nodes/digest-moments/publish-to.js +34 -0
  177. package/src/nodes/digest-moments/recompute.js +14 -0
  178. package/src/nodes/digest-moments/reset.js +14 -0
  179. package/src/nodes/digest-moments/update.js +120 -0
  180. package/src/nodes/dwell-time-tracker/index.js +14 -0
  181. package/src/nodes/dwell-time-tracker/init.js +59 -0
  182. package/src/nodes/dwell-time-tracker/introspect.js +137 -0
  183. package/src/nodes/dwell-time-tracker/publish-to.js +22 -0
  184. package/src/nodes/dwell-time-tracker/recompute.js +8 -0
  185. package/src/nodes/dwell-time-tracker/reset.js +23 -0
  186. package/src/nodes/dwell-time-tracker/update.js +103 -0
  187. package/src/nodes/emit-if/helpers.js +94 -0
  188. package/src/nodes/emit-if/index.js +16 -0
  189. package/src/nodes/emit-if/init.js +67 -0
  190. package/src/nodes/emit-if/introspect.js +102 -0
  191. package/src/nodes/emit-if/publish-to.js +13 -0
  192. package/src/nodes/emit-if/recompute.js +12 -0
  193. package/src/nodes/emit-if/reset.js +27 -0
  194. package/src/nodes/emit-if/update.js +93 -0
  195. package/src/nodes/es-correlation/index.js +19 -0
  196. package/src/nodes/es-correlation/init.js +73 -0
  197. package/src/nodes/es-correlation/introspect.js +176 -0
  198. package/src/nodes/es-correlation/publish-to.js +32 -0
  199. package/src/nodes/es-correlation/recompute.js +56 -0
  200. package/src/nodes/es-correlation/reset.js +27 -0
  201. package/src/nodes/es-correlation/update.js +110 -0
  202. package/src/nodes/es-mean/index.js +20 -0
  203. package/src/nodes/es-mean/init.js +58 -0
  204. package/src/nodes/es-mean/introspect.js +129 -0
  205. package/src/nodes/es-mean/publish-to.js +19 -0
  206. package/src/nodes/es-mean/recompute.js +16 -0
  207. package/src/nodes/es-mean/reset.js +24 -0
  208. package/src/nodes/es-mean/update.js +69 -0
  209. package/src/nodes/es-pairwise-correlation/index.js +19 -0
  210. package/src/nodes/es-pairwise-correlation/init.js +98 -0
  211. package/src/nodes/es-pairwise-correlation/introspect.js +187 -0
  212. package/src/nodes/es-pairwise-correlation/publish-to.js +31 -0
  213. package/src/nodes/es-pairwise-correlation/recompute.js +69 -0
  214. package/src/nodes/es-pairwise-correlation/reset.js +29 -0
  215. package/src/nodes/es-pairwise-correlation/update.js +89 -0
  216. package/src/nodes/es-stats/index.js +21 -0
  217. package/src/nodes/es-stats/init.js +105 -0
  218. package/src/nodes/es-stats/introspect.js +157 -0
  219. package/src/nodes/es-stats/publish-to.js +42 -0
  220. package/src/nodes/es-stats/recompute.js +74 -0
  221. package/src/nodes/es-stats/reset.js +49 -0
  222. package/src/nodes/es-stats/update-envelope.js +44 -0
  223. package/src/nodes/es-stats/update-welford.js +64 -0
  224. package/src/nodes/es-stats/update.js +59 -0
  225. package/src/nodes/index.js +83 -0
  226. package/src/nodes/invert-flag/index.js +20 -0
  227. package/src/nodes/invert-flag/init.js +36 -0
  228. package/src/nodes/invert-flag/introspect.js +115 -0
  229. package/src/nodes/invert-flag/publish-to.js +23 -0
  230. package/src/nodes/invert-flag/recompute.js +12 -0
  231. package/src/nodes/invert-flag/reset.js +12 -0
  232. package/src/nodes/invert-flag/update.js +32 -0
  233. package/src/nodes/kalman1d/index.js +20 -0
  234. package/src/nodes/kalman1d/init.js +103 -0
  235. package/src/nodes/kalman1d/introspect.js +250 -0
  236. package/src/nodes/kalman1d/publish-to.js +34 -0
  237. package/src/nodes/kalman1d/recompute.js +23 -0
  238. package/src/nodes/kalman1d/reset.js +29 -0
  239. package/src/nodes/kalman1d/update.js +144 -0
  240. package/src/nodes/kernel/index.js +18 -0
  241. package/src/nodes/kernel/init.js +66 -0
  242. package/src/nodes/kernel/introspect.js +163 -0
  243. package/src/nodes/kernel/presets.js +74 -0
  244. package/src/nodes/kernel/publish-to.js +25 -0
  245. package/src/nodes/kernel/recompute.js +14 -0
  246. package/src/nodes/kernel/reset.js +20 -0
  247. package/src/nodes/kernel/update.js +69 -0
  248. package/src/nodes/lag/index.js +21 -0
  249. package/src/nodes/lag/init.js +87 -0
  250. package/src/nodes/lag/introspect.js +202 -0
  251. package/src/nodes/lag/publish-to.js +64 -0
  252. package/src/nodes/lag/recompute.js +33 -0
  253. package/src/nodes/lag/reset.js +49 -0
  254. package/src/nodes/lag/update.js +133 -0
  255. package/src/nodes/median3/index.js +19 -0
  256. package/src/nodes/median3/init.js +40 -0
  257. package/src/nodes/median3/introspect.js +116 -0
  258. package/src/nodes/median3/publish-to.js +21 -0
  259. package/src/nodes/median3/recompute.js +12 -0
  260. package/src/nodes/median3/reset.js +15 -0
  261. package/src/nodes/median3/update.js +58 -0
  262. package/src/nodes/moments-digest/copy-from.js +12 -0
  263. package/src/nodes/moments-digest/flush.js +17 -0
  264. package/src/nodes/moments-digest/index.js +132 -0
  265. package/src/nodes/moments-digest/init.js +84 -0
  266. package/src/nodes/moments-digest/introspect.js +122 -0
  267. package/src/nodes/moments-digest/prelude.js +28 -0
  268. package/src/nodes/moments-digest/publish-to.js +31 -0
  269. package/src/nodes/moments-digest/recompute.js +9 -0
  270. package/src/nodes/moments-digest/reset.js +20 -0
  271. package/src/nodes/moments-digest/update.js +182 -0
  272. package/src/nodes/node-names.js +67 -0
  273. package/src/nodes/page-hinkley/index.js +20 -0
  274. package/src/nodes/page-hinkley/init.js +66 -0
  275. package/src/nodes/page-hinkley/introspect.js +193 -0
  276. package/src/nodes/page-hinkley/publish-to.js +28 -0
  277. package/src/nodes/page-hinkley/recompute.js +14 -0
  278. package/src/nodes/page-hinkley/reset.js +23 -0
  279. package/src/nodes/page-hinkley/update.js +105 -0
  280. package/src/nodes/pass-if/index.js +21 -0
  281. package/src/nodes/pass-if/init.js +37 -0
  282. package/src/nodes/pass-if/introspect.js +93 -0
  283. package/src/nodes/pass-if/publish-to.js +15 -0
  284. package/src/nodes/pass-if/recompute.js +15 -0
  285. package/src/nodes/pass-if/reset.js +18 -0
  286. package/src/nodes/pass-if/update.js +37 -0
  287. package/src/nodes/persist-if/helpers.js +111 -0
  288. package/src/nodes/persist-if/index.js +9 -0
  289. package/src/nodes/persist-if/init.js +98 -0
  290. package/src/nodes/persist-if/introspect.js +106 -0
  291. package/src/nodes/persist-if/publish-to.js +21 -0
  292. package/src/nodes/persist-if/recompute.js +20 -0
  293. package/src/nodes/persist-if/reset.js +35 -0
  294. package/src/nodes/persist-if/update.js +112 -0
  295. package/src/nodes/persistence-check/index.js +14 -0
  296. package/src/nodes/persistence-check/init.js +38 -0
  297. package/src/nodes/persistence-check/introspect.js +144 -0
  298. package/src/nodes/persistence-check/publish-to.js +11 -0
  299. package/src/nodes/persistence-check/recompute.js +7 -0
  300. package/src/nodes/persistence-check/reset.js +12 -0
  301. package/src/nodes/persistence-check/update.js +57 -0
  302. package/src/nodes/process-index/index.js +15 -0
  303. package/src/nodes/process-index/init.js +48 -0
  304. package/src/nodes/process-index/introspect.js +182 -0
  305. package/src/nodes/process-index/publish-to.js +29 -0
  306. package/src/nodes/process-index/recompute.js +8 -0
  307. package/src/nodes/process-index/reset.js +8 -0
  308. package/src/nodes/process-index/update.js +75 -0
  309. package/src/nodes/ratio/index.js +14 -0
  310. package/src/nodes/ratio/init.js +37 -0
  311. package/src/nodes/ratio/introspect.js +155 -0
  312. package/src/nodes/ratio/publish-to.js +15 -0
  313. package/src/nodes/ratio/recompute.js +7 -0
  314. package/src/nodes/ratio/reset.js +7 -0
  315. package/src/nodes/ratio/update.js +47 -0
  316. package/src/nodes/sanitize/index.js +82 -0
  317. package/src/nodes/sanitize/init.js +82 -0
  318. package/src/nodes/sanitize/introspect.js +194 -0
  319. package/src/nodes/sanitize/publish-to.js +15 -0
  320. package/src/nodes/sanitize/recompute.js +8 -0
  321. package/src/nodes/sanitize/reset.js +14 -0
  322. package/src/nodes/sanitize/update.js +102 -0
  323. package/src/nodes/spike-guard/index.js +14 -0
  324. package/src/nodes/spike-guard/init.js +47 -0
  325. package/src/nodes/spike-guard/introspect.js +130 -0
  326. package/src/nodes/spike-guard/publish-to.js +35 -0
  327. package/src/nodes/spike-guard/recompute.js +14 -0
  328. package/src/nodes/spike-guard/reset.js +19 -0
  329. package/src/nodes/spike-guard/update.js +89 -0
  330. package/src/nodes/sse-emitter/index.js +7 -0
  331. package/src/nodes/sse-emitter/init.js +105 -0
  332. package/src/nodes/sse-emitter/introspect.js +134 -0
  333. package/src/nodes/sse-emitter/publish-to.js +6 -0
  334. package/src/nodes/sse-emitter/recompute.js +16 -0
  335. package/src/nodes/sse-emitter/reset.js +19 -0
  336. package/src/nodes/sse-emitter/update.js +69 -0
  337. package/src/nodes/sse-emitter/utils/broadcast-heartbeat.js +36 -0
  338. package/src/nodes/sse-emitter/utils/build-message.js +31 -0
  339. package/src/nodes/sse-emitter/utils/connection-manager.js +45 -0
  340. package/src/nodes/sse-emitter/utils/endpoint-initializer.js +20 -0
  341. package/src/nodes/sse-emitter/utils/health-monitor.js +38 -0
  342. package/src/nodes/sse-emitter/utils/qos-handler.js +41 -0
  343. package/src/nodes/state-change-detector/helpers.js +35 -0
  344. package/src/nodes/state-change-detector/index.js +12 -0
  345. package/src/nodes/state-change-detector/init.js +56 -0
  346. package/src/nodes/state-change-detector/introspect.js +146 -0
  347. package/src/nodes/state-change-detector/publish-to.js +20 -0
  348. package/src/nodes/state-change-detector/recompute.js +6 -0
  349. package/src/nodes/state-change-detector/reset.js +20 -0
  350. package/src/nodes/state-change-detector/update.js +97 -0
  351. package/src/nodes/sw-stats/index.js +14 -0
  352. package/src/nodes/sw-stats/init.js +51 -0
  353. package/src/nodes/sw-stats/introspect.js +131 -0
  354. package/src/nodes/sw-stats/publish-to.js +45 -0
  355. package/src/nodes/sw-stats/recompute.js +33 -0
  356. package/src/nodes/sw-stats/reset.js +15 -0
  357. package/src/nodes/sw-stats/update.js +39 -0
  358. package/src/nodes/swing-watch/index.js +17 -0
  359. package/src/nodes/swing-watch/init.js +144 -0
  360. package/src/nodes/swing-watch/introspect.js +188 -0
  361. package/src/nodes/swing-watch/publish-to.js +53 -0
  362. package/src/nodes/swing-watch/recompute.js +22 -0
  363. package/src/nodes/swing-watch/reset.js +55 -0
  364. package/src/nodes/swing-watch/update.js +767 -0
  365. package/src/nodes/tally/index.js +15 -0
  366. package/src/nodes/tally/init.js +32 -0
  367. package/src/nodes/tally/introspect.js +116 -0
  368. package/src/nodes/tally/publish-to.js +28 -0
  369. package/src/nodes/tally/recompute.js +10 -0
  370. package/src/nodes/tally/reset.js +10 -0
  371. package/src/nodes/tally/update.js +44 -0
  372. package/src/nodes/threshold/index.js +14 -0
  373. package/src/nodes/threshold/init.js +121 -0
  374. package/src/nodes/threshold/introspect.js +192 -0
  375. package/src/nodes/threshold/publish-to.js +11 -0
  376. package/src/nodes/threshold/recompute.js +8 -0
  377. package/src/nodes/threshold/reset.js +14 -0
  378. package/src/nodes/threshold/update.js +54 -0
  379. package/src/nodes/transform/helpers.js +39 -0
  380. package/src/nodes/transform/index.js +15 -0
  381. package/src/nodes/transform/init.js +35 -0
  382. package/src/nodes/transform/introspect.js +118 -0
  383. package/src/nodes/transform/publish-to.js +23 -0
  384. package/src/nodes/transform/recompute.js +12 -0
  385. package/src/nodes/transform/reset.js +11 -0
  386. package/src/nodes/transform/update.js +32 -0
  387. package/src/nodes/trend/compute-confidence.js +112 -0
  388. package/src/nodes/trend/index.js +14 -0
  389. package/src/nodes/trend/init.js +81 -0
  390. package/src/nodes/trend/introspect.js +151 -0
  391. package/src/nodes/trend/publish-to.js +22 -0
  392. package/src/nodes/trend/recompute.js +15 -0
  393. package/src/nodes/trend/reset.js +26 -0
  394. package/src/nodes/trend/update.js +93 -0
  395. package/src/nodes/tw-stats/copy-from.js +16 -0
  396. package/src/nodes/tw-stats/flush.js +12 -0
  397. package/src/nodes/tw-stats/index.js +41 -0
  398. package/src/nodes/tw-stats/init.js +92 -0
  399. package/src/nodes/tw-stats/introspect.js +171 -0
  400. package/src/nodes/tw-stats/publish-to.js +108 -0
  401. package/src/nodes/tw-stats/recompute.js +9 -0
  402. package/src/nodes/tw-stats/reset.js +16 -0
  403. package/src/nodes/tw-stats/update.js +113 -0
  404. package/src/nodes/unbalance/index.js +15 -0
  405. package/src/nodes/unbalance/init.js +59 -0
  406. package/src/nodes/unbalance/introspect.js +167 -0
  407. package/src/nodes/unbalance/publish-to.js +52 -0
  408. package/src/nodes/unbalance/recompute.js +11 -0
  409. package/src/nodes/unbalance/reset.js +10 -0
  410. package/src/nodes/unbalance/update.js +83 -0
  411. package/src/nodes/vector-distance/index.js +14 -0
  412. package/src/nodes/vector-distance/init.js +54 -0
  413. package/src/nodes/vector-distance/introspect.js +149 -0
  414. package/src/nodes/vector-distance/publish-to.js +35 -0
  415. package/src/nodes/vector-distance/recompute.js +11 -0
  416. package/src/nodes/vector-distance/reset.js +20 -0
  417. package/src/nodes/vector-distance/update.js +139 -0
  418. package/src/nodes/winnow/index.js +12 -0
  419. package/src/nodes/winnow/init.js +82 -0
  420. package/src/nodes/winnow/introspect.js +253 -0
  421. package/src/nodes/winnow/publish-to.js +51 -0
  422. package/src/nodes/winnow/recompute.js +14 -0
  423. package/src/nodes/winnow/reset.js +34 -0
  424. package/src/nodes/winnow/update.js +203 -0
  425. package/src/tools/training/features.js +227 -0
  426. package/src/tools/training/index.js +21 -0
  427. package/src/tools/training/logistic.js +238 -0
  428. package/src/tools/training/metrics.js +126 -0
  429. package/src/tools/training/scale.js +239 -0
  430. package/src/tools/training/validate.js +103 -0
  431. package/src/windowing/count-sliding/create.js +16 -0
  432. package/src/windowing/count-sliding/get-reverse-chronological-index.js +19 -0
  433. package/src/windowing/count-sliding/index.js +6 -0
  434. package/src/windowing/count-sliding/is-not-full.js +5 -0
  435. package/src/windowing/count-sliding/push.js +15 -0
  436. package/src/windowing/count-sliding/reset.js +11 -0
  437. package/src/windowing/count-sliding/size.js +5 -0
  438. package/src/windowing/time-sliding/create.js +25 -0
  439. package/src/windowing/time-sliding/push.js +42 -0
  440. package/CODE_OF_CONDUCT.md +0 -46
  441. package/CONTRIBUTING.md +0 -132
  442. package/docs/.nojekyll +0 -0
  443. package/docs/CONTRIBUTING.md +0 -134
  444. package/docs/README.md +0 -132
  445. package/docs/_coverpage.md +0 -26
  446. package/docs/_media/bg.png +0 -0
  447. package/docs/_media/wink-logo.png +0 -0
  448. package/docs/_navbar.md +0 -14
  449. package/docs/_sidebar.md +0 -2
  450. package/docs/index.html +0 -44
  451. package/eslint.config.js +0 -283
@@ -0,0 +1,261 @@
1
+ // flow/validate.js
2
+
3
+ /**
4
+ * @fileoverview Flow validation without execution.
5
+ *
6
+ * Validates specs, checks node references, verifies trigger targets,
7
+ * verifies that adapters' declared semantic requirements are met by the
8
+ * flow runtime, and reports any configuration errors. Provides fail-fast
9
+ * validation at transpile/load time before runtime execution.
10
+ *
11
+ * Registered emitters/storages arrive as module maps
12
+ * `{ id: adapterModule }` (they used to be bare ID arrays).
13
+ * The IDs are used for the cross-flow target check; the modules
14
+ * are also used to read each adapter's `semanticsRequirement`
15
+ * declaration so that "persistIf needs an assetClass" is a derived
16
+ * fact (driven by the storage adapter's declaration), not a hardcoded
17
+ * rule baked into validate.js.
18
+ */
19
+
20
+ import { validateTriggers } from './validate-triggers.js';
21
+
22
+ /**
23
+ * Validates emitter targets in specs against registered emitters.
24
+ * Ensures all emitIf nodes reference emitters that have been registered.
25
+ *
26
+ * @param {Array} specs - Node specifications
27
+ * @param {Object} registeredEmitters - Map `{ id: adapterModule }` of registered emitters
28
+ * @returns {Array<string>} Array of error messages (empty if valid)
29
+ */
30
+ const validateEmitterTargets = function ( specs, registeredEmitters ) {
31
+ const errors = [];
32
+ const ids = Object.keys( registeredEmitters );
33
+
34
+ for ( let i = 0; i < specs.length; i += 1 ) {
35
+ const spec = specs[ i ];
36
+ if ( spec.nodeType === 'Emit If' && spec.target ) {
37
+ if ( !( spec.target in registeredEmitters ) ) {
38
+ const registeredList = ids.length > 0 ?
39
+ ids.join( ', ' ) :
40
+ 'none';
41
+ errors.push(
42
+ `emitIf '${spec.name}' targets '${spec.target}' but only these emitters are registered: [${registeredList}]`
43
+ );
44
+ }
45
+ }
46
+ }
47
+
48
+ return errors;
49
+ };
50
+
51
+ /**
52
+ * Validates storage targets in specs against registered storages.
53
+ * Ensures all persistIf nodes reference storages that have been registered.
54
+ *
55
+ * @param {Array} specs - Node specifications
56
+ * @param {Object} registeredStorages - Map `{ id: adapterModule }` of registered storages
57
+ * @returns {Array<string>} Array of error messages (empty if valid)
58
+ */
59
+ const validateStorageTargets = function ( specs, registeredStorages ) {
60
+ const errors = [];
61
+ const ids = Object.keys( registeredStorages );
62
+
63
+ for ( let i = 0; i < specs.length; i += 1 ) {
64
+ const spec = specs[ i ];
65
+ if ( spec.nodeType === 'Persist If' && spec.storageName ) {
66
+ if ( !( spec.storageName in registeredStorages ) ) {
67
+ const registeredList = ids.length > 0 ?
68
+ ids.join( ', ' ) :
69
+ 'none';
70
+ errors.push(
71
+ `persistIf '${spec.name}' targets '${spec.storageName}' but only these storages are registered: [${registeredList}]`
72
+ );
73
+ }
74
+ }
75
+ }
76
+
77
+ return errors;
78
+ };
79
+
80
+ /**
81
+ * Walks every registered emitter and storage module; for each adapter
82
+ * that declares `semanticsRequirement.assetClass.required: true`, errors
83
+ * if `assetClass` is null/undefined.
84
+ *
85
+ * Replaces the old hardcoded "persistIf requires .assetClass()" rule.
86
+ * The requirement now lives where it semantically belongs — on the
87
+ * adapter that actually reads the asset class (e.g., QuestDB declares
88
+ * required:true; a future storage that doesn't read semantics declares
89
+ * required:false or no declaration at all).
90
+ *
91
+ * One error per missing-required adapter, naming the adapter and its
92
+ * kind (storage/emitter) so the operator knows what to fix.
93
+ *
94
+ * @param {Object} registeredEmitters - Map `{ id: adapterModule }`
95
+ * @param {Object} registeredStorages - Map `{ id: adapterModule }`
96
+ * @param {Object|null} assetClass - Asset class from runtime, or null
97
+ * @returns {Array<string>} Array of error messages (empty if valid)
98
+ */
99
+ const validateSemanticsRequirements = function ( registeredEmitters, registeredStorages, assetClass ) {
100
+ if ( assetClass ) {
101
+ return [];
102
+ }
103
+
104
+ const errors = [];
105
+
106
+ const checkOne = function ( id, module, kind ) {
107
+ const requirement = module && module.semanticsRequirement;
108
+ if ( requirement && requirement.assetClass && requirement.assetClass.required ) {
109
+ errors.push(
110
+ `${kind} '${id}' declares semanticsRequirement.assetClass.required ` +
111
+ 'but the flow has no .assetClass() — add .assetClass(assetClassDef) before declaring this adapter'
112
+ );
113
+ }
114
+ };
115
+
116
+ const emitterEntries = Object.entries( registeredEmitters );
117
+ for ( let i = 0; i < emitterEntries.length; i += 1 ) {
118
+ const [ id, module ] = emitterEntries[ i ];
119
+ checkOne( id, module, 'emitter' );
120
+ }
121
+
122
+ const storageEntries = Object.entries( registeredStorages );
123
+ for ( let i = 0; i < storageEntries.length; i += 1 ) {
124
+ const [ id, module ] = storageEntries[ i ];
125
+ checkOne( id, module, 'storage' );
126
+ }
127
+
128
+ return errors;
129
+ };
130
+
131
+ /**
132
+ * Validates insightType references in persistIf specs against asset class.
133
+ *
134
+ * Each persistIf insightType must exist in the asset class's insightTypes.
135
+ * The old blanket "persistIf requires .assetClass()" check moved to
136
+ * `validateSemanticsRequirements` (capability-driven). When `assetClass`
137
+ * is null here, that earlier check has already produced its error;
138
+ * this function silently skips the cross-ref to avoid duplicate noise.
139
+ *
140
+ * @param {Array} specs - Node specifications
141
+ * @param {Object|null} assetClass - Asset class from runtime (null if not declared)
142
+ * @returns {Array<string>} Array of error messages (empty if valid)
143
+ */
144
+ const validateInsightTypeReferences = function ( specs, assetClass ) {
145
+ const errors = [];
146
+
147
+ if ( !assetClass ) {
148
+ // Either the flow doesn't need an asset class (no adapter declared
149
+ // `assetClass.required: true` — see validateSemanticsRequirements),
150
+ // or it does and that earlier check already reported the missing
151
+ // .assetClass(). Either way, no useful cross-ref work to do here.
152
+ return errors;
153
+ }
154
+
155
+ const persistIfNodes = [];
156
+ for ( let i = 0; i < specs.length; i += 1 ) {
157
+ const spec = specs[ i ];
158
+ if ( spec.nodeType === 'Persist If' && spec.insightType ) {
159
+ persistIfNodes.push( spec );
160
+ }
161
+ }
162
+
163
+ if ( persistIfNodes.length === 0 ) {
164
+ return errors;
165
+ }
166
+
167
+ const validInsightTypes = Object.keys( assetClass.insightTypes || {} );
168
+ for ( let i = 0; i < persistIfNodes.length; i += 1 ) {
169
+ const spec = persistIfNodes[ i ];
170
+ const insightType = spec.insightType;
171
+
172
+ if ( !validInsightTypes.includes( insightType ) ) {
173
+ const validList = validInsightTypes.length > 0 ?
174
+ validInsightTypes.join( ', ' ) :
175
+ 'none defined';
176
+ errors.push(
177
+ `persistIf '${spec.name}': insightType '${insightType}' not found in ` +
178
+ `asset class '${assetClass.name}' (valid: ${validList})`
179
+ );
180
+ }
181
+ }
182
+
183
+ return errors;
184
+ };
185
+
186
+ /**
187
+ * Validates the flow without executing.
188
+ *
189
+ * `registeredEmitters` / `registeredStorages` are `{ id: adapterModule }`
190
+ * maps (they used to be bare ID arrays; call sites that pass arrays
191
+ * must be updated). Tests that exercise validateFlow directly pass
192
+ * module maps. The IDs are used for cross-flow target validation; the
193
+ * modules are used for capability-driven `semanticsRequirement`
194
+ * checks.
195
+ *
196
+ * @param {string} flowName - Name of the flow
197
+ * @param {Array} specs - Node specifications
198
+ * @param {Object} nodeModules - Map of module name to node module
199
+ * @param {Object} [registeredEmitters={}] - Map `{ id: module }` of registered emitters
200
+ * @param {Object} [registeredStorages={}] - Map `{ id: module }` of registered storages
201
+ * @param {Object|null} [assetClass=null] - Asset class for capability + insightType validation
202
+ * @returns {{valid: boolean, errors: Array<string>}} Validation result
203
+ */
204
+ export const validateFlow = function ( flowName, specs, nodeModules, registeredEmitters = {}, registeredStorages = {}, assetClass = null ) {
205
+ const errors = [];
206
+
207
+ // Phase 1: Trigger validation (R1, R2, R3)
208
+ const triggerResult = validateTriggers( specs, nodeModules );
209
+ if ( !triggerResult.valid ) {
210
+ errors.push( ...triggerResult.errors );
211
+ }
212
+
213
+ // Phase 2: Emitter target validation
214
+ const emitterErrors = validateEmitterTargets( specs, registeredEmitters );
215
+ errors.push( ...emitterErrors );
216
+
217
+ // Phase 3: Storage target validation
218
+ const storageErrors = validateStorageTargets( specs, registeredStorages );
219
+ errors.push( ...storageErrors );
220
+
221
+ // Phase 4: Capability-driven semanticsRequirement check
222
+ // (replaced the hardcoded "persistIf requires .assetClass()" rule)
223
+ const semanticsErrors = validateSemanticsRequirements(
224
+ registeredEmitters,
225
+ registeredStorages,
226
+ assetClass
227
+ );
228
+ errors.push( ...semanticsErrors );
229
+
230
+ // Phase 5: insightType validation against asset class
231
+ const insightTypeErrors = validateInsightTypeReferences( specs, assetClass );
232
+ errors.push( ...insightTypeErrors );
233
+
234
+ return {
235
+ valid: errors.length === 0,
236
+ errors
237
+ };
238
+ };
239
+
240
+ /**
241
+ * Validates flow and throws if invalid.
242
+ * Convenience wrapper for fail-fast validation in pipelines.
243
+ *
244
+ * @param {string} flowName - Name of the flow
245
+ * @param {Array} specs - Node specifications
246
+ * @param {Object} nodeModules - Map of module name to node module
247
+ * @param {Object} [registeredEmitters={}] - Map `{ id: module }` of registered emitters
248
+ * @param {Object} [registeredStorages={}] - Map `{ id: module }` of registered storages
249
+ * @param {Object|null} [assetClass=null] - Asset class for capability + insightType validation
250
+ * @throws {Error} If validation fails
251
+ */
252
+ export const validateFlowOrThrow = function ( flowName, specs, nodeModules, registeredEmitters = {}, registeredStorages = {}, assetClass = null ) {
253
+ const result = validateFlow( flowName, specs, nodeModules, registeredEmitters, registeredStorages, assetClass );
254
+ if ( !result.valid ) {
255
+ const errorList = result.errors.map( ( e ) => ` - ${e}` ).join( '\n' );
256
+ throw new Error(
257
+ `Flow '${flowName}' validation failed:\n${errorList}`
258
+ );
259
+ }
260
+ };
261
+
@@ -0,0 +1,21 @@
1
+ // nodes/accumulate/index.js
2
+
3
+ /**
4
+ * @fileoverview Accumulate node module exports.
5
+ *
6
+ * Simple running sum accumulator for conditional accumulation.
7
+ * Works with controller disable/enable — no embedded predicate needed.
8
+ *
9
+ * @see ADR-004
10
+ */
11
+
12
+ export { default as init } from './init.js';
13
+ export { default as update } from './update.js';
14
+ export { default as reset } from './reset.js';
15
+ export { default as recompute } from './recompute.js';
16
+ export { default as publishTo } from './publish-to.js';
17
+ export { default as disable } from '../../core/utils/node/disable.js';
18
+ export { default as enable } from '../../core/utils/node/enable.js';
19
+ export { default as pause } from '../../core/utils/node/pause.js';
20
+ export { default as unpause } from '../../core/utils/node/unpause.js';
21
+ export * from './introspect.js';
@@ -0,0 +1,48 @@
1
+ // nodes/accumulate/init.js
2
+
3
+ /**
4
+ * @fileoverview Initializes the accumulate node state.
5
+ *
6
+ * Creates state object with running sum initialized to zero.
7
+ * No ring buffer needed — simple accumulation with disable/enable support.
8
+ *
9
+ * @see ADR-004
10
+ */
11
+
12
+ import { validateSpec } from '../../core/utils/node/index.js';
13
+ import * as introspect from './introspect.js';
14
+
15
+ /**
16
+ * Initializes the accumulate node state from a validated spec.
17
+ *
18
+ * @param {Object} spec - Node specification
19
+ * @param {string} spec.name - Unique node identifier
20
+ * @param {Object} spec.from - Input field configuration
21
+ * @param {string} spec.from.x - Input field name for values to accumulate
22
+ * @param {Object} spec.stats - Output statistics configuration
23
+ * @returns {Object} Initialized state object
24
+ */
25
+ const init = function ( spec ) {
26
+ validateSpec( spec, introspect );
27
+
28
+ const state = Object.create( null );
29
+
30
+ // ── Standard Flags ─────────────────────────────────────────────────────
31
+ state.inputValidationFailed = false;
32
+ state.disable = false;
33
+ state.pause = false;
34
+
35
+ // ── Configuration from Spec ────────────────────────────────────────────
36
+ state.x = spec.from.x;
37
+ state.stats = spec.stats;
38
+
39
+ // ── Accumulated Value ──────────────────────────────────────────────────
40
+ state.sum = 0;
41
+
42
+ // ── Metadata ───────────────────────────────────────────────────────────
43
+ state.nodeType = introspect.getNodeType();
44
+
45
+ return state;
46
+ }; // init()
47
+
48
+ export default init;
@@ -0,0 +1,123 @@
1
+ // nodes/accumulate/introspect.js
2
+
3
+ /**
4
+ * @fileoverview Introspection metadata for the accumulate node.
5
+ *
6
+ * Defines supported stats, control methods, capabilities, and DSL schema
7
+ * for a simple running sum accumulator. Works with controller disable/enable
8
+ * for conditional accumulation without embedded predicate.
9
+ *
10
+ * @see ADR-004
11
+ */
12
+
13
+ import { validators } from '../../core/utils/validate/index.js';
14
+
15
+ // ── Supported Statistics ────────────────────────────────────────────────────
16
+
17
+ const SUPPORTED_STATS = [ 'sum' ];
18
+
19
+ const STAT_DESCRIPTIONS = {
20
+ sum: 'Running sum of input values'
21
+ };
22
+
23
+ // ── Control Methods ─────────────────────────────────────────────────────────
24
+
25
+ const SUPPORTED_CONTROL_METHODS = {
26
+ reset: 'Clears accumulated sum to zero',
27
+ enable: 'Enables node processing',
28
+ disable: 'Disables node processing',
29
+ pause: 'Pauses node processing while keeping state visible',
30
+ unpause: 'Resumes node processing after pause'
31
+ };
32
+
33
+ // ── Node Identity ───────────────────────────────────────────────────────────
34
+
35
+ const NODE_TYPE = 'Accumulate';
36
+
37
+ // ── Capabilities ────────────────────────────────────────────────────────────
38
+
39
+ const CAPABILITIES = {
40
+ description: 'Accumulates numeric values into a running sum',
41
+ features: [
42
+ 'Simple running sum (no windowing)',
43
+ 'Works with controller disable/enable for conditional accumulation',
44
+ 'Expects periodic resets — unbounded sum drifts without them',
45
+ 'No ring buffer — no catch-up problem when disabled',
46
+ 'Zero allocation in hot path'
47
+ ]
48
+ };
49
+
50
+ // ── Default Options ─────────────────────────────────────────────────────────
51
+
52
+ const DEFAULT_OPTIONS = {};
53
+
54
+ // ── DSL Metadata ────────────────────────────────────────────────────────────
55
+
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: 'string',
75
+ required: true,
76
+ validator: validators.noSpaces,
77
+ error: 'from.x must not contain spaces'
78
+ }
79
+ }
80
+ },
81
+ stats: {
82
+ type: 'object',
83
+ required: true,
84
+ minProperties: 1,
85
+ propertyNames: SUPPORTED_STATS,
86
+ propertySchema: {
87
+ type: 'object',
88
+ required: true,
89
+ properties: {
90
+ storeAs: {
91
+ type: 'string',
92
+ required: true,
93
+ validator: validators.identifier,
94
+ error: 'storeAs must be a valid identifier'
95
+ }
96
+ }
97
+ }
98
+ }
99
+ },
100
+
101
+ crossFieldValidators: [],
102
+
103
+ buildSpec: ( name, x, stats, options ) => ( {
104
+ nodeType: NODE_TYPE,
105
+ name,
106
+ from: { x },
107
+ stats,
108
+ ...options
109
+ } )
110
+ };
111
+
112
+ // ── Getter Functions (defensive copies) ─────────────────────────────────────
113
+
114
+ export const getSupportedStats = () => SUPPORTED_STATS.slice();
115
+ export const getStatDescriptions = () => ( { ...STAT_DESCRIPTIONS } );
116
+ export const getSupportedControlMethods = () => ( { ...SUPPORTED_CONTROL_METHODS } );
117
+ export const getNodeType = () => NODE_TYPE;
118
+ export const getCapabilities = () => ( {
119
+ ...CAPABILITIES,
120
+ features: CAPABILITIES.features.slice()
121
+ } );
122
+ export { DEFAULT_OPTIONS };
123
+ export const getDSLMetadata = () => ( { ...DSL_METADATA } );
@@ -0,0 +1,34 @@
1
+ // nodes/accumulate/publish-to.js
2
+
3
+ /**
4
+ * @fileoverview Publishes accumulated sum to output message.
5
+ *
6
+ * Copies state.sum to the configured output field. On validation failure,
7
+ * publishes NaN for fault isolation downstream.
8
+ *
9
+ * @see ADR-004
10
+ */
11
+
12
+ import { publishNaN } from '../../core/utils/node/index.js';
13
+
14
+ /**
15
+ * Publishes the accumulated sum to the output message.
16
+ *
17
+ * @param {Object} state - Node state
18
+ * @param {Object} msg - Output message to populate
19
+ */
20
+ const publishTo = function ( state, msg ) {
21
+ // Guard: skip if disabled
22
+ if ( state.disable ) return;
23
+
24
+ // Fault isolation: propagate NaN if input validation failed
25
+ if ( state.inputValidationFailed ) {
26
+ publishNaN( state, msg );
27
+ return;
28
+ }
29
+
30
+ // Publish sum
31
+ msg[ state.stats.sum.storeAs ] = state.sum;
32
+ }; // publishTo()
33
+
34
+ export default publishTo;
@@ -0,0 +1,27 @@
1
+ // nodes/accumulate/recompute.js
2
+
3
+ /**
4
+ * @fileoverview Numerical stability handler for accumulate node.
5
+ *
6
+ * Running sum is numerically stable for bounded accumulation windows —
7
+ * controller resets prevent unbounded drift. Without resets, IEEE 754
8
+ * rounding error grows with the number of additions, and precision
9
+ * degrades when magnitudes vary widely. No recomputation is possible
10
+ * here (no ring buffer to re-sum from), so timely controller resets
11
+ * are essential.
12
+ *
13
+ * @see ADR-004
14
+ */
15
+
16
+ /**
17
+ * Handles numerical stability (no-op — no history buffer to recompute from).
18
+ *
19
+ * @returns {boolean} Always returns true
20
+ */
21
+ const recompute = function () {
22
+ // No-op: controller resets bound the accumulation window.
23
+ // Without resets, sum drifts — but there is no ring buffer to re-sum from.
24
+ return true;
25
+ }; // recompute()
26
+
27
+ export default recompute;
@@ -0,0 +1,25 @@
1
+ // nodes/accumulate/reset.js
2
+
3
+ /**
4
+ * @fileoverview Resets the accumulate node state.
5
+ *
6
+ * Clears accumulated sum to zero. Called by controller triggers
7
+ * to start a new accumulation window.
8
+ *
9
+ * @see ADR-004
10
+ */
11
+
12
+ /**
13
+ * Resets the accumulated sum to zero.
14
+ *
15
+ * @param {Object} state - Node state to reset
16
+ * @returns {boolean} Always returns true (success)
17
+ */
18
+ const reset = function ( state ) {
19
+ // Reset accumulated sum to zero
20
+ state.sum = 0;
21
+
22
+ return true;
23
+ }; // reset()
24
+
25
+ export default reset;
@@ -0,0 +1,42 @@
1
+ // nodes/accumulate/update.js
2
+
3
+ /**
4
+ * @fileoverview Hot path for accumulate node message processing.
5
+ *
6
+ * Simple running sum with zero allocation. When disabled, skips update
7
+ * entirely — sum remains unchanged. No ring buffer, so no catch-up problem
8
+ * when re-enabled after disabled period.
9
+ *
10
+ * @see ADR-004
11
+ */
12
+
13
+ /**
14
+ * Processes a message and accumulates the input value.
15
+ *
16
+ * @param {Object} state - Node state from init()
17
+ * @param {Object} msg - Incoming message with field values
18
+ * @returns {Object} Updated state
19
+ */
20
+ const update = function ( state, msg ) {
21
+ // Guard: skip if disabled or paused
22
+ if ( state.disable || state.pause ) return state;
23
+
24
+ // Extract input value
25
+ const xVal = msg[ state.x ];
26
+
27
+ // Reset health flag
28
+ state.inputValidationFailed = false;
29
+
30
+ // Validate input (catches NaN, Infinity, undefined)
31
+ if ( !Number.isFinite( xVal ) ) {
32
+ state.inputValidationFailed = true;
33
+ return state;
34
+ }
35
+
36
+ // Accumulate
37
+ state.sum += xVal;
38
+
39
+ return state;
40
+ }; // update()
41
+
42
+ export default update;
@@ -0,0 +1,64 @@
1
+ // nodes/appraise/calibrate.js
2
+
3
+ /**
4
+ * @fileoverview Burn-in calibration for the L2 decision neuron's Theta parameter.
5
+ *
6
+ * During warmup, the system observes baseline membrane activity and derives
7
+ * Theta such that steady-state conviction sits at c_target (monitor.at / 3).
8
+ * Uses a deterministic sample count — same pattern as esCorrelation and trend
9
+ * warmup (halfLifeToWarmupSamples equivalent).
10
+ *
11
+ * Formula: Theta = V2 * ( 1 - c_target ) / c_target
12
+ * When V2 = 0 at warmup end, Theta defaults to 1.0 (conservative fallback).
13
+ */
14
+
15
+ /**
16
+ * Computes the number of warmup messages needed for calibration.
17
+ * Five L2 time constants ensures the membrane has reached steady-state
18
+ * (~99.3% settled).
19
+ *
20
+ * @param {number} l2Tau - L2 time constant tau2
21
+ * @param {number} messageRate - Messages per timestamp unit
22
+ * @returns {number} Warmup sample count (integer >= 1)
23
+ */
24
+ const computeWarmupSamples = function ( l2Tau, messageRate ) {
25
+ return Math.max( 1, Math.ceil( 5 * l2Tau * messageRate ) );
26
+ }; // computeWarmupSamples()
27
+
28
+ /**
29
+ * Derives the calibration target conviction from the monitor threshold.
30
+ * Steady-state baseline should sit at one-third of the monitor threshold —
31
+ * close enough for sensitivity, far enough to avoid false triggers.
32
+ *
33
+ * @param {number} monitorAt - Monitor threshold value
34
+ * @returns {number} c_target in (0, 1)
35
+ */
36
+ const deriveCTarget = function ( monitorAt ) {
37
+ return monitorAt / 3;
38
+ }; // deriveCTarget()
39
+
40
+ /**
41
+ * Checks whether calibration is complete and derives Theta if so.
42
+ * Called once per message during the warmup phase. No-op before
43
+ * the warmup boundary, no-op after calibration is complete.
44
+ *
45
+ * @param {Object} state - Node state (mutated: l2Theta, calibrating)
46
+ */
47
+ const checkCalibration = function ( state ) {
48
+ if ( state.messageCount < state.warmupSamples ) return;
49
+
50
+ // Derive Theta from observed steady-state membrane potential
51
+ const v2 = state.l2Membrane;
52
+
53
+ if ( v2 <= 0 ) {
54
+ // No activity during warmup — use conservative default
55
+ state.l2Theta = 1.0;
56
+ } else {
57
+ // Theta = V2 * ( 1 - c_target ) / c_target
58
+ state.l2Theta = v2 * ( ( 1 - state.cTarget ) / state.cTarget );
59
+ }
60
+
61
+ state.calibrating = false;
62
+ }; // checkCalibration()
63
+
64
+ export { computeWarmupSamples, deriveCTarget, checkCalibration };