@vib3code/sdk 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,608 @@
1
+ # XR integration benchmarks (draft)
2
+
3
+ This document captures baseline metrics, targets, and tooling for XR integration work.
4
+
5
+ ## Baseline metrics to record
6
+
7
+ | Metric | Description | Unit | Desktop Target | Mobile Target |
8
+ |--------|-------------|------|----------------|---------------|
9
+ | Frame time | Time to render single frame | ms | <11ms | <14ms |
10
+ | FPS | Frames per second sustained | fps | 90 | 72 |
11
+ | CPU utilization | Main thread usage | % | <50% | <60% |
12
+ | GPU utilization | GPU compute usage | % | <80% | <85% |
13
+ | Memory usage | Total JS heap | MB | <200MB | <100MB |
14
+ | Draw calls | Per-frame draw call count | count | <100 | <50 |
15
+ | Triangles | Per-frame triangle count | count | <100K | <50K |
16
+ | Input latency | Motion-to-photon | ms | <20ms | <25ms |
17
+
18
+ ## Target thresholds
19
+
20
+ ### Desktop XR (Quest Link, SteamVR, etc.)
21
+ - **90 FPS sustained** minimum
22
+ - **<11ms frame time** (1000ms / 90fps)
23
+ - **<20ms motion-to-photon latency**
24
+ - Supports all 24 geometry variants at full fidelity
25
+
26
+ ### Mobile XR (Quest standalone, mobile AR)
27
+ - **72 FPS sustained** minimum
28
+ - **<14ms frame time** (1000ms / 72fps)
29
+ - **<25ms motion-to-photon latency**
30
+ - May use simplified geometry (LOD system)
31
+
32
+ ### Web XR (Browser-based)
33
+ - **60 FPS sustained** minimum
34
+ - **<16.67ms frame time**
35
+ - Falls back gracefully when GPU unavailable
36
+
37
+ ## Performance tiers
38
+
39
+ | Tier | Geometry | Grid Density | Effects | Target Platform |
40
+ |------|----------|--------------|---------|-----------------|
41
+ | Ultra | Full 24 | 64-100 | All | Desktop XR |
42
+ | High | Full 24 | 32-64 | Most | Desktop/Mobile XR |
43
+ | Medium | 16 variants | 16-32 | Basic | Mobile XR |
44
+ | Low | 8 variants | 8-16 | Minimal | Low-end mobile |
45
+
46
+ ## Benchmark workflow
47
+
48
+ ### 1. Scene selection
49
+
50
+ Representative test scenes for consistent benchmarking:
51
+
52
+ ```javascript
53
+ // tests/benchmarks/scenes.js
54
+ export const BENCHMARK_SCENES = {
55
+ simple: {
56
+ name: 'Simple Tetrahedron',
57
+ params: {
58
+ system: 'quantum',
59
+ geometry: 0,
60
+ gridDensity: 16,
61
+ chaos: 0,
62
+ speed: 1.0
63
+ }
64
+ },
65
+ medium: {
66
+ name: 'Medium Hypersphere',
67
+ params: {
68
+ system: 'quantum',
69
+ geometry: 8,
70
+ gridDensity: 32,
71
+ chaos: 0.3,
72
+ speed: 1.0
73
+ }
74
+ },
75
+ complex: {
76
+ name: 'Complex Holographic',
77
+ params: {
78
+ system: 'holographic',
79
+ geometry: 16,
80
+ gridDensity: 64,
81
+ chaos: 0.5,
82
+ speed: 1.5
83
+ }
84
+ },
85
+ stress: {
86
+ name: 'Stress Test',
87
+ params: {
88
+ system: 'quantum',
89
+ geometry: 23,
90
+ gridDensity: 100,
91
+ chaos: 1.0,
92
+ speed: 3.0
93
+ }
94
+ }
95
+ };
96
+ ```
97
+
98
+ ### 2. Metrics collection
99
+
100
+ ```javascript
101
+ // src/benchmarks/MetricsCollector.js
102
+ export class MetricsCollector {
103
+ constructor() {
104
+ this.samples = [];
105
+ this.frameCount = 0;
106
+ this.lastFrameTime = 0;
107
+ }
108
+
109
+ beginFrame() {
110
+ this.frameStart = performance.now();
111
+ }
112
+
113
+ endFrame() {
114
+ const frameTime = performance.now() - this.frameStart;
115
+ this.frameCount++;
116
+
117
+ this.samples.push({
118
+ timestamp: Date.now(),
119
+ frameTime,
120
+ fps: 1000 / frameTime,
121
+ memory: this.getMemoryUsage(),
122
+ drawCalls: this.getDrawCallCount(),
123
+ triangles: this.getTriangleCount()
124
+ });
125
+
126
+ // Keep last 1000 samples
127
+ if (this.samples.length > 1000) {
128
+ this.samples.shift();
129
+ }
130
+ }
131
+
132
+ getMemoryUsage() {
133
+ if (performance.memory) {
134
+ return {
135
+ used: performance.memory.usedJSHeapSize / 1024 / 1024,
136
+ total: performance.memory.totalJSHeapSize / 1024 / 1024,
137
+ limit: performance.memory.jsHeapSizeLimit / 1024 / 1024
138
+ };
139
+ }
140
+ return null;
141
+ }
142
+
143
+ getDrawCallCount() {
144
+ // Implementation depends on renderer
145
+ return this.renderer?.stats?.drawCalls ?? 0;
146
+ }
147
+
148
+ getTriangleCount() {
149
+ return this.renderer?.stats?.triangles ?? 0;
150
+ }
151
+
152
+ getStats() {
153
+ if (this.samples.length === 0) return null;
154
+
155
+ const frameTimes = this.samples.map(s => s.frameTime);
156
+ const fps = this.samples.map(s => s.fps);
157
+
158
+ return {
159
+ frameTime: {
160
+ min: Math.min(...frameTimes),
161
+ max: Math.max(...frameTimes),
162
+ avg: frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length,
163
+ p95: this.percentile(frameTimes, 95),
164
+ p99: this.percentile(frameTimes, 99)
165
+ },
166
+ fps: {
167
+ min: Math.min(...fps),
168
+ max: Math.max(...fps),
169
+ avg: fps.reduce((a, b) => a + b, 0) / fps.length
170
+ },
171
+ memory: this.samples[this.samples.length - 1].memory,
172
+ drawCalls: this.samples[this.samples.length - 1].drawCalls,
173
+ triangles: this.samples[this.samples.length - 1].triangles,
174
+ sampleCount: this.samples.length
175
+ };
176
+ }
177
+
178
+ percentile(arr, p) {
179
+ const sorted = [...arr].sort((a, b) => a - b);
180
+ const index = Math.ceil((p / 100) * sorted.length) - 1;
181
+ return sorted[index];
182
+ }
183
+
184
+ reset() {
185
+ this.samples = [];
186
+ this.frameCount = 0;
187
+ }
188
+
189
+ exportCSV() {
190
+ const headers = ['timestamp', 'frameTime', 'fps', 'memoryUsed', 'drawCalls', 'triangles'];
191
+ const rows = this.samples.map(s => [
192
+ s.timestamp,
193
+ s.frameTime.toFixed(2),
194
+ s.fps.toFixed(1),
195
+ s.memory?.used?.toFixed(1) ?? '',
196
+ s.drawCalls,
197
+ s.triangles
198
+ ]);
199
+ return [headers.join(','), ...rows.map(r => r.join(','))].join('\n');
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### 3. Benchmark runner
205
+
206
+ ```javascript
207
+ // src/benchmarks/BenchmarkRunner.js
208
+ import { MetricsCollector } from './MetricsCollector.js';
209
+ import { BENCHMARK_SCENES } from './scenes.js';
210
+
211
+ export class BenchmarkRunner {
212
+ constructor(engine) {
213
+ this.engine = engine;
214
+ this.collector = new MetricsCollector();
215
+ this.results = [];
216
+ }
217
+
218
+ async runBenchmark(sceneName, duration = 10000) {
219
+ const scene = BENCHMARK_SCENES[sceneName];
220
+ if (!scene) throw new Error(`Unknown scene: ${sceneName}`);
221
+
222
+ console.log(`Running benchmark: ${scene.name}`);
223
+
224
+ // Configure scene
225
+ this.engine.setParameters(scene.params);
226
+ this.collector.reset();
227
+
228
+ // Warm-up phase (2 seconds)
229
+ await this.runFrames(2000);
230
+ this.collector.reset();
231
+
232
+ // Measurement phase
233
+ const startTime = performance.now();
234
+ while (performance.now() - startTime < duration) {
235
+ this.collector.beginFrame();
236
+ await this.engine.renderFrame();
237
+ this.collector.endFrame();
238
+ }
239
+
240
+ const stats = this.collector.getStats();
241
+ const result = {
242
+ scene: sceneName,
243
+ sceneName: scene.name,
244
+ params: scene.params,
245
+ duration,
246
+ ...stats,
247
+ timestamp: new Date().toISOString(),
248
+ passed: this.evaluateThresholds(stats)
249
+ };
250
+
251
+ this.results.push(result);
252
+ return result;
253
+ }
254
+
255
+ async runFrames(duration) {
256
+ const startTime = performance.now();
257
+ while (performance.now() - startTime < duration) {
258
+ await this.engine.renderFrame();
259
+ }
260
+ }
261
+
262
+ evaluateThresholds(stats, platform = 'desktop') {
263
+ const thresholds = platform === 'mobile'
264
+ ? { frameTime: 14, fps: 72, memory: 100 }
265
+ : { frameTime: 11, fps: 90, memory: 200 };
266
+
267
+ return {
268
+ frameTime: stats.frameTime.p95 <= thresholds.frameTime,
269
+ fps: stats.fps.avg >= thresholds.fps,
270
+ memory: (stats.memory?.used ?? 0) <= thresholds.memory,
271
+ overall: stats.frameTime.p95 <= thresholds.frameTime && stats.fps.avg >= thresholds.fps
272
+ };
273
+ }
274
+
275
+ async runAllBenchmarks(duration = 10000) {
276
+ const results = {};
277
+ for (const sceneName of Object.keys(BENCHMARK_SCENES)) {
278
+ results[sceneName] = await this.runBenchmark(sceneName, duration);
279
+ }
280
+ return results;
281
+ }
282
+
283
+ exportReport() {
284
+ return {
285
+ generated: new Date().toISOString(),
286
+ platform: this.detectPlatform(),
287
+ results: this.results
288
+ };
289
+ }
290
+
291
+ detectPlatform() {
292
+ return {
293
+ userAgent: navigator.userAgent,
294
+ gpu: this.engine.getGPUInfo?.() ?? 'unknown',
295
+ cores: navigator.hardwareConcurrency ?? 'unknown',
296
+ memory: navigator.deviceMemory ?? 'unknown'
297
+ };
298
+ }
299
+ }
300
+ ```
301
+
302
+ ### 4. CLI benchmark command
303
+
304
+ ```bash
305
+ # Run all benchmarks
306
+ vib3 benchmark --all --duration 10s
307
+
308
+ # Run specific scene
309
+ vib3 benchmark --scene complex --duration 30s
310
+
311
+ # Output formats
312
+ vib3 benchmark --all --format json --output results.json
313
+ vib3 benchmark --all --format csv --output results.csv
314
+ vib3 benchmark --all --format markdown --output BENCHMARK_RESULTS.md
315
+
316
+ # Platform-specific
317
+ vib3 benchmark --all --platform mobile --thresholds strict
318
+ ```
319
+
320
+ ### 5. Telemetry integration
321
+
322
+ ```javascript
323
+ // Benchmark results are automatically captured in telemetry
324
+ import { TelemetryService } from '../agent/telemetry/TelemetryService.js';
325
+
326
+ async function runBenchmarkWithTelemetry(runner) {
327
+ const span = TelemetryService.startSpan('benchmark_run');
328
+
329
+ try {
330
+ const results = await runner.runAllBenchmarks();
331
+
332
+ span.setAttributes({
333
+ 'benchmark.scenes': Object.keys(results).length,
334
+ 'benchmark.passed': Object.values(results).filter(r => r.passed.overall).length,
335
+ 'benchmark.failed': Object.values(results).filter(r => !r.passed.overall).length
336
+ });
337
+
338
+ // Record individual scene results
339
+ for (const [scene, result] of Object.entries(results)) {
340
+ TelemetryService.recordMetric('benchmark.frame_time', result.frameTime.avg, {
341
+ scene,
342
+ percentile: 'avg'
343
+ });
344
+ TelemetryService.recordMetric('benchmark.fps', result.fps.avg, { scene });
345
+ }
346
+
347
+ span.setStatus({ code: 'OK' });
348
+ return results;
349
+ } catch (error) {
350
+ span.setStatus({ code: 'ERROR', message: error.message });
351
+ throw error;
352
+ } finally {
353
+ span.end();
354
+ }
355
+ }
356
+ ```
357
+
358
+ ## Regression tracking
359
+
360
+ ### Baseline storage
361
+
362
+ Benchmark baselines are stored in `tests/benchmarks/baselines/`:
363
+
364
+ ```json
365
+ // tests/benchmarks/baselines/desktop-chrome-2026-01.json
366
+ {
367
+ "generated": "2026-01-23T22:00:00Z",
368
+ "platform": {
369
+ "browser": "Chrome 120",
370
+ "os": "Windows 11",
371
+ "gpu": "NVIDIA RTX 3080"
372
+ },
373
+ "results": {
374
+ "simple": {
375
+ "frameTime": { "avg": 2.1, "p95": 3.2 },
376
+ "fps": { "avg": 476 },
377
+ "passed": true
378
+ },
379
+ "medium": {
380
+ "frameTime": { "avg": 4.5, "p95": 6.1 },
381
+ "fps": { "avg": 222 },
382
+ "passed": true
383
+ },
384
+ "complex": {
385
+ "frameTime": { "avg": 8.2, "p95": 10.1 },
386
+ "fps": { "avg": 122 },
387
+ "passed": true
388
+ },
389
+ "stress": {
390
+ "frameTime": { "avg": 12.5, "p95": 15.2 },
391
+ "fps": { "avg": 80 },
392
+ "passed": false
393
+ }
394
+ }
395
+ }
396
+ ```
397
+
398
+ ### Regression detection
399
+
400
+ ```javascript
401
+ // tests/benchmarks/regression.test.js
402
+ import { describe, it, expect } from 'vitest';
403
+ import { BenchmarkRunner } from '../../src/benchmarks/BenchmarkRunner.js';
404
+ import baseline from './baselines/desktop-chrome-2026-01.json';
405
+
406
+ const REGRESSION_THRESHOLD = 0.15; // 15% degradation allowed
407
+
408
+ describe('performance regression', () => {
409
+ let runner;
410
+
411
+ beforeAll(async () => {
412
+ const engine = await createTestEngine();
413
+ runner = new BenchmarkRunner(engine);
414
+ });
415
+
416
+ for (const [scene, baselineResult] of Object.entries(baseline.results)) {
417
+ it(`should not regress on ${scene}`, async () => {
418
+ const result = await runner.runBenchmark(scene, 5000);
419
+
420
+ const frameTimeRatio = result.frameTime.avg / baselineResult.frameTime.avg;
421
+ const fpsRatio = baselineResult.fps.avg / result.fps.avg;
422
+
423
+ expect(frameTimeRatio).toBeLessThan(1 + REGRESSION_THRESHOLD);
424
+ expect(fpsRatio).toBeLessThan(1 + REGRESSION_THRESHOLD);
425
+ });
426
+ }
427
+ });
428
+ ```
429
+
430
+ ### CI integration
431
+
432
+ ```yaml
433
+ # .github/workflows/benchmarks.yml
434
+ name: Performance Benchmarks
435
+
436
+ on:
437
+ push:
438
+ branches: [main]
439
+ pull_request:
440
+
441
+ jobs:
442
+ benchmark:
443
+ runs-on: ubuntu-latest
444
+ steps:
445
+ - uses: actions/checkout@v4
446
+ - uses: pnpm/action-setup@v2
447
+ - uses: actions/setup-node@v4
448
+ with:
449
+ node-version: '18'
450
+
451
+ - run: pnpm install
452
+ - run: pnpm bench
453
+
454
+ - name: Check for regressions
455
+ run: pnpm test -- tests/benchmarks/regression.test.js
456
+
457
+ - name: Upload benchmark results
458
+ uses: actions/upload-artifact@v4
459
+ with:
460
+ name: benchmark-results
461
+ path: benchmark-results.json
462
+ ```
463
+
464
+ ## XR-specific considerations
465
+
466
+ ### WebXR frame timing
467
+
468
+ ```javascript
469
+ // XR sessions have different timing requirements
470
+ function xrRenderLoop(time, frame) {
471
+ const session = renderer.xr.getSession();
472
+
473
+ // Get XR-specific timing
474
+ const pose = frame.getViewerPose(referenceSpace);
475
+ if (!pose) return;
476
+
477
+ // Measure actual XR frame time
478
+ const xrFrameStart = performance.now();
479
+
480
+ for (const view of pose.views) {
481
+ renderView(view);
482
+ }
483
+
484
+ const xrFrameTime = performance.now() - xrFrameStart;
485
+
486
+ // XR frame budget is stricter
487
+ if (xrFrameTime > 8) { // < 8ms for 120Hz displays
488
+ console.warn('XR frame budget exceeded:', xrFrameTime.toFixed(2), 'ms');
489
+ }
490
+ }
491
+ ```
492
+
493
+ ### Input latency measurement
494
+
495
+ ```javascript
496
+ // Measure motion-to-photon latency
497
+ class LatencyMeasurer {
498
+ constructor() {
499
+ this.pendingMeasurements = new Map();
500
+ }
501
+
502
+ recordInput(inputId) {
503
+ this.pendingMeasurements.set(inputId, performance.now());
504
+ }
505
+
506
+ recordRender(inputId) {
507
+ const inputTime = this.pendingMeasurements.get(inputId);
508
+ if (inputTime) {
509
+ const latency = performance.now() - inputTime;
510
+ this.pendingMeasurements.delete(inputId);
511
+ return latency;
512
+ }
513
+ return null;
514
+ }
515
+
516
+ // For XR controller input
517
+ measureXRInputLatency(controller, session) {
518
+ const inputTime = performance.now();
519
+ const inputId = `xr-${Date.now()}`;
520
+
521
+ // Track through render
522
+ return new Promise((resolve) => {
523
+ requestAnimationFrame(() => {
524
+ session.requestAnimationFrame(() => {
525
+ const latency = performance.now() - inputTime;
526
+ resolve(latency);
527
+ });
528
+ });
529
+ });
530
+ }
531
+ }
532
+ ```
533
+
534
+ ## Visualization dashboard
535
+
536
+ ### Debug overlay
537
+
538
+ ```javascript
539
+ // src/debug/PerformanceOverlay.js
540
+ export class PerformanceOverlay {
541
+ constructor(collector) {
542
+ this.collector = collector;
543
+ this.canvas = document.createElement('canvas');
544
+ this.ctx = this.canvas.getContext('2d');
545
+ this.canvas.style.cssText = `
546
+ position: fixed;
547
+ top: 10px;
548
+ right: 10px;
549
+ width: 200px;
550
+ height: 100px;
551
+ background: rgba(0,0,0,0.7);
552
+ border-radius: 4px;
553
+ z-index: 9999;
554
+ `;
555
+ }
556
+
557
+ render() {
558
+ const stats = this.collector.getStats();
559
+ if (!stats) return;
560
+
561
+ const ctx = this.ctx;
562
+ ctx.clearRect(0, 0, 200, 100);
563
+ ctx.fillStyle = '#fff';
564
+ ctx.font = '12px monospace';
565
+
566
+ const fps = stats.fps.avg.toFixed(1);
567
+ const frameTime = stats.frameTime.avg.toFixed(2);
568
+ const memory = stats.memory?.used?.toFixed(1) ?? 'N/A';
569
+
570
+ ctx.fillText(`FPS: ${fps}`, 10, 20);
571
+ ctx.fillText(`Frame: ${frameTime}ms`, 10, 40);
572
+ ctx.fillText(`Memory: ${memory}MB`, 10, 60);
573
+ ctx.fillText(`Draw: ${stats.drawCalls}`, 10, 80);
574
+
575
+ // Color-code based on thresholds
576
+ ctx.fillStyle = stats.fps.avg >= 60 ? '#4f4' : '#f44';
577
+ ctx.fillRect(180, 10, 10, 10);
578
+ }
579
+
580
+ show() {
581
+ document.body.appendChild(this.canvas);
582
+ }
583
+
584
+ hide() {
585
+ this.canvas.remove();
586
+ }
587
+ }
588
+ ```
589
+
590
+ ## Implementation status
591
+
592
+ | Component | Status | Location |
593
+ |-----------|--------|----------|
594
+ | MetricsCollector | TODO | `src/benchmarks/MetricsCollector.js` |
595
+ | BenchmarkRunner | TODO | `src/benchmarks/BenchmarkRunner.js` |
596
+ | Benchmark scenes | TODO | `tests/benchmarks/scenes.js` |
597
+ | CLI command | TODO | `src/cli/benchmark.js` |
598
+ | Regression tests | TODO | `tests/benchmarks/regression.test.js` |
599
+ | Performance overlay | TODO | `src/debug/PerformanceOverlay.js` |
600
+ | CI workflow | TODO | `.github/workflows/benchmarks.yml` |
601
+ | Baseline storage | TODO | `tests/benchmarks/baselines/` |
602
+
603
+ ## References
604
+
605
+ - [WebXR Device API](https://www.w3.org/TR/webxr/)
606
+ - [WebXR Performance Guidelines](https://immersive-web.github.io/webxr-reference/)
607
+ - [Meta Quest Performance Guidelines](https://developer.oculus.com/documentation/native/android/mobile-power-overview/)
608
+ - [Chrome Performance Monitoring](https://developer.chrome.com/docs/devtools/performance/)
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Clear Seas Solutions LLC / Paul Phillips
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.