yakmesh 2.8.2 → 3.0.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 (232) hide show
  1. package/CHANGELOG.md +637 -0
  2. package/CONTRIBUTING.md +42 -0
  3. package/Caddyfile +77 -0
  4. package/README.md +119 -29
  5. package/adapters/adapter-mlv-bible/README.md +124 -0
  6. package/adapters/adapter-mlv-bible/index.js +400 -0
  7. package/adapters/chat-mod-adapter.js +532 -0
  8. package/adapters/content-adapter.js +273 -0
  9. package/content/api.js +50 -41
  10. package/content/index.js +2 -2
  11. package/content/store.js +355 -173
  12. package/dashboard/index.html +19 -3
  13. package/database/replication.js +117 -37
  14. package/docs/CRYPTO-AGILITY.md +204 -0
  15. package/docs/MTLS-RESEARCH.md +367 -0
  16. package/docs/NAMCHE-SPEC.md +681 -0
  17. package/docs/PEERQUANTA-YAKMESH-INTEGRATION.md +407 -0
  18. package/docs/PRECISION-DISCLOSURE.md +96 -0
  19. package/docs/README.md +76 -0
  20. package/docs/ROADMAP-2.4.0.md +447 -0
  21. package/docs/ROADMAP-2.5.0.md +244 -0
  22. package/docs/SECURITY-AUDIT-REPORT.md +306 -0
  23. package/docs/SST-INTEGRATION.md +712 -0
  24. package/docs/STEADYWATCH-IMPLEMENTATION.md +303 -0
  25. package/docs/TERNARY-AUDIT-REPORT.md +247 -0
  26. package/docs/TME-FAQ.md +221 -0
  27. package/docs/WHITEPAPER.md +623 -0
  28. package/docs/adapters.html +1001 -0
  29. package/docs/advanced-systems.html +1045 -0
  30. package/docs/annex.html +1046 -0
  31. package/docs/api.html +970 -0
  32. package/docs/business/response-templates.md +160 -0
  33. package/docs/c2c.html +1225 -0
  34. package/docs/cli.html +1332 -0
  35. package/docs/configuration.html +1248 -0
  36. package/docs/darshan.html +1085 -0
  37. package/docs/dharma.html +966 -0
  38. package/docs/docs-bundle.html +1075 -0
  39. package/docs/docs.css +3120 -0
  40. package/docs/docs.js +556 -0
  41. package/docs/doko.html +969 -0
  42. package/docs/geo-proof.html +858 -0
  43. package/docs/getting-started.html +840 -0
  44. package/docs/gumba-tutorial.html +1144 -0
  45. package/docs/gumba.html +1098 -0
  46. package/docs/index.html +914 -0
  47. package/docs/jhilke.html +1312 -0
  48. package/docs/karma.html +1100 -0
  49. package/docs/katha.html +1037 -0
  50. package/docs/lama.html +978 -0
  51. package/docs/mandala.html +1067 -0
  52. package/docs/mani.html +964 -0
  53. package/docs/mantra.html +967 -0
  54. package/docs/mesh.html +1409 -0
  55. package/docs/nakpak.html +869 -0
  56. package/docs/namche.html +928 -0
  57. package/docs/nav-order.json +53 -0
  58. package/docs/prahari.html +1043 -0
  59. package/docs/prism-bash.min.js +1 -0
  60. package/docs/prism-javascript.min.js +1 -0
  61. package/docs/prism-json.min.js +1 -0
  62. package/docs/prism-tomorrow.min.css +1 -0
  63. package/docs/prism.min.js +1 -0
  64. package/docs/privacy.html +699 -0
  65. package/docs/quick-reference.html +1181 -0
  66. package/docs/sakshi.html +1402 -0
  67. package/docs/sandboxing.md +386 -0
  68. package/docs/seva.html +911 -0
  69. package/docs/sherpa.html +871 -0
  70. package/docs/studio.html +860 -0
  71. package/docs/stupa.html +995 -0
  72. package/docs/tailwind.min.css +2 -0
  73. package/docs/tattva.html +1332 -0
  74. package/docs/terms.html +686 -0
  75. package/docs/time-server-deployment.md +166 -0
  76. package/docs/time-sources.html +1392 -0
  77. package/docs/tivra.html +1127 -0
  78. package/docs/trademark-policy.html +686 -0
  79. package/docs/tribhuj.html +1183 -0
  80. package/docs/trust-security.html +1029 -0
  81. package/docs/tutorials/backup-recovery.html +654 -0
  82. package/docs/tutorials/dashboard.html +604 -0
  83. package/docs/tutorials/domain-setup.html +605 -0
  84. package/docs/tutorials/host-website.html +456 -0
  85. package/docs/tutorials/mesh-network.html +505 -0
  86. package/docs/tutorials/mobile-access.html +445 -0
  87. package/docs/tutorials/privacy.html +467 -0
  88. package/docs/tutorials/raspberry-pi.html +600 -0
  89. package/docs/tutorials/security-basics.html +539 -0
  90. package/docs/tutorials/share-files.html +431 -0
  91. package/docs/tutorials/troubleshooting.html +637 -0
  92. package/docs/tutorials/trust-karma.html +419 -0
  93. package/docs/tutorials/yak-protocol.html +456 -0
  94. package/docs/tutorials.html +1034 -0
  95. package/docs/vani.html +1270 -0
  96. package/docs/webserver.html +809 -0
  97. package/docs/yak-protocol.html +940 -0
  98. package/docs/yak-timeserver-design.md +475 -0
  99. package/docs/yakapp.html +1015 -0
  100. package/docs/ypc27.html +1069 -0
  101. package/docs/yurt.html +1344 -0
  102. package/embedded-docs/bundle.js +334 -74
  103. package/gossip/protocol.js +247 -27
  104. package/identity/key-resolver.js +262 -0
  105. package/identity/machine-seed.js +632 -0
  106. package/identity/node-key.js +669 -368
  107. package/identity/tribhuj-ratchet.js +506 -0
  108. package/knowledge-base.js +37 -8
  109. package/launcher/yakmesh.bat +62 -0
  110. package/launcher/yakmesh.sh +70 -0
  111. package/mesh/annex.js +462 -108
  112. package/mesh/beacon-broadcast.js +113 -1
  113. package/mesh/darshan.js +1718 -0
  114. package/mesh/gumba.js +1567 -0
  115. package/mesh/jhilke.js +651 -0
  116. package/mesh/katha.js +1012 -0
  117. package/mesh/nakpak-routing.js +8 -5
  118. package/mesh/network.js +724 -34
  119. package/mesh/pulse-sync.js +4 -1
  120. package/mesh/rate-limiter.js +127 -15
  121. package/mesh/seva.js +526 -0
  122. package/mesh/sherpa-discovery.js +89 -8
  123. package/mesh/sybil-defense.js +19 -5
  124. package/mesh/temporal-encoder.js +4 -3
  125. package/mesh/vani.js +1364 -0
  126. package/mesh/yurt.js +1340 -0
  127. package/models/entropy-sentinel.onnx +0 -0
  128. package/models/karma-trust.onnx +0 -0
  129. package/models/manifest.json +43 -0
  130. package/models/sakshi-anomaly.onnx +0 -0
  131. package/oracle/code-proof-protocol.js +7 -6
  132. package/oracle/codebase-lock.js +257 -28
  133. package/oracle/index.js +74 -15
  134. package/oracle/ma902-snmp.js +678 -0
  135. package/oracle/module-sealer.js +5 -3
  136. package/oracle/network-identity.js +16 -0
  137. package/oracle/packet-checksum.js +201 -0
  138. package/oracle/sst.js +579 -0
  139. package/oracle/ternary-144t.js +714 -0
  140. package/oracle/ternary-ml.js +481 -0
  141. package/oracle/time-api.js +239 -0
  142. package/oracle/time-source.js +137 -47
  143. package/oracle/validation-oracle-hardened.js +1111 -1071
  144. package/oracle/validation-oracle.js +4 -2
  145. package/oracle/ypc27.js +211 -0
  146. package/package.json +20 -3
  147. package/protocol/yak-handler.js +35 -9
  148. package/protocol/yak-protocol.js +28 -13
  149. package/reference/cpp/yakmesh_mceliece_shard.cpp +168 -0
  150. package/reference/cpp/yakmesh_ypc27.cpp +179 -0
  151. package/sbom.json +87 -0
  152. package/scripts/security-audit.mjs +264 -0
  153. package/scripts/update-docs-nav.js +194 -0
  154. package/scripts/update-docs-sidebar.cjs +164 -0
  155. package/security/crypto-config.js +4 -3
  156. package/security/dharma-moderation.js +517 -0
  157. package/security/doko-identity.js +193 -143
  158. package/security/domain-consensus.js +86 -85
  159. package/security/fs-hardening.js +620 -0
  160. package/security/hardware-attestation.js +5 -3
  161. package/security/hybrid-trust.js +227 -87
  162. package/security/karma-rate-limiter.js +692 -0
  163. package/security/khata-protocol.js +22 -21
  164. package/security/khata-trust-integration.js +277 -150
  165. package/security/memory-safety.js +635 -0
  166. package/security/mesh-auth.js +11 -10
  167. package/security/mesh-revocation.js +373 -5
  168. package/security/namche-gateway.js +298 -69
  169. package/security/sakshi.js +460 -3
  170. package/security/sangha.js +770 -0
  171. package/security/secure-config.js +473 -0
  172. package/security/silicon-parity.js +13 -10
  173. package/security/steadywatch.js +1142 -0
  174. package/security/strike-system.js +32 -3
  175. package/security/temporal-signing.js +488 -0
  176. package/security/trit-commitment.js +464 -0
  177. package/server/crypto/annex.js +247 -0
  178. package/server/darshan-api.js +343 -0
  179. package/server/index.js +3259 -362
  180. package/server/komm-api.js +668 -0
  181. package/utils/accel.js +2273 -0
  182. package/utils/ternary-id.js +79 -0
  183. package/utils/verify-worker.js +57 -0
  184. package/webserver/index.js +95 -5
  185. package/assets/yakmesh-logo.png +0 -0
  186. package/assets/yakmesh-logo.svg +0 -80
  187. package/assets/yakmesh-logo2.png +0 -0
  188. package/assets/yakmesh-logo2sm.png +0 -0
  189. package/assets/ymsm.png +0 -0
  190. package/website/assets/silhouettes/adapters.svg +0 -107
  191. package/website/assets/silhouettes/api-endpoints.svg +0 -115
  192. package/website/assets/silhouettes/atomic-clock.svg +0 -83
  193. package/website/assets/silhouettes/base-camp.svg +0 -81
  194. package/website/assets/silhouettes/bridge.svg +0 -69
  195. package/website/assets/silhouettes/docs-bundle.svg +0 -113
  196. package/website/assets/silhouettes/doko-basket.svg +0 -70
  197. package/website/assets/silhouettes/fortress.svg +0 -93
  198. package/website/assets/silhouettes/gateway.svg +0 -54
  199. package/website/assets/silhouettes/gears.svg +0 -93
  200. package/website/assets/silhouettes/globe-satellite.svg +0 -67
  201. package/website/assets/silhouettes/karma-wheel.svg +0 -137
  202. package/website/assets/silhouettes/lama-council.svg +0 -141
  203. package/website/assets/silhouettes/mandala-network.svg +0 -169
  204. package/website/assets/silhouettes/mani-stones.svg +0 -149
  205. package/website/assets/silhouettes/mantra-wheel.svg +0 -116
  206. package/website/assets/silhouettes/mesh-nodes.svg +0 -113
  207. package/website/assets/silhouettes/nakpak.svg +0 -56
  208. package/website/assets/silhouettes/peak-lightning.svg +0 -73
  209. package/website/assets/silhouettes/sherpa.svg +0 -69
  210. package/website/assets/silhouettes/stupa-tower.svg +0 -119
  211. package/website/assets/silhouettes/tattva-eye.svg +0 -78
  212. package/website/assets/silhouettes/terminal.svg +0 -74
  213. package/website/assets/silhouettes/webserver.svg +0 -145
  214. package/website/assets/silhouettes/yak.svg +0 -78
  215. package/website/assets/yakmesh-logo.png +0 -0
  216. package/website/assets/yakmesh-logo.webp +0 -0
  217. package/website/assets/yakmesh-logo128x140.webp +0 -0
  218. package/website/assets/yakmesh-logo2.png +0 -0
  219. package/website/assets/yakmesh-logo2.svg +0 -51
  220. package/website/assets/yakmesh-logo40x44.webp +0 -0
  221. package/website/assets/yakmesh.gif +0 -0
  222. package/website/assets/yakmesh.ico +0 -0
  223. package/website/assets/yakmesh.jpg +0 -0
  224. package/website/assets/yakmesh.pdf +0 -0
  225. package/website/assets/yakmesh.png +0 -0
  226. package/website/assets/yakmesh.svg +0 -70
  227. package/website/assets/yakmesh128.webp +0 -0
  228. package/website/assets/yakmesh32.png +0 -0
  229. package/website/assets/yakmesh32.svg +0 -65
  230. package/website/assets/yakmesh32o.ico +0 -2
  231. package/website/assets/yakmesh32o.svg +0 -65
  232. package/website/assets/yakmesh32o.svgz +0 -0
@@ -0,0 +1,481 @@
1
+ /**
2
+ * TERNARY-ML — Balanced Ternary Quantization for ML Inference
3
+ *
4
+ * Bridges TRIBHUJ balanced ternary algebra with ONNX ML inference via
5
+ * the ACCEL hardware acceleration layer. Provides:
6
+ *
7
+ * 1. Ternary quantization of float features → {-1, 0, +1} trits
8
+ * 2. SST family-aware feature encoding (digital root → family → trit)
9
+ * 3. TernaryInferenceAdapter for routing ternary-quantized data through NPU/GPU
10
+ * 4. Trust-aware consensus scoring using ternary majority logic
11
+ *
12
+ * Why ternary quantization for YAKMESH ML?
13
+ * - AMD XDNA NPU operates on INT8 but ternary {-1,0,+1} maps directly to it
14
+ * - Reduces feature space from float32 to 2 bits (ternary) per feature
15
+ * - Natural alignment with KARMA trust scores (DISTRUST/UNVERIFIED/TRUST)
16
+ * - SAKSHI anomaly detection benefits from 3-state classification
17
+ * - The 3^N state space prevents gradient-based adversarial attacks
18
+ *
19
+ * Integration:
20
+ * TRIBHUJ (algebra) → TERNARY-ML (quantization) → ACCEL (hardware)
21
+ * SST (family mapping) → TERNARY-ML (feature encoding) → ONNX (inference)
22
+ *
23
+ * @module oracle/ternary-ml
24
+ * @license MIT
25
+ * @copyright 2026 YAKMESH™ Contributors
26
+ */
27
+
28
+ import { Trit, TritArray, POSITIVE, NEUTRAL, NEGATIVE, TritState } from './tribhuj.js';
29
+ import { toFamilyTrit, getFamilyOf, SSTFamily, digitalRoot } from './sst.js';
30
+
31
+ // =============================================================================
32
+ // TERNARY QUANTIZATION
33
+ // =============================================================================
34
+
35
+ /**
36
+ * Quantize a float value to a balanced trit {-1, 0, +1}.
37
+ *
38
+ * Uses a dead-zone around zero to prevent noise from creating false signals:
39
+ * value < -threshold → NEGATIVE (-1)
40
+ * -threshold ≤ value ≤ +threshold → NEUTRAL (0)
41
+ * value > +threshold → POSITIVE (+1)
42
+ *
43
+ * @param {number} value — float value to quantize
44
+ * @param {number} [threshold=0.33] — dead-zone radius
45
+ * @returns {number} — trit value {-1, 0, +1}
46
+ */
47
+ export function quantizeToTrit(value, threshold = 0.33) {
48
+ if (value < -threshold) return NEGATIVE;
49
+ if (value > threshold) return POSITIVE;
50
+ return NEUTRAL;
51
+ }
52
+
53
+ /**
54
+ * Quantize a float array to balanced trits.
55
+ *
56
+ * @param {Float32Array | number[]} values — float values
57
+ * @param {number} [threshold=0.33] — dead-zone radius
58
+ * @returns {Int8Array} — trit values
59
+ */
60
+ export function quantizeArray(values, threshold = 0.33) {
61
+ const trits = new Int8Array(values.length);
62
+ for (let i = 0; i < values.length; i++) {
63
+ trits[i] = quantizeToTrit(values[i], threshold);
64
+ }
65
+ return trits;
66
+ }
67
+
68
+ /**
69
+ * Adaptive quantization — threshold derived from data statistics.
70
+ *
71
+ * Computes mean and standard deviation, then uses:
72
+ * threshold = max(minThreshold, sigma * factor)
73
+ *
74
+ * This prevents the dead-zone from being too narrow (noise)
75
+ * or too wide (losing signal).
76
+ *
77
+ * @param {Float32Array | number[]} values
78
+ * @param {number} [factor=0.5] — sigma multiplier
79
+ * @param {number} [minThreshold=0.1] — absolute minimum
80
+ * @returns {{ trits: Int8Array, threshold: number, mean: number, sigma: number }}
81
+ */
82
+ export function adaptiveQuantize(values, factor = 0.5, minThreshold = 0.1) {
83
+ const n = values.length;
84
+ if (n === 0) return { trits: new Int8Array(0), threshold: 0, mean: 0, sigma: 0 };
85
+
86
+ // Compute mean
87
+ let sum = 0;
88
+ for (let i = 0; i < n; i++) sum += values[i];
89
+ const mean = sum / n;
90
+
91
+ // Compute standard deviation
92
+ let sqDiffSum = 0;
93
+ for (let i = 0; i < n; i++) {
94
+ const diff = values[i] - mean;
95
+ sqDiffSum += diff * diff;
96
+ }
97
+ const sigma = Math.sqrt(sqDiffSum / n);
98
+
99
+ // Adaptive threshold
100
+ const threshold = Math.max(minThreshold, sigma * factor);
101
+
102
+ // Center and quantize
103
+ const trits = new Int8Array(n);
104
+ for (let i = 0; i < n; i++) {
105
+ trits[i] = quantizeToTrit(values[i] - mean, threshold);
106
+ }
107
+
108
+ return { trits, threshold, mean, sigma };
109
+ }
110
+
111
+ /**
112
+ * Dequantize trits back to float approximation.
113
+ * Uses mean and threshold from the quantization step.
114
+ *
115
+ * @param {Int8Array} trits
116
+ * @param {number} mean — original mean
117
+ * @param {number} threshold — quantization threshold
118
+ * @returns {Float32Array} — reconstructed approximation
119
+ */
120
+ export function dequantizeTrits(trits, mean = 0, threshold = 0.33) {
121
+ const values = new Float32Array(trits.length);
122
+ for (let i = 0; i < trits.length; i++) {
123
+ values[i] = mean + trits[i] * threshold;
124
+ }
125
+ return values;
126
+ }
127
+
128
+ // =============================================================================
129
+ // SST FAMILY FEATURE ENCODING
130
+ // =============================================================================
131
+
132
+ /**
133
+ * Encode numeric features using SST family classification.
134
+ *
135
+ * Each feature value is mapped through:
136
+ * value → digitalRoot → family → trit
137
+ *
138
+ * This creates a "harmonic fingerprint" of the feature vector
139
+ * where the 3-6-9 governing family acts as natural clustering.
140
+ *
141
+ * Use cases:
142
+ * - Node ID classification for routing
143
+ * - Trust score family grouping
144
+ * - Anomaly detection (unusual family distribution)
145
+ *
146
+ * @param {number[]} features — numeric feature values (integers)
147
+ * @returns {{ trits: Int8Array, families: string[], roots: number[] }}
148
+ */
149
+ export function sstEncodeFeatures(features) {
150
+ const n = features.length;
151
+ const trits = new Int8Array(n);
152
+ const families = new Array(n);
153
+ const roots = new Array(n);
154
+
155
+ for (let i = 0; i < n; i++) {
156
+ const val = Math.abs(Math.floor(features[i]));
157
+ roots[i] = digitalRoot(val);
158
+ families[i] = getFamilyOf(val);
159
+ trits[i] = toFamilyTrit(val).value;
160
+ }
161
+
162
+ return { trits, families, roots };
163
+ }
164
+
165
+ /**
166
+ * Compute the family balance of encoded features.
167
+ * A balanced distribution (roughly equal A, B, C) indicates
168
+ * normal/healthy data. Skew indicates anomaly.
169
+ *
170
+ * @param {string[]} families — array of 'A', 'B', 'C'
171
+ * @returns {{ a: number, b: number, c: number, balance: number, isBalanced: boolean }}
172
+ */
173
+ export function familyBalance(families) {
174
+ let a = 0, b = 0, c = 0;
175
+ for (const f of families) {
176
+ if (f === SSTFamily.A) a++;
177
+ else if (f === SSTFamily.B) b++;
178
+ else c++;
179
+ }
180
+
181
+ const n = families.length || 1;
182
+ const expected = n / 3;
183
+
184
+ // Chi-squared-like balance metric (0 = perfect balance, higher = more skewed)
185
+ const balance = Math.sqrt(
186
+ Math.pow(a - expected, 2) +
187
+ Math.pow(b - expected, 2) +
188
+ Math.pow(c - expected, 2)
189
+ ) / expected;
190
+
191
+ return {
192
+ a, b, c,
193
+ balance: +balance.toFixed(4),
194
+ isBalanced: balance < 1.0, // Within 1 standard deviation
195
+ };
196
+ }
197
+
198
+ // =============================================================================
199
+ // TERNARY FEATURE VECTOR (for ONNX model input)
200
+ // =============================================================================
201
+
202
+ /**
203
+ * Build a ternary feature vector suitable for ONNX model input.
204
+ *
205
+ * Packs multiple signal channels into a single vector:
206
+ * 1. Adaptive-quantized raw features (captures signal direction)
207
+ * 2. SST family encoding (captures harmonic structure)
208
+ * 3. Family balance metrics (captures distribution health)
209
+ *
210
+ * The result is a Float32Array ready for ONNX Tensor creation.
211
+ * Values are in {-1, 0, +1} but typed as float32 for ONNX compatibility.
212
+ *
213
+ * @param {Float32Array | number[]} rawFeatures — original float features
214
+ * @param {Object} [options]
215
+ * @param {number} [options.quantThreshold=0.33] — fixed threshold (0 = adaptive)
216
+ * @param {boolean} [options.includeSST=true] — include SST family channel
217
+ * @param {boolean} [options.includeBalance=true] — include balance metrics
218
+ * @returns {{ vector: Float32Array, channels: Object, dimensions: number }}
219
+ */
220
+ export function buildTernaryFeatureVector(rawFeatures, options = {}) {
221
+ const {
222
+ quantThreshold = 0, // 0 means adaptive
223
+ includeSST = true,
224
+ includeBalance = true,
225
+ } = options;
226
+
227
+ // Channel 1: Adaptive quantization of raw float features
228
+ const quant = quantThreshold > 0
229
+ ? { trits: quantizeArray(rawFeatures, quantThreshold), threshold: quantThreshold, mean: 0, sigma: 0 }
230
+ : adaptiveQuantize(rawFeatures);
231
+
232
+ // Channel 2: SST family encoding (if features are interpretable as integers)
233
+ let sstTrits = null;
234
+ let balance = null;
235
+ if (includeSST) {
236
+ const encoded = sstEncodeFeatures(Array.from(rawFeatures).map(v => Math.round(Math.abs(v * 1000))));
237
+ sstTrits = encoded.trits;
238
+ if (includeBalance) {
239
+ balance = familyBalance(encoded.families);
240
+ }
241
+ }
242
+
243
+ // Assemble the vector
244
+ const channels = {
245
+ quantized: quant.trits,
246
+ sst: sstTrits,
247
+ balance,
248
+ };
249
+
250
+ // Calculate total dimensions
251
+ let dimensions = quant.trits.length;
252
+ if (sstTrits) dimensions += sstTrits.length;
253
+ if (balance) dimensions += 3; // a_ratio, b_ratio, c_ratio as trits
254
+
255
+ // Pack into Float32Array for ONNX compatibility
256
+ const vector = new Float32Array(dimensions);
257
+ let offset = 0;
258
+
259
+ // Write quantized channel
260
+ for (let i = 0; i < quant.trits.length; i++) {
261
+ vector[offset++] = quant.trits[i];
262
+ }
263
+
264
+ // Write SST channel
265
+ if (sstTrits) {
266
+ for (let i = 0; i < sstTrits.length; i++) {
267
+ vector[offset++] = sstTrits[i];
268
+ }
269
+ }
270
+
271
+ // Write balance as ternary indicators
272
+ if (balance) {
273
+ const n = rawFeatures.length || 1;
274
+ vector[offset++] = quantizeToTrit((balance.a / n) - (1/3), 0.1);
275
+ vector[offset++] = quantizeToTrit((balance.b / n) - (1/3), 0.1);
276
+ vector[offset++] = quantizeToTrit((balance.c / n) - (1/3), 0.1);
277
+ }
278
+
279
+ return { vector, channels, dimensions };
280
+ }
281
+
282
+ // =============================================================================
283
+ // TERNARY INFERENCE ADAPTER
284
+ // =============================================================================
285
+
286
+ /**
287
+ * TernaryInferenceAdapter — Routes ternary-quantized features through
288
+ * the ACCEL inference engine (NPU → GPU → CPU).
289
+ *
290
+ * This adapter sits between the ternary quantization layer and the
291
+ * ONNX models, providing:
292
+ * - Ternary feature encoding
293
+ * - Model-specific input formatting
294
+ * - Output trit classification
295
+ * - Consensus-based multi-model voting
296
+ *
297
+ * The adapter does NOT load models itself — it delegates to the
298
+ * shared inference engine from accel.js.
299
+ */
300
+ export class TernaryInferenceAdapter {
301
+ /**
302
+ * @param {Object} inferenceEngine — accel.inference singleton
303
+ */
304
+ constructor(inferenceEngine) {
305
+ this._engine = inferenceEngine;
306
+ this._stats = {
307
+ totalInferences: 0,
308
+ ternaryInputs: 0,
309
+ consensusVotes: 0,
310
+ };
311
+ }
312
+
313
+ /**
314
+ * Run ternary-quantized inference on a named model.
315
+ *
316
+ * @param {string} modelName — model loaded in inference engine
317
+ * @param {Float32Array | number[]} rawFeatures — raw float features
318
+ * @param {Object} [options]
319
+ * @param {boolean} [options.ternaryOutput=true] — quantize output to trits
320
+ * @param {number} [options.outputThreshold=0.33] — output quantization threshold
321
+ * @returns {Promise<{output: Float32Array|null, trits: Int8Array|null, raw: Object|null}>}
322
+ */
323
+ async infer(modelName, rawFeatures, options = {}) {
324
+ const { ternaryOutput = true, outputThreshold = 0.33 } = options;
325
+
326
+ if (!this._engine || !this._engine.hasModel(modelName)) {
327
+ return { output: null, trits: null, raw: null };
328
+ }
329
+
330
+ // Build ternary feature vector
331
+ const { vector } = buildTernaryFeatureVector(rawFeatures);
332
+
333
+ this._stats.totalInferences++;
334
+ this._stats.ternaryInputs++;
335
+
336
+ // Run through ONNX via accel.inference
337
+ const raw = await this._engine.infer(modelName, { input: vector });
338
+
339
+ if (!raw) {
340
+ return { output: null, trits: null, raw: null };
341
+ }
342
+
343
+ // Extract primary output
344
+ const outputKey = Object.keys(raw)[0];
345
+ const output = raw[outputKey];
346
+
347
+ // Optionally quantize output to trits
348
+ const trits = ternaryOutput ? quantizeArray(output, outputThreshold) : null;
349
+
350
+ return { output, trits, raw };
351
+ }
352
+
353
+ /**
354
+ * Run ternary consensus across multiple model outputs.
355
+ *
356
+ * Each model votes with its ternary output, and the final result
357
+ * uses TRIBHUJ majority logic — if no majority, NEUTRAL wins.
358
+ * This is inherently Byzantine-fault tolerant: a single compromised
359
+ * model can't override the consensus.
360
+ *
361
+ * @param {string[]} modelNames — models to query
362
+ * @param {Float32Array | number[]} rawFeatures — shared input
363
+ * @param {Object} [options] — per-model inference options
364
+ * @returns {Promise<{consensus: Int8Array, votes: Int8Array[], models: string[]}>}
365
+ */
366
+ async consensusInfer(modelNames, rawFeatures, options = {}) {
367
+ const votes = [];
368
+ const activeModels = [];
369
+
370
+ // Collect votes from all available models
371
+ for (const name of modelNames) {
372
+ const result = await this.infer(name, rawFeatures, { ternaryOutput: true, ...options });
373
+ if (result.trits) {
374
+ votes.push(result.trits);
375
+ activeModels.push(name);
376
+ }
377
+ }
378
+
379
+ this._stats.consensusVotes++;
380
+
381
+ if (votes.length === 0) {
382
+ return { consensus: null, votes: [], models: [] };
383
+ }
384
+
385
+ // Compute element-wise majority using TRIBHUJ
386
+ const outputLen = votes[0].length;
387
+ const consensus = new Int8Array(outputLen);
388
+
389
+ for (let i = 0; i < outputLen; i++) {
390
+ // Collect votes for this output position
391
+ const posVotes = votes.map(v => v[i] || 0);
392
+ const arr = new TritArray(posVotes);
393
+ consensus[i] = arr.majority().value;
394
+ }
395
+
396
+ return { consensus, votes, models: activeModels };
397
+ }
398
+
399
+ /**
400
+ * Classify a trust score using ternary quantization.
401
+ * Maps KARMA-style trust to the three-state TRIBHUJ representation.
402
+ *
403
+ * @param {number} trustScore — 0.0 to 1.0
404
+ * @returns {{ trit: number, state: string, confidence: number }}
405
+ */
406
+ classifyTrust(trustScore) {
407
+ // Map trust to balanced range [-1, +1]
408
+ const balanced = (trustScore * 2) - 1;
409
+
410
+ // Quantize with adaptive threshold
411
+ const trit = quantizeToTrit(balanced, 0.33);
412
+
413
+ // Confidence is distance from decision boundary
414
+ const confidence = Math.abs(balanced) > 0.33
415
+ ? Math.min(1, (Math.abs(balanced) - 0.33) / 0.67)
416
+ : 0;
417
+
418
+ const stateMap = {
419
+ [NEGATIVE]: TritState.DISTRUST,
420
+ [NEUTRAL]: TritState.UNVERIFIED,
421
+ [POSITIVE]: TritState.TRUST,
422
+ };
423
+
424
+ return {
425
+ trit,
426
+ state: trit === NEGATIVE ? 'DISTRUST' : trit === POSITIVE ? 'TRUST' : 'UNVERIFIED',
427
+ confidence: +confidence.toFixed(3),
428
+ };
429
+ }
430
+
431
+ /**
432
+ * Detect anomalies using ternary family balance.
433
+ *
434
+ * A healthy feature distribution has roughly equal A/B/C families.
435
+ * Significant skew indicates potential anomaly.
436
+ *
437
+ * @param {Float32Array | number[]} features
438
+ * @param {number} [anomalyThreshold=1.5] — balance score above this = anomaly
439
+ * @returns {{ isAnomaly: boolean, balanceScore: number, distribution: Object }}
440
+ */
441
+ detectFamilyAnomaly(features, anomalyThreshold = 1.5) {
442
+ const encoded = sstEncodeFeatures(
443
+ Array.from(features).map(v => Math.round(Math.abs(v * 1000)))
444
+ );
445
+ const balance = familyBalance(encoded.families);
446
+
447
+ return {
448
+ isAnomaly: balance.balance > anomalyThreshold,
449
+ balanceScore: balance.balance,
450
+ distribution: { a: balance.a, b: balance.b, c: balance.c },
451
+ };
452
+ }
453
+
454
+ /**
455
+ * Get adapter statistics.
456
+ * @returns {Object}
457
+ */
458
+ getStats() {
459
+ return { ...this._stats };
460
+ }
461
+ }
462
+
463
+ // =============================================================================
464
+ // EXPORTS
465
+ // =============================================================================
466
+
467
+ export default {
468
+ // Quantization
469
+ quantizeToTrit,
470
+ quantizeArray,
471
+ adaptiveQuantize,
472
+ dequantizeTrits,
473
+
474
+ // SST Feature Encoding
475
+ sstEncodeFeatures,
476
+ familyBalance,
477
+ buildTernaryFeatureVector,
478
+
479
+ // Inference Adapter
480
+ TernaryInferenceAdapter,
481
+ };