@adobe/data-ai 0.9.100 → 0.9.102
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/.claude/rules/data-modelling.md +7 -3
- package/.claude/rules/features/data/state.md +68 -68
- package/.claude/rules/features/services/main-service/conformance.md +38 -28
- package/.claude/rules/features/services/main-service/transactions.md +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +3 -3
|
@@ -49,9 +49,13 @@ single source of truth, not a downstream comparison flag:
|
|
|
49
49
|
references is `ReadonlySet<number>` (a set of ids), and an unordered entity
|
|
50
50
|
*query result* is `ReadonlySet<number>`.
|
|
51
51
|
- **`ReadonlyMap<K, V>`** — a keyed lookup. This is how **identity-keyed entities**
|
|
52
|
-
are modelled: `entities: ReadonlyMap<number, EntityValue>` — the
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
are modelled: `entities: ReadonlyMap<number, EntityValue>` — the id is the key, and
|
|
53
|
+
the value carries **no `id` of its own** (identity is the key, never a field). The key
|
|
54
|
+
may be a plain `number` or the ECS `Entity` type (a branded `number`) — reusing
|
|
55
|
+
`Entity`, and reference bundles like `CoeditingRelations.OrderedChild`, is allowed:
|
|
56
|
+
they are plain value types, not ECS machinery, and keep the spec aligned with the ECS
|
|
57
|
+
(see `features/data/state.md`). Also used for deterministic-key lookups (an enum, a
|
|
58
|
+
name, a stable string).
|
|
55
59
|
|
|
56
60
|
**Entities are keyed, never id-bearing values.** An entity's identity is its map
|
|
57
61
|
key, so entity value types (`Todo`, `Bullet`) have no `id` field, and there is no
|
|
@@ -49,12 +49,18 @@ A `State` has two kinds of field:
|
|
|
49
49
|
types (`Todo`, or `Bullet | Asteroid`). Omit `entities` entirely for a feature with
|
|
50
50
|
no entities (`tictactoe`, `dashboard`) — it is then all singletons.
|
|
51
51
|
|
|
52
|
-
This maps 1:1 to the ECS
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
This maps 1:1 to the ECS. `State` must not depend on ECS *machinery* (a store, a
|
|
53
|
+
transaction, an index) — but it **may reuse ECS-related value types**: the key can be
|
|
54
|
+
the `Entity` type (it is just a branded `number`), and a reference/hierarchy bundle can
|
|
55
|
+
reuse a shared value type like `CoeditingRelations.OrderedChild` (`{ parent, order }`).
|
|
56
|
+
Those are plain serializable data, not ECS behaviour, and reusing them keeps the spec
|
|
57
|
+
and the ECS in lockstep — the same `Entity.schema` that types an id here is what
|
|
58
|
+
conformance walks to compare the two up to an id-bijection (see `conformance.md`).
|
|
59
|
+
Singletons ↔ resources; each `entities` value ↔ one entity whose **component set is the
|
|
60
|
+
value's own keys**, so `fromState` inserts a value into the archetype named by
|
|
61
|
+
`Object.keys(value)` and `toState` reads every entity back into the map. Identity lives
|
|
62
|
+
in the key, never a field — see `../../data-modelling.md` (Entities are keyed, never
|
|
63
|
+
id-bearing values).
|
|
58
64
|
|
|
59
65
|
### Entity value types — structural, id-less, one `is` guard each
|
|
60
66
|
|
|
@@ -146,7 +152,7 @@ and `.test.ts`.
|
|
|
146
152
|
fixtures the pure `spec.test.ts` **and** the ecs `runFeature` call both reuse
|
|
147
153
|
(driving transaction / action / computed conformance) — the transform's contract
|
|
148
154
|
expressed as data, not a per-file test — so they belong
|
|
149
|
-
beside the thing they specify, and `Conformance
|
|
155
|
+
beside the thing they specify, and `Conformance.cases(fn, …)` binds them to the
|
|
150
156
|
signature so they can't drift. Kept inert (no `describe`; one aggregator runs
|
|
151
157
|
them) they also sidestep the double execution vitest triggers when a single file
|
|
152
158
|
both exports cases and runs its own `describe`. Coverage is then enforced
|
|
@@ -166,18 +172,16 @@ transform/derivation files can write a one-parameter type:
|
|
|
166
172
|
// data/state/conformance-case.ts — the only per-feature conformance declaration
|
|
167
173
|
import { Conformance as ConformanceApi } from "@adobe/data-testing";
|
|
168
174
|
import type { State } from "./state.js";
|
|
169
|
-
|
|
175
|
+
// `Conformance.cases(fn, [options,] ...cases)` declares a transform's cases — the
|
|
176
|
+
// case types (args, before/after) come from `fn`. A derivation authors `Derivation<typeof fn>`.
|
|
177
|
+
export const Conformance = { cases: ConformanceApi.casesBuilder<State>() };
|
|
170
178
|
export type Derivation<F extends (...args: never[]) => unknown> = ConformanceApi.DerivationCases<F>;
|
|
171
179
|
export type Effects<Args> = ConformanceApi.Effects<Args>;
|
|
172
|
-
// The entity-reference marker for identity-addressed case args, re-exported so
|
|
173
|
-
// cases import it beside `Conformance`: `args: { id: entity(2) }`.
|
|
174
|
-
export const entity = ConformanceApi.entity;
|
|
175
180
|
```
|
|
176
181
|
|
|
177
182
|
```ts
|
|
178
183
|
// create-todo.ts
|
|
179
|
-
import {
|
|
180
|
-
import type { Conformance } from "./conformance-case.js"; // the thin per-feature alias above
|
|
184
|
+
import { Conformance } from "./conformance-case.js"; // the thin per-feature alias above
|
|
181
185
|
import type { Services } from "../../services/services.js"; // the feature's service map
|
|
182
186
|
export const createTodo = (
|
|
183
187
|
state: Pick<State, "entities">,
|
|
@@ -191,16 +195,17 @@ export const createTodo = (
|
|
|
191
195
|
return { entities: new Map(state.entities).set(id, { name, complete: false, order }) };
|
|
192
196
|
};
|
|
193
197
|
|
|
194
|
-
export const cases
|
|
198
|
+
export const cases = Conformance.cases(createTodo,
|
|
195
199
|
{ name: "adds the first todo",
|
|
196
200
|
before: {}, // empty delta — the default State.create() (empty entities)
|
|
197
201
|
args: { name: "a", analytics: AnalyticsService.createFake() },
|
|
198
|
-
// The map key is
|
|
199
|
-
//
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
+
// The map key is a PLAIN spec-id you choose (1). The ECS mints its own id, so
|
|
203
|
+
// conformance compares up to an id-bijection — the key need only be distinct.
|
|
204
|
+
// The value is id-less so content compares directly. (Maps compare entry-wise /
|
|
205
|
+
// order-independently — see conformance.md.)
|
|
206
|
+
after: { entities: new Map([[1, { name: "a", complete: false, order: 0 }]]) },
|
|
202
207
|
effects: { analytics: [["todoCreated", { name: "a" }]] } },
|
|
203
|
-
|
|
208
|
+
);
|
|
204
209
|
```
|
|
205
210
|
|
|
206
211
|
- **Signature** `(state: Pick<State, …reads>, args) => Pick<State, …writes>` — a
|
|
@@ -208,8 +213,8 @@ export const cases: Conformance<typeof createTodo> = [
|
|
|
208
213
|
transition **reads**; the return is *only the fields it **writes***. **No
|
|
209
214
|
`<T> => T` generic, no `...state` spread** in the return — return the patch and
|
|
210
215
|
let the runner merge it. **All non-state inputs go in the single `args` object**
|
|
211
|
-
(`
|
|
212
|
-
service, etc. into it, never as a third positional. A transition that takes
|
|
216
|
+
(the case's `args` type is read from `fn`'s `Parameters[1]`) — bundle a `dt`, an
|
|
217
|
+
injected service, etc. into it, never as a third positional. A transition that takes
|
|
213
218
|
**no** args omits `args` from each case entirely (the shared `Case` type makes
|
|
214
219
|
`args` optional exactly then). **Guard no-ops by returning an empty patch `{}`**
|
|
215
220
|
(or the unchanged slice), never throw.
|
|
@@ -222,61 +227,56 @@ export const cases: Conformance<typeof createTodo> = [
|
|
|
222
227
|
any barrel member) in a top-level `cases` literal dead-locks the import cycle.
|
|
223
228
|
Import the concrete helper directly (`import { create } from "./create.js"`) or
|
|
224
229
|
inline full-`State` literals.
|
|
225
|
-
- **`Conformance
|
|
226
|
-
|
|
227
|
-
|
|
230
|
+
- **`Conformance.cases(fn, ...cases)`** (the builder above) derives each case's
|
|
231
|
+
types from `fn`'s own signature — pass the transition function and cases can't drift
|
|
232
|
+
from what it accepts. **`before` is a delta over `State.create()`** — list only
|
|
228
233
|
the fields this case sets differently from the default; **`after` is the writes
|
|
229
234
|
patch** — only the fields the transition changes. The runner seeds
|
|
230
235
|
`{ ...State.create(), ...before }` and compares against
|
|
231
236
|
`{ ...State.create(), ...before, ...after }`, so any field a case doesn't mention
|
|
232
237
|
is the default and stays unchanged. (A full `before`/`after` still works — it just
|
|
233
238
|
overrides the default wholesale.)
|
|
234
|
-
- **`after`
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
`
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
239
|
+
- **`after` uses PLAIN spec-ids everywhere — no hand-authored key matchers.** An
|
|
240
|
+
entity's identity is the `entities` map **key**, not a value field, so entity content
|
|
241
|
+
compares directly. The ECS mints its **own** ids (a different set from the spec's), so
|
|
242
|
+
conformance compares the two **up to an id-bijection**: the runner reads the store's
|
|
243
|
+
schemas, finds every entity reference (a map key, and any field whose schema is
|
|
244
|
+
`Entity.schema` — recursing into a bundle like `{ parent, order }`), and matches the
|
|
245
|
+
case's spec-ids to the ECS's ids one-to-one. So a case author writes ordinary numbers
|
|
246
|
+
— `[[1, value], [2, value]]` — and **a reference field just holds the id it points at**
|
|
247
|
+
(`{ asset: 2 }`, `placement: { parent: 1, … }`). The bijection makes a key and every
|
|
248
|
+
field that names it line up on one actual id automatically — this is what killed the
|
|
249
|
+
old `Match.ref` / `Match.refMap` key-labelling (no more distinct-label bookkeeping,
|
|
250
|
+
and cross-references between entities finally compare correctly). For a **minted scalar**
|
|
251
|
+
a case does not want to pin — a generated timestamp, a random value — still use
|
|
252
|
+
`Match.anyNumber` / `Match.anyString` (imported from `@adobe/data-testing`); `Match` is
|
|
253
|
+
framework-agnostic, so vitest's `expect.stringContaining(...)` interops on the expected
|
|
254
|
+
side too. (The id-correspondence solver is now internal — the runner generates it from
|
|
255
|
+
the schema-marked spec-ids; there is no case-facing `ref`/`refMap` matcher anymore.)
|
|
256
|
+
- **Entity-addressed cases pass an `args` schema in the builder options.** State
|
|
257
|
+
references are detected from the store's schemas; an **arg** has none, so a transition
|
|
258
|
+
that addresses an entity by id gives `Conformance.cases` a leading options object whose
|
|
259
|
+
`args` schema marks the reference fields:
|
|
260
|
+
`Conformance.cases(fn, { args: { type: "object", properties: { id: Entity.schema } } }, …cases)`.
|
|
261
|
+
The case then writes the id **plain** — `args: { id: 2 }` — and the runner resolves each
|
|
262
|
+
`Entity.schema`-marked field to the seeded entity (via the `fromState` seed map) on the
|
|
263
|
+
ECS side, while the pure side reads the plain spec-id directly. Describe **only** the
|
|
264
|
+
reference fields (services and non-id args are omitted); the args type must be assignable
|
|
265
|
+
to the schema's `Schema.ToType`, so the schema can't drift from the signature (the builder
|
|
266
|
+
fails to type-check otherwise). This is the args-side analog of the `Entity.schema` mark
|
|
267
|
+
the runner reads on state.
|
|
260
268
|
- **The `entities` map key convention across a case, in one place:**
|
|
261
269
|
- **`before`** (the seed): **plain spec-id numbers** (`new Map([[1, …], [2, …]])`).
|
|
262
|
-
`fromState` seeds from these and returns the `spec-id → entity` map, so
|
|
263
|
-
{ id:
|
|
264
|
-
- **`after`** (the expectation, compared against the ECS
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
- **`samples`** (round-tripped `toState ∘ fromState`): same as `after` —
|
|
271
|
-
|
|
272
|
-
- **Building the open-keyed map — `Match.refMap(values)`.** When the entries come
|
|
273
|
-
from a list rather than hand-authored labels (a `samples` entry, a case `after`
|
|
274
|
-
whose entities you don't cross-reference), don't hand-roll the `Match.ref` keys:
|
|
275
|
-
`Match.refMap(iterableOfValues)` returns a `ReadonlyMap<number, V>` keyed by
|
|
276
|
-
process-unique open `ref`s — the standard way to build an identity-keyed collection
|
|
277
|
-
for comparison. Reach for a **hand-written `Match.ref(label)`** only when a key must
|
|
278
|
-
**correspond** to a reference elsewhere in the same case (a `selectedId`), where the
|
|
279
|
-
shared label is the whole point.
|
|
270
|
+
`fromState` seeds from these and returns the `spec-id → entity` map, so a case's
|
|
271
|
+
`args: { id: 1 }` resolves to the entity seeded for `1`.
|
|
272
|
+
- **`after`** (the expectation, compared against the ECS): **plain spec-id numbers**,
|
|
273
|
+
distinct per entry, and reference fields hold the spec-id they point at. The runner
|
|
274
|
+
refifies them and compares up to an id-bijection, so the ECS's own ids need not match.
|
|
275
|
+
You may reuse the same spec-ids as `before` for entities that persist (it reads
|
|
276
|
+
clearly), but any distinct numbers work — the comparison is by content + reference
|
|
277
|
+
structure, never by the literal id.
|
|
278
|
+
- **`samples`** (round-tripped `toState ∘ fromState`): same as `after` — plain spec-id
|
|
279
|
+
keys, compared up to a bijection against the ECS-minted ids.
|
|
280
280
|
- No per-transform test. The single **`spec.test.ts`** is one call —
|
|
281
281
|
`Conformance.runSpec({ state: State, transitions })` importing `transitions`
|
|
282
282
|
from the test-only `./transitions.js` (above) — that auto-discovers every module
|
|
@@ -37,10 +37,10 @@ installing `@adobe/data` never pulls in a `vitest` peer dependency):
|
|
|
37
37
|
|
|
38
38
|
- **`Match`** — the tolerant, matcher-aware value comparison: `matches(actual,
|
|
39
39
|
expected, options?)` and its throwing wrapper `assert(...)`, plus the matchers
|
|
40
|
-
`Match.anyNumber` / `Match.anyString`
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
`Match.anyNumber` / `Match.anyString` for minted scalars a case does not pin.
|
|
41
|
+
**Entity ids need no matcher**: a case writes plain spec-ids for map keys and
|
|
42
|
+
reference fields, and the runner compares up to an id-bijection (below), so `samples`
|
|
43
|
+
and `after` are ordinary `new Map([[1, value], …])` — no key labelling. Options are
|
|
44
44
|
`{ tolerance?: number }` — numbers snap to `tolerance` (default `0.01`) to absorb
|
|
45
45
|
F32↔f64 / trig noise. **Ordering is carried by the value's type**: a
|
|
46
46
|
`ReadonlyArray` compares **in order**, a `ReadonlySet` / `ReadonlyMap`
|
|
@@ -50,8 +50,8 @@ installing `@adobe/data` never pulls in a `vitest` peer dependency):
|
|
|
50
50
|
ignore when comparing content. Framework-agnostic: it honors any asymmetric matcher,
|
|
51
51
|
so vitest's `expect.any(...)` interops.
|
|
52
52
|
- **`Conformance`** — the case types (`Case`, `Cases`, `DerivationCase`,
|
|
53
|
-
`DerivationCases`, `Effects`, `ServiceCall`), the `
|
|
54
|
-
|
|
53
|
+
`DerivationCases`, `Effects`, `ServiceCall`), the `casesBuilder` (a feature's
|
|
54
|
+
`Conformance.cases`), `assertState` for custom harnesses, the whole-feature driver **`runFeature`**, the
|
|
55
55
|
pure-spec driver **`runSpec`**, and the lower-level per-surface drivers
|
|
56
56
|
`runTransactions` / `runActions` / `runComputeds` (internals of `runFeature`,
|
|
57
57
|
exported for the escape hatch below). Auto-pairing (transition ⇄ op by name),
|
|
@@ -167,8 +167,8 @@ Conformance.runSpec({ state: State, transitions });
|
|
|
167
167
|
It discovers every file exporting `cases`, enforces the two-exports rule, and
|
|
168
168
|
dispatches on case shape (transition → state + effects, derivation →
|
|
169
169
|
`fn(input) ≡ value`), seeding each case's `before`/`input` as a delta over
|
|
170
|
-
`State.create()`.
|
|
171
|
-
the pure side.
|
|
170
|
+
`State.create()`. On the ECS side it resolves the reference args a case's `args`
|
|
171
|
+
schema marks; the pure side reads them plain.
|
|
172
172
|
|
|
173
173
|
## The exception — a per-surface `userId`, via the lower-level runners
|
|
174
174
|
|
|
@@ -182,17 +182,21 @@ action db. `runFeature` has no place to thread two different `seedContext`s, so
|
|
|
182
182
|
this feature drops to the lower level. This is the escape hatch — ordinary
|
|
183
183
|
features never touch these drivers directly.
|
|
184
184
|
|
|
185
|
-
## Identity — the `
|
|
185
|
+
## Identity — the `args` schema
|
|
186
186
|
|
|
187
|
-
An entity-addressed transition
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
An entity-addressed transition declares an `args` schema in the builder options and
|
|
188
|
+
writes the id **plain**: `Conformance.cases(fn, { args: { type: "object", properties:
|
|
189
|
+
{ id: Entity.schema } } }, { …, args: { id: 2 }, … })`. The runner
|
|
190
|
+
finds each `Entity.schema`-marked arg field and resolves the plain spec-id to the
|
|
190
191
|
**seeded entity** via the id→entity map `fromState` returns (turned into a `resolve`
|
|
191
|
-
by `Conformance.resolver` — no feature writes `resolve` by hand)
|
|
192
|
-
make the wiring vanish: the ECS op takes the entity
|
|
193
|
-
key** (`{ id }`, same-shape args, no reshape), and
|
|
194
|
-
`ReadonlyMap<Id, Entity>` id→entity map (or `void` for an
|
|
195
|
-
feature, whose ids then resolve to `Entity.none`).
|
|
192
|
+
by `Conformance.resolver` — no feature writes `resolve` by hand); the pure side reads
|
|
193
|
+
the spec-id as-is. Two conventions make the wiring vanish: the ECS op takes the entity
|
|
194
|
+
**under the transition's own arg key** (`{ id }`, same-shape args, no reshape), and
|
|
195
|
+
`fromState` returns the `ReadonlyMap<Id, Entity>` id→entity map (or `void` for an
|
|
196
|
+
index-addressed / singleton feature, whose ids then resolve to `Entity.none`).
|
|
197
|
+
`data-lit-todo` is the reference. Describe only the reference fields — services and
|
|
198
|
+
non-id args are omitted, and the args type must be assignable to the schema's
|
|
199
|
+
`Schema.ToType` so it cannot drift from the signature.
|
|
196
200
|
|
|
197
201
|
## Name-parity — add a same-named op, never a per-item adapter
|
|
198
202
|
|
|
@@ -202,25 +206,31 @@ op is infra, and a thin **same-named** op (todo's `reorderTodo` action, space-ro
|
|
|
202
206
|
`createInitial` transaction) gives the transition something to pair with. Do **not**
|
|
203
207
|
reintroduce a per-item adapter to bridge a name mismatch — add the same-named op.
|
|
204
208
|
|
|
205
|
-
## Ordering, tolerance,
|
|
209
|
+
## Ordering, tolerance, the id-bijection
|
|
206
210
|
|
|
207
211
|
Ordering is carried by the value's **type**, not a match option — `ReadonlyArray`
|
|
208
212
|
positional, `ReadonlySet` / `ReadonlyMap` order-independent (the rule and its
|
|
209
213
|
rationale live in `../../../data-modelling.md`). What's specific to writing
|
|
210
214
|
conformance cases:
|
|
211
215
|
|
|
212
|
-
- **
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
`
|
|
216
|
+
- **The spec and the ECS mint different id sets, so comparison is up to an
|
|
217
|
+
id-bijection — automatically.** The runner reads the store's `componentSchemas`
|
|
218
|
+
(which also carry the resource schemas) and finds every entity reference: an
|
|
219
|
+
`entities` map **key** (an id by construction) and any field whose schema is
|
|
220
|
+
`Entity.schema` (`schema.entity === true`), recursing into bundled object schemas so
|
|
221
|
+
a `placement: { parent, order }` reference is found. It replaces each spec-id there
|
|
222
|
+
with a correspondence variable and solves a one-to-one matching against the ECS's
|
|
223
|
+
ids. So a case **writes plain spec-ids** for keys and reference fields, and a key and
|
|
224
|
+
every field naming it line up on one actual id with no author bookkeeping — this is
|
|
225
|
+
what retired `Match.ref` / `Match.refMap` for keys, and it is what makes a
|
|
226
|
+
cross-reference between entities (an `asset`, a `parent`) compare correctly at all.
|
|
227
|
+
- **Entity values carry no `id`** — identity is the key — so entity content compares
|
|
228
|
+
directly, with nothing to omit.
|
|
216
229
|
- **Float noise** is absorbed by the default `tolerance` (`0.01`), threaded through
|
|
217
230
|
`match?: { tolerance }`; raise it only when a case needs a looser grid.
|
|
218
|
-
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
that entity's `id`; the labels form a bijection over the actual ids.
|
|
222
|
-
`Match.anyNumber` / `anyString` leave an id a case doesn't pin fully open. `ref`
|
|
223
|
-
correspondence holds even across a `ReadonlySet` boundary.
|
|
231
|
+
- **A minted scalar** a case does not pin — a timestamp, a random draw — uses
|
|
232
|
+
`Match.anyNumber` / `Match.anyString`. Entity-id correspondence needs no matcher: the
|
|
233
|
+
runner derives it from the schema-marked spec-ids (the solver is internal).
|
|
224
234
|
|
|
225
235
|
## Recording side effects — built in, no Proxy
|
|
226
236
|
|
|
@@ -45,7 +45,7 @@ export const playMove = (t: CoreDatabase.Store, { index }: PlayMoveArgs) => {
|
|
|
45
45
|
(state only; service effects are asserted through the action). There is **no**
|
|
46
46
|
`define`/`conforms` adapter and **no** `covers` guard. A transaction taking
|
|
47
47
|
**entity ids** takes them under the transition's own arg key (`{ id }`); the runner
|
|
48
|
-
resolves each `
|
|
48
|
+
resolves each id the case's `args` schema marks via the id→entity map `fromState` returns. A
|
|
49
49
|
transaction with **no same-named transition** is infrastructure (`setInput`,
|
|
50
50
|
`setBounds`) or the drag UI op (`dragTodo`) or system-dispatched — it is simply
|
|
51
51
|
**skipped**, no guard needed. Don't add a per-item adapter for a renamed op; add a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/data-ai",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.102",
|
|
4
4
|
"description": "Cross-agent architecture skills for @adobe/data — installable as a Claude Code plugin or copied into any Agent-Skills-compatible agent (Cursor, Codex).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"skills"
|
|
30
30
|
],
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@adobe/data": "0.9.
|
|
32
|
+
"@adobe/data": "0.9.102"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"typescript": "^5.8.3",
|
|
36
36
|
"vitest": "^1.6.0",
|
|
37
|
-
"@adobe/data": "0.9.
|
|
37
|
+
"@adobe/data": "0.9.102"
|
|
38
38
|
},
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"scripts": {
|