volvoxai 0.3.0 → 0.5.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.
package/README.md CHANGED
@@ -1,321 +1,285 @@
1
1
  # VolvoxAI
2
2
 
3
- **A zero-dependency deep-learning runtime for browsers, Node.js, and native
4
- Windows, Linux, macOS, and Android targets.**
3
+ **A deep-learning runtime for browsers, Node.js, and native desktop, phone,
4
+ and robot applications.**
5
5
 
6
- VolvoxAI runs compact graph packages without embedding a general-purpose ML
7
- framework. It supports WebNN, WebGPU, WASM SIMD, JavaScript CPU, native CPU,
8
- Vulkan, OpenGL, optional CUDA, Metal, and NNAPI integrations.
6
+ VolvoxAI runs compact model packages without embedding a general-purpose ML
7
+ framework. The JavaScript package has no runtime npm dependencies. Use it to recognize objects, process text, or adapt a small model on
8
+ the device where the data is produced. The same graph and weights can run in a
9
+ browser through WebAssembly or in a native C application.
9
10
 
10
- The repository is also a from-scratch textbook:
11
+ The engine supports both inference and training. A browser application can
12
+ coordinate concurrent requests in one runtime; an edge service can schedule
13
+ vision and language workloads with explicit request and result-memory budgets.
14
+ Model-specific preprocessing, generation policy, and evaluation stay in the
15
+ application.
11
16
 
12
- - [Idea, Build, and Deep tracks](docs/textbook/README.md)
13
- - [Architecture](ARCHITECTURE.md)
14
- - [Runtime design](REFACTORING.md)
17
+ This repository is also a from-scratch textbook. Start with
18
+ [How AI Actually Works](docs/textbook/README.md) ([한국어](docs/textbook/ko/README.md))
19
+ to learn tensors, attention, training, quantization, and the engine itself.
20
+ For a first run, follow the [quickstart](docs/quickstart.md).
15
21
 
16
22
  ## Highlights
17
23
 
18
- - One explicit inference lifecycle: Runtime Model → CompiledModel →
19
- ExecutionContext ExecutionResult.
20
- - Stable named outputs on every backend. Host reads return caller-owned arrays;
21
- WebGPU results may also expose result-owned device buffers.
22
- - Independent execution and decode contexts with immutable compiled model and
23
- weight revisions.
24
- - Required or preferred backend policy with independent operator-fallback
25
- control and machine-readable reports.
26
- - A single context-aware provider contract for built-in and external devices.
27
- - A full profile with a retained Trainer for CPU, WebGPU, or strict WASM
28
- training.
29
- - Inspectable model packages using graph.json and safetensors.
30
- - Strict inference/training composition boundaries in JavaScript, WASM, and
31
- native builds.
32
-
33
- ## Install
34
-
35
- ~~~bash
24
+ - **One model package across platforms.** Inspectable `graph.json` and
25
+ SafeTensors weights describe the computation and its data.
26
+ - **CPU and GPU execution.** Browser/Node WASM SIMD, browser WebGPU, and native
27
+ CPU with optional Vulkan, OpenGL/OpenGL ES, CUDA, and Metal backends.
28
+ - **Bounded dynamic shapes.** Name a dimension such as sequence length and give
29
+ it finite bounds. The compiler checks the supported domain; each request
30
+ supplies its actual shape without rebuilding the model.
31
+ - **Independent sessions and stable results.** Reuse a compiled model across
32
+ execution contexts. Each context owns its shape and decode state, and each
33
+ result retains its own named output snapshot until released.
34
+ - **Scheduling and batching.** Run a single request directly, or use bounded
35
+ queues, priorities, deadlines, and compatible-request batching. Decode
36
+ contexts support row execution and paged KV caches on qualified routes.
37
+ - **On-device training.** The full profile provides SGD/AdamW, gradient
38
+ accumulation, checkpoints, and LoRA authoring. Training updates private
39
+ weights; an explicit commit publishes them for new inference compilations.
40
+ - **Post-training quantization.** Calibrate a float model and produce an explicit
41
+ W8A8 package, then measure its accuracy and latency against the original.
42
+ - **Separate inference and full builds.** Inference artifacts exclude compiled
43
+ training code, optimizer state, and training shaders.
44
+
45
+ Support depends on the operator, dtype, shape, and selected backend. See the
46
+ [operator guide](docs/operation_list.md) and [validation coverage](docs/c-runtime-validation.md)
47
+ for the tested domains.
48
+
49
+ ## Install and choose a profile
50
+
51
+ ```sh
36
52
  npm install volvoxai
37
- ~~~
53
+ ```
38
54
 
39
- For repository development:
55
+ | Your application needs | JavaScript entry | WASM companion |
56
+ | --- | --- | --- |
57
+ | CPU inference, text processing, graph construction, scheduling | `volvoxai/lite` | `volvoxai.lite.wasm` |
58
+ | WebGPU inference, training, or PTQ | `volvoxai` | `volvoxai.wasm` |
40
59
 
41
- ~~~bash
42
- npm install
43
- npm run typecheck
44
- npm run build:all
45
- ~~~
60
+ Both entries run WASM CPU inference. WebGPU belongs to the **full** entry (`volvoxai`).
61
+ Serve the matching WASM file beside the JavaScript bundle, or supply `wasmUrl`
62
+ when your bundler or CDN puts it elsewhere. See [browser and Node deployment](docs/browser-runtime.md).
46
63
 
47
- ## Release artifacts
64
+ For repository development, build both JavaScript entries and their companions:
48
65
 
49
- The fixed browser release files for package version 0.3.0 are:
50
-
51
- ~~~text
52
- dist/0.3.0/volvoxai.js
53
- dist/0.3.0/volvoxai.min.js
54
- dist/0.3.0/volvoxai.full.js
55
- dist/0.3.0/volvoxai.full.min.js
56
- dist/0.3.0/volvoxai.wasm.js
57
- dist/0.3.0/volvoxai.wasm.min.js
58
- dist/0.3.0/volvoxai.wasm
59
- dist/0.3.0/volvoxai.full.wasm
60
- ~~~
61
-
62
- The standard JavaScript entry is inference-only and resolves the forward-only
63
- WASM sidecar. The full entry adds training and resolves volvoxai.full.wasm.
64
- The WASM-only JavaScript entry contains strict WASM inference and training but
65
- no CPU, WebNN, WebGPU, WGSL, or Node filesystem implementation.
66
-
67
- Build all browser artifacts reproducibly with:
68
-
69
- ~~~bash
66
+ ```sh
70
67
  make build_web
71
- ~~~
68
+ ```
69
+
70
+ This uses the repository's Docker toolchain. [Quickstart](docs/quickstart.md)
71
+ explains prerequisites, local builds, and the first runnable example.
72
72
 
73
73
  ## Model packages
74
74
 
75
- An inference package contains:
75
+ A typical package contains:
76
76
 
77
- ~~~text
77
+ ```text
78
78
  graph.json
79
79
  model.safetensors
80
- ~~~
80
+ ```
81
81
 
82
- Every graph root, including named subgraphs, must carry the exact
83
- case-sensitive discriminator:
82
+ The graph describes named inputs, operations, output tensors, and dimension
83
+ bounds. SafeTensors stores the weights; larger packages may use several shards.
84
+ Every graph has the exact `"format": "volvox-graph/v1"` discriminator.
85
+ A static graph uses an empty `dimensions` object; a dynamic graph declares each
86
+ symbol's finite range. See the [model format](docs/model-format.md).
84
87
 
85
- ~~~json
86
- {
87
- "format": "volvox-graph/v1"
88
+ Recreate the example models from their public sources:
89
+
90
+ ```sh
91
+ make models_deps
92
+ make models_efficientdet
93
+ make models_tinystories
94
+ make validate_model_packages
95
+ ```
96
+
97
+ Weights are not committed. [Models and exporters](docs/models.md) explains the
98
+ sources and export options. The browser demos are
99
+ [EfficientDet](examples/efficientdet_lite0.html) and [TinyStories](examples/tinystories.html).
100
+
101
+ ## Web inference
102
+
103
+ The lifecycle is **create a runtime → load a model → compile → run → read outputs**.
104
+ This small ReLU graph needs no downloaded weights. Save the example as an `.mjs`
105
+ file in an installed project or this repository and run it with Node:
106
+
107
+ ```javascript
108
+ import { EngineHost, VxInferenceServiceClient, pb } from 'volvoxai';
109
+
110
+ const host = new EngineHost();
111
+ const inference = new VxInferenceServiceClient(host);
112
+ try {
113
+ const runtime = await inference.createRuntime(new pb.CreateRuntimeRequest());
114
+ const graphDocument = new TextEncoder().encode(JSON.stringify({
115
+ format: 'volvox-graph/v1', dimensions: {},
116
+ inputs: { x: { dtype: 'float32', shape: [2] } },
117
+ nodes: [{
118
+ id: 'relu', opType: 'ReLU', inputs: { input: 'x' },
119
+ outputs: { out: { tensor: 'y', dtype: 'float32', shape: [2] } },
120
+ params: {},
121
+ }],
122
+ outputs: ['y'],
123
+ }));
124
+ const model = await inference.loadModel(new pb.LoadModelRequest({
125
+ runtimeId: runtime.runtimeId,
126
+ package: new pb.ModelPackage({ graphDocument }),
127
+ }));
128
+ const compiled = await inference.compileModel(new pb.CompileModelRequest({
129
+ modelId: model.modelId,
130
+ }));
131
+ const values = Float32Array.of(-2, 3);
132
+ const result = await inference.run(new pb.RunRequest({
133
+ compiledModelId: compiled.compiledModelId,
134
+ inputs: [new pb.Tensor({
135
+ name: 'x', dtype: pb.DataType.DATA_TYPE_F32, shape: [2n],
136
+ inline: new Uint8Array(values.buffer, values.byteOffset, values.byteLength),
137
+ })],
138
+ }));
139
+ const output = await inference.readOutput(new pb.ReadOutputRequest({
140
+ resultId: result.resultId, name: 'y',
141
+ }));
142
+ console.log(Array.from(new Float32Array(output.tensor.inline.slice().buffer)));
143
+ // [0, 3]
144
+ } finally {
145
+ await host.close();
88
146
  }
89
- ~~~
90
-
91
- The loader rejects a missing or different discriminator before allocating
92
- weights or backend resources. Every node input must resolve to a declared graph
93
- input, a named weight, or an earlier node output.
94
-
95
- ## Inference
96
-
97
- ~~~javascript
98
- import { VolvoxAI } from 'volvoxai';
99
-
100
- const runtime = await VolvoxAI.createRuntime({
101
- backends: ['webnn', 'webgpu', 'wasm', 'cpu'],
102
- onDiagnostic(event) {
103
- console.debug(event.kind, event.report ?? event);
104
- },
105
- });
106
-
107
- const model = await runtime.loadModel(
108
- './models/my-model/model.safetensors',
109
- );
110
- const compiled = await model.compile({
111
- backend: {
112
- mode: 'prefer',
113
- order: ['webgpu', 'wasm', 'cpu'],
114
- operatorFallback: 'allow',
115
- },
116
- });
117
- const context = await compiled.createContext();
118
-
119
- const result = await context.execute({
120
- images: new Float32Array(1 * 224 * 224 * 3),
121
- });
122
- const scores = await result.output('scores').read();
123
-
124
- await result.close();
125
- await context.close();
126
- await compiled.close();
127
- await model.close();
128
- await runtime.close();
129
- ~~~
130
-
131
- Runtime loading resolves graph.json beside the first safetensors URL. Pass
132
- graphUrl in the loader options when the graph is stored elsewhere; its basename
133
- must be `graph.json` or a named `*.graph.json` document.
134
-
135
- Compilation pins an immutable topology and weight revision. Create multiple
136
- contexts from one compiled model for independent request or decode state. Each
137
- context serializes its own accepted operations, while different contexts may
138
- progress concurrently.
139
-
140
- ExecutionResult owns a stable snapshot of every declared graph output. A result
141
- remains usable after later executions and after its context closes. Each read()
142
- returns a fresh typed array. A device result may expose deviceBuffer; that
143
- buffer remains owned by the result and must not be destroyed by the caller.
144
-
145
- Use a strict policy when execution must stay on one provider:
146
-
147
- ~~~javascript
148
- const compiled = await model.compile({
149
- backend: {
150
- mode: 'require',
151
- backend: 'webgpu',
152
- operatorFallback: 'forbid',
153
- },
154
- });
155
- ~~~
156
-
157
- Backend selection finishes during compilation. Execution failure is reported
158
- and is never retried on another provider.
159
-
160
- ## Training
161
-
162
- Training is available only from the full and WASM-only profiles. Trainer owns
163
- gradients, optimizer slots, accumulation, and a private working
164
- revision. `trainStep()` mutates only that private revision. `commit()` atomically
165
- publishes it as a new Model weight revision; already compiled models and
166
- contexts remain pinned to their original revision.
167
-
168
- ~~~javascript
169
- import {
170
- ModelBuilder,
171
- VolvoxAI,
172
- } from 'volvoxai/full';
173
-
174
- const builder = new ModelBuilder();
175
- const x = builder.input('x', [1, 4]);
176
- const weight = builder.weight('projection', [4, 8], 'float32', {
177
- initializer: { type: 'xavierUniform', seed: 17 },
178
- });
179
- const logits = builder.addOp(
180
- 'MatMul',
181
- { input: x, weight },
182
- { out: { name: 'logits', shape: [1, 8] } },
183
- {},
184
- { id: 'projection', wLayout: 'din' },
185
- ).out;
186
- builder.outputs(logits);
187
- const graph = builder.build();
188
-
189
- const runtime = await VolvoxAI.createRuntime({ backends: ['cpu'] });
190
- const model = runtime.createModel(graph);
191
- const trainer = await VolvoxAI.createTrainer(model, {
192
- backend: 'cpu',
193
- });
194
-
195
- const step = await trainer.trainStep({
196
- inputs: { x: new Float32Array([1, 2, 3, 4]) },
197
- logitsTensor: 'logits',
198
- targets: new Int32Array([3]),
199
- trainableTensors: ['projection'],
200
- updateMode: 'adamw',
201
- optimizer: { learningRate: 1e-3, maxGradNorm: 1 },
202
- });
203
- await trainer.commit();
204
-
205
- await trainer.close();
206
- await model.close();
207
- await runtime.close();
208
- ~~~
209
-
210
- The same Trainer contract accepts backend: 'webgpu' or backend: 'wasm'. WASM
211
- training is strict and rejects an unsupported graph before mutating weights.
212
- There is no implicit publication: call `commit()` before compiling inference
213
- against the update, or `rollback()` to restore the last committed baseline.
214
- The full profile also exports training builders, checkpoints, gradient
215
- accumulation controls, LoRA helpers, and PTQ authoring tools. See
216
- [model construction and training](docs/model_builder_training.md) and the
217
- [operation matrix](docs/operation_list.md).
218
-
219
- ## WASM-only browser extensions
220
-
221
- For a Manifest V3 extension, package one WASM-only JavaScript variant, the full
222
- sidecar, and the model:
223
-
224
- ~~~text
225
- vendor/volvoxai.wasm.min.js
226
- vendor/volvoxai.full.wasm
227
- model/graph.json
228
- model/model.safetensors
229
- ~~~
230
-
231
- ~~~javascript
232
- import { VolvoxAI } from './vendor/volvoxai.wasm.min.js';
233
-
234
- const runtime = await VolvoxAI.createRuntime({
235
- wasmUrl: chrome.runtime.getURL('vendor/volvoxai.full.wasm'),
236
- });
237
- const model = await runtime.loadModel(
238
- chrome.runtime.getURL('model/model.safetensors'),
239
- { graphUrl: chrome.runtime.getURL('model/graph.json') },
240
- );
241
- ~~~
242
-
243
- Extension pages need wasm-unsafe-eval in their content security policy. The
244
- WASM-only release has no dynamic import and contains no alternate backend.
245
- See [Browser and Node runtime](docs/browser-runtime.md).
147
+ ```
246
148
 
247
- ## Native use
149
+ `pb` contains the request, response, and enum types. Tensor shapes use `bigint`
150
+ values such as `2n`; tensor data is an exact byte view. Inputs always state their
151
+ name, dtype, and concrete shape so the engine can validate the whole batch.
248
152
 
249
- ~~~bash
250
- make build_native
153
+ For a downloaded model, supply `graphPath` and `weightPaths`, or load their bytes
154
+ into `ModelPackage`. `GetModelInfo` reports the required inputs and outputs.
155
+ The [browser runtime guide](docs/browser-runtime.md) shows both forms, WebGPU
156
+ selection, result polling, and session cleanup. The repository also includes
157
+ [a minimal inference script](examples/call_inference.mjs).
251
158
 
252
- ./native/volvoxai --help
253
- ./native/volvoxai-full --help
254
- ~~~
159
+ ## Scheduling and generation
255
160
 
256
- The inference executable provides model-agnostic tensor execution. The full
257
- executable additionally provides training:
161
+ DIRECT is the default for one-shot inference. Choose SCHEDULED explicitly when
162
+ several producers need queue admission and arbitration in the same Runtime.
163
+ Only requests for a compatible compiled route can share a physical batch;
164
+ batching is useful when the graph preserves each request's independence.
258
165
 
259
- ~~~bash
260
- ./native/volvoxai run models/tinystories_1m \
261
- --input tokens=models/tinystories_1m/tokens.i32 \
262
- --input positions=models/tinystories_1m/positions.i32 \
263
- --output logits=out.f32
264
- ~~~
166
+ For text generation, prefill a context with a prompt and then advance it one
167
+ step at a time. Its KV cache retains previous attention state. Paged caches can
168
+ share prefixes and retire individual lanes. `DecodeGenerate` handles a supported
169
+ fixed-count greedy feedback loop; sampling, stop conditions, and task policy
170
+ remain application decisions. See [scheduling and dynamic batching](docs/scheduling-and-dynamic-batching-design.md).
265
171
 
266
- Raw files use a storage suffix matching their declared dtype: .f32, .i32,
267
- .i8, or .u8. Outputs contain the complete declared tensor; applications
268
- select task-specific rows or slices. Model-specific tokenization, image
269
- decoding, generation, and postprocessing live under examples/.
172
+ ## Full-profile training
270
173
 
271
- Native releases use embedded shaders. For shader development,
272
- VOLVOXAI_SHADER_DIR may point to generated spv/, glsl/, gles/, and metal/
273
- directories; VolvoxAI logs once when that external override is actually used.
174
+ Training follows **construct/load train evaluate → commit or roll back → save**.
175
+ The Trainer owns private parameters, gradients, and optimizer state. Existing
176
+ compiled inference models keep their earlier weights after a commit; compile
177
+ again when you want to serve the new revision.
274
178
 
275
- ## Example models
179
+ Use `FullEngineHost` and `VxTrainingServiceClient` from `volvoxai/full`.
180
+ The [training guide](docs/model_builder_training.md) walks through building a
181
+ small classifier, running AdamW, saving a checkpoint, and resuming it.
182
+ It also covers multiple losses, accumulation, shape-cache limits, and LoRA.
276
183
 
277
- Weights are not committed. Recreate the example packages from public sources:
184
+ The [quantization guide](docs/quantization.md) continues from a float package to
185
+ calibration and W8A8 export. Full WASM supports the complete PTQ workflow using
186
+ bytes; your browser application chooses how to save them.
278
187
 
279
- ~~~bash
280
- make models_deps
281
- make models_efficientdet
282
- make models_tinystories
283
- make validate_model_packages
284
- ~~~
285
-
286
- See [Models and exporters](docs/models.md).
287
-
288
- ## Repository layout
289
-
290
- ~~~text
291
- ts/core/ graph/data objects and runtime ownership
292
- ts/ops/ operators, validation, and normalization
293
- ts/backends/ backend providers and device resources
294
- ts/training/ Trainer, autograd, optimizers, checkpoints, and PTQ
295
- examples/ model-specific applications and integrations
296
- shaders/ authoritative WGSL source
297
- native/include/ public opaque inference/provider and full Trainer/PTQ C APIs
298
- native/src/runtime/ runtime/model/context/result implementation
299
- native/src/kernels/ portable and optimized CPU/WASM kernels
300
- native/src/backends/ native device integrations
301
- native/src/training/ full-profile training implementation
302
- runtime/ optional in-process Synurang FFI plugin
303
- ~~~
304
-
305
- ## Documentation
306
-
307
- - [Quickstart](docs/quickstart.md)
308
- - [Browser and Node runtime](docs/browser-runtime.md)
309
- - [Native runtime](docs/native-runtime.md)
310
- - [Backend SDK](docs/backend-sdk.md)
311
- - [Model format](docs/model-format.md)
312
- - [Graph exporter and optimizer design](docs/graph-optimizer-design.md)
313
- - [Typed PTQ](docs/typed-ptq.md)
314
- - [Model construction and training](docs/model_builder_training.md)
315
- - [Operation support matrix](docs/operation_list.md)
316
- - [Testing and validation](docs/testing.md)
317
- - [Models and exporters](docs/models.md)
318
- - [Textbook](docs/textbook/README.md)
188
+ ## Native use
189
+
190
+ ```sh
191
+ make build_native_profiles
192
+ ./native/volvoxai-lite --help
193
+ ./native/volvoxai --help
194
+ ```
195
+
196
+ Both executables run named raw tensors. Full additionally provides `train`.
197
+ For example, after the [quickstart](docs/quickstart.md#4-run-tinystories-from-native-c)
198
+ prepares a TinyStories package and six I32 tokens and positions:
199
+
200
+ ```sh
201
+ ./native/volvoxai-lite run models/tinystories_1m \
202
+ --input 'tokens[1,6]=build/quickstart/tokens.i32' \
203
+ --input 'positions[1,6]=build/quickstart/positions.i32' \
204
+ --output logits=build/quickstart/logits.f32
205
+ ```
206
+
207
+ Use the [native guide](docs/native-runtime.md) for input preparation, CPU threads,
208
+ backend selection, embedding, and macOS/Android builds. The
209
+ [task CLI](examples/native_task_cli/README.md) adds image decoding and detection.
210
+ Native releases embed shaders; `VOLVOXAI_SHADER_DIR` provides a development
211
+ override and logs once when used.
212
+
213
+ ## Python
214
+
215
+ The [Python package](python/README.md) provides native CPU/GPU inference,
216
+ training, quantization, tokenization, graph planning and scheduling through the
217
+ same generated API. Linux x86_64 wheels bundle inference/full libraries and the
218
+ loader, with CUDA, Vulkan and OpenGL backends. They also include ONNX conversion
219
+ and a PTQ command-line workflow.
220
+
221
+ ```sh
222
+ make build_wheel
223
+ python3 -m pip install dist/python/0.5.0/*.whl
224
+ ```
225
+
226
+ For an exported model with one input, `InferenceSession` handles loading,
227
+ compilation, NumPy input/output and cleanup. CPU and automatic thread selection
228
+ are the defaults; FP32/INT8 precision comes from the model:
229
+
230
+ ```python
231
+ import numpy as np
232
+ import volvoxai as vx
233
+
234
+ with vx.InferenceSession("path/to/model") as session:
235
+ outputs = session.run(np.load("input.npy"))
236
+ ```
237
+
238
+ Use `AsyncInferenceSession` for asyncio, `vx.quantize` for streaming NumPy
239
+ calibration, and `TrainingSession` for training, saving and checkpoint resumption.
240
+ These workflows select the appropriate library and raise Python exceptions.
241
+ `InferenceSession.run_tensors()` retains CPU/CUDA results, reuses them as
242
+ inputs, and shares compatible buffers with PyTorch through DLPack.
243
+ `run()` continues to return NumPy arrays; GPU array libraries remain optional.
244
+ See the Python guide for full workflows, supported environments and PyPI
245
+ publishing. Python artifacts live outside the fixed npm release directory.
246
+
247
+ ## Documentation and API reference
248
+
249
+ The [documentation index](docs/README.md) separates learning material from
250
+ integration and engine-development guides. Useful starting points:
251
+
252
+ - [Quickstart](docs/quickstart.md) and [textbook](docs/textbook/README.md)
253
+ - [Model format](docs/model-format.md) and [operator support](docs/operation_list.md)
254
+ - [Architecture](ARCHITECTURE.md) and [backend development](docs/backend-sdk.md)
255
+ - [Testing](docs/testing.md) and [profiling](docs/profiling.md)
256
+
257
+ The schema in [volvoxai.proto](proto/volvoxai.proto) defines the shared API for
258
+ applications and AI agents. For field-level lookup and programmatic discovery,
259
+ use [API discovery](docs/api-discovery.md) and the generated
260
+ [inference](docs/generated/api-contract.inference.md) / [full](docs/generated/api-contract.full.md)
261
+ references. [Runtime integration](runtime/README.md) covers C/Python bindings
262
+ and regeneration. These references complement the task-oriented guides above.
263
+
264
+ ## Build and verify
265
+
266
+ ```sh
267
+ npm ci
268
+ npm run build:all # build JS first; this removes stale WASM companions
269
+ make build_wasm # both WASM profiles
270
+ make build_native_profiles # both native profiles
271
+ npm run test:proto-api
272
+ npm run test:wasm-ptq
273
+ npm run test:wasm-training-smoke
274
+ make test_native
275
+ npm run check:release
276
+ ```
277
+
278
+ The fixed release inventory is four JS files (`volvoxai.lite.js`, `volvoxai.lite.min.js`,
279
+ `volvoxai.js`, `volvoxai.min.js`) and two WASM files (`volvoxai.lite.wasm`,
280
+ `volvoxai.wasm`) under `dist/<package-version>/`, plus `native/volvoxai-lite`
281
+ and `native/volvoxai`. See [testing](docs/testing.md) for release gates and
282
+ [deployment](docs/browser-runtime.md#packaging-and-browser-extensions) for runtime ZIPs and extensions.
319
283
 
320
284
  ## License
321
285