Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-monorepo",
"version": "0.9.88",
"version": "0.9.89",
"private": true,
"engines": {
"node": ">=22"
Expand Down
2 changes: 1 addition & 1 deletion packages/data-ai/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "adobe-data-ai",
"version": "0.9.88",
"version": "0.9.89",
"description": "Architecture skills for @adobe/data — data-oriented modelling, archetype iteration, hot-path performance, and related conventions.",
"author": {
"name": "Adobe"
Expand Down
2 changes: 1 addition & 1 deletion packages/data-ai/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-ai",
"version": "0.9.88",
"version": "0.9.89",
"description": "Cross-agent architecture skills for @adobe/data — installable as a Claude Code plugin or copied into any Agent-Skills-compatible agent (Cursor, Codex).",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-gpu-hopper/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-gpu-hopper",
"version": "0.9.88",
"version": "0.9.89",
"description": "Hopper sample - real-time ECS game rendered as colored cubes via @adobe/data-gpu",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-gpu-samples/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-gpu-samples",
"version": "0.9.88",
"version": "0.9.89",
"description": "WebGPU samples built on @adobe/data-gpu",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-gpu/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-gpu",
"version": "0.9.88",
"version": "0.9.89",
"description": "Adobe data WebGPU plugins and types for graphics and compute",
"type": "module",
"private": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ interface SkinMesh {
export const boneColliders = Database.Plugin.create({
extends: Database.Plugin.combine(physicsData, jointData, ragdollTrigger, pbrSkinning, modelLoader, transform),
components: {
_boneJoint: { ...Entity.schema, nonPersistent: true }, // the skeleton joint this capsule tracks
_boneOffsetPos: { ...Vec3.schema, nonPersistent: true }, // capsule offset in the bone's bind-local frame
_boneOffsetRot: { ...Quat.schema, nonPersistent: true },
_ragdollBuilt: { ...True.schema, nonPersistent: true }, // tag: this skeleton's bone capsules have been generated
_boneJoint: { ...Entity.schema, default: undefined, nonPersistent: true }, // the skeleton joint this capsule tracks
_boneOffsetPos: { ...Vec3.schema, default: undefined, nonPersistent: true }, // capsule offset in the bone's bind-local frame
_boneOffsetRot: { ...Quat.schema, default: undefined, nonPersistent: true },
_ragdollBuilt: { ...True.schema, default: undefined, nonPersistent: true }, // tag: this skeleton's bone capsules have been generated
},
archetypes: {
// a kinematic capsule body bound to a skeleton joint (collisionGroup 1 ⇒ the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Vec3, Quat } from "@adobe/data/math";
*/
export const displayTransform = Database.Plugin.create({
components: {
_renderPosition: { ...Vec3.schema, nonPersistent: true }, // derived: interpolated pose to render at (else use `position`)
_renderRotation: { ...Quat.schema, nonPersistent: true },
_renderPosition: { ...Vec3.schema, default: undefined, nonPersistent: true }, // derived: interpolated pose to render at (else use `position`)
_renderRotation: { ...Quat.schema, default: undefined, nonPersistent: true },
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const FACTOR_MATERIAL_COMPONENTS = [
export const materialPaletteGpu = Database.Plugin.create({
extends: Database.Plugin.combine(Material.plugin, core),
components: {
_paletteIndex: { ...U32.schema, nonPersistent: true },
_paletteIndex: { ...U32.schema, default: undefined, nonPersistent: true },
},
resources: {
_factorPalette: { default: null as GPUBuffer | null, nonPersistent: true },
Expand Down
10 changes: 5 additions & 5 deletions packages/data-gpu/src/graphics/rendering/pbr-core-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ export const pbrCore = Database.Plugin.create({
* null for static primitives. Drives skinned-pipeline dispatch. */
_skinVertexBuffer: { default: null as GPUBuffer | null, nonPersistent: true },
_indexBuffer: { default: null as GPUBuffer | null, nonPersistent: true },
_indexCount: { ...U32.schema, nonPersistent: true },
_indexCount: { ...U32.schema, default: undefined, nonPersistent: true },
_indexFormat: { default: "uint16" as GPUIndexFormat, nonPersistent: true },
_materialBindGroup: { default: null as GPUBindGroup | null, nonPersistent: true },
/** Back-reference from a _PbrPrimitive / _VisibleMaterial to the
* baked mesh asset that owns it. */
_mesh: { ...Entity.schema, nonPersistent: true },
_material: { ...Entity.schema, nonPersistent: true },
_mesh: { ...Entity.schema, default: undefined, nonPersistent: true },
_material: { ...Entity.schema, default: undefined, nonPersistent: true },
/** Node-local-to-model-root matrix baked at load time. The renderer
* pre-multiplies it with the per-instance model-root world matrix. */
_nodeLocalMatrix: { ...Mat4x4.schema, nonPersistent: true },
_nodeLocalMatrix: { ...Mat4x4.schema, default: undefined, nonPersistent: true },
/** Skeleton-side back-references the renderer reads when dispatching
* the skinned pipeline. Populated by `pbrSkinning`. */
_skeletonModelRef: { ...Entity.schema, nonPersistent: true },
_skeletonModelRef: { ...Entity.schema, default: undefined, nonPersistent: true },
_skeletonJointMatrixBindGroup: { default: null as GPUBindGroup | null, nonPersistent: true },
},
archetypes: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const pbrSkinning = Database.Plugin.create({
extends: Database.Plugin.combine(modelLoader, pbrCore, transform, animation),
components: {
_skeletonJoints: { default: [] as number[], nonPersistent: true },
_skeletonMesh: { ...Entity.schema, nonPersistent: true },
_skeletonMesh: { ...Entity.schema, default: undefined, nonPersistent: true },
_skeletonInstanceBuffer: { default: null as GPUBuffer | null, nonPersistent: true },
_skeletonJointMatrixBuffer: { default: null as GPUBuffer | null, nonPersistent: true },
},
Expand Down
4 changes: 2 additions & 2 deletions packages/data-gpu/src/graphics/scene/node/node-data-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export const nodeData = Database.Plugin.create({
rotation: Quat.schema,
scale: Vec3.schema,
parent: Entity.schema,
_worldMatrix: { ...Mat4x4.schema, nonPersistent: true },
_worldBounds: { ...Aabb.schema, nonPersistent: true },
_worldMatrix: { ...Mat4x4.schema, default: undefined, nonPersistent: true },
_worldBounds: { ...Aabb.schema, default: undefined, nonPersistent: true },
},
archetypes: {
Node: ["position", "rotation", "scale", "parent", "visible"],
Expand Down
4 changes: 2 additions & 2 deletions packages/data-gpu/src/physics/physics-data-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export const physicsData = Database.Plugin.create({
rotation: Quat.schema, // unified with Node.rotation so a body renders directly
linearVelocity: Vec3.schema,
angularVelocity: Vec3.schema,
_prevPosition: { ...Vec3.schema, nonPersistent: true }, // derived: pose before the last fixed step (render interpolation)
_prevRotation: { ...Quat.schema, nonPersistent: true },
_prevPosition: { ...Vec3.schema, default: undefined, nonPersistent: true }, // derived: pose before the last fixed step (render interpolation)
_prevRotation: { ...Quat.schema, default: undefined, nonPersistent: true },
// Bodies sharing the same non-zero collisionGroup do not collide with each
// other (they still collide with group 0 / the world) — e.g. a ragdoll's
// bones. 0 = default (collide with everything). Honored by both solvers
Expand Down
4 changes: 2 additions & 2 deletions packages/data-gpu/src/physics/solvers/jolt-solver-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ export interface JoltContext {
export const joltSolver = Database.Plugin.create({
extends: Database.Plugin.combine(physicsData, jointData, physicsClock),
components: {
_joltBody: { ...True.schema, nonPersistent: true }, // tag: this body has been mirrored into the Jolt world
_joltJoint: { ...True.schema, nonPersistent: true }, // tag: this joint has been mirrored into the Jolt world
_joltBody: { ...True.schema, default: undefined, nonPersistent: true }, // tag: this body has been mirrored into the Jolt world
_joltJoint: { ...True.schema, default: undefined, nonPersistent: true }, // tag: this joint has been mirrored into the Jolt world
},
resources: {
_joltContext: { default: null as JoltContext | null, nonPersistent: true },
Expand Down
4 changes: 2 additions & 2 deletions packages/data-gpu/src/physics/solvers/rapier-solver-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ interface MatProps { density: number; restitution: number; friction: number }
export const rapierSolver = Database.Plugin.create({
extends: Database.Plugin.combine(physicsData, jointData, physicsClock),
components: {
_rapierBody: { ...True.schema, nonPersistent: true }, // tag: this body has been mirrored into the Rapier world
_rapierJoint: { ...True.schema, nonPersistent: true }, // tag: this joint has been mirrored into the Rapier world
_rapierBody: { ...True.schema, default: undefined, nonPersistent: true }, // tag: this body has been mirrored into the Rapier world
_rapierJoint: { ...True.schema, default: undefined, nonPersistent: true }, // tag: this joint has been mirrored into the Rapier world
},
systems: {
rapierStep: {
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit-space-rock-game/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-lit-space-rock-game",
"version": "0.9.88",
"version": "0.9.89",
"description": "Space Rock Game sample - real-time ECS game with Lit and @adobe/data",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit-tictactoe/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-lit-tictactoe",
"version": "0.9.88",
"version": "0.9.89",
"description": "Tic-Tac-Toe sample - Lit web components with @adobe/data-lit and AgenticService",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit-todo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-lit-todo",
"version": "0.9.88",
"version": "0.9.89",
"description": "Todo application - Lit web components with @adobe/data ECS",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-lit",
"version": "0.9.88",
"version": "0.9.89",
"description": "Adobe data Lit bindings - hooks, elements, decorators",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-p2p-tictactoe/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-p2p-tictactoe",
"version": "0.9.88",
"version": "0.9.89",
"description": "Serverless P2P tic-tac-toe — WebRTC DataChannel + @adobe/data-sync",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-persistence/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-persistence",
"version": "0.9.88",
"version": "0.9.89",
"description": "Worker-based incremental persistence layer for @adobe/data ECS over OPFS (browser) and node:fs (server).",
"type": "module",
"sideEffects": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe("createNodeWorkerTransport (E2E)", () => {
// Verify on-disk artifacts exist.
const metaStat = await stat(join(tmpRoot, "meta.json"));
expect(metaStat.size).toBeGreaterThan(0);
const eltStat = await stat(join(tmpRoot, "entity-location.bin"));
const eltStat = await stat(join(tmpRoot, "entity-location-0.bin"));
expect(eltStat.size).toBeGreaterThan(0);

// Loading phase: fresh database, same plugin, recover via load().
Expand Down Expand Up @@ -136,7 +136,7 @@ describe("createNodeWorkerTransport (E2E)", () => {
}
});

it("writes column files and entity-location.bin via the worker", async () => {
it("writes column files and entity-location files via the worker", async () => {
const workerScript = ensureBuilt();

const db = Database.create(particlePlugin);
Expand All @@ -161,8 +161,8 @@ describe("createNodeWorkerTransport (E2E)", () => {
const archetypeDir = archetypeDirs[0]!;
const cols = [...(await backend.list(`archetypes/${archetypeDir}`))].sort();
// position, velocity, mass — all .bin files. The implicit `id`
// column is intentionally not persisted (it's recoverable from
// entity-location.bin).
// column is intentionally not persisted (it is recoverable from the
// entity-location files).
expect(cols).toEqual(["mass.bin", "position.bin", "velocity.bin"]);

await service.dispose();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// © 2026 Adobe. MIT License. See /LICENSE for details.
//
// A component whose schema is marked `nonPersistent: true` must not be saved.
// On load it is reconstructed via the hybrid rule: a defaulted one is reset to
// its default (present); a no-default one is stripped (the entity restores into
// the reduced archetype). This exercises the full worker/checkpoint/reload path.

import { Database } from "@adobe/data/ecs";
import type { Schema } from "@adobe/data/schema";
import { F32 } from "@adobe/data/math";
import { beforeEach, describe, expect, it } from "vitest";
import { createMemoryBackend } from "../backend/memory-backend.js";
import { createWorkerPersistenceService } from "./create-worker-persistence-service.js";

const plugin = Database.Plugin.create({
components: {
value: F32.schema,
// Defaulted nonPersistent component → reset to default on load.
cache: { type: "number", default: 7, nonPersistent: true } as const,
// No-default nonPersistent component → stripped on load.
derived: { type: "number", nonPersistent: true } as const,
// undefined-default (type-only placeholder, e.g. a GPUBuffer handle) →
// treated as no default → stripped on load.
gpuRef: { default: undefined as unknown, nonPersistent: true } satisfies Schema,
},
archetypes: {
Item: ["value", "cache", "derived", "gpuRef"],
},
transactions: {
spawn(t, args: { value: number; cache: number; derived: number; gpuRef: unknown }) {
return t.archetypes.Item.insert(args);
},
},
});

const noCheckpoint = { everyNTransactions: 0, idleMs: 0 } as const;

describe("component-level nonPersistent durability", () => {
let backend: ReturnType<typeof createMemoryBackend>;

beforeEach(() => {
backend = createMemoryBackend();
});

it("does not persist nonPersistent columns: defaulted resets, no-default strips", async () => {
const db1 = Database.create(plugin);
const svc1 = await createWorkerPersistenceService({ database: db1, backend, checkpoint: noCheckpoint });
const e = db1.transactions.spawn({ value: 5, cache: 99, derived: 42, gpuRef: 12345 })!;
await svc1.flush();
await svc1.checkpoint();
await svc1.dispose();

const db2 = Database.create(plugin);
const svc2 = await createWorkerPersistenceService({ database: db2, backend, checkpoint: noCheckpoint });
await svc2.load();
await svc2.dispose();

const view = db2.read(e) as { value: number; cache?: number; derived?: number; gpuRef?: unknown } | null;
expect(view).not.toBeNull();
expect(view!.value).toBe(5); // persistent component preserved
expect(view!.cache).toBe(7); // defaulted nonPersistent → reset to default
expect("derived" in view!).toBe(false); // no-default nonPersistent → stripped
expect("gpuRef" in view!).toBe(false); // null-default nonPersistent → stripped
});
});
Loading