@cyberart-io/engine 0.0.4 → 0.0.5
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 +41 -18
- package/dist/headless.d.ts +497 -67
- package/dist/headless.js +1 -1
- package/dist/index.d.ts +470 -7
- package/dist/index.js +1 -1
- package/docs/asset-resolver.md +4 -4
- package/docs/browser-harness.md +126 -0
- package/docs/capability-manifest.md +18 -7
- package/docs/compositor.md +103 -0
- package/docs/deterministic-mode.md +1 -1
- package/docs/events.md +75 -13
- package/docs/headless-harness.md +44 -14
- package/docs/presentation-adapter.md +8 -8
- package/docs/presentation-cue.md +2 -2
- package/docs/replay-inspector.md +88 -0
- package/docs/runtime-group.md +9 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,13 +89,16 @@ Full API for the event router, deterministic replay, and CI harness (so agents c
|
|
|
89
89
|
|
|
90
90
|
- [Events and router](docs/events.md) — mailbox, envelope, typed contracts, `createEventRouter`, hops, idempotency, rejections
|
|
91
91
|
- [Deterministic mode](docs/deterministic-mode.md) — `step` / `schedule`, clocks, `ScriptedAction`, replay diffs
|
|
92
|
-
- [Headless harness](docs/headless-harness.md) — `createHeadlessHarness` from `@cyberart-io/engine/headless`,
|
|
92
|
+
- [Headless harness](docs/headless-harness.md) — `createHeadlessHarness` from `@cyberart-io/engine/headless`, software Canvas2D, `compareImageData` / `assertPixelsEqual`, inspect / screenshot
|
|
93
93
|
- [Presentation adapter](docs/presentation-adapter.md) — host-owned render model, intents, loading / error / unsupported
|
|
94
94
|
- [Asset resolver](docs/asset-resolver.md) — host-pluggable images/audio/fonts/spritesheets, cache, preload, fallbacks
|
|
95
95
|
- [Presentation cue](docs/presentation-cue.md) — deterministic `createPresentationTimeline`, duplicate policy, reduced-motion, lifecycle events
|
|
96
96
|
- [Capability manifest](docs/capability-manifest.md) — versioned JSON for runtime features, phases, managers, assets, events, permissions, integrations
|
|
97
97
|
- [Normalized geometry](docs/normalized-geometry.md) — coordinate spaces, contain/cover/crop layout, landmarks, hit regions, debug overlay
|
|
98
98
|
- [Runtime group](docs/runtime-group.md) — `createRuntimeGroup`, shared router attach, lockstep clock; `createHeadlessMultiCartHarness` from `@cyberart-io/engine/headless`
|
|
99
|
+
- [Compositor](docs/compositor.md) — `createCompositor`, transparent stacking, `screen` blend, `writeComposedFrame`
|
|
100
|
+
- [Browser harness](docs/browser-harness.md) — `createBrowserHarness`, DOM clicks, viewport/DPR, composed screenshots
|
|
101
|
+
- [Replay inspector](docs/replay-inspector.md) — `createReplayInspector`, causation trees, redacted export/import, headless replay
|
|
99
102
|
|
|
100
103
|
## Write a cart
|
|
101
104
|
|
|
@@ -244,9 +247,9 @@ CI and agents should drive the **same** `createRuntime({ deterministic })` path.
|
|
|
244
247
|
- Carts and production hosts: `import { createRuntime } from '@cyberart-io/engine'`
|
|
245
248
|
- Tests, CI, and frame capture: `import { createHeadlessHarness, createHeadlessMultiCartHarness } from '@cyberart-io/engine/headless'`
|
|
246
249
|
|
|
247
|
-
`@cyberart-io/engine` does not re-export the harness. `installHeadlessCanvas` is the documented jsdom install (test-only). `createHeadlessHarness` sizes a container, mounts, and wraps step / input / inspect / snapshot.
|
|
250
|
+
`@cyberart-io/engine` does not re-export the harness. `installHeadlessCanvas` is the documented jsdom install (test-only). It attaches a deterministic software Canvas2D (paths, arcs, atlas text, transforms, clip, alpha, gradients, `drawImage`). Unsupported ops throw `HeadlessUnsupportedOperationError`. `createHeadlessHarness` sizes a container, mounts, and wraps step / input / inspect / snapshot. Pixel compare: `compareImageData`, `assertPixelsEqual`, `writeVisualArtifacts` (`CYBERART_UPDATE_GOLDEN=1` to refresh goldens).
|
|
248
251
|
|
|
249
|
-
Full options, `click` clock rule, Node-only `captureFrame`, remount, and the reproduce command: [headless harness](docs/headless-harness.md).
|
|
252
|
+
Full options, `click` clock rule, Node-only `captureFrame`, remount, visual asserts, and the reproduce command: [headless harness](docs/headless-harness.md).
|
|
250
253
|
|
|
251
254
|
```ts
|
|
252
255
|
import { createHeadlessHarness } from '@cyberart-io/engine/headless';
|
|
@@ -285,11 +288,11 @@ import {
|
|
|
285
288
|
createEventRouter,
|
|
286
289
|
} from '@cyberart-io/engine';
|
|
287
290
|
|
|
288
|
-
const exit = defineIntent('
|
|
291
|
+
const exit = defineIntent('host.intent.exit-requested', {
|
|
289
292
|
version: 1,
|
|
290
293
|
fields: { exitId: { type: 'string' } },
|
|
291
294
|
});
|
|
292
|
-
const room = defineStateEvent('
|
|
295
|
+
const room = defineStateEvent('host.state.room-changed', {
|
|
293
296
|
version: 1,
|
|
294
297
|
fields: { roomId: { type: 'string' } },
|
|
295
298
|
});
|
|
@@ -302,6 +305,26 @@ const router = createEventRouter({
|
|
|
302
305
|
router.attach('presentation', runtime.hostChannel, deriveAttachOptions(contracts, 'cart'));
|
|
303
306
|
```
|
|
304
307
|
|
|
308
|
+
## Presentation cue
|
|
309
|
+
|
|
310
|
+
Frame-stepped effects (overlays, pulses, scene fades). No `setTimeout` / rAF. Drive `step` from the same clock as deterministic `cart.step`.
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { createPresentationTimeline } from '@cyberart-io/engine';
|
|
314
|
+
|
|
315
|
+
const timeline = createPresentationTimeline({ originFrame: 0, reducedMotion: false });
|
|
316
|
+
timeline.play({
|
|
317
|
+
name: 'checkmark',
|
|
318
|
+
idempotencyKey: 'gold',
|
|
319
|
+
durationFrames: 90,
|
|
320
|
+
easing: 'ease-out',
|
|
321
|
+
onDuplicate: 'replace',
|
|
322
|
+
});
|
|
323
|
+
timeline.step(90);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Lifecycle names `cue.started` / `cue.completed` / `cue.cancelled` / `cue.replaced` are local to the timeline. They are not router envelopes unless you define a contract. Duplicate policy, late-play catch-up, and reduced-motion: [presentation cue](docs/presentation-cue.md).
|
|
327
|
+
|
|
305
328
|
## Capability manifest
|
|
306
329
|
|
|
307
330
|
JSON for what a cart needs from the host. `validateCapabilityManifest` returns structured diagnostics instead of throwing.
|
|
@@ -313,14 +336,14 @@ import {
|
|
|
313
336
|
} from '@cyberart-io/engine';
|
|
314
337
|
|
|
315
338
|
const defined = defineCapabilityManifest({
|
|
316
|
-
id: '
|
|
339
|
+
id: 'host.presentation',
|
|
317
340
|
runtime: { minContractVersion: 1, features: ['router'] },
|
|
318
341
|
phases: ['loading', 'ready', 'error', 'unsupported'],
|
|
319
342
|
managers: ['pointer', 'hostChannel'],
|
|
320
|
-
assets: { kinds: ['image'], declarations: [{ id: '
|
|
321
|
-
acceptedEvents: ['
|
|
322
|
-
emittedEvents: ['
|
|
323
|
-
permissions: { emit: ['
|
|
343
|
+
assets: { kinds: ['image'], declarations: [{ id: 'backdrop', kind: 'image' }] },
|
|
344
|
+
acceptedEvents: ['host.state.*'],
|
|
345
|
+
emittedEvents: ['host.intent.exit-requested'],
|
|
346
|
+
permissions: { emit: ['host.intent.*'], subscribe: ['host.state.*'] },
|
|
324
347
|
integrations: ['tone'],
|
|
325
348
|
});
|
|
326
349
|
if (!defined.ok) throw new Error(defined.errors.map((e) => e.detail).join('; '));
|
|
@@ -328,8 +351,8 @@ validateCapabilityManifest(defined.manifest, {
|
|
|
328
351
|
contractVersion: 1,
|
|
329
352
|
features: ['router'],
|
|
330
353
|
integrations: ['tone'],
|
|
331
|
-
emit: ['
|
|
332
|
-
subscribe: ['
|
|
354
|
+
emit: ['host.intent.*'],
|
|
355
|
+
subscribe: ['host.state.*'],
|
|
333
356
|
});
|
|
334
357
|
```
|
|
335
358
|
|
|
@@ -345,17 +368,17 @@ import { createRuntimeGroup } from '@cyberart-io/engine';
|
|
|
345
368
|
const group = createRuntimeGroup({
|
|
346
369
|
origin: 0,
|
|
347
370
|
participants: [
|
|
348
|
-
{ id: 'effects', cart: effectsCart, emit: ['ambience.intent.*'], subscribe: ['
|
|
371
|
+
{ id: 'effects', cart: effectsCart, emit: ['ambience.intent.*'], subscribe: ['host.state.*'] },
|
|
349
372
|
{ id: 'ambience', cart: ambienceCart, subscribe: ['ambience.intent.*'] },
|
|
350
373
|
],
|
|
351
374
|
});
|
|
352
|
-
group.publish({ type: '
|
|
375
|
+
group.publish({ type: 'host.state.accepted', kind: 'state', payload: { id: 'north' } });
|
|
353
376
|
await group.step(2);
|
|
354
377
|
const { trace } = await group.inspect();
|
|
355
378
|
group.destroy();
|
|
356
379
|
```
|
|
357
380
|
|
|
358
|
-
Headless / CI: `createHeadlessMultiCartHarness` from `@cyberart-io/engine/headless` is the same handle after `installHeadlessCanvas()`. Full options: [runtime group](docs/runtime-group.md).
|
|
381
|
+
Headless / CI: `createHeadlessMultiCartHarness` from `@cyberart-io/engine/headless` is the same handle after `installHeadlessCanvas()`. Full options: [runtime group](docs/runtime-group.md). Causation trees, redaction, and tape replay: [replay inspector](docs/replay-inspector.md).
|
|
359
382
|
|
|
360
383
|
## Normalized geometry
|
|
361
384
|
|
|
@@ -400,7 +423,7 @@ const adapter = attachPresentationAdapter(harness);
|
|
|
400
423
|
adapter.present({
|
|
401
424
|
contractVersion: 1,
|
|
402
425
|
phase: 'ready',
|
|
403
|
-
view: { title: '
|
|
426
|
+
view: { title: 'Overlook', regions: [] },
|
|
404
427
|
});
|
|
405
428
|
```
|
|
406
429
|
|
|
@@ -418,7 +441,7 @@ import {
|
|
|
418
441
|
} from '@cyberart-io/engine';
|
|
419
442
|
|
|
420
443
|
const roomAssets = [
|
|
421
|
-
{ id: '
|
|
444
|
+
{ id: 'backdrop', ref: 'moltazine:post/porch-1#primary-image', type: 'image' as const },
|
|
422
445
|
{
|
|
423
446
|
id: 'ambience',
|
|
424
447
|
ref: 'world:asset/stream-loop',
|
|
@@ -524,7 +547,7 @@ A canvas the host adopted is left in place on destroy; a canvas the engine creat
|
|
|
524
547
|
|
|
525
548
|
## Publishing this package (maintainers)
|
|
526
549
|
|
|
527
|
-
Not part of writing a cart. Engine source lives in `packages/engine/src/` (not mixed into the site). The npm tarball is built from `packages/engine/src/index.ts` and `packages/engine/src/headless.ts` and contains minified `dist/index.js` + `dist/headless.js`, rolled-up `.d.ts` for both, `LICENSE`, `README.md`, `docs/` (
|
|
550
|
+
Not part of writing a cart. Engine source lives in `packages/engine/src/` (not mixed into the site). The npm tarball is built from `packages/engine/src/index.ts` and `packages/engine/src/headless.ts` and contains minified `dist/index.js` + `dist/headless.js`, rolled-up `.d.ts` for both, `LICENSE`, `README.md`, `docs/` (including compositor, browser harness, and replay inspector), and `package.json`. Site code that still imports `src/ui/lib/...` hits thin re-export shims so those paths keep working.
|
|
528
551
|
|
|
529
552
|
```bash
|
|
530
553
|
pnpm run pack:engine
|