@cyberart-io/engine 0.0.11 → 0.0.12

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.
@@ -8,6 +8,7 @@ Related: [Events and router](events.md) (CYB-59 contracts), [Replay inspector](r
8
8
 
9
9
  ```bash
10
10
  pnpm exec vitest run packages/engine/src/canvas/cyb-80-job-orchestration.repro.spec.ts
11
+ pnpm exec vitest run packages/engine/src/canvas/cyb-112-job-payload-validation.repro.spec.ts
11
12
  ```
12
13
 
13
14
  ## When to use
@@ -20,7 +21,7 @@ pnpm exec vitest run packages/engine/src/canvas/cyb-80-job-orchestration.repro.s
20
21
  ## Contract
21
22
 
22
23
  1. **Definitions** are versioned: request schema, result kind, retry/lease/timeout, declared fallback.
23
- 2. **Submit** with a stable idempotency key and a correlation id for the initiating player intent. Duplicate keys return the same job.
24
+ 2. **Submit** with a stable idempotency key and a correlation id for the initiating player intent. The `request` payload is validated against the definition's `requestSchema` before any coordinator mutation — missing required fields and undeclared keys fail closed unless `requestSchema.additionalProperties` is `true`. Duplicate keys return the same job only after a prior valid submission persisted.
24
25
  3. **States:** queued → claimed → awaiting-evaluation → ready → applied, plus retry-scheduled, failed, canceled, superseded.
25
26
  4. **Results** are refs (`uri` + `kind`), not embedded media/world payloads.
26
27
  5. **Evaluator** may accept, reject, or request a bounded revision.
@@ -0,0 +1,95 @@
1
+ # Loading indicator
2
+
3
+ Host-facing contract for deterministic, parameterized loading carts. Presentation-only: seeded visual variation without inventing progress or mutating authoritative host/game state.
4
+
5
+ Related: [Presentation cue](presentation-cue.md) (frame stepping), [Visual layers](visual-layers.md) (reduced motion), [Events and router](events.md). Back to the [package README](../README.md).
6
+
7
+ ## One-command reproduce (this repo)
8
+
9
+ ```bash
10
+ pnpm exec vitest run packages/engine/src/canvas/cyb-111-loading-indicator.repro.spec.ts
11
+ ```
12
+
13
+ ## When to use
14
+
15
+ | Surface | Import | Use |
16
+ |---|---|---|
17
+ | Production host | `createLoadingIndicatorController` from `@cyberart-io/engine` | Mount locally registered loader carts; persist `snapshot()` in envelope `hostState`. |
18
+ | Vitest / jsdom | same, or `@cyberart-io/engine/headless` | Identical controller; reference cart in `fixtures/loadingPulseCart.ts`. |
19
+
20
+ ## Contract
21
+
22
+ 1. **Params JSON** — validated before any live mutation: `schemaVersion`, stable `seed`, `mode: "indeterminate" \| "determinate"`, host `statusText`, optional `progress` (determinate only, 0..1), `stage`, `context`, bounded `presentation`, optional `cartId`.
23
+ 2. **Lifecycle** — `start → update → complete | fail | cancel`. Presentation-only; never advances gameplay or accepts job results.
24
+ 3. **Determinate honesty** — displays only host-supplied `progress`. Indeterminate mode keeps `progress: null`; frame stepping never synthesizes a percentage.
25
+ 4. **Seeded variation** — `variant` (hue, motif, intensity, palette) is derived deterministically from `seed` and bounded presentation params.
26
+ 5. **Reduced motion** — host flag yields static or low-motion `pulsePhase` (motif `static` or `setReducedMotion(true)`).
27
+ 6. **Accessibility** — `statusText` is host-controlled and exposed on `inspect().view` independently of the visual cart.
28
+ 7. **Fallback** — unknown or failing cart init falls back immediately to the built-in indicator (`usingFallback: true`, `fallbackReason` set) with a diagnostic. Intentional `cartId: "builtin"` (or omitting `cartId`) uses the built-in cart without setting `usingFallback`.
29
+ 8. **Restore** — versioned `snapshot()` / `restore()` validates JSON and schema version before mutate; tampered input returns `{ ok: false }` and leaves state unchanged.
30
+ 9. **Budgets** — optional `maxStepFrames`, `maxIntensity`, `maxVariant`; violations emit `loading.indicator.diagnostic` with code `budget-exceeded`.
31
+
32
+ ```ts
33
+ import {
34
+ createLoadingIndicatorController,
35
+ LOADING_INDICATOR_STARTED_EVENT,
36
+ } from '@cyberart-io/engine';
37
+ import { createLoadingPulseCartFactory } from '@cyberart-io/engine/dist/…'; // or local fixture in tests
38
+
39
+ const loading = createLoadingIndicatorController({
40
+ carts: { pulse: createLoadingPulseCartFactory() },
41
+ reducedMotion: hostPrefersReducedMotion,
42
+ });
43
+
44
+ loading.start({
45
+ seed: travelSeed,
46
+ mode: 'indeterminate',
47
+ statusText: 'Traveling to the grove',
48
+ context: 'travel',
49
+ cartId: 'pulse',
50
+ presentation: { motif: 'pulse', intensity: 0.7 },
51
+ });
52
+
53
+ loading.step(framesElapsed);
54
+ loading.update({ stage: 'route', statusText: 'Finding the path' });
55
+ loading.complete();
56
+ ```
57
+
58
+ ## Params
59
+
60
+ | Field | Required | Notes |
61
+ |---|---|---|
62
+ | `schemaVersion` | yes | Must be `1`. |
63
+ | `seed` | yes | Stable deterministic identity for variant selection. |
64
+ | `mode` | yes | `indeterminate` or `determinate`. |
65
+ | `statusText` | yes | Host-owned a11y string; not generated by the cart. |
66
+ | `progress` | determinate only | 0..1; forbidden in indeterminate mode. |
67
+ | `stage` | no | Semantic stage label; may change animation without implying numeric completion. |
68
+ | `context` | no | `travel`, `worldgen`, `content`, `audio`, or host string. |
69
+ | `presentation` | no | Bounded: `#RRGGBB` palette, intensity 0..1, motif enum, variant 0..7. |
70
+ | `cartId` | no | Registered local cart; omitted or `"builtin"` → built-in cart (`usingFallback` stays false). |
71
+
72
+ ## Lifecycle events
73
+
74
+ | `type` | When |
75
+ |---|---|
76
+ | `loading.indicator.started` | `start()` accepted |
77
+ | `loading.indicator.updated` | `update()` accepted |
78
+ | `loading.indicator.completed` | `complete()` |
79
+ | `loading.indicator.failed` | `fail(reasonCode?)` |
80
+ | `loading.indicator.canceled` | `cancel()` |
81
+ | `loading.indicator.diagnostic` | Validation, fallback, budget, restore errors |
82
+
83
+ Register contracts with `loadingIndicatorEventContracts()` on the event router ([Events](events.md)).
84
+
85
+ ## Snapshot
86
+
87
+ `schemaVersion: 1` sidecar: `{ frame, reducedMotion, phase, params, variant, usingFallback, fallbackReason, cartId, events, diagnostics }`. Store in envelope `hostState` (for example `{ loadingIndicator: snapshot }`).
88
+
89
+ ## Reference cart
90
+
91
+ `packages/engine/src/canvas/fixtures/loadingPulseCart.ts` — `createLoadingPulseCart()` and `createLoadingPulseCartFactory()` demonstrate seeded hue/motif variation, determinate progress labels, and reduced-motion static rendering.
92
+
93
+ ## Exports
94
+
95
+ `LOADING_INDICATOR_*` constants, `createLoadingIndicatorController`, `parseLoadingIndicatorParams`, `parseLoadingIndicatorSnapshot`, `loadingIndicatorEventContracts`, `isLoadingIndicatorEventType`, `isLoadingIndicatorMode`, and related types from `@cyberart-io/engine` and `@cyberart-io/engine/headless`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyberart-io/engine",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "CyberArt host engine: mount carts, events, capability manifests, geometry, runtime groups, and a Node/jsdom headless entry.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",