@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 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`, jsdom canvas, inspect / screenshot
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('adventure.intent.exit-requested', {
291
+ const exit = defineIntent('host.intent.exit-requested', {
289
292
  version: 1,
290
293
  fields: { exitId: { type: 'string' } },
291
294
  });
292
- const room = defineStateEvent('adventure.state.room-changed', {
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: 'adventure.presentation',
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: 'room-bg', kind: 'image' }] },
321
- acceptedEvents: ['adventure.state.*'],
322
- emittedEvents: ['adventure.intent.exit-requested'],
323
- permissions: { emit: ['adventure.intent.*'], subscribe: ['adventure.state.*'] },
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: ['adventure.intent.*'],
332
- subscribe: ['adventure.state.*'],
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: ['adventure.state.*'] },
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: 'adventure.state.loon-whistle', kind: 'state', payload: { habitat: 'pond' } });
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: 'Joiner Brook', regions: [] },
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: 'room-bg', ref: 'moltazine:post/porch-1#primary-image', type: 'image' as const },
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/` (event / deterministic / harness / presentation-adapter / asset-resolver / presentation-cue API), and `package.json`. Site code that still imports `src/ui/lib/...` hits thin re-export shims so those paths keep working.
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