@vib3code/sdk 2.0.3-canary.6f35b4c → 2.0.3-canary.74aebb4

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 (89) hide show
  1. package/DOCS/EXPANSION_DESIGN.md +977 -0
  2. package/DOCS/EXPANSION_DESIGN_ULTRA.md +387 -0
  3. package/DOCS/MASTER_PLAN_2026-01-31.md +2 -2
  4. package/DOCS/OPTIMIZATION_PLAN_MATH.md +118 -0
  5. package/DOCS/SYSTEM_INVENTORY.md +2 -2
  6. package/DOCS/WEBGPU_STATUS.md +119 -38
  7. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +38 -0
  8. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +142 -0
  9. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +108 -0
  10. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +308 -0
  11. package/docs/webgpu-live.html +1 -1
  12. package/package.json +10 -1
  13. package/src/agent/index.js +1 -3
  14. package/src/agent/mcp/MCPServer.js +542 -188
  15. package/src/agent/mcp/index.js +1 -1
  16. package/src/agent/mcp/tools.js +132 -32
  17. package/src/cli/index.js +374 -44
  18. package/src/core/VIB3Engine.js +55 -3
  19. package/src/core/index.js +18 -0
  20. package/src/core/renderers/FacetedRendererAdapter.js +10 -9
  21. package/src/core/renderers/HolographicRendererAdapter.js +11 -7
  22. package/src/core/renderers/QuantumRendererAdapter.js +11 -7
  23. package/src/creative/index.js +11 -0
  24. package/src/experimental/GameLoop.js +72 -0
  25. package/src/experimental/LatticePhysics.js +100 -0
  26. package/src/experimental/LiveDirector.js +143 -0
  27. package/src/experimental/PlayerController4D.js +154 -0
  28. package/src/experimental/VIB3Actor.js +138 -0
  29. package/src/experimental/VIB3Compositor.js +117 -0
  30. package/src/experimental/VIB3Link.js +122 -0
  31. package/src/experimental/VIB3Orchestrator.js +146 -0
  32. package/src/experimental/VIB3Universe.js +109 -0
  33. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  34. package/src/export/index.js +11 -1
  35. package/src/faceted/FacetedSystem.js +27 -10
  36. package/src/games/glyph-war/GlyphWarVisualizer.js +641 -0
  37. package/src/geometry/generators/Crystal.js +2 -2
  38. package/src/holograms/HolographicVisualizer.js +58 -89
  39. package/src/holograms/RealHolographicSystem.js +126 -31
  40. package/src/math/Mat4x4.js +192 -19
  41. package/src/math/Rotor4D.js +93 -39
  42. package/src/math/Vec4.js +119 -78
  43. package/src/math/index.js +7 -7
  44. package/src/quantum/QuantumVisualizer.js +24 -20
  45. package/src/reactivity/index.js +3 -5
  46. package/src/render/LayerPresetManager.js +372 -0
  47. package/src/render/LayerReactivityBridge.js +344 -0
  48. package/src/render/LayerRelationshipGraph.js +610 -0
  49. package/src/render/MultiCanvasBridge.js +148 -25
  50. package/src/render/ShaderLoader.js +38 -0
  51. package/src/render/ShaderProgram.js +4 -4
  52. package/src/render/UnifiedRenderBridge.js +1 -1
  53. package/src/render/backends/WebGPUBackend.js +8 -4
  54. package/src/render/index.js +27 -2
  55. package/src/scene/index.js +4 -4
  56. package/src/shaders/common/geometry24.glsl +65 -0
  57. package/src/shaders/common/geometry24.wgsl +54 -0
  58. package/src/shaders/common/rotation4d.glsl +4 -4
  59. package/src/shaders/common/rotation4d.wgsl +2 -2
  60. package/src/shaders/common/uniforms.wgsl +15 -8
  61. package/src/shaders/faceted/faceted.frag.wgsl +19 -6
  62. package/src/shaders/holographic/holographic.frag.wgsl +7 -5
  63. package/src/shaders/quantum/quantum.frag.wgsl +7 -5
  64. package/src/testing/ParallelTestFramework.js +2 -2
  65. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
  66. package/src/viewer/GalleryUI.js +17 -0
  67. package/src/viewer/ViewerPortal.js +2 -2
  68. package/tools/shader-sync-verify.js +6 -4
  69. package/types/adaptive-sdk.d.ts +204 -5
  70. package/types/agent/cli.d.ts +78 -0
  71. package/types/agent/index.d.ts +18 -0
  72. package/types/agent/mcp.d.ts +87 -0
  73. package/types/agent/telemetry.d.ts +190 -0
  74. package/types/core/VIB3Engine.d.ts +26 -0
  75. package/types/core/index.d.ts +261 -0
  76. package/types/creative/AestheticMapper.d.ts +72 -0
  77. package/types/creative/ChoreographyPlayer.d.ts +96 -0
  78. package/types/creative/index.d.ts +17 -0
  79. package/types/export/index.d.ts +243 -0
  80. package/types/geometry/index.d.ts +164 -0
  81. package/types/math/index.d.ts +214 -0
  82. package/types/render/LayerPresetManager.d.ts +78 -0
  83. package/types/render/LayerReactivityBridge.d.ts +85 -0
  84. package/types/render/LayerRelationshipGraph.d.ts +174 -0
  85. package/types/render/index.d.ts +3 -0
  86. package/types/scene/index.d.ts +204 -0
  87. package/types/systems/index.d.ts +244 -0
  88. package/types/variations/index.d.ts +62 -0
  89. package/types/viewer/index.d.ts +225 -0
@@ -160,21 +160,42 @@ export class Mat4x4 {
160
160
  * @returns {Mat4x4} New matrix = this * m
161
161
  */
162
162
  multiply(m) {
163
+ const out = new Mat4x4();
164
+ const r = out.data;
163
165
  const a = this.data;
164
166
  const b = m.data;
165
- const result = new Float32Array(16);
166
167
 
167
- for (let col = 0; col < 4; col++) {
168
- for (let row = 0; row < 4; row++) {
169
- let sum = 0;
170
- for (let k = 0; k < 4; k++) {
171
- sum += a[k * 4 + row] * b[col * 4 + k];
172
- }
173
- result[col * 4 + row] = sum;
174
- }
175
- }
168
+ const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
169
+ const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
170
+ const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
171
+ const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
176
172
 
177
- return new Mat4x4(result);
173
+ const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
174
+ const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
175
+ const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
176
+ const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
177
+
178
+ r[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
179
+ r[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
180
+ r[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
181
+ r[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
182
+
183
+ r[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
184
+ r[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
185
+ r[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
186
+ r[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
187
+
188
+ r[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
189
+ r[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
190
+ r[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
191
+ r[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
192
+
193
+ r[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
194
+ r[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
195
+ r[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
196
+ r[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
197
+
198
+ return out;
178
199
  }
179
200
 
180
201
  /**
@@ -183,8 +204,44 @@ export class Mat4x4 {
183
204
  * @returns {Mat4x4} this
184
205
  */
185
206
  multiplyInPlace(m) {
186
- const result = this.multiply(m);
187
- this.data.set(result.data);
207
+ const a = this.data;
208
+ const b = m.data;
209
+
210
+ // Cache values to avoid aliasing issues and repeated array access
211
+ const a00 = a[0], a01 = a[4], a02 = a[8], a03 = a[12];
212
+ const a10 = a[1], a11 = a[5], a12 = a[9], a13 = a[13];
213
+ const a20 = a[2], a21 = a[6], a22 = a[10], a23 = a[14];
214
+ const a30 = a[3], a31 = a[7], a32 = a[11], a33 = a[15];
215
+
216
+ const b00 = b[0], b01 = b[4], b02 = b[8], b03 = b[12];
217
+ const b10 = b[1], b11 = b[5], b12 = b[9], b13 = b[13];
218
+ const b20 = b[2], b21 = b[6], b22 = b[10], b23 = b[14];
219
+ const b30 = b[3], b31 = b[7], b32 = b[11], b33 = b[15];
220
+
221
+ // Column 0
222
+ a[0] = a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30;
223
+ a[1] = a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30;
224
+ a[2] = a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30;
225
+ a[3] = a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30;
226
+
227
+ // Column 1
228
+ a[4] = a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31;
229
+ a[5] = a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31;
230
+ a[6] = a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31;
231
+ a[7] = a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31;
232
+
233
+ // Column 2
234
+ a[8] = a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32;
235
+ a[9] = a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32;
236
+ a[10] = a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32;
237
+ a[11] = a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32;
238
+
239
+ // Column 3
240
+ a[12] = a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33;
241
+ a[13] = a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33;
242
+ a[14] = a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33;
243
+ a[15] = a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33;
244
+
188
245
  return this;
189
246
  }
190
247
 
@@ -490,6 +547,122 @@ export class Mat4x4 {
490
547
  return new Mat4x4(json.data);
491
548
  }
492
549
 
550
+ // ========== IN-PLACE ROTATIONS ==========
551
+
552
+ /**
553
+ * Rotate in XY plane in place
554
+ * @param {number} angle
555
+ * @returns {Mat4x4} this
556
+ */
557
+ rotateXY(angle) {
558
+ const c = Math.cos(angle);
559
+ const s = Math.sin(angle);
560
+ const m = this.data;
561
+
562
+ for (let i = 0; i < 4; i++) {
563
+ const a0 = m[i]; // Col 0
564
+ const a1 = m[i + 4]; // Col 1
565
+ m[i] = a0 * c + a1 * s;
566
+ m[i + 4] = -a0 * s + a1 * c;
567
+ }
568
+ return this;
569
+ }
570
+
571
+ /**
572
+ * Rotate in XZ plane in place
573
+ * @param {number} angle
574
+ * @returns {Mat4x4} this
575
+ */
576
+ rotateXZ(angle) {
577
+ const c = Math.cos(angle);
578
+ const s = Math.sin(angle);
579
+ const m = this.data;
580
+
581
+ for (let i = 0; i < 4; i++) {
582
+ const a0 = m[i]; // Col 0
583
+ const a2 = m[i + 8]; // Col 2
584
+ m[i] = a0 * c - a2 * s;
585
+ m[i + 8] = a0 * s + a2 * c;
586
+ }
587
+ return this;
588
+ }
589
+
590
+ /**
591
+ * Rotate in YZ plane in place
592
+ * @param {number} angle
593
+ * @returns {Mat4x4} this
594
+ */
595
+ rotateYZ(angle) {
596
+ const c = Math.cos(angle);
597
+ const s = Math.sin(angle);
598
+ const m = this.data;
599
+
600
+ for (let i = 0; i < 4; i++) {
601
+ const a1 = m[i + 4]; // Col 1
602
+ const a2 = m[i + 8]; // Col 2
603
+ m[i + 4] = a1 * c + a2 * s;
604
+ m[i + 8] = -a1 * s + a2 * c;
605
+ }
606
+ return this;
607
+ }
608
+
609
+ /**
610
+ * Rotate in XW plane in place
611
+ * @param {number} angle
612
+ * @returns {Mat4x4} this
613
+ */
614
+ rotateXW(angle) {
615
+ const c = Math.cos(angle);
616
+ const s = Math.sin(angle);
617
+ const m = this.data;
618
+
619
+ for (let i = 0; i < 4; i++) {
620
+ const a0 = m[i]; // Col 0
621
+ const a3 = m[i + 12]; // Col 3
622
+ m[i] = a0 * c + a3 * s;
623
+ m[i + 12] = -a0 * s + a3 * c;
624
+ }
625
+ return this;
626
+ }
627
+
628
+ /**
629
+ * Rotate in YW plane in place
630
+ * @param {number} angle
631
+ * @returns {Mat4x4} this
632
+ */
633
+ rotateYW(angle) {
634
+ const c = Math.cos(angle);
635
+ const s = Math.sin(angle);
636
+ const m = this.data;
637
+
638
+ for (let i = 0; i < 4; i++) {
639
+ const a1 = m[i + 4]; // Col 1
640
+ const a3 = m[i + 12]; // Col 3
641
+ m[i + 4] = a1 * c + a3 * s;
642
+ m[i + 12] = -a1 * s + a3 * c;
643
+ }
644
+ return this;
645
+ }
646
+
647
+ /**
648
+ * Rotate in ZW plane in place
649
+ * @param {number} angle
650
+ * @returns {Mat4x4} this
651
+ */
652
+ rotateZW(angle) {
653
+ const c = Math.cos(angle);
654
+ const s = Math.sin(angle);
655
+ const m = this.data;
656
+
657
+ for (let i = 0; i < 4; i++) {
658
+ const a2 = m[i + 8]; // Col 2
659
+ const a3 = m[i + 12]; // Col 3
660
+ m[i + 8] = a2 * c + a3 * s;
661
+ m[i + 12] = -a2 * s + a3 * c;
662
+ }
663
+ return this;
664
+ }
665
+
493
666
  // ========== ROTATION MATRICES FOR ALL 6 PLANES ==========
494
667
 
495
668
  /**
@@ -624,12 +797,12 @@ export class Mat4x4 {
624
797
  static rotationFromAngles(angles) {
625
798
  let result = Mat4x4.identity();
626
799
 
627
- if (angles.xy) result = result.multiply(Mat4x4.rotationXY(angles.xy));
628
- if (angles.xz) result = result.multiply(Mat4x4.rotationXZ(angles.xz));
629
- if (angles.yz) result = result.multiply(Mat4x4.rotationYZ(angles.yz));
630
- if (angles.xw) result = result.multiply(Mat4x4.rotationXW(angles.xw));
631
- if (angles.yw) result = result.multiply(Mat4x4.rotationYW(angles.yw));
632
- if (angles.zw) result = result.multiply(Mat4x4.rotationZW(angles.zw));
800
+ if (angles.xy) result.rotateXY(angles.xy);
801
+ if (angles.xz) result.rotateXZ(angles.xz);
802
+ if (angles.yz) result.rotateYZ(angles.yz);
803
+ if (angles.xw) result.rotateXW(angles.xw);
804
+ if (angles.yw) result.rotateYW(angles.yw);
805
+ if (angles.zw) result.rotateZW(angles.zw);
633
806
 
634
807
  return result;
635
808
  }
@@ -323,54 +323,108 @@ export class Rotor4D {
323
323
  /**
324
324
  * Rotate a 4D vector using sandwich product: v' = R v R†
325
325
  *
326
+ * Matrix math is inlined to avoid allocating a temporary Float32Array(16).
327
+ * Pass an optional target Vec4 to eliminate all allocations.
328
+ *
326
329
  * @param {Vec4} v - Vector to rotate
327
- * @returns {Vec4} Rotated vector
330
+ * @param {Vec4} [target] - Optional pre-allocated Vec4 to write result into
331
+ * @returns {Vec4} Rotated vector (target if provided, otherwise new Vec4)
328
332
  */
329
- rotate(v) {
330
- // For efficiency, we expand the sandwich product directly
331
- // rather than doing two rotor multiplications
332
-
333
+ rotate(v, target) {
333
334
  const x = v.x, y = v.y, z = v.z, w = v.w;
334
335
 
335
- // Compute R v (rotor times vector)
336
- // Vector in GA is: x*e1 + y*e2 + z*e3 + w*e4
337
- // This produces a mixed multivector
338
-
339
- // Then multiply by R† (reverse of rotor)
340
- // Extract the vector part of the result
336
+ // Normalize for numerical stability (same as toMatrix)
337
+ const n = this.norm();
338
+ const invN = n > 1e-10 ? 1 / n : 1;
341
339
 
342
- // Pre-compute some common terms
343
- const s = this.s;
344
- const xy = this.xy, xz = this.xz, yz = this.yz;
345
- const xw = this.xw, yw = this.yw, zw = this.zw;
346
- const xyzw = this.xyzw;
340
+ const s = this.s * invN;
341
+ const xy = this.xy * invN;
342
+ const xz = this.xz * invN;
343
+ const yz = this.yz * invN;
344
+ const xw = this.xw * invN;
345
+ const yw = this.yw * invN;
346
+ const zw = this.zw * invN;
347
+ const xyzw = this.xyzw * invN;
347
348
 
348
- // Squared terms for the rotation formula
349
+ // Squared terms
349
350
  const s2 = s * s;
350
- const xy2 = xy * xy, xz2 = xz * xz, yz2 = yz * yz;
351
- const xw2 = xw * xw, yw2 = yw * yw, zw2 = zw * zw;
351
+ const xy2 = xy * xy;
352
+ const xz2 = xz * xz;
353
+ const yz2 = yz * yz;
354
+ const xw2 = xw * xw;
355
+ const yw2 = yw * yw;
356
+ const zw2 = zw * zw;
352
357
  const xyzw2 = xyzw * xyzw;
353
358
 
354
- // The full rotation formula derived from R v R†
355
- const newX =
356
- x * (s2 + xy2 + xz2 - yz2 + xw2 - yw2 - zw2 - xyzw2) +
357
- 2 * y * (s * xy + xz * yz + xw * yw - s * xyzw * zw + xy * s - xyzw * zw) +
358
- 2 * z * (s * xz - xy * yz + xw * zw + xyzw * yw) +
359
- 2 * w * (s * xw - xy * yw - xz * zw - xyzw * yz);
360
-
361
- // Simplified rotation using matrix form
362
- // This is equivalent but clearer
363
-
364
- // Actually, let's use the direct matrix multiplication approach
365
- // which is more numerically stable
366
-
367
- const m = this.toMatrix();
368
- return new Vec4(
369
- m[0] * x + m[4] * y + m[8] * z + m[12] * w,
370
- m[1] * x + m[5] * y + m[9] * z + m[13] * w,
371
- m[2] * x + m[6] * y + m[10] * z + m[14] * w,
372
- m[3] * x + m[7] * y + m[11] * z + m[15] * w
373
- );
359
+ // Cross terms (pre-multiplied by 2)
360
+ const sxy = 2 * s * xy;
361
+ const sxz = 2 * s * xz;
362
+ const syz = 2 * s * yz;
363
+ const sxw = 2 * s * xw;
364
+ const syw = 2 * s * yw;
365
+ const szw = 2 * s * zw;
366
+
367
+ const xzyz = 2 * xz * yz;
368
+ const xyyz = 2 * xy * yz;
369
+ const xyxz = 2 * xy * xz;
370
+ const xyxw = 2 * xy * xw;
371
+ const xyyw = 2 * xy * yw;
372
+
373
+ const xzxw = 2 * xz * xw;
374
+ const xzyw = 2 * xz * yw;
375
+ const xzzw = 2 * xz * zw;
376
+
377
+ const yzxw = 2 * yz * xw;
378
+ const yzyw = 2 * yz * yw;
379
+ const yzzw = 2 * yz * zw;
380
+
381
+ const xwyw = 2 * xw * yw;
382
+ const xwzw = 2 * xw * zw;
383
+ const ywzw = 2 * yw * zw;
384
+
385
+ const xyxyzw = 2 * xy * xyzw;
386
+ const xzxyzw = 2 * xz * xyzw;
387
+ const yzxyzw = 2 * yz * xyzw;
388
+ const xwxyzw = 2 * xw * xyzw;
389
+ const ywxyzw = 2 * yw * xyzw;
390
+ const zwxyzw = 2 * zw * xyzw;
391
+
392
+ // Column-major 4x4 rotation matrix entries (inlined from toMatrix)
393
+ // Column 0
394
+ const m0 = s2 - xy2 - xz2 + yz2 - xw2 + yw2 + zw2 - xyzw2;
395
+ const m1 = sxy + xzyz + xwyw - zwxyzw;
396
+ const m2 = sxz - xyyz + xwzw + ywxyzw;
397
+ const m3 = sxw - xyyw - xzzw - yzxyzw;
398
+ // Column 1
399
+ const m4 = -sxy + xzyz + xwyw + zwxyzw;
400
+ const m5 = s2 - xy2 + xz2 - yz2 + xw2 - yw2 + zw2 - xyzw2;
401
+ const m6 = syz + xyxz + ywzw - xwxyzw;
402
+ const m7 = syw + xyxw - yzzw + xzxyzw;
403
+ // Column 2
404
+ const m8 = -sxz - xyyz + xwzw - ywxyzw;
405
+ const m9 = -syz + xyxz + ywzw + xwxyzw;
406
+ const m10 = s2 + xy2 - xz2 - yz2 + xw2 + yw2 - zw2 - xyzw2;
407
+ const m11 = szw + xzxw + yzyw - xyxyzw;
408
+ // Column 3
409
+ const m12 = -sxw - xyyw - xzzw + yzxyzw;
410
+ const m13 = -syw + xyxw - yzzw - xzxyzw;
411
+ const m14 = -szw + xzxw + yzyw + xyxyzw;
412
+ const m15 = s2 + xy2 + xz2 + yz2 - xw2 - yw2 - zw2 - xyzw2;
413
+
414
+ // Matrix-vector multiply
415
+ const rx = m0 * x + m4 * y + m8 * z + m12 * w;
416
+ const ry = m1 * x + m5 * y + m9 * z + m13 * w;
417
+ const rz = m2 * x + m6 * y + m10 * z + m14 * w;
418
+ const rw = m3 * x + m7 * y + m11 * z + m15 * w;
419
+
420
+ if (target) {
421
+ target.x = rx;
422
+ target.y = ry;
423
+ target.z = rz;
424
+ target.w = rw;
425
+ return target;
426
+ }
427
+ return new Vec4(rx, ry, rz, rw);
374
428
  }
375
429
 
376
430
  /**