@adobe/data-ai 0.9.83 → 0.9.86
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/README.md +42 -0
- package/.claude/rules/archetypes.md +60 -0
- package/.claude/rules/cohesion.md +66 -0
- package/.claude/rules/data-modelling.md +71 -0
- package/.claude/rules/element.md +130 -0
- package/.claude/rules/features/data/index.md +35 -0
- package/.claude/rules/features/data/state.md +56 -0
- package/.claude/rules/features/ecs/actions.md +32 -0
- package/.claude/rules/features/ecs/archetypes.md +46 -0
- package/.claude/rules/features/ecs/components.md +41 -0
- package/.claude/rules/features/ecs/computed.md +26 -0
- package/.claude/rules/features/ecs/conformance.md +71 -0
- package/.claude/rules/features/ecs/index.md +179 -0
- package/.claude/rules/features/ecs/indexes.md +63 -0
- package/.claude/rules/features/ecs/resources.md +28 -0
- package/.claude/rules/features/ecs/services.md +24 -0
- package/.claude/rules/features/ecs/systems.md +132 -0
- package/.claude/rules/features/ecs/transactions.md +45 -0
- package/.claude/rules/features/index.md +95 -0
- package/.claude/rules/features/services/index.md +34 -0
- package/.claude/rules/features/ui/index.md +31 -0
- package/.claude/rules/function-references.md +35 -0
- package/.claude/rules/lazy-element.md +127 -0
- package/.claude/rules/namespace.md +179 -0
- package/.claude/rules/plugin-modelling.md +170 -0
- package/.claude/rules/presentation.md +83 -0
- package/.claude/rules/type-casts.md +94 -0
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +54 -76
- package/bin/cli.mjs +81 -26
- package/package.json +9 -2
- package/skills/build-actions/SKILL.md +16 -0
- package/skills/build-app-entry/SKILL.md +15 -0
- package/skills/build-application/SKILL.md +12 -0
- package/skills/build-computed/SKILL.md +16 -0
- package/skills/build-core-database/SKILL.md +24 -0
- package/skills/build-data/SKILL.md +22 -0
- package/skills/build-feature/SKILL.md +18 -0
- package/skills/build-game/SKILL.md +21 -0
- package/skills/build-indexes/SKILL.md +16 -0
- package/skills/build-service-database/SKILL.md +16 -0
- package/skills/build-services/SKILL.md +16 -0
- package/skills/build-systems/SKILL.md +24 -0
- package/skills/build-transactions/SKILL.md +15 -0
- package/skills/build-ui/SKILL.md +13 -0
- package/skills/graph-execute/SKILL.md +13 -0
- package/skills/meta-build/SKILL.md +43 -0
- package/skills/review/SKILL.md +25 -0
- package/skills/structure/SKILL.md +7 -0
- package/skills/x-alpha/SKILL.md +7 -0
- package/skills/x-beta/SKILL.md +7 -0
- package/skills/x-double/SKILL.md +7 -0
- package/skills/x-execute/SKILL.md +16 -0
- package/skills/x-log/SKILL.md +12 -0
- package/skills/x-pow/SKILL.md +9 -0
- package/skills/x-subagent/SKILL.md +8 -0
- package/skills/x-trace/SKILL.md +11 -0
- package/skills/x-validate/SKILL.md +67 -0
- package/skills/bar/SKILL.md +0 -8
- package/skills/foo/SKILL.md +0 -8
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- 'packages/**/*.ts'
|
|
4
|
+
- 'packages/**/*.tsx'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Type casts — only two valid uses
|
|
8
|
+
|
|
9
|
+
`as` is dangerous. It silently turns off the type checker for the cast
|
|
10
|
+
expression. Every cast is a place a future refactor can break in
|
|
11
|
+
silence. There are exactly two valid uses:
|
|
12
|
+
|
|
13
|
+
1. **Proving a type the compiler cannot see.** A runtime invariant you
|
|
14
|
+
have established but TypeScript has no way to verify — e.g.
|
|
15
|
+
"validated JSON matches `User.schema`", "this `unknown` from a loose
|
|
16
|
+
API is `number` because the schema declared it", "this DOM node is
|
|
17
|
+
`HTMLInputElement` because the selector matched `input`".
|
|
18
|
+
|
|
19
|
+
2. **Widening a literal or default to a useful container type.** A
|
|
20
|
+
resource or component default is `0` (the literal) without help.
|
|
21
|
+
`0 as F32` widens it to `F32` so the resource can hold any number,
|
|
22
|
+
not just zero. Same for `[] as User[]`, `false as boolean`,
|
|
23
|
+
`{} as State`. Without the cast, the inferred type is so narrow it
|
|
24
|
+
blocks every later assignment.
|
|
25
|
+
|
|
26
|
+
Anything else is the cast hiding a real defect. Most often: an identity
|
|
27
|
+
cast that neither narrows nor widens, used to make a type error go
|
|
28
|
+
away without fixing the underlying type.
|
|
29
|
+
|
|
30
|
+
## The acceptance test
|
|
31
|
+
|
|
32
|
+
Before every `as`, articulate in one sentence which of the two it is:
|
|
33
|
+
|
|
34
|
+
- **Case 1:** "I know `<expr>` is `<T>` because <runtime invariant>."
|
|
35
|
+
- **Case 2:** "I'm widening `<literal>` so the container can hold any `<T>`."
|
|
36
|
+
|
|
37
|
+
If your sentence reduces to "TypeScript is wrong" or "I just want this
|
|
38
|
+
to compile", the cast is hiding a real defect — fix the type at its
|
|
39
|
+
source, do not cast at the consumer.
|
|
40
|
+
|
|
41
|
+
## Common violations
|
|
42
|
+
|
|
43
|
+
### Identity casts (neither widening nor narrowing)
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// ❌ `cameraAngle + delta` is already F32 (= number). Cast does nothing.
|
|
47
|
+
t.resources.cameraAngle = (t.resources.cameraAngle + delta) as F32;
|
|
48
|
+
|
|
49
|
+
// ✅
|
|
50
|
+
t.resources.cameraAngle = t.resources.cameraAngle + delta;
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Casting `any` to a specific shape just to call a property
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// ❌ `prev` is already any; the cast adds no information.
|
|
57
|
+
const n = (prev as ArrayLike<number>).length;
|
|
58
|
+
|
|
59
|
+
// ✅
|
|
60
|
+
const n = prev.length;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Casting wider than necessary
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// ❌ Loses the value-side type for no reason.
|
|
67
|
+
const map = t.componentSchemas as Record<string, any>;
|
|
68
|
+
|
|
69
|
+
// ✅ Same key widening, but values stay typed as Schema.
|
|
70
|
+
const map = t.componentSchemas as Record<string, Schema>;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Casting to silence an error you should fix at the source
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// declaration (your code)
|
|
77
|
+
export const emit = (name: string, payload: unknown): void => {
|
|
78
|
+
return inner.send(name, payload); // actually returns Promise<Ack>
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// ❌ cast hides the lie; every caller will duplicate it
|
|
82
|
+
const ack = await (emit("save", data) as Promise<Ack>);
|
|
83
|
+
|
|
84
|
+
// ✅ fix the declaration once; every consumer benefits
|
|
85
|
+
export const emit = (name: string, payload: unknown): Promise<Ack> => {
|
|
86
|
+
return inner.send(name, payload);
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## When the lying type is in code you control
|
|
91
|
+
|
|
92
|
+
Fix the declaration. A consumer-side cast is a leaky patch every other
|
|
93
|
+
caller will duplicate; one declaration change removes the cast
|
|
94
|
+
everywhere and protects future call sites the compiler will now catch.
|
package/README.md
CHANGED
|
@@ -1,102 +1,80 @@
|
|
|
1
1
|
# @adobe/data-ai
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI architecture skills + rules for building applications with
|
|
4
|
+
[`@adobe/data`](https://www.npmjs.com/package/@adobe/data) — a layered,
|
|
5
|
+
spec-first feature structure (`data → ecs → ui`) kept honest by conformance
|
|
6
|
+
tests. Versioned in lockstep with the library: `@adobe/data-ai@x.y.z` targets
|
|
7
|
+
`@adobe/data@x.y.z`.
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
It installs two things:
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
- **skills** — `build-*` commands that scaffold features and applications.
|
|
12
|
+
- **rules** — the path-scoped conventions those skills follow while building.
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
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.
|
|
11
18
|
|
|
12
|
-
## Install
|
|
19
|
+
## Install — Claude Code
|
|
13
20
|
|
|
14
|
-
|
|
21
|
+
Skills load as a marketplace plugin; rules install into the project. Run these
|
|
22
|
+
three from a shell (agent-runnable):
|
|
15
23
|
|
|
16
|
-
```
|
|
24
|
+
```
|
|
25
|
+
claude plugin marketplace add adobe/data --scope project
|
|
26
|
+
claude plugin install adobe-data-ai@adobe-data-skills --scope project
|
|
17
27
|
npx @adobe/data-ai@latest install
|
|
18
28
|
```
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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).
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
npx @adobe/data-ai@latest install --dir=./sub # into a specific base dir
|
|
27
|
-
npx @adobe/data-ai@latest list # show bundled skills
|
|
28
|
-
```
|
|
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`.
|
|
29
38
|
|
|
30
|
-
## Install (
|
|
39
|
+
## Install — Cursor (and Codex / other `.agents` agents)
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
One command installs both:
|
|
33
42
|
|
|
34
|
-
Interactive:
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
/plugin marketplace add adobe/data
|
|
38
|
-
/plugin install adobe-data-ai@adobe-data-skills
|
|
39
43
|
```
|
|
40
|
-
|
|
41
|
-
Or declaratively, so collaborators are prompted to auto-install on next launch — commit to your repo's `.claude/settings.json`:
|
|
42
|
-
|
|
43
|
-
```json
|
|
44
|
-
{
|
|
45
|
-
"extraKnownMarketplaces": {
|
|
46
|
-
"adobe-data-skills": {
|
|
47
|
-
"source": { "source": "github", "repo": "adobe/data" }
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"enabledPlugins": {
|
|
51
|
-
"adobe-data-ai@adobe-data-skills": true
|
|
52
|
-
}
|
|
53
|
-
}
|
|
44
|
+
npx @adobe/data-ai@latest install
|
|
54
45
|
```
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# Pragmatic Programming
|
|
47
|
+
- Skills → `.agents/skills/adobe-data-ai/`.
|
|
48
|
+
- Rules → `.claude/rules/adobe-data-ai/`.
|
|
49
|
+
- **Update:** re-run the same command.
|
|
61
50
|
|
|
62
|
-
##
|
|
51
|
+
## Use
|
|
63
52
|
|
|
64
|
-
|
|
53
|
+
Ask your agent to run a build command — skills are available by name:
|
|
65
54
|
|
|
66
|
-
|
|
55
|
+
- **`build-application`** — build a whole app: a base feature that hosts
|
|
56
|
+
lazily-loaded peer features.
|
|
57
|
+
- **`build-feature`** — build one feature end to end. Pipes the per-layer skills
|
|
58
|
+
(`data → core-database → transactions → … → ui`), then conformance-tests the
|
|
59
|
+
result against its pure `data/` spec.
|
|
67
60
|
|
|
68
|
-
|
|
61
|
+
Both compose finer-grained skills that are installed alongside and discoverable
|
|
62
|
+
by name when you want a single phase or a specialized flow: `build-data`,
|
|
63
|
+
`build-core-database`, `build-indexes`, `build-transactions`, `build-computed`,
|
|
64
|
+
`build-services`, `build-service-database`, `build-actions`, `build-systems`,
|
|
65
|
+
`build-ui`, `build-app-entry`; plus `build-game`, `meta-build` (phase-by-phase
|
|
66
|
+
in subagents), `review` (audit output against the rules), and `structure`
|
|
67
|
+
(reason about layout).
|
|
69
68
|
|
|
70
|
-
|
|
69
|
+
## One-liner: install + build an app
|
|
71
70
|
|
|
72
|
-
|
|
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.
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
- Velocity: Write applications faster. ▼time
|
|
75
|
+
This presumes you are already running the agent within the directory you want to use as your project root.
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
3. Changeable: Quickly and safely modified or extended.
|
|
82
|
-
|
|
83
|
-
There is occasionally some tension between clarity and changeability. More abstraction or generic parameters may make things more changeable at the cost of some clarity.
|
|
84
|
-
|
|
85
|
-
### Code Challenges
|
|
86
|
-
|
|
87
|
-
- Complexity: Undermines every single one of our code priorities.
|
|
88
|
-
|
|
89
|
-
Complexity is the limiting factor which defines the upper limit on how sophisticated of an application we are able to create and maintain at a practical velocity.
|
|
90
|
-
|
|
91
|
-
The difficulty of dealing with complexity tends to increase at a greater than linear rate, especially once the short term context window of a human or ai agent is exceeded.
|
|
92
|
-
|
|
93
|
-
### General Principles
|
|
94
|
-
|
|
95
|
-
- Separation of Concerns: If two concerns can be separated then do it.
|
|
96
|
-
- Avoid mutation: Immutable values are easier to reason about.
|
|
97
|
-
- Use Small files: Aim for less than 200 loc. Decompose if > 500 loc.
|
|
98
|
-
- Single concern per file: Export only a single declaration per file.
|
|
99
|
-
- Avoid object oriented classes: Combines data concerns with functions.
|
|
100
|
-
- Distinguish services from data: Services do things, data stores things.
|
|
101
|
-
- Use static typing: Finds errors earlier and guides both AI and humans.
|
|
102
|
-
- Avoid side effects: Pure functions are easier to comprehend and test.
|
|
77
|
+
```
|
|
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 <promt here>
|
|
80
|
+
```
|
package/bin/cli.mjs
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Installer for the @adobe/data-ai
|
|
2
|
+
// Installer for the @adobe/data-ai bundle (Cursor / Codex / .agents-standard agents).
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
// bundle directory that agents which recurse `.agents/skills/` will discover:
|
|
4
|
+
// Lays down two managed, namespaced directories the agent discovers:
|
|
6
5
|
//
|
|
7
|
-
// .agents/skills/adobe-data-ai/<name>/SKILL.md
|
|
6
|
+
// .agents/skills/adobe-data-ai/<name>/SKILL.md — the build-* skills
|
|
7
|
+
// .claude/rules/adobe-data-ai/**/*.md — the architecture rules
|
|
8
8
|
//
|
|
9
|
-
// We own
|
|
10
|
-
// wipe-and-recopy — it never touches
|
|
9
|
+
// We own both `adobe-data-ai/` directories outright, so a refresh is a clean
|
|
10
|
+
// wipe-and-recopy — it never touches files you authored elsewhere. Re-running
|
|
11
|
+
// the installer is therefore also how you update.
|
|
11
12
|
//
|
|
12
|
-
// Claude Code is intentionally NOT a target: it does not scan `.agents/`,
|
|
13
|
-
// copying into `.claude/skills/` could collide with a user's own skills
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// Claude Code is intentionally NOT a skills target: it does not scan `.agents/`,
|
|
14
|
+
// and copying into `.claude/skills/` could collide with a user's own skills — it
|
|
15
|
+
// consumes the skills as the `adobe-data-ai` marketplace plugin instead. The
|
|
16
|
+
// rules, however, install into `.claude/rules/adobe-data-ai/` for every agent
|
|
17
|
+
// (Claude auto-injects them by their `paths:` globs; other agents read them by
|
|
18
|
+
// name as their skills run). See README.
|
|
16
19
|
|
|
17
20
|
import {
|
|
18
21
|
cpSync,
|
|
@@ -30,12 +33,39 @@ import { fileURLToPath } from "node:url";
|
|
|
30
33
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
31
34
|
const pkgRoot = resolve(here, "..");
|
|
32
35
|
const skillsSrc = join(pkgRoot, "skills");
|
|
36
|
+
const rulesSrc = join(pkgRoot, ".claude", "rules");
|
|
33
37
|
const pkg = JSON.parse(readFileSync(join(pkgRoot, "package.json"), "utf8"));
|
|
34
38
|
const { name: PKG_NAME, version: VERSION } = pkg;
|
|
35
39
|
|
|
36
|
-
// Namespaced bundle folder — the whole directory belongs to this package
|
|
40
|
+
// Namespaced bundle folder — the whole directory belongs to this package, under
|
|
41
|
+
// each agent root.
|
|
37
42
|
const BUNDLE = "adobe-data-ai";
|
|
38
43
|
|
|
44
|
+
// A do-not-edit notice dropped at each bundle root. Claude Code loads nested
|
|
45
|
+
// CLAUDE.md files when working in a subtree, so an agent that opens one of these
|
|
46
|
+
// folders sees the notice before touching anything. `extra` adds a pointer to
|
|
47
|
+
// the companion bundle.
|
|
48
|
+
function notice(extra) {
|
|
49
|
+
return `# Externally managed — do not edit
|
|
50
|
+
|
|
51
|
+
The files in this folder are installed and managed by the \`${PKG_NAME}\`
|
|
52
|
+
package. This entire directory is **deleted and rebuilt** on every
|
|
53
|
+
\`npx ${PKG_NAME} install\`, so any local edit here is silently discarded on the
|
|
54
|
+
next reinstall or version upgrade.
|
|
55
|
+
|
|
56
|
+
To change them, edit upstream in the \`${PKG_NAME}\` package and publish a new
|
|
57
|
+
version, then reinstall — do not modify these files in place.
|
|
58
|
+
${extra ? `\n${extra}\n` : ""}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function writeMeta(bundleDir, noticeBody, extraMeta) {
|
|
62
|
+
writeFileSync(join(bundleDir, "CLAUDE.md"), noticeBody);
|
|
63
|
+
writeFileSync(
|
|
64
|
+
join(bundleDir, ".data-ai.json"),
|
|
65
|
+
JSON.stringify({ package: PKG_NAME, version: VERSION, ...extraMeta }, null, 2) + "\n",
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
39
69
|
function discoverSkills() {
|
|
40
70
|
if (!existsSync(skillsSrc)) return [];
|
|
41
71
|
return readdirSync(skillsSrc, { withFileTypes: true })
|
|
@@ -44,17 +74,41 @@ function discoverSkills() {
|
|
|
44
74
|
.sort();
|
|
45
75
|
}
|
|
46
76
|
|
|
47
|
-
|
|
48
|
-
|
|
77
|
+
// Recursively count the rule `.md` files, excluding the top-level README.md
|
|
78
|
+
// (rules-authoring meta doc, not a rule — and it carries no `paths:` guard).
|
|
79
|
+
function countRules(dir) {
|
|
80
|
+
let n = 0;
|
|
81
|
+
for (const d of readdirSync(dir, { withFileTypes: true })) {
|
|
82
|
+
if (d.isDirectory()) n += countRules(join(dir, d.name));
|
|
83
|
+
else if (d.name.endsWith(".md") && !(dir === rulesSrc && d.name === "README.md")) n += 1;
|
|
84
|
+
}
|
|
85
|
+
return n;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function installSkills(base, skills) {
|
|
89
|
+
const bundleDir = join(base, ".agents", "skills", BUNDLE);
|
|
49
90
|
rmSync(bundleDir, { recursive: true, force: true });
|
|
50
91
|
mkdirSync(bundleDir, { recursive: true });
|
|
51
92
|
for (const name of skills) {
|
|
52
93
|
cpSync(join(skillsSrc, name), join(bundleDir, name), { recursive: true });
|
|
53
94
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
95
|
+
writeMeta(
|
|
96
|
+
bundleDir,
|
|
97
|
+
notice("The architecture rules these skills follow are installed at\n`.claude/rules/adobe-data-ai/` (referenced by name from each SKILL.md)."),
|
|
98
|
+
{ skills },
|
|
57
99
|
);
|
|
100
|
+
return bundleDir;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function installRules(base) {
|
|
104
|
+
const bundleDir = join(base, ".claude", "rules", BUNDLE);
|
|
105
|
+
rmSync(bundleDir, { recursive: true, force: true });
|
|
106
|
+
mkdirSync(bundleDir, { recursive: true });
|
|
107
|
+
// Copy the whole rules tree, minus the top-level README.md meta doc.
|
|
108
|
+
const readme = join(rulesSrc, "README.md");
|
|
109
|
+
cpSync(rulesSrc, bundleDir, { recursive: true, filter: (src) => src !== readme });
|
|
110
|
+
writeMeta(bundleDir, notice(), { rules: countRules(rulesSrc) });
|
|
111
|
+
return bundleDir;
|
|
58
112
|
}
|
|
59
113
|
|
|
60
114
|
function parseArgs(argv) {
|
|
@@ -72,19 +126,20 @@ function parseArgs(argv) {
|
|
|
72
126
|
|
|
73
127
|
const HELP = `${PKG_NAME} v${VERSION}
|
|
74
128
|
|
|
75
|
-
Install the architecture
|
|
76
|
-
|
|
129
|
+
Install the architecture skills + rules for Cursor, Codex, and other agents.
|
|
130
|
+
(Claude Code gets the skills from the marketplace plugin; the rules install the
|
|
131
|
+
same way for every agent — see README.)
|
|
77
132
|
|
|
78
133
|
Usage:
|
|
79
134
|
npx ${PKG_NAME}@latest install [options]
|
|
80
135
|
npx ${PKG_NAME}@latest list
|
|
81
136
|
|
|
82
137
|
Commands:
|
|
83
|
-
install
|
|
138
|
+
install Skills → .agents/skills/${BUNDLE}/, rules → .claude/rules/${BUNDLE}/ (default).
|
|
84
139
|
list Print the skills bundled in this package.
|
|
85
140
|
|
|
86
141
|
Options:
|
|
87
|
-
--global, -g Install into your home directory (~/.agents
|
|
142
|
+
--global, -g Install into your home directory (~/.agents, ~/.claude)
|
|
88
143
|
instead of the current project.
|
|
89
144
|
--dir=<path> Base directory to install into (default: cwd).
|
|
90
145
|
--help, -h Show this help.
|
|
@@ -119,13 +174,13 @@ function main() {
|
|
|
119
174
|
}
|
|
120
175
|
|
|
121
176
|
const base = flags.has("global") ? homedir() : dir ? resolve(dir) : process.cwd();
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
177
|
+
const skillsDir = installSkills(base, skills);
|
|
178
|
+
const rulesDir = installRules(base);
|
|
179
|
+
const ruleCount = countRules(rulesSrc);
|
|
125
180
|
|
|
126
|
-
process.stdout.write(`Installed ${
|
|
127
|
-
process.stdout.write(` ${
|
|
128
|
-
process.stdout.write(`
|
|
181
|
+
process.stdout.write(`Installed ${PKG_NAME} v${VERSION}\n`);
|
|
182
|
+
process.stdout.write(` ${skills.length} skills → ${skillsDir}\n`);
|
|
183
|
+
process.stdout.write(` ${ruleCount} rules → ${rulesDir}\n`);
|
|
129
184
|
}
|
|
130
185
|
|
|
131
186
|
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/data-ai",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.86",
|
|
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,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"skills",
|
|
16
|
+
".claude",
|
|
16
17
|
"bin",
|
|
17
18
|
".claude-plugin",
|
|
18
19
|
"README.md",
|
|
@@ -27,12 +28,18 @@
|
|
|
27
28
|
"codex",
|
|
28
29
|
"skills"
|
|
29
30
|
],
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@adobe/data": "0.9.86"
|
|
33
|
+
},
|
|
30
34
|
"devDependencies": {
|
|
31
|
-
"
|
|
35
|
+
"typescript": "^5.8.3",
|
|
36
|
+
"vitest": "^1.6.0",
|
|
37
|
+
"@adobe/data": "0.9.86"
|
|
32
38
|
},
|
|
33
39
|
"license": "MIT",
|
|
34
40
|
"scripts": {
|
|
35
41
|
"build": "cp ../../LICENSE .",
|
|
42
|
+
"typecheck": "true",
|
|
36
43
|
"test": "vitest --run --passWithNoTests",
|
|
37
44
|
"publish-public": "pnpm build && pnpm publish --no-git-checks --access public"
|
|
38
45
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-actions
|
|
3
|
+
description: Build a feature's ecs action-database — async orchestration over services and transactions. If the feature has async flows or side effects outside of the main store.
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Skip if this feature doesn't contain or require actions.
|
|
9
|
+
|
|
10
|
+
Create `ecs/action-database/`: `action-database.ts` (extends `ServiceDatabase`, adds `actions`
|
|
11
|
+
from `./actions/index.js`) plus an `actions/` folder — one async orchestrator per file. An action
|
|
12
|
+
takes `db: ServiceDatabase`, awaits `services/` ports, then commits **exactly one** transaction.
|
|
13
|
+
|
|
14
|
+
The top ecs layer; comes after `service-database`.
|
|
15
|
+
|
|
16
|
+
The how is in the auto-loading `features/ecs/actions.md` rule.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-app-entry
|
|
3
|
+
description: Wire built features into a running application — import peer schemas, lazy-load peers, and mount the root UI.
|
|
4
|
+
input: app
|
|
5
|
+
output: app
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
- The base (`features/main`) core-database `imports` each peer feature's core-database
|
|
9
|
+
plugin, so all schemas coexist, persist, and sync while the base type stays decoupled.
|
|
10
|
+
- The base reaches a peer only through a lazy element wrapper (dynamic import), so peers
|
|
11
|
+
load on demand.
|
|
12
|
+
- The entry point creates the live database from `FeatureDatabase.plugin` (the base
|
|
13
|
+
feature's assembled database — see `features/ecs/index.md`) and mounts the root UI.
|
|
14
|
+
|
|
15
|
+
See `features/index.md` (one-app-many-features) for the wiring rules.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-application
|
|
3
|
+
description: Build an application — a base feature hosting lazily-loaded peer features.
|
|
4
|
+
input: app
|
|
5
|
+
output: app
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
/graph-execute
|
|
9
|
+
/build-feature (base — features/main)
|
|
10
|
+
for each sub feature
|
|
11
|
+
/build-feature
|
|
12
|
+
/build-app-entry
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-computed
|
|
3
|
+
description: Build a feature's ecs computed-database — derived observable values.
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Skip if this feature doesn't contain or require computed values.
|
|
9
|
+
|
|
10
|
+
Create `ecs/computed-database/`: `computed-database.ts` (extends the previous layer, adds
|
|
11
|
+
`computed` from `./computed/index.js`) plus a `computed/` folder — one `cached` derived value
|
|
12
|
+
per file + barrel. Derivation logic lives in `data/`; a computed only wires a db observable to it.
|
|
13
|
+
|
|
14
|
+
Comes after `transaction-database`.
|
|
15
|
+
|
|
16
|
+
The how is in the auto-loading `features/ecs/computed.md` rule.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-core-database
|
|
3
|
+
description: Build a feature's ecs schema — the core-database (components, resources, archetypes). The first ecs layer.
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Create `ecs/core-database/` — `core-database.ts` plus one single-export file per facet
|
|
9
|
+
the feature actually uses (`components`, `resources`, `archetypes` are each optional on
|
|
10
|
+
`Database.Plugin.create`). Create only the facet files you need; omit the rest rather than
|
|
11
|
+
shipping empty `Database.components({})` boilerplate. A feature with **no entities** (a
|
|
12
|
+
singleton whose whole state is resources) is just `resources.ts` + `core-database.ts`.
|
|
13
|
+
|
|
14
|
+
- `components.ts` → `Database.components({ document, settings, presence, session })` (scopes optional) — only if the feature has entities.
|
|
15
|
+
- `resources.ts` → `Database.resources({ … })` (every entry needs a `default`) — for singleton / global state.
|
|
16
|
+
- `archetypes.ts` → `Database.archetypes(components, { … })` — only alongside components.
|
|
17
|
+
- `core-database.ts` → `Database.Plugin.create({ imports?, components?, resources?, archetypes? })`, exporting the `CoreDatabase` namespace.
|
|
18
|
+
|
|
19
|
+
The schema root; comes after `data/` (and `services/`). Bind each schema from its `data/`
|
|
20
|
+
type — don't author shapes here. Components use JSON schemas; resources use the
|
|
21
|
+
`{ default }` convention (a schemaless aggregate binds via `{ default: State.create() }`).
|
|
22
|
+
|
|
23
|
+
The how is in the auto-loading `features/ecs/index.md` + `components.md` / `resources.md` /
|
|
24
|
+
`archetypes.md` rules.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-data
|
|
3
|
+
description: Build a feature's data/ layer — data-type namespaces and the State spec. The first, foundational feature phase.
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Create the feature's `data/` layer (pure spec; depends on nothing but `@adobe/data`
|
|
9
|
+
and other `data/` declarations):
|
|
10
|
+
|
|
11
|
+
- one namespace folder per data type — `<type>/{<type>.ts, schema.ts, public.ts, <helper>.ts}`;
|
|
12
|
+
- `data/state/` — the `State` aggregate plus its pure transforms/derivations.
|
|
13
|
+
|
|
14
|
+
**Always create `data/state/`** — even for a shell feature whose only field is a
|
|
15
|
+
boolean or enum. A feature with ECS resources/transactions but no `State` is
|
|
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
|
+
|
|
18
|
+
The schema is the single source of truth; the type derives from it (`Schema.ToType`).
|
|
19
|
+
Helpers are pure and unit-tested. Run this first — every other layer imports `data/`.
|
|
20
|
+
|
|
21
|
+
The how is in the auto-loading rules: `features/data/index.md`, `features/data/state.md`, and
|
|
22
|
+
`namespace.md`.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-feature
|
|
3
|
+
description: Build a complete feature step by step
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
/graph-execute
|
|
9
|
+
/build-data
|
|
10
|
+
/build-services
|
|
11
|
+
/build-core-database
|
|
12
|
+
/build-indexes
|
|
13
|
+
/build-transactions
|
|
14
|
+
/build-computed
|
|
15
|
+
/build-service-database
|
|
16
|
+
/build-actions
|
|
17
|
+
/build-systems
|
|
18
|
+
/build-ui
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-game
|
|
3
|
+
description: Build a game — an application whose features model game state, rules, and rendering.
|
|
4
|
+
input: game
|
|
5
|
+
output: game
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
/build-application — a game is an application.
|
|
9
|
+
|
|
10
|
+
Map game concepts to feature layers: data/ = state + rules (+ per-tick step math),
|
|
11
|
+
components/archetypes = entity kinds, indexes = spatial/lookup queries,
|
|
12
|
+
transactions = moves/spawns, computed = score/status/winner, ui = view + input.
|
|
13
|
+
|
|
14
|
+
- **Turn-based** uses the reactive transaction → computed → ui loop, no systems
|
|
15
|
+
(see data-lit-tictactoe).
|
|
16
|
+
- **Real-time** adds the `build-systems` phase: a per-frame tick loop (movement,
|
|
17
|
+
collision, lifetime) driven by the scheduler, over many entities in distinct
|
|
18
|
+
archetypes. Systems must stay O(1) per touched entity — never project the whole
|
|
19
|
+
`State` into/out of the store each frame (see `features/ecs/systems.md`).
|
|
20
|
+
This is where components, archetypes, indexes, and systems all carry real
|
|
21
|
+
weight.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-indexes
|
|
3
|
+
description: Build a feature's ecs index-database — component/archetype indexes for O(1) lookup. As needed.
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Skip if this feature doesn't contain or require indexes.
|
|
9
|
+
|
|
10
|
+
Create `ecs/index-database/`: `index-database.ts` (extends `CoreDatabase`, adds the `indexes`
|
|
11
|
+
facet from `./indexes/index.js`) plus an `indexes/` folder — one index per file + an `index.ts`
|
|
12
|
+
barrel.
|
|
13
|
+
|
|
14
|
+
Only if the feature needs indexed lookups. Comes after `core-database`.
|
|
15
|
+
|
|
16
|
+
The how is in the auto-loading `features/ecs/indexes.md` rule.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-service-database
|
|
3
|
+
description: Build a feature's ecs service-database — db-bound service factories. If the feature exposes services.
|
|
4
|
+
input: feature
|
|
5
|
+
output: feature
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Create `ecs/service-database/`: `service-database.ts` (extends the previous layer, registers the
|
|
9
|
+
`services` facet). Two forms:
|
|
10
|
+
|
|
11
|
+
- db-bound factories `create<Name>Service(db, …)` in `service-database/services/` (one per file + barrel), for services that read `db.observe.*` / call `db.transactions.*`; or
|
|
12
|
+
- plain async ports registered straight from the feature's `services/` contracts.
|
|
13
|
+
|
|
14
|
+
Comes after `computed-database`.
|
|
15
|
+
|
|
16
|
+
The how is in the auto-loading `features/ecs/services.md` rule.
|