@adobe/design-data-spec 2.5.0 → 2.7.0
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/conformance/README.md +23 -0
- package/conformance/generation/README.md +61 -0
- package/conformance/generation/alias-rewire/expected/tokens.json +12 -0
- package/conformance/generation/alias-rewire/input/tokens.tokens.json +14 -0
- package/conformance/generation/deprecated-token/expected/tokens.json +9 -0
- package/conformance/generation/deprecated-token/input/tokens.tokens.json +11 -0
- package/conformance/generation/flat-token/expected/tokens.json +8 -0
- package/conformance/generation/flat-token/input/tokens.tokens.json +9 -0
- package/conformance/generation/mode-set-edit/expected/tokens.json +25 -0
- package/conformance/generation/mode-set-edit/input/tokens.tokens.json +40 -0
- package/conformance/generation/mode-set-token/expected/tokens.json +19 -0
- package/conformance/generation/mode-set-token/input/tokens.tokens.json +30 -0
- package/conformance/generation/renamed-token/expected/tokens.json +14 -0
- package/conformance/generation/renamed-token/input/tokens.tokens.json +16 -0
- package/conformance/invalid/SPEC-047/dataset.json +25 -0
- package/conformance/invalid/SPEC-047/expected-errors.json +10 -0
- package/conformance/valid/SPEC-047/dataset.json +25 -0
- package/package.json +1 -1
- package/rules/rules.yaml +17 -0
- package/schemas/field.schema.json +5 -0
- package/schemas/token.schema.json +8 -0
- package/spec/agent-surface.md +3 -3
- package/spec/authoring-workflow.md +279 -0
- package/spec/evolution.md +17 -0
- package/spec/index.md +2 -0
- package/spec/taxonomy.md +21 -0
- package/spec/token-format.md +19 -0
package/conformance/README.md
CHANGED
|
@@ -67,6 +67,29 @@ The Rust SDK drives these fixtures in `sdk/core/src/lib.rs` (`diff_conformance`
|
|
|
67
67
|
|
|
68
68
|
***
|
|
69
69
|
|
|
70
|
+
## Generation conformance fixtures
|
|
71
|
+
|
|
72
|
+
Each **generation** case lives under `generation/<name>/` with:
|
|
73
|
+
|
|
74
|
+
* `input/` — cascade-format `.tokens.json` files (array-of-objects format)
|
|
75
|
+
* `expected/` — expected deterministic legacy set-format output (keyed-object format, one file per input file)
|
|
76
|
+
|
|
77
|
+
These fixtures verify the field-mapping contract in [Evolution — Legacy format contract](../spec/evolution.md#legacy-format-contract): given the same cascade input, the output generator MUST produce byte-identical output on successive runs.
|
|
78
|
+
|
|
79
|
+
| Folder | Intent |
|
|
80
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `generation/flat-token` | A single cascade token with no mode sets maps to a single keyed entry `{ slug: { value, uuid } }`. |
|
|
82
|
+
| `generation/mode-set-token` | Multiple cascade tokens sharing a `set_uuid` merge into a single `sets`-keyed entry. |
|
|
83
|
+
|
|
84
|
+
The Rust SDK drives these fixtures via `design-data migrate legacy-output` (see `sdk/core/src/legacy.rs`).
|
|
85
|
+
Consumer implementations MUST regenerate each `input/` and diff against `expected/` to claim conformance
|
|
86
|
+
with the output-generator determinism contract.
|
|
87
|
+
|
|
88
|
+
See [`generation/README.md`](generation/README.md) for the fixture format, the run command, and
|
|
89
|
+
documentation of the `set_uuid`/`set_schema` cascade grouping fields used in `mode-set-token`.
|
|
90
|
+
|
|
91
|
+
***
|
|
92
|
+
|
|
70
93
|
## Query conformance fixtures
|
|
71
94
|
|
|
72
95
|
Each **query** case lives under `query/<name>/` with:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Generation conformance fixtures
|
|
2
|
+
|
|
3
|
+
Each case pairs a cascade-format input with the expected byte-identical legacy set-format output
|
|
4
|
+
produced by the output generator. These fixtures verify the determinism contract in
|
|
5
|
+
[Evolution — Legacy format contract](../../spec/evolution.md#legacy-format-contract).
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
generation/<case>/
|
|
11
|
+
input/ — cascade-format *.tokens.json files (array-of-objects)
|
|
12
|
+
expected/ — expected legacy output (keyed-object format, one file per input file)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Automated driver
|
|
16
|
+
|
|
17
|
+
These fixtures are exercised automatically by the `generation_conformance` module in
|
|
18
|
+
`sdk/core/src/lib.rs`. Each test case runs `legacy::convert_dir` twice and asserts:
|
|
19
|
+
|
|
20
|
+
1. **Byte-identical output** — the generated files match `expected/` exactly.
|
|
21
|
+
2. **Determinism** — pass 1 and pass 2 output are identical.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Run all generation conformance tests:
|
|
25
|
+
moon run sdk:test
|
|
26
|
+
# or directly:
|
|
27
|
+
cd sdk && cargo test generation_conformance
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
To regenerate `expected/` after changing conversion logic, run the CLI and commit the result:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
design-data migrate legacy-output <case>/input --output <case>/expected
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Cases
|
|
37
|
+
|
|
38
|
+
| Case | What it exercises |
|
|
39
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
40
|
+
| `flat-token` | Basic flat token conversion (property key derivation, field passthrough) |
|
|
41
|
+
| `mode-set-token` | Color-set reconstruction from per-mode cascade records (`set_uuid`/`set_schema`) |
|
|
42
|
+
| `deprecated-token` | `deprecated: "version"` string → `true` boolean; `deprecated_comment` passthrough; `plannedRemoval` dropped |
|
|
43
|
+
| `renamed-token` | `replaced_by: "<uuid>"` → `renamed: "<property-name>"` via global UUID→name map |
|
|
44
|
+
| `alias-rewire` | `$ref: "<uuid>"` → `value: "{<property-name>}"` (alias denormalization with UUID resolution) |
|
|
45
|
+
| `mode-set-edit` | `deprecated`/`renamed` hoisted to outer set level when consistent across all mode entries |
|
|
46
|
+
|
|
47
|
+
## Cascade grouping fields (`set_uuid` / `set_schema`)
|
|
48
|
+
|
|
49
|
+
The `mode-set-token` and `mode-set-edit` fixtures use two cascade-internal grouping fields:
|
|
50
|
+
|
|
51
|
+
| Field | Type | Role |
|
|
52
|
+
| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
53
|
+
| `set_uuid` | string | Shared UUID that groups per-mode cascade records into one set-keyed legacy entry. The SDK registers this as `set_uuid → child-key list` in `sdk/core/src/graph.rs` and the legacy generator collapses all records sharing a `set_uuid` into a single `sets`-keyed output object. |
|
|
54
|
+
| `set_schema` | string | The `$schema` URI of the aggregate set token emitted at the outer (non-mode-keyed) level in the legacy output (e.g. `color-set.json`). |
|
|
55
|
+
|
|
56
|
+
These fields are not yet in the normative token-format field table — they are Rust SDK
|
|
57
|
+
implementation fields defined in `sdk/core/src/graph.rs` and emitted by the cascade ingest
|
|
58
|
+
pipeline (`sdk/core/src/cascade.rs`). A future spec update will add them to
|
|
59
|
+
`spec/token-format.md` as normative cascade fields. Until then, implementors of the output
|
|
60
|
+
generator MUST read the SDK implementation as the reference and treat these fixtures as
|
|
61
|
+
illustrative of the expected grouping behavior.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"background": {
|
|
3
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
4
|
+
"value": "{gray-100}",
|
|
5
|
+
"uuid": "ffffffff-0001-4000-8000-000000000001"
|
|
6
|
+
},
|
|
7
|
+
"gray-100": {
|
|
8
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
9
|
+
"value": "rgb(255, 255, 255)",
|
|
10
|
+
"uuid": "ffffffff-0002-4000-8000-000000000002"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": { "property": "color", "colorFamily": "background" },
|
|
4
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
5
|
+
"$ref": "ffffffff-0002-4000-8000-000000000002",
|
|
6
|
+
"uuid": "ffffffff-0001-4000-8000-000000000001"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": { "property": "color", "colorFamily": "gray-100" },
|
|
10
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
11
|
+
"value": "rgb(255, 255, 255)",
|
|
12
|
+
"uuid": "ffffffff-0002-4000-8000-000000000002"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"red": {
|
|
3
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
4
|
+
"value": "rgb(255, 0, 0)",
|
|
5
|
+
"uuid": "dddddddd-0001-4000-8000-000000000001",
|
|
6
|
+
"deprecated": true,
|
|
7
|
+
"deprecated_comment": "Use color-blue-100 instead"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": { "property": "color", "colorFamily": "red" },
|
|
4
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
5
|
+
"value": "rgb(255, 0, 0)",
|
|
6
|
+
"uuid": "dddddddd-0001-4000-8000-000000000001",
|
|
7
|
+
"deprecated": "2.0",
|
|
8
|
+
"deprecated_comment": "Use color-blue-100 instead",
|
|
9
|
+
"plannedRemoval": "3.0"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": { "property": "color", "colorFamily": "black" },
|
|
4
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
5
|
+
"value": "rgb(0, 0, 0)",
|
|
6
|
+
"uuid": "aaaaaaaa-0001-4000-8000-000000000001",
|
|
7
|
+
"private": true
|
|
8
|
+
}
|
|
9
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"accent-400": {
|
|
3
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json",
|
|
4
|
+
"uuid": "11111111-0003-4000-8000-000000000003",
|
|
5
|
+
"deprecated": true,
|
|
6
|
+
"sets": {
|
|
7
|
+
"light": {
|
|
8
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
9
|
+
"value": "rgb(20, 115, 230)",
|
|
10
|
+
"uuid": "11111111-0001-4000-8000-000000000001"
|
|
11
|
+
},
|
|
12
|
+
"dark": {
|
|
13
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
14
|
+
"value": "rgb(56, 145, 254)",
|
|
15
|
+
"uuid": "11111111-0002-4000-8000-000000000002"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"renamed": "accent-new-400"
|
|
19
|
+
},
|
|
20
|
+
"accent-new-400": {
|
|
21
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
22
|
+
"value": "rgb(20, 115, 230)",
|
|
23
|
+
"uuid": "11111111-0004-4000-8000-000000000004"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": {
|
|
4
|
+
"property": "color",
|
|
5
|
+
"colorFamily": "accent",
|
|
6
|
+
"scaleIndex": 400,
|
|
7
|
+
"colorScheme": "light"
|
|
8
|
+
},
|
|
9
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
10
|
+
"value": "rgb(20, 115, 230)",
|
|
11
|
+
"uuid": "11111111-0001-4000-8000-000000000001",
|
|
12
|
+
"set_uuid": "11111111-0003-4000-8000-000000000003",
|
|
13
|
+
"set_schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json",
|
|
14
|
+
"deprecated": true,
|
|
15
|
+
"replaced_by": "11111111-0004-4000-8000-000000000004"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": {
|
|
19
|
+
"property": "color",
|
|
20
|
+
"colorFamily": "accent",
|
|
21
|
+
"scaleIndex": 400,
|
|
22
|
+
"colorScheme": "dark"
|
|
23
|
+
},
|
|
24
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
25
|
+
"value": "rgb(56, 145, 254)",
|
|
26
|
+
"uuid": "11111111-0002-4000-8000-000000000002",
|
|
27
|
+
"set_uuid": "11111111-0003-4000-8000-000000000003",
|
|
28
|
+
"set_schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json",
|
|
29
|
+
"deprecated": true,
|
|
30
|
+
"replaced_by": "11111111-0004-4000-8000-000000000004"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": { "property": "color", "colorFamily": "accent-new-400" },
|
|
34
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
35
|
+
"value": "rgb(20, 115, 230)",
|
|
36
|
+
"uuid": "11111111-0004-4000-8000-000000000004",
|
|
37
|
+
"set_uuid": "11111111-0005-4000-8000-000000000005",
|
|
38
|
+
"set_schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"blue-100": {
|
|
3
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json",
|
|
4
|
+
"uuid": "cccccccc-0001-4000-8000-000000000001",
|
|
5
|
+
"private": true,
|
|
6
|
+
"sets": {
|
|
7
|
+
"light": {
|
|
8
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
9
|
+
"value": "rgb(245, 249, 255)",
|
|
10
|
+
"uuid": "bbbbbbbb-0001-4000-8000-000000000001"
|
|
11
|
+
},
|
|
12
|
+
"dark": {
|
|
13
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
14
|
+
"value": "rgb(14, 23, 63)",
|
|
15
|
+
"uuid": "bbbbbbbb-0002-4000-8000-000000000002"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": {
|
|
4
|
+
"property": "color",
|
|
5
|
+
"colorFamily": "blue",
|
|
6
|
+
"scaleIndex": 100,
|
|
7
|
+
"colorScheme": "light"
|
|
8
|
+
},
|
|
9
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
10
|
+
"value": "rgb(245, 249, 255)",
|
|
11
|
+
"uuid": "bbbbbbbb-0001-4000-8000-000000000001",
|
|
12
|
+
"set_uuid": "cccccccc-0001-4000-8000-000000000001",
|
|
13
|
+
"set_schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json",
|
|
14
|
+
"private": true
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": {
|
|
18
|
+
"property": "color",
|
|
19
|
+
"colorFamily": "blue",
|
|
20
|
+
"scaleIndex": 100,
|
|
21
|
+
"colorScheme": "dark"
|
|
22
|
+
},
|
|
23
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
24
|
+
"value": "rgb(14, 23, 63)",
|
|
25
|
+
"uuid": "bbbbbbbb-0002-4000-8000-000000000002",
|
|
26
|
+
"set_uuid": "cccccccc-0001-4000-8000-000000000001",
|
|
27
|
+
"set_schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color-set.json",
|
|
28
|
+
"private": true
|
|
29
|
+
}
|
|
30
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"gray": {
|
|
3
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
4
|
+
"value": "rgb(128, 128, 128)",
|
|
5
|
+
"uuid": "eeeeeeee-0001-4000-8000-000000000001",
|
|
6
|
+
"deprecated": true,
|
|
7
|
+
"renamed": "neutral"
|
|
8
|
+
},
|
|
9
|
+
"neutral": {
|
|
10
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
11
|
+
"value": "rgb(128, 128, 128)",
|
|
12
|
+
"uuid": "eeeeeeee-0002-4000-8000-000000000002"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": { "property": "color", "colorFamily": "gray" },
|
|
4
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
5
|
+
"value": "rgb(128, 128, 128)",
|
|
6
|
+
"uuid": "eeeeeeee-0001-4000-8000-000000000001",
|
|
7
|
+
"deprecated": true,
|
|
8
|
+
"replaced_by": "eeeeeeee-0002-4000-8000-000000000002"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": { "property": "color", "colorFamily": "neutral" },
|
|
12
|
+
"$schema": "https://opensource.adobe.com/spectrum-design-data/schemas/token-types/color.json",
|
|
13
|
+
"value": "rgb(128, 128, 128)",
|
|
14
|
+
"uuid": "eeeeeeee-0002-4000-8000-000000000002"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tokens": [
|
|
3
|
+
{
|
|
4
|
+
"name": {
|
|
5
|
+
"component": "accordion",
|
|
6
|
+
"property": "space-between",
|
|
7
|
+
"from": "top",
|
|
8
|
+
"to": "banana"
|
|
9
|
+
},
|
|
10
|
+
"value": "8px"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"components": [
|
|
14
|
+
{
|
|
15
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/accordion.json",
|
|
16
|
+
"name": "accordion",
|
|
17
|
+
"displayName": "Accordion",
|
|
18
|
+
"meta": {
|
|
19
|
+
"category": "containers",
|
|
20
|
+
"documentationUrl": "https://spectrum.adobe.com/page/accordion/"
|
|
21
|
+
},
|
|
22
|
+
"anatomy": [{ "name": "handle", "description": "Drag handle." }]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tokens": [
|
|
3
|
+
{
|
|
4
|
+
"name": {
|
|
5
|
+
"component": "accordion",
|
|
6
|
+
"property": "space-between",
|
|
7
|
+
"from": "bottom",
|
|
8
|
+
"to": "handle"
|
|
9
|
+
},
|
|
10
|
+
"value": "8px"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"components": [
|
|
14
|
+
{
|
|
15
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/accordion.json",
|
|
16
|
+
"name": "accordion",
|
|
17
|
+
"displayName": "Accordion",
|
|
18
|
+
"meta": {
|
|
19
|
+
"category": "containers",
|
|
20
|
+
"documentationUrl": "https://spectrum.adobe.com/page/accordion/"
|
|
21
|
+
},
|
|
22
|
+
"anatomy": [{ "name": "handle", "description": "Drag handle." }]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
package/package.json
CHANGED
package/rules/rules.yaml
CHANGED
|
@@ -527,3 +527,20 @@ rules:
|
|
|
527
527
|
message: "Guideline '{name}' references '{ref}' which is not a known component or guideline"
|
|
528
528
|
spec_ref: spec/guideline-format.md#related-references
|
|
529
529
|
introduced_in: "1.0.0-draft"
|
|
530
|
+
|
|
531
|
+
- id: SPEC-047
|
|
532
|
+
name: space-between-endpoint-valid
|
|
533
|
+
severity: error
|
|
534
|
+
layer: 2
|
|
535
|
+
category: reference-integrity
|
|
536
|
+
assert: >
|
|
537
|
+
A token name-object with `property` "space-between" MUST carry both `from` and
|
|
538
|
+
`to` fields, and `from`/`to` MUST NOT appear unless `property` is "space-between".
|
|
539
|
+
Each of `from`/`to` MUST be one of: an edge position (`positions.json`), a generic
|
|
540
|
+
anatomy term (`anatomy-terms.json`), or — when `component` is present and declares
|
|
541
|
+
an `anatomy` array — the `name` of a declared anatomy part on that component.
|
|
542
|
+
Mirrors SPEC-020's component→anatomy resolution, unioned with the position and
|
|
543
|
+
generic-anatomy vocabularies.
|
|
544
|
+
message: "Token '{token}' has space-between endpoint '{endpoint}' that is not a known position, anatomy term, or declared anatomy part on component '{component}'"
|
|
545
|
+
spec_ref: spec/token-format.md#space-between-endpoints
|
|
546
|
+
introduced_in: "1.0.0-draft"
|
|
@@ -79,6 +79,11 @@
|
|
|
79
79
|
"enum": ["string", "integer"],
|
|
80
80
|
"description": "Type of the field value. Default: 'string'.",
|
|
81
81
|
"default": "string"
|
|
82
|
+
},
|
|
83
|
+
"excludeFromLegacyKey": {
|
|
84
|
+
"type": "boolean",
|
|
85
|
+
"description": "When true, this field is omitted from legacy key generation in naming.rs. Opt-in: absence means false. Use for mode-set selectors, color-domain fields, and legacy-annotation fields that must not appear in the serialized token name.",
|
|
86
|
+
"default": false
|
|
82
87
|
}
|
|
83
88
|
},
|
|
84
89
|
"additionalProperties": false
|
|
@@ -71,6 +71,14 @@
|
|
|
71
71
|
"type": "string",
|
|
72
72
|
"description": "Semantic: overall component shape (e.g. uniform)."
|
|
73
73
|
},
|
|
74
|
+
"from": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"description": "Semantic: starting endpoint of a space-between measurement (e.g. top, edge, text). Paired with `to`; used with property `space-between`."
|
|
77
|
+
},
|
|
78
|
+
"to": {
|
|
79
|
+
"type": "string",
|
|
80
|
+
"description": "Semantic: ending endpoint of a space-between measurement (e.g. text, visual, control). Paired with `from`; used with property `space-between`."
|
|
81
|
+
},
|
|
74
82
|
"colorScheme": {
|
|
75
83
|
"type": "string",
|
|
76
84
|
"description": "Mode set: color scheme mode (e.g. light, dark, wireframe)."
|
package/spec/agent-surface.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Agent-readable surface
|
|
2
2
|
|
|
3
3
|
**Spec version:** `1.0.0-draft` (see [Overview](index.md))\
|
|
4
|
-
**Status:** Implemented — RFC-C / Phase 8 (epic [#830](https://github.com/adobe/spectrum-design-data/issues/830)). Core read/validate/write surface shipped. `write_component`
|
|
4
|
+
**Status:** Implemented — RFC-C / Phase 8 (epic [#830](https://github.com/adobe/spectrum-design-data/issues/830)). Core read/validate/write surface shipped. `write_component` is Phase B scheduled (see [Authoring workflow — Scheduled promotion](authoring-workflow.md#scheduled-promotion)); `explain` is pending `get_guidance` wire-up.
|
|
5
5
|
|
|
6
6
|
This document defines the **agent-readable surface**: the contract an external AI agent uses to consume design data conformant with this specification. It standardizes a small set of operations exposed through three transports — a CLI, a Model Context Protocol (MCP) server, and a Claude Code Agent Skill — all backed by the same resolver, validator, and query implementations that power the rest of the SDK.
|
|
7
7
|
|
|
@@ -35,9 +35,9 @@ The surface targets three consumer shapes:
|
|
|
35
35
|
| `get_guidance` | token UUID, component identifier, or anatomy reference | attached document blocks (Phase 9 / RFC-D); falls back to empty list pre-RFC-D | document blocks |
|
|
36
36
|
| `diff_datasets` | two dataset roots | `DiffReport` per [Diff](diff.md) | `diff::semantic_diff` |
|
|
37
37
|
| `write_token` | token object + optional rationale string | updated product-layer token file + `product-context.json` (RECOMMENDED, not NORMATIVE in v1) | `write::write_token` — shipped: `design-data write-token` (CLI) / `authoring_session_commit` (MCP) |
|
|
38
|
-
| `write_component` | component object + optional rationale string | updated
|
|
38
|
+
| `write_component` | component object + optional rationale string | updated dataset-root component file (RECOMMENDED, not NORMATIVE in v1; scheduled to become MUST — see [Scheduled promotion](authoring-workflow.md#scheduled-promotion)) | `write::write_component` — Phase B scheduled; not yet implemented |
|
|
39
39
|
|
|
40
|
-
**NORMATIVE:** `validate_usage`, `resolve_token`, `query_tokens`, `diff_datasets`, and `describe_component` MUST be implemented in a conforming agent surface. `suggest_token`, `get_guidance`, `write_token`, and `write_component` are RECOMMENDED.
|
|
40
|
+
**NORMATIVE:** `validate_usage`, `resolve_token`, `query_tokens`, `diff_datasets`, and `describe_component` MUST be implemented in a conforming agent surface. `suggest_token`, `get_guidance`, `write_token`, and `write_component` are RECOMMENDED. `write_token` and `write_component` are scheduled to become MUST when the Phase B foundation-corpus write target ships — see [Authoring workflow — Scheduled promotion](authoring-workflow.md#scheduled-promotion).
|
|
41
41
|
|
|
42
42
|
**RECOMMENDED:** When `write_token` or `write_component` is invoked, the implementation SHOULD capture a `rationale` argument from the agent session context and record it in both the token's inline `rationale` field and the product context document's `overrides[].rationale` or `extensions.tokens[].rationale`. See [Product context — Agent capture behavior](product-context.md#agent-capture-behavior).
|
|
43
43
|
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Authoring workflow
|
|
2
|
+
|
|
3
|
+
<!-- Copyright 2026 Adobe. All rights reserved. -->
|
|
4
|
+
|
|
5
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))\
|
|
6
|
+
**Status:** Draft — RFC [#625](https://github.com/adobe/spectrum-design-data/discussions/625) / Phase 4 (umbrella epic [#714](https://github.com/adobe/spectrum-design-data/discussions/714))
|
|
7
|
+
|
|
8
|
+
This document defines the **authoring workflow** for spec-conformant design data: the normative contract governing how design tokens and related design-system artifacts are **created, edited, and maintained** over time.
|
|
9
|
+
|
|
10
|
+
The source-of-truth direction is already normative in [Evolution](evolution.md#legacy-format-contract): the cascade format is the authoritative source; the legacy format is generated from it. This document extends that contract by specifying *where* the authoritative source lives, *what tooling* is expected to author it, and *what lifecycle operations* a conforming authoring surface MUST support across all data categories.
|
|
11
|
+
|
|
12
|
+
## Goals
|
|
13
|
+
|
|
14
|
+
1. **Single authoritative source.** All Spectrum design data is authored in `packages/design-data/` (or any spec-conformant dataset root) — not in legacy output directories. Generated outputs are derived artifacts.
|
|
15
|
+
2. **Tool-mediated authoring.** Design data is authored via tooling (`design-data` CLI, `design-data-tui`, MCP authoring-session tools, future management app), not by direct JSON editing of production files. Tooling enforces schema validity, name-object decomposition, and UUID consistency.
|
|
16
|
+
3. **Full lifecycle coverage.** Authoring surfaces cover the complete artifact lifecycle — create, edit, deprecate, rename, alias-rewire, and mode-set management — not just creation.
|
|
17
|
+
4. **All data categories.** The authoring contract applies to every dataset category: tokens, components, fields, registry, mode sets, and guidelines.
|
|
18
|
+
|
|
19
|
+
## Non-goals
|
|
20
|
+
|
|
21
|
+
* Specifying the *output format* of generated artifacts. Legacy format mapping is defined in [Evolution — Legacy format contract](evolution.md#legacy-format-contract); DTCG and StyleDictionary outputs are deferred (RFC [#627](https://github.com/adobe/spectrum-design-data/discussions/627)).
|
|
22
|
+
* Specifying the *consumer-facing API* of published packages (`@adobe/spectrum-tokens`, platform SDKs). Those are separately governed.
|
|
23
|
+
* Specifying the *UI* of the authoring tools; this document defines behavioral contracts, not user-interface design.
|
|
24
|
+
* Multi-user collaboration, permissions models, and Figma sync direction (open questions in RFC [#625](https://github.com/adobe/spectrum-design-data/discussions/625)).
|
|
25
|
+
|
|
26
|
+
## Authoritative source
|
|
27
|
+
|
|
28
|
+
Per [Evolution — Legacy format contract](evolution.md#legacy-format-contract), `packages/design-data/` (or the dataset root declared in the active `.design-data.toml`) is the **authoritative source** for all design data; output directories are derived artifacts. This document extends that contract with the following authoring-specific obligations:
|
|
29
|
+
|
|
30
|
+
**NORMATIVE:** The dataset root MUST be the only location where design artifacts are authored. Output directories — including `packages/tokens/src/` and any platform-SDK directories — MUST NOT be independently edited.
|
|
31
|
+
|
|
32
|
+
**NORMATIVE:** An authoring tool that writes design data MUST write to the dataset root's registered directories (`tokens/`, `components/`, `fields/`, `mode-sets/`, `registry/`, `guidelines/`) as defined in [Dataset layout](dataset-layout.md). Writing to legacy output directories (`foundation.json`, `platform.json`, `product.json`) constitutes a non-conforming write operation for Spectrum foundation corpus authoring.
|
|
33
|
+
|
|
34
|
+
## Authoring tools
|
|
35
|
+
|
|
36
|
+
The following tools constitute the normative authoring surface:
|
|
37
|
+
|
|
38
|
+
| Tool | Form | Status | Scope |
|
|
39
|
+
| -------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
40
|
+
| `design-data` CLI | `design-data write-token` subcommand | Shipped — product-layer token creation | Foundation corpus authoring: see [Gap — Phase B](#scheduled-promotion) |
|
|
41
|
+
| `design-data-tui` | interactive token naming + creation wizard | Shipped (RFC [#973](https://github.com/adobe/spectrum-design-data/discussions/973)) | Foundation corpus authoring: see [Gap — Phase B](#scheduled-promotion) |
|
|
42
|
+
| MCP authoring session | `start_authoring_session` / `authoring_session_commit` tools | Shipped (RFC [#973](https://github.com/adobe/spectrum-design-data/discussions/973)) | Foundation corpus authoring: see [Gap — Phase B](#scheduled-promotion) |
|
|
43
|
+
| Design Data management app | future browser-based tool | Not yet shipped | Full CRUD across all categories |
|
|
44
|
+
|
|
45
|
+
**RECOMMENDED:** Authors SHOULD use the TUI or MCP authoring session rather than editing cascade JSON files directly. Tooling enforces UUID uniqueness, name-object field decomposition, and referential integrity that is difficult to maintain manually.
|
|
46
|
+
|
|
47
|
+
### Scheduled promotion {#scheduled-promotion}
|
|
48
|
+
|
|
49
|
+
The shipped CLI/TUI/MCP write path currently targets product-layer files (`foundation.json`, `platform.json`, `product.json`) — the distributed design system model introduced for product teams. Redirecting those tools to write to the foundation Spectrum corpus (`packages/design-data/tokens/*.tokens.json`) is Phase B work.
|
|
50
|
+
|
|
51
|
+
**NORMATIVE:** Once the Phase B authoring engine ships, all authoring tools described above MUST write to the dataset root, not to legacy layer files. The `write_token` and `write_component` operations in [Agent-readable surface](agent-surface.md) are currently RECOMMENDED; they are **scheduled to become required** (MUST) when the Phase B foundation-corpus write target ships. The exact promotion version is tracked in RFC [#625](https://github.com/adobe/spectrum-design-data/discussions/625). This mirrors the SPEC-017 escalation precedent in [Token format](token-format.md#string-name-escape-hatch--spec-017-severity-schedule).
|
|
52
|
+
|
|
53
|
+
## Lifecycle operations
|
|
54
|
+
|
|
55
|
+
The following table defines the **target token-authoring contract**: the complete set of lifecycle operations a fully conforming authoring tool MUST support. Current shipped conformance covers **create only**; edit and remaining lifecycle operations are Phase B work (see [Per-category authoring contracts](#per-category-authoring-contracts) and [Scheduled promotion](#scheduled-promotion)). Operations for non-token categories are specified in the per-category authoring contracts.
|
|
56
|
+
|
|
57
|
+
### Token lifecycle operations
|
|
58
|
+
|
|
59
|
+
| Operation | Description | Required fields |
|
|
60
|
+
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
|
61
|
+
| **create** | Introduce a new token to the dataset. Assign a fresh UUID. Populate name object, value or alias `$ref`, `introduced` version. | `uuid`, `name`, `value` or `$ref` |
|
|
62
|
+
| **edit** | Update a token's value, alias target, rationale, or name-object fields. Preserve UUID. | `uuid` (for identity lookup) |
|
|
63
|
+
| **deprecate** | Set `deprecated` to the current spec version string; optionally set `replaced_by` and `deprecated_comment`. | `deprecated`, `uuid` |
|
|
64
|
+
| **rename** | Assign a new name object. Introduce a `replaced_by` pointer on the old token (or retire it). Preserve UUID on the renamed token. | Name-object fields, `replaced_by` |
|
|
65
|
+
| **alias-rewire** | Change the `$ref` target UUID of an alias token. Verify the new target resolves in the cascade. | `$ref` |
|
|
66
|
+
| **mode-set management** | Add, rename, or remove a mode-set entry. Update affected `mode` fields across tokens. | Mode-set file + affected token entries |
|
|
67
|
+
| **remove** | Delete a token that has passed its migration window. Verify no `$ref` in the dataset resolves to the removed UUID. | n/a |
|
|
68
|
+
|
|
69
|
+
**NORMATIVE:** A conforming authoring tool MUST assign UUIDs at creation time and MUST NOT change the UUID of an existing token during any edit, deprecate, rename, or alias-rewire operation. UUID stability is the identity contract that allows `$ref`, `replaced_by`, and external consumers to reference tokens across versions.
|
|
70
|
+
|
|
71
|
+
**NORMATIVE:** A conforming authoring tool MUST write a valid `introduced` version on create, using the declared spec version of the active dataset (`specVersion` field in `dataset.json` or `.design-data.toml`).
|
|
72
|
+
|
|
73
|
+
**NORMATIVE:** A conforming authoring tool MUST validate the written dataset against Layer 1 (JSON Schema) and Layer 2 (semantic rules) before persisting the write. A write operation that produces a Layer 1 error MUST be rejected.
|
|
74
|
+
|
|
75
|
+
**RECOMMENDED:** A conforming authoring tool SHOULD capture an optional `rationale` argument at creation or edit time and record it in the token's inline `rationale` field. See [Product context](product-context.md#agent-capture-behavior) for the product-layer rationale convention.
|
|
76
|
+
|
|
77
|
+
## Per-category authoring contracts
|
|
78
|
+
|
|
79
|
+
The following per-category contracts specify what the authoring surface authors in each registered directory and which validation rules gate the output. Detailed authoring workflows per category are specified in separate subsections of this document as Phase A work progresses.
|
|
80
|
+
|
|
81
|
+
| Category | Directory | Authoring status | Validation gate |
|
|
82
|
+
| ---------- | ------------- | -------------------------------------------------------------------------------- | ------------------------------------------ |
|
|
83
|
+
| Tokens | `tokens/` | Shipped (create only; edit/lifecycle operations are Phase B) | SPEC-001–017, SPEC-041, SPEC-042, SPEC-043 |
|
|
84
|
+
| Components | `components/` | Not yet shipped (`write_component` deferred — [Agent surface](agent-surface.md)) | SPEC-018–040 |
|
|
85
|
+
| Fields | `fields/` | Not yet shipped | SPEC-042, SPEC-043 |
|
|
86
|
+
| Mode sets | `mode-sets/` | Not yet shipped | SPEC-005, SPEC-008, SPEC-041 |
|
|
87
|
+
| Guidelines | `guidelines/` | Not yet shipped | SPEC-045, SPEC-046 |
|
|
88
|
+
| Registry | `registry/` | Not yet shipped (vocabulary is hand-maintained) | SPEC-033, SPEC-034, SPEC-035 |
|
|
89
|
+
|
|
90
|
+
### Token authoring contract
|
|
91
|
+
|
|
92
|
+
Tokens are authored in `tokens/**/*.tokens.json`. Files may be nested arbitrarily within
|
|
93
|
+
`tokens/`; the convention is one thematic `.tokens.json` file per token group (e.g.
|
|
94
|
+
`color-palette.tokens.json`, `typography.tokens.json`).
|
|
95
|
+
|
|
96
|
+
**Required at creation:** A conforming authoring tool MUST write:
|
|
97
|
+
|
|
98
|
+
| Field | Requirement | Notes |
|
|
99
|
+
| ----------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| `name` | REQUIRED | Name object with at least `property`; MUST be decomposed via the `fields/` catalog — see [Taxonomy-aware authoring](#taxonomy-aware-authoring) |
|
|
101
|
+
| `uuid` | REQUIRED | Fresh UUID v4 assigned by the tool; MUST NOT change for the lifetime of the token |
|
|
102
|
+
| `value` or `$ref` | REQUIRED (exactly one) | Literal value or alias reference to another token's UUID |
|
|
103
|
+
| `$schema` | RECOMMENDED | Token-type schema URI (e.g. `color.json`, `typography.json`) from `packages/design-data-spec/schemas/` |
|
|
104
|
+
| `introduced` | RECOMMENDED | Spec version string of the active dataset at creation time |
|
|
105
|
+
|
|
106
|
+
**Validation gate:** SPEC-001–017 (name, value, lifecycle, tech-debt), SPEC-041 (mode-set
|
|
107
|
+
conformance), SPEC-042 (field-scope), SPEC-043 (domain-required-fields).
|
|
108
|
+
|
|
109
|
+
**Edit and lifecycle operations (Phase B):** Edit, deprecate, rename, alias-rewire, mode-set
|
|
110
|
+
management, and remove are specified in [Lifecycle operations](#lifecycle-operations) and are
|
|
111
|
+
implemented in Phase B.
|
|
112
|
+
|
|
113
|
+
***
|
|
114
|
+
|
|
115
|
+
### Component authoring contract
|
|
116
|
+
|
|
117
|
+
Components are authored in `components/{name}.json`. Each file declares one component and MUST
|
|
118
|
+
be named with the component's `name` field value (e.g. `button.json` for `name: "button"`).
|
|
119
|
+
|
|
120
|
+
**Required at creation:**
|
|
121
|
+
|
|
122
|
+
| Field | Requirement | Notes |
|
|
123
|
+
| ----------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
124
|
+
| `$id` | REQUIRED | URI: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/{name}.json` |
|
|
125
|
+
| `name` | REQUIRED | Kebab-case slug, unique within the dataset |
|
|
126
|
+
| `displayName` | REQUIRED | Human-readable name (e.g. `"Button"`) |
|
|
127
|
+
| `meta.category` | REQUIRED | One of: `actions`, `containers`, `data visualization`, `feedback`, `inputs`, `navigation`, `status`, `typography` |
|
|
128
|
+
| `meta.documentationUrl` | REQUIRED | URI to component documentation page |
|
|
129
|
+
|
|
130
|
+
**Recommended at creation:** `options` (component API), `anatomy` (anatomy parts array),
|
|
131
|
+
`states` (state declarations array).
|
|
132
|
+
|
|
133
|
+
**Validation gate:** SPEC-018–022 (anatomy/state/slot structure), SPEC-024–027 (tokenBindings,
|
|
134
|
+
cross-references), SPEC-034 (category registry sync), SPEC-035 (anatomy-term registry sync),
|
|
135
|
+
SPEC-038–040 (lifecycle, display name, schema).
|
|
136
|
+
|
|
137
|
+
**Authoring status:** Not yet shipped — `write_component` is Phase B scheduled (see
|
|
138
|
+
[Scheduled promotion](#scheduled-promotion)).
|
|
139
|
+
|
|
140
|
+
***
|
|
141
|
+
|
|
142
|
+
### Field authoring contract
|
|
143
|
+
|
|
144
|
+
Name-object field declarations are authored in `fields/{fieldName}.json`. Each file declares
|
|
145
|
+
one field. Field declarations extend the `fields/` catalog that the SDK and authoring tools
|
|
146
|
+
load for classification decomposition.
|
|
147
|
+
|
|
148
|
+
**Required at creation:**
|
|
149
|
+
|
|
150
|
+
| Field | Requirement | Notes |
|
|
151
|
+
| ------------------------ | ----------- | ------------------------------------------------------------------ |
|
|
152
|
+
| `name` | REQUIRED | Field key on the token name object (e.g. `colorFamily`, `variant`) |
|
|
153
|
+
| `kind` | REQUIRED | One of: `semantic`, `mode-set`, `numeric` |
|
|
154
|
+
| `validation` | REQUIRED | One of: `strict` (error), `advisory` (warning), `none` |
|
|
155
|
+
| `serialization.position` | REQUIRED | Integer; order in default serialized name string |
|
|
156
|
+
|
|
157
|
+
**Recommended at creation:** `description`, `registry` (path to vocabulary file, or `null`),
|
|
158
|
+
`scope` (domain restriction string, or `null` for universal fields).
|
|
159
|
+
|
|
160
|
+
**Validation gate:** SPEC-042 (field-scope-violation), SPEC-043 (domain-required-fields).
|
|
161
|
+
|
|
162
|
+
**Authoring status:** Not yet shipped — field declarations are currently hand-authored JSON.
|
|
163
|
+
Phase C will add tooling for field creation.
|
|
164
|
+
|
|
165
|
+
***
|
|
166
|
+
|
|
167
|
+
### Mode-set authoring contract
|
|
168
|
+
|
|
169
|
+
Mode sets are authored in `mode-sets/{name}.json`. Each file declares one mode set. Mode-set
|
|
170
|
+
names MUST be stable identifiers — they are referenced by tokens' mode-keyed `sets` objects
|
|
171
|
+
and by manifests; renaming a mode set is a breaking operation.
|
|
172
|
+
|
|
173
|
+
**Required at creation:**
|
|
174
|
+
|
|
175
|
+
| Field | Requirement | Notes |
|
|
176
|
+
| --------- | ----------- | ----------------------------------------------------------------------- |
|
|
177
|
+
| `name` | REQUIRED | Stable mode-set identifier (e.g. `colorScheme`, `scale`) |
|
|
178
|
+
| `modes` | REQUIRED | Non-empty array of unique mode-value strings (e.g. `["light", "dark"]`) |
|
|
179
|
+
| `default` | REQUIRED | A member of `modes`; MUST satisfy SPEC-005 |
|
|
180
|
+
|
|
181
|
+
**Recommended at creation:** `description`.
|
|
182
|
+
|
|
183
|
+
**Validation gate:** SPEC-005 (default-mode-not-in-modes), SPEC-008 (base-variant-absence),
|
|
184
|
+
SPEC-041 (platform mode-set conformance).
|
|
185
|
+
|
|
186
|
+
**Authoring status:** Not yet shipped — mode sets are hand-authored JSON. Phase C will add
|
|
187
|
+
tooling for mode-set management.
|
|
188
|
+
|
|
189
|
+
***
|
|
190
|
+
|
|
191
|
+
### Guideline authoring contract
|
|
192
|
+
|
|
193
|
+
Guideline documents are authored in `guidelines/{name}.json`. Each file declares one guideline
|
|
194
|
+
document. The filename MUST match the document's `name` field.
|
|
195
|
+
|
|
196
|
+
**Required at creation:**
|
|
197
|
+
|
|
198
|
+
| Field | Requirement | Notes |
|
|
199
|
+
| ---------------- | ----------- | ------------------------------------------------------------------------------------- |
|
|
200
|
+
| `$id` | REQUIRED | URI: `https://opensource.adobe.com/spectrum-design-data/guidelines/{name}.json` |
|
|
201
|
+
| `name` | REQUIRED | Kebab-case slug matching filename |
|
|
202
|
+
| `title` | REQUIRED | Human-readable page title |
|
|
203
|
+
| `category` | REQUIRED | One of: `designing`, `fundamentals`, `developing`, `support` |
|
|
204
|
+
| `documentBlocks` | REQUIRED | Array with at least one block (SPEC-045 requires a `purpose` block SHOULD be present) |
|
|
205
|
+
|
|
206
|
+
**Recommended at creation:** `sourceUrl`, `lastUpdated`, `tags`.
|
|
207
|
+
|
|
208
|
+
**Validation gate:** SPEC-045 (guideline-purpose-block), SPEC-046 (guideline-related-references-resolve).
|
|
209
|
+
|
|
210
|
+
**Authoring status:** Not yet shipped — guidelines are hand-authored JSON. Phase C will add
|
|
211
|
+
tooling for guideline creation.
|
|
212
|
+
|
|
213
|
+
***
|
|
214
|
+
|
|
215
|
+
### Registry authoring contract
|
|
216
|
+
|
|
217
|
+
Registry files in `registry/` declare vocabulary collections — the canonical term lists for
|
|
218
|
+
anatomy, component categories, states, variants, and other classified fields. Registry files
|
|
219
|
+
are currently **hand-maintained**: they are not yet authored via tooling.
|
|
220
|
+
|
|
221
|
+
Each registry file is a JSON object with `type`, `description`, and a `values` array. Each
|
|
222
|
+
value entry carries:
|
|
223
|
+
|
|
224
|
+
| Field | Requirement | Notes |
|
|
225
|
+
| ------- | ----------- | -------------------------------------------------------------------- |
|
|
226
|
+
| `id` | REQUIRED | Canonical value string (kebab-case); unique within the registry file |
|
|
227
|
+
| `label` | REQUIRED | Human-readable display name |
|
|
228
|
+
|
|
229
|
+
**Recommended per entry:** `description`, `usedIn` (declarative metadata — see
|
|
230
|
+
[Registry spec](registry.md) for the field definition).
|
|
231
|
+
|
|
232
|
+
**Validation gate:** SPEC-009 (name-field-enum-sync, advisory), SPEC-033 (cross-registry ID
|
|
233
|
+
overlap is permitted), SPEC-034 (component-categories registry sync), SPEC-035
|
|
234
|
+
(anatomy-part-names registry sync).
|
|
235
|
+
|
|
236
|
+
**Authoring status:** Hand-maintained vocabulary — the `registry/` directory has an
|
|
237
|
+
`AUTHORING.md` guide in `packages/design-data/AUTHORING.md`. Tooling-assisted registry
|
|
238
|
+
authoring is Phase C scope; vocabulary additions today follow the manual process in that guide.
|
|
239
|
+
|
|
240
|
+
***
|
|
241
|
+
|
|
242
|
+
## Taxonomy-aware authoring
|
|
243
|
+
|
|
244
|
+
**NORMATIVE:** A conforming authoring tool MUST decompose the token name into name-object fields using the `fields/` catalog rather than accepting a freeform `property` string. At minimum, authoring tools MUST offer structured field selection for all fields declared in `packages/design-data/fields/*.json` (or the equivalent dataset-relative path).
|
|
245
|
+
|
|
246
|
+
**RECOMMENDED:** Authoring tools SHOULD validate candidate field values against the corresponding registry (where a `registry` path is declared on the field descriptor) and SHOULD warn the author when a value does not match any registered term.
|
|
247
|
+
|
|
248
|
+
**RATIONALE:** Baking taxonomy concepts (size, variant, density, etc.) into the `property` slug reproduces technical debt that the structured name-object format was designed to eliminate. SPEC-043 (`domain-required-fields`) tracks this decomposition debt at advisory severity; it is scheduled to tighten — see [Taxonomy — SPEC-043 severity schedule](taxonomy.md#spec-043-severity-schedule) for the escalation schedule and promotion conditions.
|
|
249
|
+
|
|
250
|
+
## Output generation
|
|
251
|
+
|
|
252
|
+
**NORMATIVE:** After any authoring operation that modifies the `tokens/` directory, the legacy output (`packages/tokens/src/`) MUST be regenerated by running the output generator pipeline (`design-data:legacy-output` moon task). The regenerated output MUST pass the round-trip verification gates (`design-data:roundtrip-verify`, `tokens:verifyLegacyRoundtrip`, `tokens:verifyLegacyOutput`).
|
|
253
|
+
|
|
254
|
+
**NORMATIVE:** The output generator MUST be deterministic: given the same input cascade files, it MUST produce byte-identical output on successive runs. See [Evolution — Legacy format contract](evolution.md#legacy-format-contract) for the field-mapping specification.
|
|
255
|
+
|
|
256
|
+
**RECOMMENDED:** Authoring tooling SHOULD trigger output regeneration automatically after a successful write, so that the generated outputs stay in sync without a manual pipeline step.
|
|
257
|
+
|
|
258
|
+
## Conformance
|
|
259
|
+
|
|
260
|
+
**NORMATIVE:** An authoring tool implementation that claims conformance with this section MUST:
|
|
261
|
+
|
|
262
|
+
1. Write all authored artifacts to the dataset root's registered directories (not to legacy output files).
|
|
263
|
+
2. Assign UUIDs at creation time and preserve them across all subsequent operations.
|
|
264
|
+
3. Write a valid `introduced` version on all created artifacts.
|
|
265
|
+
4. Validate written artifacts against Layer 1 (JSON Schema) and Layer 2 (semantic rules) before persisting.
|
|
266
|
+
5. Support structured name-object field decomposition using the `fields/` catalog for token creation.
|
|
267
|
+
|
|
268
|
+
## References
|
|
269
|
+
|
|
270
|
+
* [#625 — Token Authoring Workflow](https://github.com/adobe/spectrum-design-data/discussions/625) — RFC discussion
|
|
271
|
+
* [#714 — Design Data Specification (umbrella)](https://github.com/adobe/spectrum-design-data/discussions/714)
|
|
272
|
+
* [#973 — Interactive TUI & Token Authoring Wizard](https://github.com/adobe/spectrum-design-data/discussions/973) — shipped authoring tooling
|
|
273
|
+
* [Dataset layout](dataset-layout.md) — normative directory structure and discovery algorithm
|
|
274
|
+
* [Agent-readable surface](agent-surface.md) — write operations and transport contracts
|
|
275
|
+
* [Evolution — Legacy format contract](evolution.md#legacy-format-contract) — cascade-is-source-of-truth policy
|
|
276
|
+
* [Token format](token-format.md) — token name object, lifecycle fields
|
|
277
|
+
* [Taxonomy](taxonomy.md) — name-object fields and vocabulary
|
|
278
|
+
* [`sdk/core/src/write.rs`](../../../sdk/core/src/write.rs) — reference write implementation
|
|
279
|
+
* [`sdk/core/src/legacy.rs`](../../../sdk/core/src/legacy.rs) — legacy output generator
|
package/spec/evolution.md
CHANGED
|
@@ -87,6 +87,23 @@ The `@adobe/spectrum-tokens` package continues to publish tokens in the **legacy
|
|
|
87
87
|
| `plannedRemoval` | Not emitted |
|
|
88
88
|
| `deprecated_comment` | `deprecated_comment` (passed through) |
|
|
89
89
|
|
|
90
|
+
### Output-generator determinism
|
|
91
|
+
|
|
92
|
+
**NORMATIVE:** The output generator MUST be deterministic: given the same cascade input files, it
|
|
93
|
+
MUST produce byte-identical output on successive runs. Key rules:
|
|
94
|
+
|
|
95
|
+
* Object keys in the generated legacy file MUST be sorted by token slug (lexicographic order).
|
|
96
|
+
* The `sets` object within a set token MUST preserve the order modes appear in the source cascade
|
|
97
|
+
file (first occurrence of each mode name, in file order).
|
|
98
|
+
* No ephemeral fields (timestamps, run IDs, etc.) MUST be written to the output.
|
|
99
|
+
|
|
100
|
+
**Conformance fixtures:** The `conformance/generation/` corpus provides annotated input/expected
|
|
101
|
+
pairs that an implementation MUST produce byte-identically to claim conformance with this
|
|
102
|
+
determinism contract. See [Conformance fixtures](../conformance/README.md#generation-conformance-fixtures).
|
|
103
|
+
|
|
104
|
+
The Rust SDK drives these fixtures via `design-data migrate legacy-output`
|
|
105
|
+
(see [`sdk/core/src/legacy.rs`](../../../sdk/core/src/legacy.rs)).
|
|
106
|
+
|
|
90
107
|
### Coexistence during migration
|
|
91
108
|
|
|
92
109
|
Both formats are published simultaneously. The cascade format is the source of truth; the legacy format is generated from it. This dual-format period continues until platform consumers have migrated to the cascade format or to platform SDKs that consume it.
|
package/spec/index.md
CHANGED
|
@@ -27,6 +27,7 @@ The specification defines:
|
|
|
27
27
|
13. **Evolution** — deprecation lifecycle, migration windows, change classification, and legacy format contract ([Evolution](evolution.md)).
|
|
28
28
|
14. **Dataset layout** — normative directory structure of a dataset (`tokens/`, `components/`, `fields/`, `mode-sets/`, `registry/`, `guidelines/`), discovery algorithm, and optional root descriptor ([Dataset layout](dataset-layout.md)).
|
|
29
29
|
15. **Guideline documents** — standalone JSON files representing non-component design guidance pages (color, typography, motion, spacing, principles, etc.); each wraps page metadata and a `documentBlocks` body ([Guideline format](guideline-format.md)).
|
|
30
|
+
16. **Authoring workflow** — normative contract for authoring design data via tooling: authoritative source location, lifecycle operations (create / edit / deprecate / rename / alias-rewire / mode-set management), taxonomy-aware decomposition requirement, and output-generation obligations ([Authoring workflow](authoring-workflow.md)).
|
|
30
31
|
|
|
31
32
|
## Conformance
|
|
32
33
|
|
|
@@ -81,6 +82,7 @@ Full governance (compatibility tiers, migration, CLI `--spec-version`) is discus
|
|
|
81
82
|
| [Evolution](evolution.md) | Deprecation lifecycle, migration windows, change classification. |
|
|
82
83
|
| [Dataset layout](dataset-layout.md) | Normative dataset directory structure, discovery algorithm, optional root descriptor, and SPEC-044 structural pre-check. |
|
|
83
84
|
| [Guideline format](guideline-format.md) | Standalone guideline document shape: metadata fields, `category` enum, `related` cross-references, and required `documentBlocks` body (SPEC-045/046). |
|
|
85
|
+
| [Authoring workflow](authoring-workflow.md) | Normative authoring contract: authoritative source location, lifecycle operations, taxonomy-aware decomposition, and output-generation obligations. |
|
|
84
86
|
|
|
85
87
|
## JSON Schema `$id` and versioning
|
|
86
88
|
|
package/spec/taxonomy.md
CHANGED
|
@@ -145,6 +145,27 @@ Motion tokens describe timing, easing, and animation role for UI animation. Thei
|
|
|
145
145
|
|
|
146
146
|
Example: `motionRole=enter` + `easing=ease-out` → `enter-ease-out`. `motionRole=transition` + `scaleIndex=100` → `transition-100`.
|
|
147
147
|
|
|
148
|
+
### SPEC-043 severity schedule {#spec-043-severity-schedule}
|
|
149
|
+
|
|
150
|
+
Domain-specific tokens (color, typography, motion) that are missing required domain-identifying
|
|
151
|
+
fields trigger SPEC-043 (`domain-required-fields`) at **`warning`** severity (see the individual
|
|
152
|
+
domain sections above). Authors **SHOULD** treat SPEC-043 warnings as actionable decomposition
|
|
153
|
+
debt — tracking which tokens are missing structured field annotations and working toward
|
|
154
|
+
eliminating the gap incrementally.
|
|
155
|
+
|
|
156
|
+
**NORMATIVE:** SPEC-043 **MUST** graduate from `warning` to `error` at spec version `2.0.0`,
|
|
157
|
+
no earlier than two minor versions after Phase B (catalog-aware authoring — see [Authoring
|
|
158
|
+
workflow — Taxonomy-aware authoring](authoring-workflow.md#taxonomy-aware-authoring)) ships.
|
|
159
|
+
This conforms to the [evolution policy](evolution.md) — rule severity tightening is a major
|
|
160
|
+
change. Tightening is conditional on Phase B shipping because authors need catalog-aware
|
|
161
|
+
tooling before they can systematically resolve SPEC-043 warnings without hand-editing
|
|
162
|
+
cascade JSON.
|
|
163
|
+
|
|
164
|
+
Until Phase B ships and the foundation corpus reaches ≥ 90% SPEC-043 compliance per domain,
|
|
165
|
+
SPEC-043 stays advisory. No SPEC-043 warning blocks a conforming dataset today. Adoption
|
|
166
|
+
progress is tracked in RFC [#806](https://github.com/adobe/spectrum-design-data/discussions/806)
|
|
167
|
+
and RFC [#625](https://github.com/adobe/spectrum-design-data/discussions/625).
|
|
168
|
+
|
|
148
169
|
### Alias / semantic token name objects
|
|
149
170
|
|
|
150
171
|
Alias tokens (`$schema: …/alias.json`) MAY carry name objects using the same field vocabulary
|
package/spec/token-format.md
CHANGED
|
@@ -71,6 +71,25 @@ The table below lists all semantic fields. Fields marked with a scope are domain
|
|
|
71
71
|
| `density` | OPTIONAL | Density | Space within or around component parts (e.g. `spacious`, `compact`). |
|
|
72
72
|
| `shape` | OPTIONAL | Shape | Relative to overall component shape (e.g. `uniform`). |
|
|
73
73
|
| `scaleIndex` | OPTIONAL | — | Numeric scale index appended at the end of the serialized name (e.g. `100`, `200`, `900`). Used by color palette, spacing, font-size, and motion duration tokens. |
|
|
74
|
+
| `from` | OPTIONAL | — | Starting endpoint of a `space-between` measurement (e.g. `top`, `edge`, `text`). See [Space-between endpoints](#space-between-endpoints). |
|
|
75
|
+
| `to` | OPTIONAL | — | Ending endpoint of a `space-between` measurement (e.g. `text`, `visual`, `control`). See [Space-between endpoints](#space-between-endpoints). |
|
|
76
|
+
|
|
77
|
+
#### Space-between endpoints
|
|
78
|
+
|
|
79
|
+
A token whose `property` is **`space-between`** represents the spacing between two named endpoints (e.g. an edge and an anatomy part, or two anatomy parts) and **MUST** carry both the `from` and `to` fields; conversely, `from`/`to` **MUST NOT** appear unless `property` is `space-between` (rule `SPEC-047`).
|
|
80
|
+
|
|
81
|
+
Each of `from`/`to` **MUST** be one of:
|
|
82
|
+
|
|
83
|
+
* an edge position from `registry/positions.json` (e.g. `top`, `bottom`, `start`, `end`, `affixed`);
|
|
84
|
+
* a generic anatomy term from `registry/anatomy-terms.json` (e.g. `text`, `icon`, `label`);
|
|
85
|
+
* when `component` is present and declares an `anatomy` array, the `name` of a declared anatomy part on that component (e.g. `handle` on `accordion`).
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{ "name": { "component": "accordion", "property": "space-between", "from": "bottom", "to": "handle" },
|
|
89
|
+
"value": "8px" }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The `space-between` property term does not itself appear in the serialized legacy key; the key is reconstructed from the endpoints as `{component}-{from}-to-{to}` (e.g. `accordion-bottom-to-handle`).
|
|
74
93
|
|
|
75
94
|
**Domain-scoped semantic fields** (only valid on the indicated token type):
|
|
76
95
|
|