@adobe/data-ai 0.9.91 → 0.9.93

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
@@ -11,46 +11,95 @@ It installs two things:
11
11
  - **skills** — `build-*` commands that scaffold features and applications.
12
12
  - **rules** — the path-scoped conventions those skills follow while building.
13
13
 
14
- > **For the installing agent:** find the block below that matches your host
15
- > (Claude Code or Cursor/other), run its commands, and stop. Each install owns a
16
- > namespaced folder and is a clean wipe-and-recopy, so re-running is also how you
17
- > **update** — it never touches files you authored.
14
+ The **rules** are the part that evolves often, so `install` pins the package and
15
+ re-copies them automatically on every install: bump the version and they refresh —
16
+ no manual step, no committed diff, no hand-editing.
18
17
 
19
- ## Install — Claude Code
18
+ ## Quick start
20
19
 
21
- Skills load as a marketplace plugin; rules install into the project. Run these
22
- three from a shell (agent-runnable):
20
+ From your project folder root:
21
+
22
+ **1. Install** — one command:
23
23
 
24
24
  ```
25
- claude plugin marketplace add adobe/data --scope project
26
- claude plugin install adobe-data-ai@adobe-data-skills --scope project
27
25
  npx @adobe/data-ai@latest install
28
26
  ```
29
27
 
30
- In an interactive Claude session you can instead use the slash-command form of
31
- the first two — `/plugin marketplace add adobe/data` then
32
- `/plugin install adobe-data-ai@adobe-data-skills` — but an agent driving a shell
33
- should use the `claude plugin …` commands above (slash commands aren't
34
- shell-runnable).
28
+ *(Claude Code only:* also add the skills plugin once — see
29
+ [Claude Code](#claude-code--add-the-skills-plugin-one-time). Cursor/Codex need
30
+ nothing extra; `install` copies their skills.*)*
31
+
32
+ **2. Restart your AI agent** so it loads the newly installed skills and rules.
33
+
34
+ **3. Create an application** — ask your agent:
35
+
36
+ ```
37
+ /build-application <a description of the app you want>
38
+ ```
39
+
40
+ That's the whole flow. Everything below explains what `install` does and the
41
+ other build skills available.
42
+
43
+ ## What `install` does
44
+
45
+ `install` does two things: it **copies the bundle now** (rules →
46
+ `.claude/rules/adobe-data-ai/`, and for Cursor/Codex skills →
47
+ `.agents/skills/adobe-data-ai/`), and it **wires the repo so future installs
48
+ self-update**, editing your `package.json` and `.gitignore` to:
35
49
 
36
- - Skills → the `adobe-data-ai` plugin. **Update:** `claude plugin update adobe-data-ai`.
37
- - Rules → `.claude/rules/adobe-data-ai/`. **Update:** re-run `npx @adobe/data-ai@latest install`.
50
+ 1. pin `@adobe/data-ai` in `devDependencies` at the **exact version it just
51
+ resolved** (never a range, so a later install can't silently pull an
52
+ unreviewed release);
53
+ 2. add `data-ai install` to **your own** `postinstall` script (chaining if one
54
+ exists) — it must be *your* script: pnpm does not run a dependency's lifecycle
55
+ scripts, so a `postinstall` shipped inside the package would silently not fire;
56
+ 3. gitignore the managed bundle folders.
38
57
 
39
- ## Install — Cursor (and Codex / other `.agents` agents)
58
+ The copied files are regenerated artifacts — never committed, never edited in
59
+ place. The wiring is idempotent, so re-running is harmless; with `--global` or in a
60
+ directory with no `package.json`, `install` just copies (no wiring).
40
61
 
41
- One command installs both:
62
+ After that first run, sync your lockfile with a normal install (`pnpm install`) so
63
+ the pinned dev-dependency is recorded; from then on every install refreshes the
64
+ bundle via the postinstall.
65
+
66
+ **Why `@latest` for the first command but a pinned version afterward?** The one
67
+ command you type is a one-time, human-initiated bootstrap, so `@latest` is fine
68
+ (the same posture as `npm create …@latest`). The part that *repeats* — every
69
+ teammate's and CI's install — runs from the **exact version `install` pinned into
70
+ your `devDependencies`**, never a moving tag, so no unreviewed release ever
71
+ auto-executes. Pinning happens where it matters, automatically.
72
+
73
+ **Update:** bump the `@adobe/data-ai` version in `package.json` and install again.
74
+ That's it.
75
+
76
+ ### Claude Code — add the skills plugin (one time)
77
+
78
+ Claude Code loads skills from a marketplace plugin, not from `.claude/skills/`, so
79
+ its skills are a separate one-time install (the `install` step above already
80
+ handles the rules for Claude Code):
42
81
 
43
82
  ```
44
- npx @adobe/data-ai@latest install
83
+ claude plugin marketplace add adobe/data --scope project
84
+ claude plugin install adobe-data-ai@adobe-data-skills --scope project
45
85
  ```
46
86
 
47
- - Skills → `.agents/skills/adobe-data-ai/`.
48
- - Rules → `.claude/rules/adobe-data-ai/`.
49
- - **Update:** re-run the same command.
87
+ (Interactive sessions can use `/plugin marketplace add adobe/data` then
88
+ `/plugin install adobe-data-ai@adobe-data-skills`.) **Update the skills:**
89
+ `claude plugin update adobe-data-ai`. Cursor/Codex need no plugin — `install`
90
+ copies their skills too.
91
+
92
+ ### Just the files, no managed dependency
50
93
 
51
- ## Use
94
+ If you don't want the auto-update wiring — a throwaway scaffold, a non-Node repo,
95
+ or you'd rather commit the bundle and update it on your own schedule — run
96
+ `install` where it can't wire (no `package.json`, or pass `--global`), or simply
97
+ delete the `postinstall`/dev-dependency lines it added. Re-running `install` is
98
+ always a clean wipe-and-recopy; you then update by re-running it yourself.
52
99
 
53
- Ask your agent to run a build command — skills are available by name:
100
+ ## Build skills
101
+
102
+ Step 3 above uses `build-application`; the skills are available by name:
54
103
 
55
104
  - **`build-application`** — build a whole app: a base feature that hosts
56
105
  lazily-loaded peer features.
@@ -66,15 +115,16 @@ by name when you want a single phase or a specialized flow: `build-data`,
66
115
  in subagents), `review` (audit output against the rules), and `structure`
67
116
  (reason about layout).
68
117
 
69
- ## One-liner: install + build an app
70
-
71
- Paste one of these into a shell, replacing the quoted text with your own app
72
- description. It installs the bundle, then runs `build-application` headlessly on
73
- your prompt.
118
+ ## One-liner: install + build an app (headless)
74
119
 
75
- This presumes you are already running the agent within the directory you want to use as your project root.
120
+ Paste this into an agent already running in your project root, replacing the
121
+ quoted text with your own app description. It installs the bundle, then runs
122
+ `build-application` on your prompt:
76
123
 
77
124
  ```
78
- Find the @adobe/data-ai package on npmjs and then install it in the current directory.
79
- Next use it's /build-application skill to build <prompt here>
125
+ Set up @adobe/data-ai in the current directory: run
126
+ `npx @adobe/data-ai@latest install` (this copies the bundle and pins the exact
127
+ version so rules auto-update on every install). On Claude Code also add the
128
+ skills plugin per the package README. Then use its /build-application skill to
129
+ build <prompt here>
80
130
  ```
package/bin/cli.mjs CHANGED
@@ -157,6 +157,78 @@ version on every install. Package: <https://www.npmjs.com/package/${PKG_NAME}>
157
157
  return file;
158
158
  }
159
159
 
160
+ // Wire the consumer repo for auto-updating installs (part of `install`, not a
161
+ // separate step). Idempotently:
162
+ // 1. pins `@adobe/data-ai` in devDependencies (exact version — never a range,
163
+ // so an install can't silently pull an unreviewed release),
164
+ // 2. adds `data-ai install` to the consumer's OWN `postinstall` (a dependency's
165
+ // lifecycle script does NOT run under pnpm, so it must live here), and
166
+ // 3. gitignores the managed, regenerated bundle folders.
167
+ // After this, bumping the pinned version and re-installing recopies the bundle —
168
+ // no manual step, no committed diff. Skips gracefully with a note when there is
169
+ // no package.json (the bundle is still copied; the repo just isn't auto-wired).
170
+ const MANAGED_GITIGNORE = [
171
+ `# ${PKG_NAME} — managed, regenerated on install; do not edit or commit`,
172
+ ".claude/rules/adobe-data-ai/",
173
+ ".claude/rules/adobe-data-ai-bootstrap.md",
174
+ ".agents/skills/adobe-data-ai/",
175
+ ];
176
+
177
+ function wireManagedUpdates(base) {
178
+ const pkgPath = join(base, "package.json");
179
+ if (!existsSync(pkgPath)) {
180
+ process.stdout.write(
181
+ ` (no package.json in ${base} — auto-update not wired; the bundle was still copied.\n` +
182
+ ` Add one, re-run install to wire it, or re-run manually to update.)\n`,
183
+ );
184
+ return;
185
+ }
186
+ const consumer = JSON.parse(readFileSync(pkgPath, "utf8"));
187
+ const changes = [];
188
+
189
+ // 1. pinned devDependency
190
+ consumer.devDependencies ??= {};
191
+ let pinnedDep = false;
192
+ if (consumer.devDependencies[PKG_NAME] !== VERSION) {
193
+ consumer.devDependencies[PKG_NAME] = VERSION;
194
+ changes.push(`devDependencies["${PKG_NAME}"] = "${VERSION}" (exact)`);
195
+ pinnedDep = true;
196
+ }
197
+
198
+ // 2. own postinstall runs the installer (chain if one already exists)
199
+ consumer.scripts ??= {};
200
+ const INSTALL = "data-ai install";
201
+ const post = consumer.scripts.postinstall;
202
+ if (!post) {
203
+ consumer.scripts.postinstall = INSTALL;
204
+ changes.push(`scripts.postinstall = "${INSTALL}"`);
205
+ } else if (!post.includes(INSTALL)) {
206
+ consumer.scripts.postinstall = `${post} && ${INSTALL}`;
207
+ changes.push(`scripts.postinstall += " && ${INSTALL}"`);
208
+ }
209
+ if (changes.length) writeFileSync(pkgPath, JSON.stringify(consumer, null, 2) + "\n");
210
+
211
+ // 3. gitignore the managed bundle folders
212
+ const giPath = join(base, ".gitignore");
213
+ const gi = existsSync(giPath) ? readFileSync(giPath, "utf8") : "";
214
+ if (!gi.includes(MANAGED_GITIGNORE[0])) {
215
+ const sep = gi === "" ? "" : gi.endsWith("\n") ? "\n" : "\n\n";
216
+ writeFileSync(giPath, gi + sep + MANAGED_GITIGNORE.join("\n") + "\n");
217
+ changes.push(".gitignore += managed bundle paths");
218
+ }
219
+
220
+ for (const c of changes) process.stdout.write(` wired: ${c}\n`);
221
+ if (!changes.length) process.stdout.write(" auto-update already wired\n");
222
+ // Adding/repinning the dev-dependency leaves the lockfile out of sync until a
223
+ // normal install records it (and CI with a frozen lockfile would fail until then).
224
+ if (pinnedDep) {
225
+ process.stdout.write(
226
+ "\nNext: run your package manager's install to sync the lockfile\n" +
227
+ " pnpm install # or npm install / yarn\n",
228
+ );
229
+ }
230
+ }
231
+
160
232
  function parseArgs(argv) {
161
233
  const positional = [];
162
234
  const flags = new Set();
@@ -177,11 +249,17 @@ Install the architecture skills + rules for Cursor, Codex, and other agents.
177
249
  same way for every agent — see README.)
178
250
 
179
251
  Usage:
180
- npx ${PKG_NAME}@latest install [options]
252
+ npx ${PKG_NAME}@latest install # copy the bundle AND wire auto-updates (default)
181
253
  npx ${PKG_NAME}@latest list
182
254
 
183
255
  Commands:
184
- install Skills → .agents/skills/${BUNDLE}/, rules → .claude/rules/${BUNDLE}/ (default).
256
+ install Copy the bundle (skills → .agents/skills/${BUNDLE}/, rules →
257
+ .claude/rules/${BUNDLE}/) AND wire this repo for auto-updating installs:
258
+ pin ${PKG_NAME} in devDependencies (exact), add \`data-ai install\` to the
259
+ repo's own postinstall, and gitignore the managed bundle folders. Run once;
260
+ thereafter a plain install refreshes the bundle and bumping the pinned
261
+ version updates it. Skips the wiring (copies only) with \`--global\` or when
262
+ there's no package.json.
185
263
  list Print the skills bundled in this package.
186
264
 
187
265
  Options:
@@ -229,6 +307,10 @@ function main() {
229
307
  process.stdout.write(` ${skills.length} skills → ${skillsDir}\n`);
230
308
  process.stdout.write(` ${ruleCount} rules → ${rulesDir}\n`);
231
309
  process.stdout.write(` bootstrap → ${bootstrapFile}\n`);
310
+
311
+ // A project install also wires the repo for auto-updating installs (idempotent).
312
+ // A global install has no consumer package.json to wire, so it only copies.
313
+ if (!flags.has("global")) wireManagedUpdates(base);
232
314
  }
233
315
 
234
316
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/data-ai",
3
- "version": "0.9.91",
3
+ "version": "0.9.93",
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.91"
32
+ "@adobe/data": "0.9.93"
33
33
  },
34
34
  "devDependencies": {
35
35
  "typescript": "^5.8.3",
36
36
  "vitest": "^1.6.0",
37
- "@adobe/data": "0.9.91"
37
+ "@adobe/data": "0.9.93"
38
38
  },
39
39
  "license": "MIT",
40
40
  "scripts": {
@@ -9,7 +9,7 @@ output: app
9
9
  plugin, so all schemas coexist, persist, and sync while the base type stays decoupled.
10
10
  - The base reaches a peer only through a lazy element wrapper (dynamic import), so peers
11
11
  load on demand.
12
- - The entry point creates the live database from `FeatureDatabase.plugin` (the base
12
+ - The entry point creates the live database from `MainService.plugin` (the base
13
13
  feature's assembled database — see `features/services/main-service/index.md`) and mounts the root UI.
14
14
 
15
15
  See `features/index.md` (one-app-many-features) for the wiring rules.
@@ -8,14 +8,14 @@ output: feature
8
8
  Create the feature's `data/` layer (pure spec; depends on nothing but `@adobe/data`
9
9
  and other `data/` declarations):
10
10
 
11
- - one namespace folder per data type — `<type>/{<type>.ts, schema.ts, public.ts, <helper>.ts}`;
11
+ - one namespace folder per data type — `<type>/{<type>.ts, public.ts, <helper>.ts}` (+ `schema.ts` only when a runtime boundary needs it);
12
12
  - `data/state/` — the `State` aggregate plus its pure transforms/derivations.
13
13
 
14
14
  **Always create `data/state/`** — even for a shell feature whose only field is a
15
15
  boolean or enum. A feature with ECS resources/transactions but no `State` is
16
16
  incomplete: the transaction must wrap a pure transform, not invent the logic. In rare circumstances, there may be no real state in a feature in which case the state type = {}
17
17
 
18
- The schema is the single source of truth; the type derives from it (`Schema.ToType`).
18
+ The hand-authored type in `<type>.ts` is the source of truth. The schema is optional up front — add `schema.ts` only when a runtime boundary (persistence, wire, or an ECS component/resource) needs one, write it to match the type, and pin it with `type _Pin = Assert<Equal<Schema.ToType<typeof schema>, <Type>>>` so it cannot drift. `Schema.ToType` is used only in that assertion, never as the exported type.
19
19
  Helpers are pure and unit-tested. Run this first — every other layer imports `data/`.
20
20
 
21
21
  The how is in the auto-loading rules: `features/data/index.md`, `features/data/state.md`, and
@@ -12,7 +12,7 @@ Create `services/main-service/system-database/system-database.ts`: `Database.Plu
12
12
  Database.Plugin.combine(<currentTop>.plugin, scheduler), systems })` — combine `scheduler` with the
13
13
  feature's **current top** main-service layer (`ActionDatabase` / `ServiceDatabase` / `ComputedDatabase`,
14
14
  whichever it built), never a hardcoded `ComputedDatabase`, so systems *and* any services/actions
15
- compose into the one `FeatureDatabase`. The `systems`
15
+ compose into the one `MainService`. The `systems`
16
16
  map is declared **inline** (see `features/services/main-service/systems.md` — inline is required for `db` to be
17
17
  typed and for system-name inference; a `systems/` folder is optional, only for extracted
18
18
  per-frame body helpers).