@nexart/codemode-sdk 1.7.0 → 1.8.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.
package/README.md CHANGED
@@ -1,279 +1,285 @@
1
- # NexArt Code Mode Runtime SDK
2
-
3
- **Version: 1.7.0 (Protocol v1.2.0)**
4
-
5
- ╔══════════════════════════════════════════════════════════════════════════════╗
6
- ║ @nexart/codemode-sdk — Canonical Execution Surface ║
7
- ║ ║
8
- ║ This SDK IS the protocol. All implementations MUST use this SDK. ║
9
- ║ ║
10
- ║ Protocol: nexart ║
11
- ║ Engine: codemode ║
12
- ║ SDK Version: 1.7.0 ║
13
- ║ Protocol Version: 1.2.0 ║
14
- ║ Phase: 3 ║
15
- ║ Enforcement: HARD ║
16
- ╚══════════════════════════════════════════════════════════════════════════════╝
1
+ # @nexart/codemode-sdk
17
2
 
18
- ---
19
-
20
- ## Commercial Licensing
21
-
22
- > **Commercial usage of NexArt Protocol requires a license.**
23
- > **Enforcement is not active yet.**
3
+ **Version: 1.8.1 (Protocol v1.2.0)**
24
4
 
25
- The SDK is currently provided under the MIT License for all usage. A future version may introduce commercial licensing requirements. See [LICENSE.md](./LICENSE.md) for details.
5
+ A deterministic execution runtime for reproducible, verifiable computation.
26
6
 
27
7
  ---
28
8
 
29
- ## PROTOCOL LOCK v1.x
30
-
31
- | Property | Value |
32
- |----------|-------|
33
- | Protocol Name | NexArt Code Mode |
34
- | Version | v1.2.0 |
35
- | Status | **STABLE** |
36
- | Phase | 3 |
37
- | Lock Date | January 2026 |
38
-
39
- **Core protocol surface is frozen. Any breaking change requires v2.0.0.**
9
+ ## What This SDK Does
40
10
 
41
- The following are locked and will not change in v1.x:
11
+ This SDK provides a **deterministic runtime layer** for executing code that must produce identical output given identical inputs — across environments, over time, and under verification.
42
12
 
43
- - Execution model (Static and Loop modes)
44
- - VAR[0..9] specification (0-10 read-only variables, missing indices return 0)
45
- - Determinism guarantee (seed + VAR → identical output)
46
- - Time semantics (t, frameCount, time, tGlobal, totalFrames)
47
- - Random and noise behavior (seeded Mulberry32, Perlin)
48
- - Forbidden patterns list (13 patterns)
49
- - Canvas pre-initialization (no createCanvas)
13
+ **Core guarantees:**
14
+ - Same `seed` + `vars` + `code` identical output (always)
15
+ - Cross-environment stability (browser, Node.js, CI pipelines)
16
+ - Strict mode blocks non-deterministic APIs (`Math.random`, `Date.now`, etc.)
17
+ - Canonical state snapshots for replay and verification
18
+ - Stable digest for integrity verification
50
19
 
51
20
  ---
52
21
 
53
- A minimal, deterministic rendering engine for generative art.
22
+ ## Who This Is For
23
+
24
+ **Use this SDK if determinism is non-negotiable:**
54
25
 
55
- ## Protocol Authority
26
+ - **On-chain generative art** — NFTs, archival renders, mint verification
27
+ - **Procedural games** — Open-world generation, replay systems, save states
28
+ - **Simulations** — Physics, agent-based models, reproducible experiments
29
+ - **Finance research** — Backtesting, Monte Carlo, reproducible analysis
30
+ - **Education labs** — Repeatable demonstrations, grading consistency
56
31
 
57
- **This SDK is the single source of truth for Code Mode semantics.**
32
+ **Skip this SDK if you're building:**
58
33
 
59
- If someone asks: "How does Code Mode work in NexArt?"
34
+ - CRUD apps
35
+ - Dashboards
36
+ - E-commerce
37
+ - Typical web applications without reproducibility requirements
60
38
 
61
- The answer is: "Whatever @nexart/codemode-sdk does — that is the protocol."
39
+ For most applications, seeded randomness is unnecessary complexity.
62
40
 
63
41
  ---
64
42
 
65
- ## What's New in v1.7.0
43
+ ## For AI Coding Agents (Replit / Lovable / Claude Code)
66
44
 
67
- **Browser-Safe Entrypoint + Conditional Exports**
45
+ **Use `createRuntime({ seed, strict: true })` for deterministic execution.**
68
46
 
69
- This release makes the SDK reliably usable in browser environments (Vite/React) without any Node.js dependency leakage.
47
+ ```typescript
48
+ import { createRuntime } from "@nexart/codemode-sdk";
70
49
 
71
- ### New Entry Points
72
- - `@nexart/codemode-sdk/browser` — Browser-safe modules only (no Node.js dependencies)
73
- - `@nexart/codemode-sdk/node` Full SDK including static-engine (requires `canvas` package)
50
+ const runtime = createRuntime({
51
+ seed: "my-artwork-42",
52
+ vars: [50, 75, 25],
53
+ strict: true, // Throws on Math.random, Date.now, etc.
54
+ mode: "static"
55
+ });
74
56
 
75
- ### Package.json Conditional Exports
76
- - Default import (`.`) now uses conditional exports: browser gets browser entry, Node gets Node entry
77
- - Explicit subpaths: `./browser` and `./node` for direct control
57
+ // Deterministic APIs
58
+ const value = runtime.random(); // [0, 1)
59
+ const intVal = runtime.randomInt(0, 10); // integer in range
60
+ const n = runtime.noise(x, y); // Perlin noise
78
61
 
79
- ### Why This Matters
80
- - AI agents and bundlers will no longer accidentally import Node.js modules in browser builds
81
- - Vite/React apps can safely import the SDK without "createRequire is not defined" errors
82
- - Server-side code gets full functionality including static image rendering
62
+ // Verification
63
+ console.log(runtime.digest()); // Stable hash
64
+ console.log(runtime.getState()); // Canonical state snapshot
65
+ ```
83
66
 
84
- ### No Breaking Changes
85
- - Protocol behavior and determinism unchanged
86
- - API surface unchanged
87
- - Existing Node.js code continues to work
67
+ **Strict mode throws actionable errors:**
68
+ - `NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.`
69
+ - `NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.`
88
70
 
89
71
  ---
90
72
 
91
- ## What's New in v1.6.0
92
-
93
- **Licensing & Builder Identity Scaffolding (Metadata Only)**
73
+ ## Where This Fits
94
74
 
95
- This is a non-breaking, metadata-only release. No changes to execution or determinism.
96
-
97
- ### Licensing (Informational Only)
98
- - Added `LICENSE.md` with draft commercial licensing terms
99
- - Enforcement is NOT active — all usage currently permitted under MIT
100
-
101
- ### Builder Manifest Schema
102
- - Added `builder.manifest.schema.json` for optional builder attribution
103
- - Fields: `builder_id`, `project_name`, `contact`, `website`, `intended_use`
104
- - This file is **optional**, **not validated**, and **not loaded at runtime**
75
+ ```
76
+ ┌─────────────────────────────────────────────────────────┐
77
+ │ Your Application │
78
+ │ (React, Canvas, Three.js, game engine, simulation) │
79
+ └────────────────────────┬────────────────────────────────┘
80
+
81
+
82
+ ┌─────────────────────────────────────────────────────────┐
83
+ │ @nexart/codemode-sdk │
84
+ │ Deterministic runtime layer │
85
+ │ - Seeded PRNG (Mulberry32) │
86
+ │ - Seeded noise (Perlin) │
87
+ │ - Strict mode enforcement │
88
+ │ - State snapshots + digest │
89
+ └────────────────────────┬────────────────────────────────┘
90
+
91
+
92
+ ┌─────────────────────────────────────────────────────────┐
93
+ │ Output │
94
+ │ - Deterministic result │
95
+ │ - Verification digest │
96
+ │ - Replay state │
97
+ └─────────────────────────────────────────────────────────┘
98
+ ```
105
99
 
106
- ### Documentation
107
- - SDK positioned as "canonical execution surface"
108
- - Explicit determinism guarantees documented
109
- - Real product references (ByX, Frontierra)
100
+ The SDK sits between your UI/framework and your output. It does not render, does not manage state, does not touch the DOM. It provides deterministic primitives.
110
101
 
111
102
  ---
112
103
 
113
- ## Determinism Guarantees
114
-
115
- **The NexArt Code Mode SDK guarantees deterministic output.**
104
+ ## Why Not Roll Your Own?
116
105
 
117
- Given identical inputs:
118
- - Same `source` code
119
- - Same `seed`
120
- - Same `vars` array
121
- - Same `width` and `height`
122
- - Same `mode`
106
+ **What's easy:**
107
+ - Seeded PRNG (dozens of implementations exist)
108
+ - Noise libraries (simplex, Perlin, available everywhere)
123
109
 
124
- The SDK will produce **byte-for-byte identical output** across all executions.
110
+ **What's hard:**
111
+ - **Cross-environment stability** — Same seed producing same sequence across browser versions, Node.js versions, bundlers, and platforms
112
+ - **Strict enforcement** — Actually blocking `Math.random()` and `Date.now()` during execution, with actionable error messages
113
+ - **Replay and verification** — Canonical state snapshots that can reconstruct execution
114
+ - **Long-term drift resistance** — Guaranteeing identical output years later, not just today
125
115
 
126
- ### What Breaks Determinism
116
+ If you need a quick seeded random, use any PRNG. If you need guaranteed reproducibility across time, environments, and verification systems — that's what this SDK provides.
127
117
 
128
- The following actions will break determinism and are **blocked** by the SDK:
118
+ ---
129
119
 
130
- | Pattern | Reason | Enforcement |
131
- |---------|--------|-------------|
132
- | `Math.random()` | Unseeded randomness | BLOCKED |
133
- | `Date.now()` | Time-based entropy | BLOCKED |
134
- | `new Date()` | Time-based entropy | BLOCKED |
135
- | `performance.now()` | Timing entropy | BLOCKED |
136
- | `crypto.getRandomValues()` | Crypto randomness | BLOCKED |
137
- | `fetch()` | External IO | BLOCKED |
138
- | External imports | Uncontrolled code | BLOCKED |
120
+ ## Determinism Contract
139
121
 
140
- Use `random()` (seeded) and `noise()` (seeded) for all randomness needs.
122
+ **Guaranteed:**
123
+ - Same `sdkVersion` + `seed` + `vars` → identical output
124
+ - Cross-environment stable digest (browser, Node.js, CI)
125
+ - Seeded PRNG via `runtime.random()` (Mulberry32)
126
+ - Seeded noise via `runtime.noise()` (Perlin)
141
127
 
142
- ### Oracle Verification
128
+ **Forbidden (blocked in strict mode):**
129
+ - `Math.random()` — use `runtime.random()` instead
130
+ - `Date.now()` — pass time as input or use frame counters
131
+ - `performance.now()` — use deterministic timing
132
+ - External IO during deterministic runs
143
133
 
144
- Before any release, run the determinism check:
134
+ ---
145
135
 
146
- ```bash
147
- npx tsx scripts/check-determinism.ts
148
- ```
136
+ ## Feature Comparison
149
137
 
150
- This compares output against a known oracle hash. If the hash changes without a protocol version bump, the release is invalid.
138
+ | Feature | Plain PRNG | This SDK |
139
+ |---------|-----------|----------|
140
+ | Seeded random | ✅ | ✅ |
141
+ | Seeded noise | ❌ (separate lib) | ✅ built-in |
142
+ | Strict mode (blocks entropy) | ❌ | ✅ |
143
+ | Canonical state snapshot | ❌ | ✅ `getState()` |
144
+ | Cross-env stable digest | ❌ | ✅ `digest()` |
145
+ | VAR protocol (0-100 inputs) | ❌ | ✅ |
146
+ | Replay/verification | Manual | Built-in |
147
+ | Error messages for agents | ❌ | ✅ actionable |
151
148
 
152
149
  ---
153
150
 
154
- ## Products Using This SDK
151
+ ## Environment Imports
155
152
 
156
- - **NexArt**: Primary generative art platform
157
- - **ByX**: Curated collection system
158
- - **Frontierra**: External builder integration
153
+ | Environment | Import Path |
154
+ |-------------|-------------|
155
+ | Browser / Vite / Next.js / React | `import { createRuntime } from "@nexart/codemode-sdk"` |
156
+ | Node.js (general use) | `import { createRuntime } from "@nexart/codemode-sdk"` |
157
+ | Node.js server rendering (canvas) | `import { executeCodeMode } from "@nexart/codemode-sdk/node"` |
159
158
 
160
- ---
159
+ **The default import is browser-safe.** Node-only features require explicit `/node` import.
161
160
 
162
- ## v1.5.1
161
+ ---
163
162
 
164
- **Builder Manifest — Passive Attribution (Write-Only)**
163
+ ## Used By
165
164
 
166
- - `registerBuilderManifest(manifest?)`Declare builder identity for future attribution
165
+ - **NexArt**Generative art platform
166
+ - **ByX** — Curated collections
167
+ - **Frontierra** — External builder integration
167
168
 
168
- The Builder Manifest is a declaration of intent, not a capability. Write-only, optional, non-enforced.
169
+ These are examples the SDK is designed for any system requiring deterministic execution.
169
170
 
170
171
  ---
171
172
 
172
- ## v1.4.0 (Protocol v1.2.0)
173
+ ## Protocol Stability
173
174
 
174
- **Phase 3 Pixel & Graphics**
175
+ | Property | Value |
176
+ |----------|-------|
177
+ | Protocol Version | v1.2.0 |
178
+ | Status | **STABLE** |
179
+ | SDK Version | 1.8.1 |
175
180
 
176
- - **Vertex Functions**: `curveVertex(x, y)`, `bezierVertex(cx1, cy1, cx2, cy2, x, y)` for smooth curves
177
- - **Pixel System**: `loadPixels()`, `updatePixels()`, `pixels[]`, `get(x, y)`, `set(x, y, color)`
178
- - **Graphics System**: `createGraphics(w, h)`, `image(pg, x, y, w, h)` for offscreen rendering
179
- - **totalFrames**: Now injected into Loop Mode runtime
181
+ **Core protocol surface is frozen. Breaking changes require v2.0.0.**
180
182
 
181
- ## v1.3.0 (Protocol v1.1.0)
183
+ The following are locked in v1.x:
184
+ - Execution model (Static and Loop modes)
185
+ - VAR[0..9] specification
186
+ - Determinism guarantee
187
+ - Time semantics (t, frameCount, time, tGlobal, totalFrames)
188
+ - Random and noise behavior
189
+ - Forbidden patterns list
182
190
 
183
- **Phase 2 — Expressive Extensions**
191
+ ---
184
192
 
185
- - **Math Helpers**: `fract(n)`, `sign(n)`
186
- - **Vector Helpers**: `vec`, `vecAdd`, `vecSub`, `vecMult`, `vecMag`, `vecNorm`, `vecDist`
187
- - **Shape Helpers**: `polygon()`, `star()`
188
- - **Blend Modes**: `blendMode(NORMAL|ADD|MULTIPLY|SCREEN)`
189
- - **Noise Extensions**: `fbm()`, `ridgedNoise()`, `curlNoise()`
190
- - **Easing Functions**: `easeIn`, `easeOut`, `easeInOut`, `easeCubic`, `easeExpo`
193
+ ## Licensing
191
194
 
192
- ## v1.2.0
195
+ Free for personal projects, experiments, research, and open-source.
193
196
 
194
- - Added `bezier()`, `curve()`, `strokeCap()`, `strokeJoin()`, `shearX()`, `shearY()`
195
- - Added text system: `text()`, `textSize()`, `textFont()`, `textAlign()`, `textWidth()`
196
- - Added `sq()`, `int()`, `TAU`, arc mode constants
197
+ Commercial production deployments require a license.
197
198
 
198
- ## v1.1.1
199
+ See [COMMERCIAL.md](./COMMERCIAL.md) for details.
199
200
 
200
- - **Critical Fix**: `random()` now uses seeded Mulberry32 PRNG (was using Math.random)
201
- - All randomness is now deterministic
201
+ ---
202
202
 
203
- ## v1.0.x (Protocol Lock)
203
+ ## Installation
204
204
 
205
- - **Protocol Lock**: Phase 1 execution surface is now LOCKED
206
- - **Canonical Entry Point**: `executeCodeMode()` is the official execution API
207
- - **VAR[0..9] Protocol Variables**: First-class protocol inputs (read-only, 0-100)
208
- - **Determinism Guarantee**: Same code + seed + vars = identical output
205
+ ```bash
206
+ npm install @nexart/codemode-sdk
207
+ ```
209
208
 
210
209
  ---
211
210
 
212
- ## What This SDK Is
213
-
214
- This SDK provides the **canonical runtime** for executing p5.js-style generative art:
215
-
216
- - **Static Mode**: Executes `setup()` only, outputs PNG
217
- - **Loop Mode**: Frame-authoritative rendering, outputs MP4
218
- - **Deterministic**: Seed-controlled randomness, no external state
219
- - **Protocol-Compliant**: All outputs include verification metadata
211
+ ## Runtime API
220
212
 
221
- The SDK enforces the **NexArt Code Mode Protocol v1.2.0** for reproducible, mint-safe generative art.
213
+ ### `createRuntime(options)`
222
214
 
223
- ---
215
+ Create a deterministic runtime instance.
224
216
 
225
- ## What This SDK Is NOT
217
+ ```typescript
218
+ import { createRuntime } from "@nexart/codemode-sdk";
219
+
220
+ const runtime = createRuntime({
221
+ seed: "my-seed",
222
+ vars: [50, 75],
223
+ strict: true,
224
+ mode: "static",
225
+ metadata: { artist: "demo" }
226
+ });
226
227
 
227
- - **Not a suggestion** — This SDK IS the protocol, not a reference implementation
228
- - **Not a UI library** — No React components, no wallet integration
229
- - **Not an IPFS client** — Does not handle storage or minting
230
- - **Not p5.js** Uses a minimal subset of p5.js-like functions
228
+ runtime.random(); // Deterministic PRNG
229
+ runtime.randomInt(0, 100); // Deterministic integer
230
+ runtime.noise(x, y, z); // Deterministic Perlin noise
231
+ runtime.digest(); // Stable hash for verification
232
+ runtime.getState(); // Canonical state snapshot
233
+ runtime.run(() => { ... }); // Execute with strict enforcement
234
+ ```
231
235
 
232
- ---
236
+ ### Strict Mode
233
237
 
234
- ## Installation
238
+ When `strict: true`, the runtime intercepts non-deterministic APIs during `run()`:
235
239
 
236
- ```bash
237
- # Copy the sdk/codemode folder to your project
238
- cp -r sdk/codemode your-project/lib/codemode
240
+ ```typescript
241
+ runtime.run(() => {
242
+ Math.random(); // Throws: NEXART_STRICT: Non-deterministic API used
243
+ });
239
244
  ```
240
245
 
246
+ Strict mode:
247
+ - Only applies during `runtime.run()` — non-invasive
248
+ - Does NOT globally mutate your application
249
+ - Provides actionable error messages
250
+
241
251
  ---
242
252
 
243
- ## Browser Usage (v1.7.0+)
253
+ ## Browser Usage
244
254
 
245
- For Vite, React, Next.js, or any browser environment, import from the browser-safe entry:
255
+ For Vite, React, Next.js, or any browser environment:
246
256
 
247
257
  ```typescript
248
258
  import {
259
+ createRuntime,
249
260
  runLoopMode,
250
261
  cancelLoopMode,
251
262
  createP5Runtime,
252
263
  validateCodeModeSource,
253
- PROTOCOL_IDENTITY,
254
- DEFAULT_CONFIG,
255
- } from '@nexart/codemode-sdk/browser';
264
+ } from '@nexart/codemode-sdk';
256
265
  ```
257
266
 
258
- **What's included in `@nexart/codemode-sdk/browser`:**
259
- - All types (RenderMode, EngineConfig, ExecuteCodeModeInput, etc.)
267
+ **What's included:**
268
+ - Runtime API (createRuntime)
260
269
  - P5 runtime (createP5Runtime, injectTimeVariables, injectProtocolVariables)
261
270
  - Loop engine (runLoopMode, cancelLoopMode)
262
271
  - Execution sandbox (FORBIDDEN_APIS, createSafeMath)
263
272
  - Validation (validateCodeModeSource)
264
- - Builder manifest (registerBuilderManifest)
265
273
 
266
274
  **What's NOT included (Node.js only):**
267
- - `executeCodeMode` — Uses static-engine which requires Node.js canvas
268
- - `runStaticMode` — Requires Node.js canvas package
269
-
270
- For static rendering in browser apps, use your server-side API endpoint.
275
+ - `executeCodeMode` — Requires Node.js canvas
276
+ - `runStaticMode` — Requires Node.js canvas
271
277
 
272
278
  ---
273
279
 
274
- ## Node.js Usage (v1.7.0+)
280
+ ## Node.js Usage
275
281
 
276
- For server-side rendering, oracles, or CLI tools, import from the Node entry:
282
+ For server-side rendering, oracles, or CLI tools:
277
283
 
278
284
  ```typescript
279
285
  import {
@@ -284,27 +290,20 @@ import {
284
290
  } from '@nexart/codemode-sdk/node';
285
291
  ```
286
292
 
287
- **What's included in `@nexart/codemode-sdk/node`:**
288
- - Everything from the browser entry
289
- - `executeCodeMode` — Canonical execution API
290
- - `runStaticMode` — Node.js static rendering (requires `canvas` package)
291
-
292
293
  **Requirements:**
293
294
  - Node.js 18+
294
- - `canvas` package installed for static mode (`npm install canvas`)
295
+ - `canvas` package for static mode
295
296
 
296
297
  ---
297
298
 
298
- ## Canonical API
299
-
300
- ### `executeCodeMode(input: ExecuteCodeModeInput): Promise<ExecuteCodeModeResult>`
299
+ ## Canonical Execution API
301
300
 
302
- **This is the official, canonical entry point for Code Mode execution.**
301
+ ### `executeCodeMode(input): Promise<Result>`
303
302
 
304
- All implementations MUST use this function.
303
+ For systems requiring p5.js-style execution with full protocol metadata:
305
304
 
306
305
  ```typescript
307
- import { executeCodeMode } from '@nexart/codemode-sdk';
306
+ import { executeCodeMode } from '@nexart/codemode-sdk/node';
308
307
 
309
308
  const result = await executeCodeMode({
310
309
  source: `
@@ -322,180 +321,24 @@ const result = await executeCodeMode({
322
321
  mode: 'static'
323
322
  });
324
323
 
325
- // Result includes protocol metadata
326
- console.log(result.metadata.protocol); // 'nexart'
327
- console.log(result.metadata.engine); // 'codemode'
328
- console.log(result.metadata.protocolVersion); // '1.2.0'
329
- console.log(result.metadata.deterministic); // true
330
- console.log(result.image); // PNG Blob
331
- ```
332
-
333
- ### Input Parameters
334
-
335
- | Parameter | Type | Required | Description |
336
- |-----------|------|----------|-------------|
337
- | `source` | `string` | ✅ | Code with setup() and optional draw() |
338
- | `width` | `number` | ✅ | Canvas width in pixels |
339
- | `height` | `number` | ✅ | Canvas height in pixels |
340
- | `seed` | `number` | ✅ | Seed for deterministic randomness |
341
- | `vars` | `number[]` | ❌ | VAR[0..9] values (0-100), defaults to all zeros |
342
- | `mode` | `'static' \| 'loop'` | ✅ | Execution mode |
343
- | `totalFrames` | `number` | ⚠️ | Required for loop mode |
344
-
345
- ### Result Structure
346
-
347
- ```typescript
348
- interface ExecuteCodeModeResult {
349
- image?: Blob; // Static mode: PNG
350
- video?: Blob; // Loop mode: MP4
351
- frames?: ImageData[]; // Optional: raw frame data
352
- metadata: {
353
- protocol: 'nexart';
354
- engine: 'codemode';
355
- protocolVersion: '1.0.0';
356
- phase: 1;
357
- deterministic: true;
358
- seed: number;
359
- vars: number[];
360
- width: number;
361
- height: number;
362
- mode: 'static' | 'loop';
363
- totalFrames?: number;
364
- }
365
- }
324
+ console.log(result.metadata.deterministic); // true
325
+ console.log(result.image); // PNG Blob
366
326
  ```
367
327
 
368
328
  ---
369
329
 
370
- ## Legacy API
371
-
372
- > ⚠️ **Note**: The `createEngine()` API is still supported but new implementations should use `executeCodeMode()`.
373
-
374
- ### `createEngine(config: EngineConfig): Engine`
375
-
376
- Create a rendering engine instance.
377
-
378
- ```typescript
379
- import { createEngine } from './codemode';
380
-
381
- const engine = createEngine({
382
- mode: 'static', // 'static' | 'loop'
383
- width: 1950, // Optional, default: 1950
384
- height: 2400, // Optional, default: 2400
385
- duration: 2, // Loop mode only, 1-4 seconds
386
- fps: 30, // Loop mode only, default: 30
387
- });
388
- ```
389
-
390
- ### `engine.run(options: RunOptions): Promise<void>`
391
-
392
- Execute code and produce output.
393
-
394
- ```typescript
395
- await engine.run({
396
- code: `
397
- function setup() {
398
- background(255);
399
- fill(0);
400
- // Use VAR for external control
401
- let size = map(VAR[0], 0, 100, 50, 200);
402
- ellipse(width/2, height/2, size);
403
- }
404
- `,
405
- seed: 12345, // Optional: seed for deterministic randomness
406
- vars: [50, 75, 0, 0, 0, 0, 0, 0, 0, 0], // Optional: VAR[0..9] values (0-100)
407
- onPreview: (canvas) => {
408
- // Optional: called with canvas after first frame
409
- },
410
- onProgress: (info) => {
411
- // Optional: progress updates
412
- console.log(info.message, info.percent + '%');
413
- },
414
- onComplete: (result) => {
415
- // Required: called with final result
416
- console.log(result.type); // 'image' | 'video'
417
- console.log(result.blob); // Blob
418
- },
419
- onError: (error) => {
420
- // Optional: called on error
421
- console.error(error);
422
- },
423
- });
424
- ```
425
-
426
- ### Protocol Variables (VAR[0..9]) — Protocol v1.0.0
427
-
428
- Protocol variables are first-class inputs that control artwork parameters.
429
-
430
- **VAR Specification (SDK v1.0.2):**
431
-
432
- | Property | Value | Enforcement |
433
- |----------|-------|-------------|
434
- | Input count | 0-10 (VAR[0]..VAR[9]) | HARD — throws if > 10 |
435
- | Runtime count | Always 10 | Padded with zeros |
436
- | Type | finite number | HARD — throws if non-number |
437
- | Range | 0-100 | HARD — throws if out of range |
438
- | Mutability | Read-only | HARD — Proxy blocks writes |
439
- | Injection | Before execution | Guaranteed |
440
- | Lifecycle | Stable for entire render | Guaranteed |
441
- | Default | All zeros | If not provided |
442
-
443
- ```typescript
444
- // Pass values when running (0-10 elements)
445
- await engine.run({
446
- code: myCode,
447
- vars: [80, 50, 25], // VAR[0]=80, VAR[1]=50, VAR[2]=25, VAR[3..9]=0
448
- onComplete: (result) => { /* ... */ },
449
- });
450
-
451
- // Or omit entirely (all zeros)
452
- await engine.run({
453
- code: myCode,
454
- onComplete: (result) => { /* ... */ },
455
- });
456
-
457
- // Access in sketch code
458
- function setup() {
459
- let density = map(VAR[0], 0, 100, 10, 200);
460
- let speed = map(VAR[1], 0, 100, 0.5, 5);
461
- // VAR[5] returns 0 if not provided
462
- }
463
- ```
464
-
465
- **Rules (Protocol Law):**
466
- - Input accepts 0-10 elements; runtime VAR is always 10 elements
467
- - VAR is injected BEFORE code execution (padded with zeros if needed)
468
- - VAR values are READ-ONLY at runtime (Proxy-protected)
469
- - Writing to VAR throws a protocol error
470
- - Values MUST be in range 0-100 (throws if out of range)
471
- - Same code + same seed + same VARs = identical output
472
-
473
- ### `engine.stop(): void`
474
-
475
- Cancel a running render (Loop mode only).
476
-
477
- ### `engine.getConfig(): EngineConfig`
478
-
479
- Get the resolved engine configuration.
480
-
481
- ---
482
-
483
330
  ## Execution Rules
484
331
 
485
332
  ### Static Mode
486
-
487
- 1. `setup()` is executed once
488
- 2. `draw()` is **NOT** executed
489
- 3. Canvas is captured as PNG
490
- 4. Time variables are all `0`
333
+ 1. `setup()` executes once
334
+ 2. `draw()` is NOT executed
335
+ 3. Canvas captured as PNG
336
+ 4. Time variables are 0
491
337
 
492
338
  ### Loop Mode
493
-
494
- 1. `setup()` is executed once
495
- 2. `draw()` is executed once per frame
496
- 3. Canvas is **cleared** before each `draw()` call
497
- 4. If artist calls `background()` in draw, it paints over the clear
498
- 5. No canvas persistence between frames
339
+ 1. `setup()` executes once
340
+ 2. `draw()` executes per frame
341
+ 3. Canvas cleared before each `draw()`
499
342
 
500
343
  **Time Variables:**
501
344
 
@@ -505,277 +348,49 @@ Get the resolved engine configuration.
505
348
  | `t` | float | Normalized time [0.0, 1.0) |
506
349
  | `time` | float | Elapsed seconds |
507
350
  | `tGlobal` | float | Alias for `t` |
351
+ | `totalFrames` | int | Total frames in loop |
508
352
 
509
353
  ---
510
354
 
511
- ## Forbidden Patterns — LOCKED v1.0.0
355
+ ## Forbidden Patterns
512
356
 
513
- The following 13 patterns are rejected with `[Code Mode Protocol Error]`:
357
+ The following are rejected with `[Code Mode Protocol Error]`:
514
358
 
515
359
  | Pattern | Reason |
516
360
  |---------|--------|
517
- | `setTimeout` | Async timing breaks determinism |
518
- | `setInterval` | Async timing breaks determinism |
519
- | `requestAnimationFrame` | Async timing breaks determinism |
520
- | `Date.now()` | Time-based entropy forbidden |
521
- | `new Date()` | Time-based entropy forbidden |
522
- | `Math.random()` | Use seeded `random()` instead |
523
- | `fetch()` | External IO forbidden |
524
- | `XMLHttpRequest` | External IO forbidden |
525
- | `createCanvas()` | Canvas is pre-initialized |
526
- | `document.*` | DOM access forbidden |
527
- | `window.*` | DOM access forbidden |
528
- | `import` | External imports forbidden |
529
- | `require()` | External imports forbidden |
530
-
531
- Additionally in Loop Mode:
532
- - `noLoop()` — Incompatible with frame capture
533
-
534
- ---
535
-
536
- ## Example: Static Mode
537
-
538
- ```typescript
539
- import { createEngine } from './codemode';
540
-
541
- const engine = createEngine({ mode: 'static' });
542
-
543
- await engine.run({
544
- code: `
545
- function setup() {
546
- background(30);
547
- noStroke();
548
- for (let i = 0; i < 100; i++) {
549
- fill(random(255), random(255), random(255));
550
- ellipse(random(width), random(height), 50);
551
- }
552
- }
553
- `,
554
- onComplete: (result) => {
555
- // result.type === 'image'
556
- // result.blob is a PNG Blob
557
- const url = URL.createObjectURL(result.blob);
558
- document.body.innerHTML = `<img src="${url}" />`;
559
- },
560
- });
561
- ```
562
-
563
- ---
564
-
565
- ## Example: Loop Mode
566
-
567
- ```typescript
568
- import { createEngine } from './codemode';
569
-
570
- const engine = createEngine({
571
- mode: 'loop',
572
- duration: 2, // 2 second loop
573
- });
574
-
575
- await engine.run({
576
- code: `
577
- function setup() {
578
- // Called once
579
- }
580
-
581
- function draw() {
582
- background(30);
583
-
584
- // t goes from 0 to 1 over the loop duration
585
- let x = width/2 + cos(t * TWO_PI) * 200;
586
- let y = height/2 + sin(t * TWO_PI) * 200;
587
-
588
- fill(255);
589
- ellipse(x, y, 80);
590
- }
591
- `,
592
- onProgress: (info) => {
593
- console.log(info.message);
594
- },
595
- onComplete: (result) => {
596
- // result.type === 'video'
597
- // result.blob is an MP4 Blob
598
- const url = URL.createObjectURL(result.blob);
599
- document.body.innerHTML = `<video src="${url}" autoplay loop />`;
600
- },
601
- });
602
- ```
361
+ | `Math.random()` | Use seeded `random()` |
362
+ | `Date.now()` | Time-based entropy |
363
+ | `new Date()` | Time-based entropy |
364
+ | `performance.now()` | Timing entropy |
365
+ | `crypto.getRandomValues()` | Crypto randomness |
366
+ | `fetch()` | External IO |
367
+ | `setTimeout` | Async timing |
368
+ | `setInterval` | Async timing |
369
+ | `requestAnimationFrame` | Async timing |
370
+ | `document.*` | DOM access |
371
+ | `window.*` | DOM access |
372
+ | `import` | External imports |
373
+ | `require()` | External imports |
603
374
 
604
375
  ---
605
376
 
606
- ## Supported Functions
607
-
608
- The SDK includes a comprehensive p5.js-like runtime with 130+ functions:
609
-
610
- **Drawing:**
611
- `background`, `clear`, `fill`, `noFill`, `stroke`, `noStroke`, `strokeWeight`, `strokeCap`, `strokeJoin`
612
-
613
- **Shapes:**
614
- `ellipse`, `circle`, `rect`, `square`, `line`, `point`, `triangle`, `quad`, `arc`, `bezier`, `curve`
615
-
616
- **Vertex (v1.4.0):**
617
- `beginShape`, `vertex`, `curveVertex`, `bezierVertex`, `endShape`
618
-
619
- **Shape Helpers (v1.3.0):**
620
- `polygon`, `star`
621
-
622
- **Transform:**
623
- `push`, `pop`, `translate`, `rotate`, `scale`, `resetMatrix`, `shearX`, `shearY`
624
-
625
- **Color:**
626
- `colorMode`, `color`, `lerpColor`, `red`, `green`, `blue`, `alpha`, `hue`, `saturation`, `brightness`
627
-
628
- **Text:**
629
- `text`, `textSize`, `textFont`, `textAlign`, `textWidth`
630
-
631
- **Blend Modes (v1.3.0):**
632
- `blendMode(NORMAL|ADD|MULTIPLY|SCREEN)`
633
-
634
- **Pixel System (v1.4.0):**
635
- `loadPixels`, `updatePixels`, `pixels[]`, `get`, `set`
636
-
637
- **Graphics (v1.4.0):**
638
- `createGraphics`, `image`
639
-
640
- **Color Formats:**
641
- All of the following are accepted by `fill()`, `stroke()`, `background()`:
642
- - Grayscale: `fill(128)`, `fill(128, 127)`
643
- - RGB: `fill(255, 0, 0)`, `fill(255, 0, 0, 128)`
644
- - Hex: `fill('#ff0000')`, `fill('#f00')`
645
- - CSS: `fill('rgb(255,0,0)')`, `fill('rgba(255,0,0,0.5)')`, `fill('hsl(180,50%,50%)')`
646
-
647
- **Protocol Variables:**
648
- `VAR` — Array of 10 values (VAR[0] through VAR[9])
649
-
650
- **Math:**
651
- `random`, `noise`, `map`, `constrain`, `lerp`, `dist`, `mag`, `norm`, `sq`, `int`, `fract`, `sign`
377
+ ## Examples
652
378
 
653
- **Vectors (v1.3.0):**
654
- `vec`, `vecAdd`, `vecSub`, `vecMult`, `vecMag`, `vecNorm`, `vecDist`
655
-
656
- **Noise Extensions (v1.3.0):**
657
- `fbm`, `ridgedNoise`, `curlNoise`
658
-
659
- **Easing (v1.3.0):**
660
- `easeIn`, `easeOut`, `easeInOut`, `easeCubic`, `easeExpo`
661
-
662
- **Trig:**
663
- `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `radians`, `degrees`
664
-
665
- **Constants:**
666
- `PI`, `TWO_PI`, `TAU`, `HALF_PI`, `QUARTER_PI`, `width`, `height`, `frameCount`, `totalFrames`
667
-
668
- ---
669
-
670
- ## Video Encoding
671
-
672
- Loop Mode requires server-side video encoding. The SDK calls:
673
-
674
- ```
675
- POST /api/encode-loop
676
- ```
677
-
678
- Ensure your server has this endpoint available (NexArt provides this).
679
-
680
- ---
681
-
682
- ## Files
683
-
684
- ```
685
- sdk/codemode/
686
- ├── entry/
687
- │ ├── browser.ts # Browser-safe entry point (v1.7.0)
688
- │ └── node.ts # Node.js entry point (v1.7.0)
689
- ├── index.ts # Main export (app integration layer)
690
- ├── core-index.ts # Core runtime exports
691
- ├── execute.ts # executeCodeMode canonical entry point
692
- ├── engine.ts # createEngine entry point (legacy)
693
- ├── types.ts # TypeScript types
694
- ├── static-engine.ts # Static mode implementation (Node.js)
695
- ├── loop-engine.ts # Loop mode implementation (browser)
696
- ├── p5-runtime.ts # p5.js-like runtime
697
- ├── execution-sandbox.ts # Determinism enforcement
698
- ├── builder-manifest.ts # Builder manifest (write-only)
699
- ├── CHANGELOG.md # Version history
700
- └── README.md # This file
379
+ ```bash
380
+ npm run example:basic # Basic usage
381
+ npm run example:verify # Determinism verification
701
382
  ```
702
383
 
703
384
  ---
704
385
 
705
- ## License
386
+ ## Changelog
706
387
 
707
- MIT License
708
-
709
- Copyright (c) 2024-2026 NexArt
388
+ See [CHANGELOG.md](./CHANGELOG.md) for version history.
710
389
 
711
390
  ---
712
391
 
713
- ## External Builders
714
-
715
- This SDK is designed for use by:
716
-
717
- - **NexArt App**: The main generative art platform
718
- - **ByX**: Curated collection system
719
- - **External Builders**: Any platform consuming NexArt Code Mode
720
-
721
- ### Integration Example
722
-
723
- ```typescript
724
- import { executeCodeMode } from '@nexart/codemode-sdk';
725
-
726
- // Execute with explicit VAR values
727
- const result = await executeCodeMode({
728
- source: artistCode,
729
- width: 1950,
730
- height: 2400,
731
- seed: 12345,
732
- vars: [50, 75, 25, 0, 0, 0, 0, 0, 0, 0], // Exactly 10 values
733
- mode: 'static'
734
- });
735
-
736
- // Result includes full protocol metadata for verification
737
- const { image, metadata } = result;
738
- console.log(metadata.protocolVersion); // '1.2.0'
739
- console.log(metadata.deterministic); // true
740
- ```
741
-
742
- ### Error Handling
743
-
744
- All protocol violations throw descriptive errors:
745
-
746
- ```typescript
747
- try {
748
- await executeCodeMode({ ... });
749
- } catch (error) {
750
- // "[Code Mode Protocol Error] VAR array must have exactly 10 elements, got 5"
751
- // "[Code Mode Protocol Error] Forbidden pattern: Math.random()"
752
- console.error(error.message);
753
- }
754
- ```
755
-
756
- ---
757
-
758
- ## Frozen Execution Guarantees — v1.0.0
759
-
760
- The following guarantees are LOCKED and will not change in v1.x:
761
-
762
- | Guarantee | Description |
763
- |-----------|-------------|
764
- | Determinism | Same code + same seed + same VARs = identical output |
765
- | Static Mode | `setup()` only, single PNG output |
766
- | Loop Mode | Frame-authoritative, `draw()` per frame, MP4 output |
767
- | Time Semantics | `t` ∈ [0,1), `frameCount` ∈ [0,totalFrames), `time` in seconds |
768
- | Random | Seeded Mulberry32 PRNG via `random()` |
769
- | Noise | Seeded Perlin noise via `noise()` |
770
- | Canvas | Pre-initialized, no `createCanvas()` |
771
- | VAR | Exactly 10 read-only protocol variables |
772
- | Forbidden Patterns | 13 patterns rejected (see above) |
773
-
774
- ---
392
+ ## About
775
393
 
776
- ## Future Work (Phase 4+)
394
+ This SDK is a reference implementation of a deterministic execution protocol designed for replay, verification, and long-term stability.
777
395
 
778
- - External asset loading (controlled)
779
- - WebGL/3D rendering support
780
- - GIF output option
781
- - GSL v1 SDK (protocol layer) — separate package
396
+ It prioritizes correctness and reproducibility over features.