@reqvire-org/ads 0.2.9 → 0.3.1
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 +2 -2
- package/dist/bootstrap-ds/ADS.md +19 -8
- package/dist/bootstrap-ds/README.md +13 -11
- package/dist/bootstrap-ds/design-system/index.ts +1 -1
- package/dist/bootstrap-ds/design-system/patterns/token-preview/Scenario.tsx +4 -0
- package/dist/bootstrap-ds/design-system/patterns/token-preview/TokenPreview.tsx +31 -0
- package/dist/bootstrap-ds/design-system/patterns/token-preview/fixture.ts +8 -0
- package/dist/bootstrap-ds/design-system/tokens/Foundation.fixture.ts +44 -43
- package/dist/bootstrap-ds/design-system/tokens/Foundation.scenario.tsx +3 -13
- package/dist/bootstrap-ds/ds.config.json +10 -0
- package/dist/check.mjs +2 -9
- package/dist/init.mjs +22 -5
- package/dist/mcp/apps.mjs +2 -2
- package/dist/mcp/context.mjs +1 -1
- package/dist/mcp/preview-widget.bundle.js +40 -38
- package/dist/mcp/project-widget.bundle.js +42 -38
- package/dist/mcp/prompts.mjs +1 -1
- package/dist/mcp/server.mjs +5 -5
- package/dist/preview-resources.mjs +1 -1
- package/dist/scenarios.mjs +16 -5
- package/dist/skills/README.md +1 -1
- package/dist/skills/ads-assimilate/SKILL.md +28 -12
- package/dist/skills/ads-assimilate/references/cli.md +2 -2
- package/dist/skills/ads-break-ui/SKILL.md +28 -12
- package/dist/skills/ads-break-ui/references/verification.md +4 -0
- package/dist/skills/ads-designer/SKILL.md +30 -14
- package/dist/skills/ads-designer/assets/bootstrap-ds/ADS.md +19 -8
- package/dist/skills/ads-designer/assets/bootstrap-ds/README.md +13 -11
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/index.ts +1 -1
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/patterns/token-preview/Scenario.tsx +4 -0
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/patterns/token-preview/TokenPreview.tsx +31 -0
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/patterns/token-preview/fixture.ts +8 -0
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/tokens/Foundation.fixture.ts +44 -43
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/tokens/Foundation.scenario.tsx +3 -13
- package/dist/skills/ads-designer/assets/bootstrap-ds/ds.config.json +10 -0
- package/dist/skills/ads-designer/references/cli.md +2 -2
- package/dist/skills/ads-import/SKILL.md +28 -12
- package/dist/skills/ads-import/references/cli.md +2 -2
- package/dist/skills/ads-motion/SKILL.md +28 -12
- package/dist/token-policy.mjs +12 -0
- package/dist/token-samples.mjs +8 -0
- package/dist/units.mjs +34 -10
- package/docs/ADS.md +23 -9
- package/docs/ARCHITECTURE.md +12 -0
- package/docs/CHANGELOG.md +16 -1
- package/docs/GUIDE.md +16 -13
- package/docs/MCP.md +44 -2
- package/package.json +5 -5
package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/tokens/Foundation.fixture.ts
CHANGED
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
export const fixture = {
|
|
2
2
|
"title": "Foundation",
|
|
3
|
-
"
|
|
4
|
-
|
|
5
|
-
"--accent-
|
|
6
|
-
"--accent-
|
|
7
|
-
"--
|
|
8
|
-
"--bg-
|
|
9
|
-
"--bg-
|
|
10
|
-
"--
|
|
11
|
-
"--border-
|
|
12
|
-
"--border-
|
|
13
|
-
"--
|
|
14
|
-
"--dur-
|
|
15
|
-
"--
|
|
16
|
-
"--
|
|
17
|
-
"--focus-
|
|
18
|
-
"--
|
|
19
|
-
"--font-
|
|
20
|
-
"--
|
|
21
|
-
"--leading-
|
|
22
|
-
"--
|
|
23
|
-
"--radius-
|
|
24
|
-
"--radius-
|
|
25
|
-
"--
|
|
26
|
-
"--shadow-
|
|
27
|
-
"--
|
|
28
|
-
"--space-
|
|
29
|
-
"--space-
|
|
30
|
-
"--space-
|
|
31
|
-
"--space-
|
|
32
|
-
"--space-
|
|
33
|
-
"--space-
|
|
34
|
-
"--
|
|
35
|
-
"--text-
|
|
36
|
-
"--text-
|
|
37
|
-
"--text-
|
|
38
|
-
"--text-
|
|
39
|
-
"--text-
|
|
40
|
-
"--text-
|
|
41
|
-
"--text-
|
|
42
|
-
"--
|
|
43
|
-
"--weight-
|
|
44
|
-
"--weight-
|
|
45
|
-
"--
|
|
3
|
+
"text": "Aa",
|
|
4
|
+
samples: [
|
|
5
|
+
{"token": "--accent", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
6
|
+
{"token": "--accent-fg", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
7
|
+
{"token": "--accent-hover", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
8
|
+
{"token": "--bg-canvas", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
9
|
+
{"token": "--bg-hover", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
10
|
+
{"token": "--bg-surface", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
11
|
+
{"token": "--border-default", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
12
|
+
{"token": "--border-focus", "property": "background-color", "probe": "rgb(31, 97, 163)"},
|
|
13
|
+
{"token": "--border-w", "property": "width", "probe": "13.375px"},
|
|
14
|
+
{"token": "--dur-fast", "property": "animation-duration", "probe": "0.375s"},
|
|
15
|
+
{"token": "--dur-normal", "property": "animation-duration", "probe": "0.375s"},
|
|
16
|
+
{"token": "--ease-standard", "property": "animation-timing-function", "probe": "cubic-bezier(.13,.27,.61,.83)"},
|
|
17
|
+
{"token": "--focus-offset", "property": "width", "probe": "13.375px"},
|
|
18
|
+
{"token": "--focus-w", "property": "width", "probe": "13.375px"},
|
|
19
|
+
{"token": "--font-mono", "property": "font-family", "probe": "monospace, serif"},
|
|
20
|
+
{"token": "--font-sans", "property": "font-family", "probe": "monospace, serif"},
|
|
21
|
+
{"token": "--leading-normal", "property": "line-height", "probe": "2.375"},
|
|
22
|
+
{"token": "--leading-tight", "property": "line-height", "probe": "2.375"},
|
|
23
|
+
{"token": "--radius-lg", "property": "border-radius", "probe": "13.375px"},
|
|
24
|
+
{"token": "--radius-md", "property": "border-radius", "probe": "13.375px"},
|
|
25
|
+
{"token": "--radius-sm", "property": "border-radius", "probe": "13.375px"},
|
|
26
|
+
{"token": "--shadow-raised", "property": "box-shadow", "probe": "1px 3px 5px rgb(31, 97, 163)"},
|
|
27
|
+
{"token": "--shadow-xs", "property": "box-shadow", "probe": "1px 3px 5px rgb(31, 97, 163)"},
|
|
28
|
+
{"token": "--space-0", "property": "width", "probe": "13.375px"},
|
|
29
|
+
{"token": "--space-12", "property": "width", "probe": "13.375px"},
|
|
30
|
+
{"token": "--space-16", "property": "width", "probe": "13.375px"},
|
|
31
|
+
{"token": "--space-2", "property": "width", "probe": "13.375px"},
|
|
32
|
+
{"token": "--space-4", "property": "width", "probe": "13.375px"},
|
|
33
|
+
{"token": "--space-6", "property": "width", "probe": "13.375px"},
|
|
34
|
+
{"token": "--space-8", "property": "width", "probe": "13.375px"},
|
|
35
|
+
{"token": "--text-base", "property": "font-size", "probe": "41.375px"},
|
|
36
|
+
{"token": "--text-body", "property": "color", "probe": "rgb(31, 97, 163)"},
|
|
37
|
+
{"token": "--text-inverse", "property": "color", "probe": "rgb(31, 97, 163)"},
|
|
38
|
+
{"token": "--text-lg", "property": "font-size", "probe": "41.375px"},
|
|
39
|
+
{"token": "--text-muted", "property": "color", "probe": "rgb(31, 97, 163)"},
|
|
40
|
+
{"token": "--text-sm", "property": "font-size", "probe": "41.375px"},
|
|
41
|
+
{"token": "--text-strong", "property": "color", "probe": "rgb(31, 97, 163)"},
|
|
42
|
+
{"token": "--text-xl", "property": "font-size", "probe": "41.375px"},
|
|
43
|
+
{"token": "--weight-medium", "property": "font-weight", "probe": "327"},
|
|
44
|
+
{"token": "--weight-normal", "property": "font-weight", "probe": "327"},
|
|
45
|
+
{"token": "--weight-semibold", "property": "font-weight", "probe": "327"},
|
|
46
|
+
{"token": "--z-overlay", "property": "z-index", "probe": "367"},
|
|
46
47
|
]
|
|
47
48
|
} as const;
|
package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/tokens/Foundation.scenario.tsx
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TokenPreview } from "@ds";
|
|
2
2
|
import { fixture } from "./Foundation.fixture";
|
|
3
|
-
export const scenario = { title: fixture.title, covers: [],
|
|
4
|
-
export default function Scenario() {
|
|
5
|
-
const [values, setValues] = useState<Record<string, string>>({});
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
const read = () => { const style = getComputedStyle(document.documentElement); setValues(Object.fromEntries(fixture.tokens.map(name => [name, style.getPropertyValue(name).trim()]))); };
|
|
8
|
-
read();
|
|
9
|
-
const observer = new MutationObserver(read);
|
|
10
|
-
observer.observe(document.documentElement, {attributes: true, attributeFilter: ["data-theme"]});
|
|
11
|
-
return () => observer.disconnect();
|
|
12
|
-
}, []);
|
|
13
|
-
return <section><h1>{fixture.title}</h1><dl>{fixture.tokens.map(name => <div key={name}><dt><code>{name}</code></dt><dd>{values[name]}</dd></div>)}</dl></section>;
|
|
14
|
-
}
|
|
3
|
+
export const scenario = { title: fixture.title, covers: ["TokenPreview"], samples: fixture.samples };
|
|
4
|
+
export default function Scenario() { return <TokenPreview {...fixture} />; }
|
|
@@ -55,7 +55,7 @@ If no published distribution exists, build and pack the tooling checkout with
|
|
|
55
55
|
From inside an existing test project:
|
|
56
56
|
|
|
57
57
|
```sh
|
|
58
|
-
ads_tool_package="/absolute/path/to/reqvire-org-ads-0.3.
|
|
58
|
+
ads_tool_package="/absolute/path/to/reqvire-org-ads-0.3.1.tgz"
|
|
59
59
|
npx --yes --package "$ads_tool_package" ads --help
|
|
60
60
|
npx --yes --package "$ads_tool_package" ads init --framework react --tool-package "$ads_tool_package"
|
|
61
61
|
npm install
|
|
@@ -93,7 +93,7 @@ component rules through the project's plugin adapter and `ds.config.json`, then
|
|
|
93
93
|
run its actual build. Use `lint-config` directly for custom pipeline integration
|
|
94
94
|
or debugging, not as a separate routine setup step.
|
|
95
95
|
|
|
96
|
-
Use ADS 0.3 or later for the shared-resource preview compiler. `mcp` starts stdio
|
|
96
|
+
Use ADS 0.3.1 or later for the shared-resource preview compiler. `mcp` starts stdio
|
|
97
97
|
plus its local website; `showcase` starts the browser-only MCP runtime. Open the existing runtime URL from `ads_status` when
|
|
98
98
|
connected; otherwise use `npm run dev:showcase` or the installed `ads showcase`.
|
|
99
99
|
The tool client discovers entries and renders MCP Apps. Init adds the launch
|
|
@@ -21,9 +21,15 @@ relevant ranges with `ads_read_file` and send only a Git unified diff through
|
|
|
21
21
|
`ads_apply_patch({ unit, patch, dryRun })`. A unit includes its own implementation,
|
|
22
22
|
scenarios and fixtures; imported peers remain separate. `tokens` is the token
|
|
23
23
|
foundation unit. Unit discovery and file ownership are distinct from preview IDs.
|
|
24
|
-
Include only that owner's required re-exports in the public entry
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
Include only that owner's required re-exports in the public entry; preserve
|
|
25
|
+
unrelated statements. Its real re-export may accompany removal of a redundant
|
|
26
|
+
`export {};` placeholder; do not add empty exports. A `tokens` manifest lists the foundation
|
|
27
|
+
entry in `companionFiles`: when creating/deleting a canonical token file such as
|
|
28
|
+
`fonts.css`, include only its required import change there in the same patch.
|
|
29
|
+
Preserve other imports/comments and the canonical order. Use `dryRun: true` to
|
|
30
|
+
inspect validation; applying re-runs the gates. Fix rejected patches in their
|
|
31
|
+
owner. Report unsupported coupled changes instead of bypassing a rejection with
|
|
32
|
+
direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
27
33
|
`documentation`, and branding/fonts use their discovered `assets/*` unit.
|
|
28
34
|
Intentional configuration, rule exceptions, registered guard code and compiler
|
|
29
35
|
changes use `configuration`; validate the proposed settings and keep mandatory
|
|
@@ -266,15 +272,25 @@ entry independently and verify real behavior at narrow/wide sizes in both themes
|
|
|
266
272
|
The older `showcase-coverage` policy separately checks application references.
|
|
267
273
|
|
|
268
274
|
Token previews use that same scenario pipeline. Colocate a token scenario and
|
|
269
|
-
fixture under the configured token directory.
|
|
270
|
-
`{ title:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
275
|
+
fixture under the configured token directory. Declare metadata
|
|
276
|
+
`{ title: fixture.title, covers: ["TokenSamples"], samples: fixture.samples }`.
|
|
277
|
+
The renderer name is project-owned; use its real public API. Each literal fixture
|
|
278
|
+
sample declares `{ token, property, probe }`: a real token, the CSS property its
|
|
279
|
+
sample demonstrates, and a valid test value different from that token's current
|
|
280
|
+
value. Pass `samples` into the rendered public review pattern. Names, sample text,
|
|
281
|
+
bindings and probes are fixture data; displayed values come from foundation CSS.
|
|
282
|
+
There is no property catalogue, token-name mapping or probe palette in ADS.
|
|
283
|
+
Every token needs sample coverage; fabricated tokens, missing bindings/probes,
|
|
284
|
+
unused fixtures and value-only lists fail the static gates. `covers: []` is invalid.
|
|
285
|
+
During App rendering, the browser checks sample markers `data-ads-token` and
|
|
286
|
+
`data-ads-property`, validates CSS with its own `CSS.supports`, and temporarily
|
|
287
|
+
probes each token to verify that the declared sample property responds. It restores
|
|
288
|
+
values immediately. Missing, hidden, invalid or hardcoded samples produce a preview
|
|
289
|
+
error instead of a successful review. These browser checks apply to the mounted
|
|
290
|
+
scenario/theme, not every application state or pixel-level design quality.
|
|
291
|
+
Keep styles in the project renderer; do not add inline-style exemptions to scenarios.
|
|
292
|
+
Fix `token-scenario-reference`, `token-scenario-render` and `token-scenario-coverage`
|
|
293
|
+
findings. Metadata and unused fixture fields do not count. Discover exact token IDs with `ads_scenarios({kind:"tokens"})`; mount them
|
|
278
294
|
with `ads_show_scenario({id})` or `ads_show_tokens({category:id})`. With the shared
|
|
279
295
|
resource compiler, omitting category opens the first project token scenario.
|
|
280
296
|
Legacy compilers retain the generic definition inspector. Use `ads_tokens` for
|
|
@@ -55,7 +55,7 @@ If no published distribution exists, build and pack the tooling checkout with
|
|
|
55
55
|
From inside an existing test project:
|
|
56
56
|
|
|
57
57
|
```sh
|
|
58
|
-
ads_tool_package="/absolute/path/to/reqvire-org-ads-0.3.
|
|
58
|
+
ads_tool_package="/absolute/path/to/reqvire-org-ads-0.3.1.tgz"
|
|
59
59
|
npx --yes --package "$ads_tool_package" ads --help
|
|
60
60
|
npx --yes --package "$ads_tool_package" ads init --framework react --tool-package "$ads_tool_package"
|
|
61
61
|
npm install
|
|
@@ -93,7 +93,7 @@ component rules through the project's plugin adapter and `ds.config.json`, then
|
|
|
93
93
|
run its actual build. Use `lint-config` directly for custom pipeline integration
|
|
94
94
|
or debugging, not as a separate routine setup step.
|
|
95
95
|
|
|
96
|
-
Use ADS 0.3 or later for the shared-resource preview compiler. `mcp` starts stdio
|
|
96
|
+
Use ADS 0.3.1 or later for the shared-resource preview compiler. `mcp` starts stdio
|
|
97
97
|
plus its local website; `showcase` starts the browser-only MCP runtime. Open the existing runtime URL from `ads_status` when
|
|
98
98
|
connected; otherwise use `npm run dev:showcase` or the installed `ads showcase`.
|
|
99
99
|
The tool client discovers entries and renders MCP Apps. Init adds the launch
|
|
@@ -42,9 +42,15 @@ relevant ranges with `ads_read_file` and send only a Git unified diff through
|
|
|
42
42
|
`ads_apply_patch({ unit, patch, dryRun })`. A unit includes its own implementation,
|
|
43
43
|
scenarios and fixtures; imported peers remain separate. `tokens` is the token
|
|
44
44
|
foundation unit. Unit discovery and file ownership are distinct from preview IDs.
|
|
45
|
-
Include only that owner's required re-exports in the public entry
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
Include only that owner's required re-exports in the public entry; preserve
|
|
46
|
+
unrelated statements. Its real re-export may accompany removal of a redundant
|
|
47
|
+
`export {};` placeholder; do not add empty exports. A `tokens` manifest lists the foundation
|
|
48
|
+
entry in `companionFiles`: when creating/deleting a canonical token file such as
|
|
49
|
+
`fonts.css`, include only its required import change there in the same patch.
|
|
50
|
+
Preserve other imports/comments and the canonical order. Use `dryRun: true` to
|
|
51
|
+
inspect validation; applying re-runs the gates. Fix rejected patches in their
|
|
52
|
+
owner. Report unsupported coupled changes instead of bypassing a rejection with
|
|
53
|
+
direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
48
54
|
`documentation`, and branding/fonts use their discovered `assets/*` unit.
|
|
49
55
|
Intentional configuration, rule exceptions, registered guard code and compiler
|
|
50
56
|
changes use `configuration`; validate the proposed settings and keep mandatory
|
|
@@ -156,15 +162,25 @@ entry independently and verify real behavior at narrow/wide sizes in both themes
|
|
|
156
162
|
The older `showcase-coverage` policy separately checks application references.
|
|
157
163
|
|
|
158
164
|
Token previews use that same scenario pipeline. Colocate a token scenario and
|
|
159
|
-
fixture under the configured token directory.
|
|
160
|
-
`{ title:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
fixture under the configured token directory. Declare metadata
|
|
166
|
+
`{ title: fixture.title, covers: ["TokenSamples"], samples: fixture.samples }`.
|
|
167
|
+
The renderer name is project-owned; use its real public API. Each literal fixture
|
|
168
|
+
sample declares `{ token, property, probe }`: a real token, the CSS property its
|
|
169
|
+
sample demonstrates, and a valid test value different from that token's current
|
|
170
|
+
value. Pass `samples` into the rendered public review pattern. Names, sample text,
|
|
171
|
+
bindings and probes are fixture data; displayed values come from foundation CSS.
|
|
172
|
+
There is no property catalogue, token-name mapping or probe palette in ADS.
|
|
173
|
+
Every token needs sample coverage; fabricated tokens, missing bindings/probes,
|
|
174
|
+
unused fixtures and value-only lists fail the static gates. `covers: []` is invalid.
|
|
175
|
+
During App rendering, the browser checks sample markers `data-ads-token` and
|
|
176
|
+
`data-ads-property`, validates CSS with its own `CSS.supports`, and temporarily
|
|
177
|
+
probes each token to verify that the declared sample property responds. It restores
|
|
178
|
+
values immediately. Missing, hidden, invalid or hardcoded samples produce a preview
|
|
179
|
+
error instead of a successful review. These browser checks apply to the mounted
|
|
180
|
+
scenario/theme, not every application state or pixel-level design quality.
|
|
181
|
+
Keep styles in the project renderer; do not add inline-style exemptions to scenarios.
|
|
182
|
+
Fix `token-scenario-reference`, `token-scenario-render` and `token-scenario-coverage`
|
|
183
|
+
findings. Metadata and unused fixture fields do not count. Discover exact token IDs with `ads_scenarios({kind:"tokens"})`; mount them
|
|
168
184
|
with `ads_show_scenario({id})` or `ads_show_tokens({category:id})`. With the shared
|
|
169
185
|
resource compiler, omitting category opens the first project token scenario.
|
|
170
186
|
Legacy compilers retain the generic definition inspector. Use `ads_tokens` for
|
package/dist/token-policy.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import valueParser from "postcss-value-parser";
|
|
2
4
|
|
|
3
5
|
export const tokenContract = JSON.parse(readFileSync(new URL("./contracts/tokens.json", import.meta.url), "utf8"));
|
|
4
6
|
|
|
@@ -8,3 +10,13 @@ export function isSharedToken(name) {
|
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export const foundationFiles = ["fonts.css", "colors.css", "typography.css", "spacing.css", "elevation.css", "base.css"];
|
|
13
|
+
|
|
14
|
+
/** The foundation entry accepts only a single, unconditional local import. */
|
|
15
|
+
export function foundationImportTarget(node, file) {
|
|
16
|
+
if (node.type !== "atrule" || node.name !== "import" || node.nodes) return null;
|
|
17
|
+
const parts = valueParser(node.params).nodes.filter(part => part.type !== "space" && part.type !== "comment");
|
|
18
|
+
if (parts.length !== 1) return null;
|
|
19
|
+
const part = parts[0];
|
|
20
|
+
const value = part.type === "string" ? part.value : part.type === "function" && part.value === "url" && part.nodes.length === 1 ? part.nodes[0].value : null;
|
|
21
|
+
return value ? path.resolve(path.dirname(file), value) : null;
|
|
22
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Projects declare bindings and verification inputs; ADS supplies no sample catalogue. */
|
|
2
|
+
export function validTokenSamples(samples) {
|
|
3
|
+
return Array.isArray(samples) && samples.length > 0 && samples.every(sample => sample && typeof sample === "object"
|
|
4
|
+
&& typeof sample.token === "string" && /^--[\w-]+$/.test(sample.token)
|
|
5
|
+
&& typeof sample.property === "string" && /^-?[a-z][a-z0-9-]*$/.test(sample.property)
|
|
6
|
+
&& typeof sample.probe === "string" && sample.probe.trim().length > 0)
|
|
7
|
+
&& new Set(samples.map(sample => `${sample.token}:${sample.property}`)).size === samples.length;
|
|
8
|
+
}
|
package/dist/units.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
+
import postcss from "postcss";
|
|
4
5
|
import { isInside } from "./config.mjs";
|
|
5
6
|
import { importResolver } from "./boundaries.mjs";
|
|
6
7
|
import { isProjectDocument, projectGuideFiles } from "./project-documents.mjs";
|
|
8
|
+
import { foundationFiles, foundationImportTarget } from "./token-policy.mjs";
|
|
7
9
|
|
|
8
10
|
const source = /\.[cm]?[jt]sx?$/;
|
|
9
11
|
const slash = file => file.replaceAll("\\", "/");
|
|
@@ -89,6 +91,7 @@ export function inspectUnits(options) {
|
|
|
89
91
|
}))].sort((a, b) => b.length - a.length);
|
|
90
92
|
const publicEntry = slash(path.relative(dsRoot, path.join(dsRoot, config.publicEntry)));
|
|
91
93
|
const tokenDir = slash(path.relative(dsRoot, path.join(dsRoot, config.tokenDir)));
|
|
94
|
+
const stylesEntry = slash(path.relative(dsRoot, path.join(dsRoot, config.stylesEntry)));
|
|
92
95
|
function owner(relative) {
|
|
93
96
|
const projectFile = slash(path.relative(root, path.resolve(dsRoot, relative)));
|
|
94
97
|
if (setup.has(projectFile)) return "configuration";
|
|
@@ -107,6 +110,8 @@ export function inspectUnits(options) {
|
|
|
107
110
|
const units = new Map();
|
|
108
111
|
units.set("configuration", { id: "configuration", kind: "configuration", files: [...setup].filter(file => existsSync(path.join(root, file))).sort() });
|
|
109
112
|
for (const id of ["foundation", "documentation", "tokens", "assets/brand", "assets/fonts"]) units.set(id, { id, kind: id.split("/")[0], files: [] });
|
|
113
|
+
units.get("tokens").companionFiles = [{ path: slash(path.relative(root, path.join(dsRoot, stylesEntry))),
|
|
114
|
+
allowedChanges: "Only add/remove canonical foundation imports required by token foundation files created/deleted in this patch; preserve other imports and comments." }];
|
|
110
115
|
units.get("documentation").files = projectGuideFiles(root);
|
|
111
116
|
for (const relative of files) {
|
|
112
117
|
const id = owner(relative);
|
|
@@ -115,7 +120,7 @@ export function inspectUnits(options) {
|
|
|
115
120
|
const file = slash(path.relative(root, path.join(dsRoot, relative)));
|
|
116
121
|
if (!units.get(id).files.includes(file)) units.get(id).files.push(file);
|
|
117
122
|
}
|
|
118
|
-
return { units: [...units.values()].sort((a, b) => a.id.localeCompare(b.id)), owner, publicEntry,
|
|
123
|
+
return { units: [...units.values()].sort((a, b) => a.id.localeCompare(b.id)), owner, publicEntry, stylesEntry, tokenDir,
|
|
119
124
|
relative: file => slash(path.relative(dsRoot, path.resolve(root, file))) };
|
|
120
125
|
}
|
|
121
126
|
|
|
@@ -130,6 +135,7 @@ export function checkUnitFiles(options, unit, changes, inventory = inspectUnits(
|
|
|
130
135
|
const relative = inventory.relative(change.path);
|
|
131
136
|
if (allowNew && unit === "configuration") continue; // The candidate must register every setup/extension file.
|
|
132
137
|
if (relative === inventory.publicEntry) continue;
|
|
138
|
+
if (unit === "tokens" && relative === inventory.stylesEntry) continue; // Controlled foundation import bookkeeping.
|
|
133
139
|
if (allowNew && change.originalContent === null && (relative.startsWith(unit + "/") || relative.startsWith(unit + "."))) continue;
|
|
134
140
|
const owner = inventory.owner(relative);
|
|
135
141
|
if (owner !== unit) throw fail(`This patch targets ${unit}; ${change.path} belongs to ${owner ?? "a different ADS layer"}. Submit a separate unit patch.`, change.path);
|
|
@@ -147,22 +153,40 @@ export function checkUnitCandidate(afterOptions, unit, changes, before) {
|
|
|
147
153
|
if (unit === "configuration" && (entry.id === "configuration" || after.owner(relative) === "configuration")) continue;
|
|
148
154
|
if (after.owner(relative) !== entry.id) throw fail("A patch cannot change ownership of existing peer units. Choose an unoccupied owner path.", file);
|
|
149
155
|
}
|
|
156
|
+
const foundationChange = changes.find(change => before.relative(change.path) === before.stylesEntry);
|
|
157
|
+
if (unit === "tokens" && foundationChange) {
|
|
158
|
+
const { originalContent: current, content: proposed } = foundationChange;
|
|
159
|
+
if (typeof current !== "string" || typeof proposed !== "string") throw fail("A token patch cannot create or delete the foundation entry.", foundationChange.path);
|
|
160
|
+
const canonical = new Set(foundationFiles.map(name => slash(path.join(before.tokenDir, name))));
|
|
161
|
+
const affected = new Set(changes.filter(change => (change.originalContent === null || change.content === null) && canonical.has(before.relative(change.path)))
|
|
162
|
+
.map(change => path.join(afterOptions.dsRoot, before.relative(change.path))));
|
|
163
|
+
if (!affected.size) throw fail("Foundation companion changes require creating or deleting a canonical token foundation file in the same token patch.", foundationChange.path);
|
|
164
|
+
const file = path.join(afterOptions.dsRoot, afterOptions.config.stylesEntry);
|
|
165
|
+
function unrelated(content) {
|
|
166
|
+
try {
|
|
167
|
+
return postcss.parse(content, { from: file }).nodes.filter(node => !affected.has(foundationImportTarget(node, file))).map(node => node.toString());
|
|
168
|
+
} catch (error) { throw fail(`Invalid foundation import companion: ${error.reason ?? error.message}`, foundationChange.path); }
|
|
169
|
+
}
|
|
170
|
+
if (JSON.stringify(unrelated(current)) !== JSON.stringify(unrelated(proposed))) throw fail("Foundation companion patches may change only canonical imports for token files created/deleted in this patch; preserve all other imports and comments.", foundationChange.path);
|
|
171
|
+
}
|
|
150
172
|
const exportChange = changes.find(change => before.relative(change.path) === before.publicEntry);
|
|
151
173
|
if (exportChange) {
|
|
152
174
|
if (!["components", "patterns"].includes(unit.split("/")[0])) throw fail("Only a component/pattern unit may update its public re-exports.", exportChange.path);
|
|
153
175
|
const current = exportChange.originalContent ?? "", proposed = exportChange.content;
|
|
154
176
|
if (proposed === null) throw fail("The shared public entry cannot be deleted.", exportChange.path);
|
|
155
177
|
const resolve = importResolver(afterOptions);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
178
|
+
const file = path.join(afterOptions.dsRoot, afterOptions.config.publicEntry);
|
|
179
|
+
const original = ts.createSourceFile(file, current, ts.ScriptTarget.Latest, true);
|
|
180
|
+
const candidate = ts.createSourceFile(file, proposed, ts.ScriptTarget.Latest, true);
|
|
181
|
+
const emptyExport = statement => ts.isExportDeclaration(statement) && !statement.moduleSpecifier && statement.exportClause && ts.isNamedExports(statement.exportClause) && !statement.exportClause.elements.length;
|
|
182
|
+
function ownedExport(statement) {
|
|
183
|
+
if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier || !ts.isStringLiteralLike(statement.moduleSpecifier)) return false;
|
|
184
|
+
const targets = resolve(statement.moduleSpecifier.text, file);
|
|
185
|
+
return targets.length && targets.every(target => isInside(afterOptions.dsRoot, target) && after.owner(slash(path.relative(afterOptions.dsRoot, target))) === unit);
|
|
164
186
|
}
|
|
165
|
-
|
|
187
|
+
const cleanup = candidate.statements.some(ownedExport) && !candidate.statements.some(emptyExport);
|
|
188
|
+
const unrelated = ast => ast.statements.filter(statement => !ownedExport(statement) && !(cleanup && emptyExport(statement))).map(statement => statement.getText(ast)).join("\n");
|
|
189
|
+
if (unrelated(original) !== unrelated(candidate)) throw fail("Public-entry patches may change only re-exports from the selected unit and remove a redundant empty export alongside its real re-export; preserve all other statements.", exportChange.path);
|
|
166
190
|
}
|
|
167
191
|
if (!before.units.some(entry => entry.id === unit) && !after.units.some(entry => entry.id === unit)) throw fail("The patched files do not establish the selected ADS unit.");
|
|
168
192
|
}
|
package/docs/ADS.md
CHANGED
|
@@ -13,6 +13,8 @@ before application. This includes
|
|
|
13
13
|
foundation, documentation, original assets and an explicit configuration unit for
|
|
14
14
|
project settings, registered guard code and compiler integration. Configuration
|
|
15
15
|
patches validate the proposed policy; mandatory core gates remain enabled.
|
|
16
|
+
Required public re-exports and canonical foundation import changes may accompany
|
|
17
|
+
their owner under the narrow companion rules in the MCP editing contract.
|
|
16
18
|
Source checks do not establish visual correctness; normal lint/build gates
|
|
17
19
|
remain required for edits made through other tools.
|
|
18
20
|
See the [MCP editing contract](MCP.md#guarded-editing).
|
|
@@ -89,13 +91,24 @@ design-system/
|
|
|
89
91
|
Flat owners may use `Button.scenario.tsx` and `Button.fixture.ts` instead.
|
|
90
92
|
`Scenario.tsx` exports a default independently mountable view and literal metadata
|
|
91
93
|
`export const scenario = { title: "Button states", covers: ["Button"] };`.
|
|
92
|
-
Token entries under the configured token directory
|
|
93
|
-
`export const scenario = { title:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
Token entries under the configured token directory declare
|
|
95
|
+
`export const scenario = { title: fixture.title, covers: ["TokenSamples"], samples: fixture.samples };`.
|
|
96
|
+
`TokenSamples` is any project-owned public review pattern, not a required name.
|
|
97
|
+
Its colocated fixture declares literal `samples: [{ token, property, probe }]`.
|
|
98
|
+
Each token must exist and have sample coverage; duplicate bindings, missing probes,
|
|
99
|
+
empty covers and value-only inspectors fail. The default entry passes the declared
|
|
100
|
+
samples to a rendered public pattern's `samples` prop. No token-name/property mapping
|
|
101
|
+
or sample values are embedded in the tool. Display values come from foundation CSS;
|
|
102
|
+
probes are isolated verification inputs owned by the fixture.
|
|
103
|
+
|
|
104
|
+
The renderer marks the actual styled element with `data-ads-token` and
|
|
105
|
+
`data-ads-property`. In a browser, the App validates the declared property/value and
|
|
106
|
+
probe using `CSS.supports`, checks the sample is rendered, then temporarily changes
|
|
107
|
+
that token to its fixture probe. Its computed sample property must respond. Values
|
|
108
|
+
are restored before yielding to painting; hardcoded lookalikes fail. Source gates
|
|
109
|
+
prove the contract structure, not successful rendering. The browser check covers
|
|
110
|
+
the mounted scenario and theme; visual quality and other states still need review.
|
|
111
|
+
|
|
99
112
|
It imports real public UI through `@ds` and its local fixture. The adapter supplies
|
|
100
113
|
initial state, callbacks and simulated services. The default entry needs no
|
|
101
114
|
mandatory caller inputs or prior page initialization. Related parts may share a
|
|
@@ -279,8 +292,9 @@ Validate accepted and rejected cases, configuration, and false-positive limits.
|
|
|
279
292
|
Root [bootstrap-ds/](../bootstrap-ds/README.md) is the canonical empty scaffold.
|
|
280
293
|
Its identical copy under `skills/ads-designer/assets/bootstrap-ds/` makes the
|
|
281
294
|
skill self-contained. Run `npm run sync:skill-starter` after edits and
|
|
282
|
-
`npm run check:skill-starter` to verify the copy. Both contain empty component
|
|
283
|
-
|
|
295
|
+
`npm run check:skill-starter` to verify the copy. Both contain empty product component/composition directories and a minimal project-owned
|
|
296
|
+
token review pattern. The scaffold pattern can be renamed or replaced; the tool
|
|
297
|
+
does not require that name or its styles and ships no product UI catalogue.
|
|
284
298
|
|
|
285
299
|
Tool releases should version contract changes, rules, skills, bootstrap support,
|
|
286
300
|
and migration guidance. Existing project implementations and external source
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -273,6 +273,11 @@ replace the managed process while retaining the MCP connection. Normal build gat
|
|
|
273
273
|
remain in place for source changes made through other editors; preview review remains
|
|
274
274
|
necessary after either editing path.
|
|
275
275
|
|
|
276
|
+
Required shared-entry bookkeeping can accompany its owner: component/pattern
|
|
277
|
+
re-exports and canonical foundation imports for token files created or deleted in
|
|
278
|
+
the same patch. ADS restricts these companion edits and validates the complete
|
|
279
|
+
candidate before writing, so coupled changes do not need a guard bypass.
|
|
280
|
+
|
|
276
281
|
The architecture makes that inspection practical. A public export has an owning
|
|
277
282
|
source and addressable preview coverage. Token definitions expose its visual
|
|
278
283
|
vocabulary; local guides explain contracts when present. An agent can discover a
|
|
@@ -309,3 +314,10 @@ For concrete instructions, use:
|
|
|
309
314
|
- [Tool guide](GUIDE.md) for prerequisites, supported formats, configuration, and build wiring.
|
|
310
315
|
- [Working example guide](../design-system/README.md) for Linaria composition, extraction, and project commands.
|
|
311
316
|
- Component-local READMEs for APIs, lifecycle, tests, and provenance.
|
|
317
|
+
|
|
318
|
+
Token preview completeness has two checks. Static guards require explicit fixture
|
|
319
|
+
bindings (`token`, CSS `property`, and project-selected `probe`) consumed by a public
|
|
320
|
+
review pattern. The App then verifies rendered samples in the actual browser by
|
|
321
|
+
probing those bindings and restoring them. The tool supplies no token/property
|
|
322
|
+
classification or visual sample palette. A source build alone is not a rendered
|
|
323
|
+
verification, and the browser check does not judge design quality.
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.3.1
|
|
4
|
+
|
|
5
|
+
- Stop generating redundant empty public exports. Allow an owning unit's public
|
|
6
|
+
re-export companion to remove an obsolete placeholder without changing peers.
|
|
7
|
+
- Require token fixtures to declare real CSS sample bindings and project-owned
|
|
8
|
+
probes, consumed by a public review pattern. Reject empty covers and plain lists.
|
|
9
|
+
Apps verify rendered property dependencies in the browser before reporting ready.
|
|
10
|
+
The tool infers no token roles and contains no property/probe catalogue. Existing
|
|
11
|
+
projects need a token scenario migration and preview rebuild.
|
|
12
|
+
- Restore native scrolling inside resource preview Apps for scenarios taller or
|
|
13
|
+
wider than their viewport, while retaining full-height composition layouts.
|
|
14
|
+
- Allow a `tokens` mutation to add/remove the required foundation import together
|
|
15
|
+
with its canonical token file. Discover the entry through `ads_units` companion
|
|
16
|
+
metadata; preserve unrelated imports/comments and validate before writing.
|
|
17
|
+
|
|
18
|
+
## 0.3.0
|
|
4
19
|
|
|
5
20
|
- Rebrand the tool as ADS — Agentic Design System: `@reqvire-org/ads`, the `ads`
|
|
6
21
|
CLI, `ads_*` MCP tools, `ads://` resources and `ads-*` skills. Keep project
|
package/docs/GUIDE.md
CHANGED
|
@@ -12,7 +12,7 @@ fonts, mock screens, or UI runtime dependency.
|
|
|
12
12
|
Linaria is required for component and pattern styling. Projects choose their
|
|
13
13
|
UI framework and visual design; `init` preserves framework configuration and
|
|
14
14
|
adds no React runtime dependency. See the
|
|
15
|
-
[architecture](https://github.com/reqvire-org/
|
|
15
|
+
[architecture](https://github.com/reqvire-org/ads/blob/main/docs/ARCHITECTURE.md#linaria-is-the-implementation-mechanism)
|
|
16
16
|
for the rationale.
|
|
17
17
|
|
|
18
18
|
Current source checking supports `.js`, `.jsx`, `.ts`, `.tsx`, their module
|
|
@@ -45,9 +45,9 @@ project's existing build:
|
|
|
45
45
|
result. Static source checks do not establish complete extraction or
|
|
46
46
|
unused-style removal.
|
|
47
47
|
|
|
48
|
-
The [empty starter's dependencies](https://github.com/reqvire-org/
|
|
49
|
-
[entry build](https://github.com/reqvire-org/
|
|
50
|
-
and [preview compiler](https://github.com/reqvire-org/
|
|
48
|
+
The [empty starter's dependencies](https://github.com/reqvire-org/ads/blob/main/bootstrap-ds/package.json),
|
|
49
|
+
[entry build](https://github.com/reqvire-org/ads/blob/main/bootstrap-ds/vite.config.ts),
|
|
50
|
+
and [preview compiler](https://github.com/reqvire-org/ads/blob/main/bootstrap-ds/scripts/build-mcp-previews.mjs)
|
|
51
51
|
provide the React/Vite setup. Merge the needed integration into an existing
|
|
52
52
|
project instead of replacing its configuration.
|
|
53
53
|
|
|
@@ -78,8 +78,8 @@ attributes when the project/file JSX runtime or factory is native Preact. Preact
|
|
|
78
78
|
and exports DOM types such as `HTMLAttributes` directly; Preact 10's `JSX` type
|
|
79
79
|
namespace is also recognized by guards. See the [Preact upgrade guide](https://preactjs.com/guide/v11/upgrade-guide/).
|
|
80
80
|
|
|
81
|
-
The [working example](https://github.com/reqvire-org/
|
|
82
|
-
and its [compiler adapter](https://github.com/reqvire-org/
|
|
81
|
+
The [working example](https://github.com/reqvire-org/ads/tree/main/design-system)
|
|
82
|
+
and its [compiler adapter](https://github.com/reqvire-org/ads/blob/main/scripts/build-mcp-previews.mjs)
|
|
83
83
|
show the native setup. When converting the copied React starter to Preact,
|
|
84
84
|
update its runtime dependencies, JSX settings, framework transform, mount adapter,
|
|
85
85
|
and existing `framework` field together. Change the existing foundation scenario's
|
|
@@ -215,7 +215,7 @@ refresh generated resource manifests. Existing `DS.md` project guides are still
|
|
|
215
215
|
discovered; the tool's contract and new scaffold use `ADS.md`.
|
|
216
216
|
|
|
217
217
|
npm has no in-place package rename: publish `@reqvire-org/ads` as a new package.
|
|
218
|
-
Set up its own trusted publisher for `reqvire-org/
|
|
218
|
+
Set up its own trusted publisher for `reqvire-org/ads`, workflow
|
|
219
219
|
`release.yml`, allowing `npm publish` and `npm dist-tag`. Once ADS is available,
|
|
220
220
|
deprecate the old package with a migration message:
|
|
221
221
|
|
|
@@ -302,7 +302,7 @@ For iterative development, use the linking workflow above. From the repository r
|
|
|
302
302
|
npm install
|
|
303
303
|
npm run build
|
|
304
304
|
npm run pack:tool
|
|
305
|
-
ads_tool_package="$PWD/output/npm/reqvire-org-ads-0.3.
|
|
305
|
+
ads_tool_package="$PWD/output/npm/reqvire-org-ads-0.3.1.tgz"
|
|
306
306
|
```
|
|
307
307
|
|
|
308
308
|
Then change into an existing test project containing `package.json`:
|
|
@@ -430,19 +430,22 @@ export default function Scenario() { return <Button>{fixture.label}</Button>; }
|
|
|
430
430
|
IDs derive from filenames; do not maintain another registry or hand-assigned IDs.
|
|
431
431
|
Token scenarios live beside foundation CSS under the configured token directory.
|
|
432
432
|
The starter includes `tokens/Foundation.scenario.tsx` and its local fixture for
|
|
433
|
-
|
|
434
|
-
public project review pattern and keep its presentation in that pattern:
|
|
433
|
+
a project-owned token review pattern. Keep its presentation in that pattern:
|
|
435
434
|
|
|
436
435
|
```tsx
|
|
437
436
|
import { TokenSamples } from "@ds";
|
|
438
437
|
import { fixture } from "./Typography.fixture";
|
|
439
|
-
export const scenario = { title: fixture.title, covers: ["TokenSamples"],
|
|
438
|
+
export const scenario = { title: fixture.title, covers: ["TokenSamples"], samples: fixture.samples };
|
|
440
439
|
export default function Scenario() { return <TokenSamples {...fixture} />; }
|
|
441
440
|
```
|
|
442
441
|
|
|
443
442
|
`TokenSamples` is an example project-owned pattern, not an npm tool component.
|
|
444
|
-
The fixture defines literal
|
|
445
|
-
|
|
443
|
+
The fixture defines literal `samples: [{ token, property, probe }]` and sample text.
|
|
444
|
+
Token values come from foundation CSS; the fixture owns a distinct, valid CSS probe
|
|
445
|
+
for verifying each declared property. Add/remove samples when tokens change.
|
|
446
|
+
The renderer marks its styled elements with `data-ads-token` and `data-ads-property`.
|
|
447
|
+
The App probes their computed properties in the browser; name/value labels alone
|
|
448
|
+
do not pass. No CSS-property list or test palette is built into ADS. `token-scenario-reference`,
|
|
446
449
|
`token-scenario-render` and `token-scenario-coverage` enforce real references and
|
|
447
450
|
coverage for every token. The same source/style/import checks apply under tokens/.
|
|
448
451
|
|