@adobe/design-data-spec 0.6.0 → 0.8.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/package.json +1 -1
- package/rules/rules.yaml +24 -0
- package/schemas/anatomy-part.schema.json +6 -0
- package/schemas/component.schema.json +11 -0
- package/schemas/document-block.schema.json +43 -0
- package/schemas/product-context.schema.json +95 -0
- package/schemas/token.schema.json +20 -0
- package/spec/agent-surface.md +15 -11
- package/spec/cascade.md +5 -5
- package/spec/component-format.md +42 -10
- package/spec/document-blocks.md +182 -0
- package/spec/index.md +1 -0
- package/spec/manifest.md +4 -0
- package/spec/product-context.md +120 -0
- package/spec/token-format.md +10 -9
package/package.json
CHANGED
package/rules/rules.yaml
CHANGED
|
@@ -244,3 +244,27 @@ rules:
|
|
|
244
244
|
message: "Component '{component}' tokenBindings references unknown token '{token}'"
|
|
245
245
|
spec_ref: spec/component-format.md#token-bindings
|
|
246
246
|
introduced_in: "1.0.0-draft"
|
|
247
|
+
|
|
248
|
+
- id: SPEC-028
|
|
249
|
+
name: document-block-agents-equals-content
|
|
250
|
+
severity: warning
|
|
251
|
+
category: completeness
|
|
252
|
+
assert: >
|
|
253
|
+
A document block's agents field, when present, SHOULD contain phrasing that differs from
|
|
254
|
+
content. An identical copy provides no agent-specific value and SHOULD be omitted or refined.
|
|
255
|
+
Applies to tokens, components, and anatomy parts.
|
|
256
|
+
message: "'{entity}' has a document block whose agents text is identical to content — tailor it for agent consumption or omit the agents field"
|
|
257
|
+
spec_ref: spec/document-blocks.md
|
|
258
|
+
introduced_in: "1.0.0-draft"
|
|
259
|
+
|
|
260
|
+
- id: SPEC-029
|
|
261
|
+
name: document-block-missing-purpose
|
|
262
|
+
severity: warning
|
|
263
|
+
category: completeness
|
|
264
|
+
assert: >
|
|
265
|
+
An entity that carries a non-empty documentBlocks array SHOULD include at least one block
|
|
266
|
+
with type 'purpose' to document the entity's intent.
|
|
267
|
+
Applies to tokens, components, and anatomy parts.
|
|
268
|
+
message: "'{entity}' has documentBlocks but no purpose block — add a block with type 'purpose'"
|
|
269
|
+
spec_ref: spec/document-blocks.md
|
|
270
|
+
introduced_in: "1.0.0-draft"
|
|
@@ -29,6 +29,12 @@
|
|
|
29
29
|
},
|
|
30
30
|
"uniqueItems": true,
|
|
31
31
|
"description": "Informative list of child anatomy part names nested within this part. Does not carry enforcement semantics."
|
|
32
|
+
},
|
|
33
|
+
"documentBlocks": {
|
|
34
|
+
"type": "array",
|
|
35
|
+
"items": { "$ref": "document-block.schema.json" },
|
|
36
|
+
"minItems": 1,
|
|
37
|
+
"description": "Typed prose blocks for this anatomy part. See spec/document-blocks.md (Phase 9)."
|
|
32
38
|
}
|
|
33
39
|
},
|
|
34
40
|
"additionalProperties": false
|
|
@@ -68,6 +68,12 @@
|
|
|
68
68
|
"type": "array",
|
|
69
69
|
"items": { "$ref": "#/$defs/tokenBinding" },
|
|
70
70
|
"description": "Tokens this component uses, including foundation/structure tokens not scoped to the component in their name-object. See spec/component-format.md#token-bindings (Phase 6.7)."
|
|
71
|
+
},
|
|
72
|
+
"documentBlocks": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"items": { "$ref": "document-block.schema.json" },
|
|
75
|
+
"minItems": 1,
|
|
76
|
+
"description": "Typed prose blocks for this component. See spec/document-blocks.md (Phase 9)."
|
|
71
77
|
}
|
|
72
78
|
},
|
|
73
79
|
"additionalProperties": false,
|
|
@@ -203,6 +209,11 @@
|
|
|
203
209
|
"type": "array",
|
|
204
210
|
"items": { "type": "string" },
|
|
205
211
|
"description": "Informative: anatomy part names nested within this part."
|
|
212
|
+
},
|
|
213
|
+
"documentBlocks": {
|
|
214
|
+
"type": "array",
|
|
215
|
+
"items": { "$ref": "document-block.schema.json" },
|
|
216
|
+
"description": "Typed prose blocks for this anatomy part. See spec/document-blocks.md (Phase 9)."
|
|
206
217
|
}
|
|
207
218
|
},
|
|
208
219
|
"additionalProperties": false
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/document-block.schema.json",
|
|
4
|
+
"title": "Document block",
|
|
5
|
+
"description": "A typed prose block attachable to tokens, components, or anatomy parts. See spec/document-blocks.md.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["type", "content"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"type": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"enum": ["purpose", "guideline", "accessibility", "do-dont", "examples"],
|
|
12
|
+
"description": "Block type. One of: purpose, guideline, accessibility, do-dont, examples."
|
|
13
|
+
},
|
|
14
|
+
"content": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"minLength": 1,
|
|
17
|
+
"description": "Human-readable prose for this block."
|
|
18
|
+
},
|
|
19
|
+
"agents": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"minLength": 1,
|
|
22
|
+
"description": "Optional LLM-tuned rephrasing of content for agent consumption. Should differ from content."
|
|
23
|
+
},
|
|
24
|
+
"do": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"minLength": 1,
|
|
27
|
+
"description": "Recommended practice. Meaningful only on do-dont blocks."
|
|
28
|
+
},
|
|
29
|
+
"dont": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"minLength": 1,
|
|
32
|
+
"description": "Anti-pattern to avoid. Meaningful only on do-dont blocks."
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"if": {
|
|
37
|
+
"properties": { "type": { "const": "do-dont" } },
|
|
38
|
+
"required": ["type"]
|
|
39
|
+
},
|
|
40
|
+
"then": {
|
|
41
|
+
"anyOf": [{ "required": ["do"] }, { "required": ["dont"] }]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/product-context.schema.json",
|
|
4
|
+
"title": "Product context document",
|
|
5
|
+
"description": "Layer 3 — product-layer record of rationale, overrides, and extensions. See spec/product-context.md.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["specVersion", "layer"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"specVersion": {
|
|
10
|
+
"const": "1.0.0-draft"
|
|
11
|
+
},
|
|
12
|
+
"layer": {
|
|
13
|
+
"const": "product"
|
|
14
|
+
},
|
|
15
|
+
"rationale": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Why this product-layer working copy exists (e.g. feature name, project, team)."
|
|
18
|
+
},
|
|
19
|
+
"createdBy": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"description": "Tool or agent attribution.",
|
|
22
|
+
"properties": {
|
|
23
|
+
"type": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": ["agent", "human"]
|
|
26
|
+
},
|
|
27
|
+
"tool": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Tool name (e.g. 'design-data', 'figma-plugin', 'manual')."
|
|
30
|
+
},
|
|
31
|
+
"model": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Model identifier when type is 'agent'."
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"additionalProperties": false
|
|
37
|
+
},
|
|
38
|
+
"createdAt": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"format": "date-time",
|
|
41
|
+
"description": "ISO 8601 datetime when the document was first created."
|
|
42
|
+
},
|
|
43
|
+
"overrides": {
|
|
44
|
+
"type": "array",
|
|
45
|
+
"description": "Overrides of foundation or platform tokens.",
|
|
46
|
+
"items": {
|
|
47
|
+
"$ref": "#/$defs/override"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"extensions": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"description": "Net-new tokens and components added at this layer.",
|
|
53
|
+
"properties": {
|
|
54
|
+
"tokens": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"description": "New token objects. Each item MUST conform to token.schema.json.",
|
|
57
|
+
"items": {
|
|
58
|
+
"type": "object"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"components": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"description": "New component objects. Each item MUST conform to component.schema.json.",
|
|
64
|
+
"items": {
|
|
65
|
+
"type": "object"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"additionalProperties": false
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"additionalProperties": false,
|
|
73
|
+
"$defs": {
|
|
74
|
+
"override": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"required": ["uuid", "value"],
|
|
77
|
+
"description": "A product-layer value override of an existing token.",
|
|
78
|
+
"properties": {
|
|
79
|
+
"uuid": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"format": "uuid",
|
|
82
|
+
"description": "UUID of the token being overridden. MUST match a token in the merged cascade."
|
|
83
|
+
},
|
|
84
|
+
"value": {
|
|
85
|
+
"description": "The overriding value. MUST be type-compatible with the original token value type."
|
|
86
|
+
},
|
|
87
|
+
"rationale": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"description": "Why this specific value was chosen."
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"additionalProperties": false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -172,10 +172,20 @@
|
|
|
172
172
|
"type": "string",
|
|
173
173
|
"description": "Plain text describing the token's purpose (aligns with DTCG $description)."
|
|
174
174
|
},
|
|
175
|
+
"rationale": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"description": "Why this token has its current value. Intended for product-layer authoring context; see spec/product-context.md."
|
|
178
|
+
},
|
|
175
179
|
"componentBindings": {
|
|
176
180
|
"type": "array",
|
|
177
181
|
"items": { "$ref": "#/$defs/componentBinding" },
|
|
178
182
|
"description": "Reverse index: components that declare this token in their tokenBindings. Optional and derivable from component files."
|
|
183
|
+
},
|
|
184
|
+
"documentBlocks": {
|
|
185
|
+
"type": "array",
|
|
186
|
+
"items": { "$ref": "document-block.schema.json" },
|
|
187
|
+
"minItems": 1,
|
|
188
|
+
"description": "Typed prose blocks for this token. See spec/document-blocks.md (Phase 9)."
|
|
179
189
|
}
|
|
180
190
|
},
|
|
181
191
|
"additionalProperties": false
|
|
@@ -246,10 +256,20 @@
|
|
|
246
256
|
"type": "string",
|
|
247
257
|
"description": "Plain text describing the token's purpose (aligns with DTCG $description)."
|
|
248
258
|
},
|
|
259
|
+
"rationale": {
|
|
260
|
+
"type": "string",
|
|
261
|
+
"description": "Why this token has its current value. Intended for product-layer authoring context; see spec/product-context.md."
|
|
262
|
+
},
|
|
249
263
|
"componentBindings": {
|
|
250
264
|
"type": "array",
|
|
251
265
|
"items": { "$ref": "#/$defs/componentBinding" },
|
|
252
266
|
"description": "Reverse index: components that declare this token in their tokenBindings. Optional and derivable from component files."
|
|
267
|
+
},
|
|
268
|
+
"documentBlocks": {
|
|
269
|
+
"type": "array",
|
|
270
|
+
"items": { "$ref": "document-block.schema.json" },
|
|
271
|
+
"minItems": 1,
|
|
272
|
+
"description": "Typed prose blocks for this token. See spec/document-blocks.md (Phase 9)."
|
|
253
273
|
}
|
|
254
274
|
},
|
|
255
275
|
"additionalProperties": false
|
package/spec/agent-surface.md
CHANGED
|
@@ -25,17 +25,21 @@ The surface targets three consumer shapes:
|
|
|
25
25
|
|
|
26
26
|
**NORMATIVE:** A conforming implementation MUST expose the following operations. Transport-specific naming (CLI subcommand vs MCP tool name vs skill action) MAY differ; the semantics MUST NOT.
|
|
27
27
|
|
|
28
|
-
| Operation | Reads | Returns | Backed by
|
|
29
|
-
| -------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
-
| `resolve_token` | property + dimension context | winning token (literal or resolved alias) with file/UUID/specificity | `cascade::resolve`
|
|
31
|
-
| `query_tokens` | filter expression (see [Query](query.md)) | matching token list | `query::filter`
|
|
32
|
-
| `validate_usage` | candidate token document or fragment | `ValidationReport` (Layer 1 + Layer 2 diagnostics) | `validate::validate_*`
|
|
33
|
-
| `describe_component` | component identifier | component contract (anatomy, options, states, tokenBindings); see [#832](https://github.com/adobe/spectrum-design-data/discussions/832) and [Phase 6.7](#describe_component-return-shape) | (Phase 6 contract)
|
|
34
|
-
| `suggest_token` | natural-language intent + optional property hint | ranked candidate tokens with rationale (RECOMMENDED, not NORMATIVE in v1) | registry + query
|
|
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
|
-
| `diff_datasets` | two dataset roots | `DiffReport` per [Diff](diff.md) | `diff::semantic_diff`
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
| Operation | Reads | Returns | Backed by |
|
|
29
|
+
| -------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
30
|
+
| `resolve_token` | property + dimension context | winning token (literal or resolved alias) with file/UUID/specificity | `cascade::resolve` |
|
|
31
|
+
| `query_tokens` | filter expression (see [Query](query.md)) | matching token list | `query::filter` |
|
|
32
|
+
| `validate_usage` | candidate token document or fragment | `ValidationReport` (Layer 1 + Layer 2 diagnostics) | `validate::validate_*` |
|
|
33
|
+
| `describe_component` | component identifier | component contract (anatomy, options, states, tokenBindings); see [#832](https://github.com/adobe/spectrum-design-data/discussions/832) and [Phase 6.7](#describe_component-return-shape) | (Phase 6 contract) |
|
|
34
|
+
| `suggest_token` | natural-language intent + optional property hint | ranked candidate tokens with rationale (RECOMMENDED, not NORMATIVE in v1) | registry + query |
|
|
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
|
+
| `diff_datasets` | two dataset roots | `DiffReport` per [Diff](diff.md) | `diff::semantic_diff` |
|
|
37
|
+
| `write_token` | token object + optional rationale string | updated product-layer token file + `product-context.json` (RECOMMENDED, not NORMATIVE in v1) | `write::write_token` (Phase 8.x, not yet implemented) |
|
|
38
|
+
| `write_component` | component object + optional rationale string | updated product-layer component file + `product-context.json` (RECOMMENDED, not NORMATIVE in v1) | `write::write_component` (Phase 8.x, not yet implemented) |
|
|
39
|
+
|
|
40
|
+
**NORMATIVE:** `validate_usage`, `resolve_token`, `query_tokens`, and `diff_datasets` MUST be implemented in a conforming agent surface. `suggest_token`, `get_guidance`, `write_token`, and `write_component` are RECOMMENDED. `describe_component` becomes NORMATIVE once [#832](https://github.com/adobe/spectrum-design-data/discussions/832) reaches implemented status.
|
|
41
|
+
|
|
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).
|
|
39
43
|
|
|
40
44
|
## Session primer
|
|
41
45
|
|
package/spec/cascade.md
CHANGED
|
@@ -8,11 +8,11 @@ This document defines the **cascade model**: three **layers**, **semantic specif
|
|
|
8
8
|
|
|
9
9
|
Design data is organized in three layers, ordered from lowest to highest precedence when values conflict:
|
|
10
10
|
|
|
11
|
-
| Layer | Name | Description
|
|
12
|
-
| ----- | -------------- |
|
|
13
|
-
| 1 | **Foundation** | Canonical design system data (e.g. Spectrum foundation).
|
|
14
|
-
| 2 | **Platform** | Platform-specific adjustments; **MUST** remain type-compatible with foundation.
|
|
15
|
-
| 3 | **Product** | Product-specific overrides; **MUST** remain type-compatible with the resolved lower layers. |
|
|
11
|
+
| Layer | Name | Description |
|
|
12
|
+
| ----- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| 1 | **Foundation** | Canonical design system data (e.g. Spectrum foundation). |
|
|
14
|
+
| 2 | **Platform** | Platform-specific adjustments; **MUST** remain type-compatible with foundation. |
|
|
15
|
+
| 3 | **Product** | Product-specific overrides; **MUST** remain type-compatible with the resolved lower layers. A product-layer working copy **SHOULD** include a `product-context.json` document recording its rationale and overrides. See [Product context](product-context.md). |
|
|
16
16
|
|
|
17
17
|
**NORMATIVE:** When two candidates match the same context, the candidate from the **higher** layer (larger number above) **MUST** win.
|
|
18
18
|
|
package/spec/component-format.md
CHANGED
|
@@ -29,16 +29,17 @@ A component declaration **MUST** contain:
|
|
|
29
29
|
|
|
30
30
|
### Optional fields
|
|
31
31
|
|
|
32
|
-
| Field
|
|
33
|
-
|
|
|
34
|
-
| `specVersion`
|
|
35
|
-
| `description`
|
|
36
|
-
| `options`
|
|
37
|
-
| `slots`
|
|
38
|
-
| `anatomy`
|
|
39
|
-
| `states`
|
|
40
|
-
| `lifecycle`
|
|
41
|
-
| `tokenBindings`
|
|
32
|
+
| Field | Type | Description |
|
|
33
|
+
| ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
34
|
+
| `specVersion` | string | Declares which spec version this document targets. Currently `"1.0.0-draft"`; future stable releases will accept their own version string. |
|
|
35
|
+
| `description` | string | Plain-text description of the component's purpose. |
|
|
36
|
+
| `options` | object | Component API options — see [Options](#options). |
|
|
37
|
+
| `slots` | array | Named content injection points — see [Slots](#slots). |
|
|
38
|
+
| `anatomy` | array | Named anatomy parts — see [Anatomy (stub)](#anatomy-stub). |
|
|
39
|
+
| `states` | array | Per-component state declarations — see [States (stub)](#states-stub). |
|
|
40
|
+
| `lifecycle` | object | Version lifecycle metadata — see [Lifecycle](#lifecycle). |
|
|
41
|
+
| `tokenBindings` | array | Tokens this component uses — see [Token bindings](#token-bindings) (Phase 6.7). |
|
|
42
|
+
| `documentBlocks` | array | Typed prose blocks for this component — see [Document blocks](#document-blocks) (Phase 9). |
|
|
42
43
|
|
|
43
44
|
**NORMATIVE:** No properties beyond those listed above are permitted at the top level of a component declaration. Additional fields **MUST** cause a Layer 1 schema error.
|
|
44
45
|
|
|
@@ -349,3 +350,34 @@ A complete button component declaration:
|
|
|
349
350
|
}
|
|
350
351
|
}
|
|
351
352
|
```
|
|
353
|
+
|
|
354
|
+
## Document blocks
|
|
355
|
+
|
|
356
|
+
**Phase 9.** Component declarations MAY carry a `documentBlocks` array at the top level, and individual anatomy parts MAY carry their own `documentBlocks` arrays. See [spec/document-blocks.md](document-blocks.md) for the full block schema, type vocabulary, and SPEC rules.
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"name": "button",
|
|
361
|
+
"displayName": "Button",
|
|
362
|
+
"meta": { "category": "actions", "documentationUrl": "https://spectrum.adobe.com/page/button/" },
|
|
363
|
+
"documentBlocks": [
|
|
364
|
+
{
|
|
365
|
+
"type": "purpose",
|
|
366
|
+
"content": "Buttons trigger a discrete action or event.",
|
|
367
|
+
"agents": "Use Button when the user must trigger an action. For navigation, use Link."
|
|
368
|
+
}
|
|
369
|
+
],
|
|
370
|
+
"anatomy": [
|
|
371
|
+
{
|
|
372
|
+
"name": "label",
|
|
373
|
+
"required": true,
|
|
374
|
+
"documentBlocks": [
|
|
375
|
+
{
|
|
376
|
+
"type": "guideline",
|
|
377
|
+
"content": "Button labels should be action verbs (Save, Delete, Submit)."
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
}
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
```
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Document blocks
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines **document blocks**: typed prose objects attachable to tokens, components, and anatomy parts. Blocks carry design guidance — intent, usage rules, accessibility notes, do/don't pairs, and examples — alongside the structured data they describe, making that guidance machine-readable and queryable by agents.
|
|
6
|
+
|
|
7
|
+
Design guidance like "accent backgrounds are for primary CTAs only" or "don't combine `negative` with `subtle`" previously lived in scattered Markdown documents invisible to the spec's resolver, validator, and agent surface. Document blocks attach that prose directly to the entities it describes so it cascades with the tokens and components it governs.
|
|
8
|
+
|
|
9
|
+
Inspired by the [Design System Documentation Spec (DSDS)](https://designsystemdocspec.org/) document-block model.
|
|
10
|
+
|
|
11
|
+
Scoped under RFC-D / Phase 9. See [rfc-coordination.md](../docs/rfc-coordination.md).
|
|
12
|
+
|
|
13
|
+
## Document block shape
|
|
14
|
+
|
|
15
|
+
A document block is a JSON object conforming to [`document-block.schema.json`](../schemas/document-block.schema.json).
|
|
16
|
+
|
|
17
|
+
### Required fields
|
|
18
|
+
|
|
19
|
+
| Field | Type | Description |
|
|
20
|
+
| --------- | ------ | ---------------------------------------- |
|
|
21
|
+
| `type` | string | Block type — one of the five types below |
|
|
22
|
+
| `content` | string | Human-readable prose for this block |
|
|
23
|
+
|
|
24
|
+
### Optional fields
|
|
25
|
+
|
|
26
|
+
| Field | Type | Description |
|
|
27
|
+
| -------- | ------ | ----------------------------------------------------------- |
|
|
28
|
+
| `agents` | string | LLM-tuned rephrasing of `content` for agent consumption |
|
|
29
|
+
| `do` | string | Recommended practice — meaningful only on `do-dont` blocks |
|
|
30
|
+
| `dont` | string | Anti-pattern to avoid — meaningful only on `do-dont` blocks |
|
|
31
|
+
|
|
32
|
+
**NORMATIVE:** `type` and `content` are required on every document block. A block with an empty string for either field **MUST** fail Layer 1 schema validation.
|
|
33
|
+
|
|
34
|
+
**NORMATIVE:** `do` and `dont` are defined on all block shapes (Layer 1 does not restrict them by type), but implementations SHOULD treat them as meaningful only on `do-dont` blocks. Using them on other block types is valid but has no defined semantics.
|
|
35
|
+
|
|
36
|
+
**RECOMMENDED:** When `agents` is present, its content SHOULD differ meaningfully from `content`. An `agents` value identical to `content` provides no agent-specific value and SHOULD be omitted or refined (see SPEC-028).
|
|
37
|
+
|
|
38
|
+
## Block types
|
|
39
|
+
|
|
40
|
+
### `purpose`
|
|
41
|
+
|
|
42
|
+
Describes the intent and design role of the entity. Answers "what is this for?"
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"type": "purpose",
|
|
47
|
+
"content": "Accent background tokens represent the primary brand call-to-action surface. They establish hierarchy by drawing attention to the most important interactive element on screen.",
|
|
48
|
+
"agents": "Use accent-background tokens on the highest-priority interactive element. They signal 'primary action here' to users."
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### `guideline`
|
|
53
|
+
|
|
54
|
+
A usage rule or constraint. Answers "how should this be used?"
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"type": "guideline",
|
|
59
|
+
"content": "Accent backgrounds should appear on no more than one element per focal area. Multiple accent surfaces compete for attention and dilute the hierarchy signal."
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### `accessibility`
|
|
64
|
+
|
|
65
|
+
Accessibility notes specific to this entity — contrast behavior, screen reader considerations, or interaction semantics.
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"type": "accessibility",
|
|
70
|
+
"content": "Accent background tokens must maintain a minimum 3:1 contrast ratio against the surface they sit on in both light and dark schemes. The high-contrast dimension variant provides an alternative that meets 4.5:1."
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `do-dont`
|
|
75
|
+
|
|
76
|
+
A paired recommended practice and anti-pattern. The `do` and `dont` fields carry the pairing; `content` provides context or a summary heading.
|
|
77
|
+
|
|
78
|
+
**NORMATIVE:** A `do-dont` block **MUST** include at least one of `do` or `dont`. A `do-dont` block with neither field **MUST** fail Layer 1 schema validation.
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"type": "do-dont",
|
|
83
|
+
"content": "Combining semantic backgrounds",
|
|
84
|
+
"do": "Use accent-background for the primary CTA and informative-background for supporting UI.",
|
|
85
|
+
"dont": "Combine accent-background with negative-background in the same focal area — both are high-attention surfaces and the pairing creates visual conflict."
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### `examples`
|
|
90
|
+
|
|
91
|
+
Concrete usage examples — code snippets, component references, or scenario descriptions.
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"type": "examples",
|
|
96
|
+
"content": "A primary Button uses accent-background-color-default. A disabled Button uses gray-background-color-default. A destructive Button uses negative-background-color-default."
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Attachment points
|
|
101
|
+
|
|
102
|
+
**NORMATIVE:** Document blocks MAY be attached to the following entities. When `documentBlocks` is present, it **MUST** contain at least one block — an empty array **MUST** fail Layer 1 schema validation.
|
|
103
|
+
|
|
104
|
+
### Tokens
|
|
105
|
+
|
|
106
|
+
Add a `documentBlocks` array at the top level of a token object:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"name": { "property": "background-color", "variant": "accent" },
|
|
111
|
+
"value": "#0265DC",
|
|
112
|
+
"documentBlocks": [
|
|
113
|
+
{
|
|
114
|
+
"type": "purpose",
|
|
115
|
+
"content": "Primary call-to-action background. Use for the most important interactive element in a focal area."
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"type": "guideline",
|
|
119
|
+
"content": "Limit to one accent background per focal area to preserve hierarchy."
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Components
|
|
126
|
+
|
|
127
|
+
Add a `documentBlocks` array at the top level of a component declaration:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"name": "button",
|
|
132
|
+
"displayName": "Button",
|
|
133
|
+
"meta": { "category": "actions", "documentationUrl": "https://spectrum.adobe.com/page/button/" },
|
|
134
|
+
"documentBlocks": [
|
|
135
|
+
{
|
|
136
|
+
"type": "purpose",
|
|
137
|
+
"content": "Buttons trigger an action or event, such as submitting a form, opening a dialog, or performing a destructive operation.",
|
|
138
|
+
"agents": "Use Button when the user needs to trigger a discrete action. For navigation, use a Link instead."
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Anatomy parts
|
|
145
|
+
|
|
146
|
+
Add a `documentBlocks` array within an anatomy part object:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"name": "label",
|
|
151
|
+
"required": true,
|
|
152
|
+
"description": "Button text visible to the user.",
|
|
153
|
+
"documentBlocks": [
|
|
154
|
+
{
|
|
155
|
+
"type": "guideline",
|
|
156
|
+
"content": "Button labels should be action verbs (Save, Delete, Submit). Avoid noun-only labels like 'Confirmation'."
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## SPEC rules
|
|
163
|
+
|
|
164
|
+
| Rule ID | Severity | Name | Assert |
|
|
165
|
+
| -------- | -------- | ------------------------------------ | ------------------------------------------------------------------------ |
|
|
166
|
+
| SPEC-028 | warning | document-block-agents-equals-content | A block's `agents` field SHOULD differ from `content` |
|
|
167
|
+
| SPEC-029 | warning | document-block-missing-purpose | An entity with `documentBlocks` SHOULD have at least one `purpose` block |
|
|
168
|
+
|
|
169
|
+
Both rules are `warning` severity — they do not block validation.
|
|
170
|
+
|
|
171
|
+
## `agents` field guidance
|
|
172
|
+
|
|
173
|
+
The `agents` field exists to let documentation authors provide LLM-optimized phrasing alongside human prose. Human content may use visual formatting cues, assumed visual context, or prose conventions that agents process poorly. The `agents` field carries alternative phrasing tuned for programmatic consumption.
|
|
174
|
+
|
|
175
|
+
**RECOMMENDED:** `agents` text SHOULD:
|
|
176
|
+
|
|
177
|
+
* Omit references to visual appearance that agents cannot act on ("the blue button")
|
|
178
|
+
* Use explicit, unambiguous phrasing ("Use Button when triggering an action, not Link")
|
|
179
|
+
* Include the token or component name explicitly rather than relying on surrounding context
|
|
180
|
+
* Be shorter and more directive than `content` where possible
|
|
181
|
+
|
|
182
|
+
When no agent-specific rephrasing is needed, omit the `agents` field entirely. A duplicate of `content` adds size with no benefit.
|
package/spec/index.md
CHANGED
|
@@ -63,6 +63,7 @@ Full governance (compatibility tiers, migration, CLI `--spec-version`) is discus
|
|
|
63
63
|
| [Cascade](cascade.md) | Layers, specificity, resolution algorithm. |
|
|
64
64
|
| [Dimensions](dimensions.md) | Dimension declarations, built-in dimensions, coverage. |
|
|
65
65
|
| [Manifest](manifest.md) | Platform manifest fields and validation expectations. |
|
|
66
|
+
| [Product context](product-context.md) | Product-layer context document: rationale, overrides, and extensions. |
|
|
66
67
|
| [Diff](diff.md) | Semantic diff change taxonomy, token identity, property changes. |
|
|
67
68
|
| [Query](query.md) | Filter notation for selecting tokens by structured fields. |
|
|
68
69
|
| [Evolution](evolution.md) | Deprecation lifecycle, migration windows, change classification. |
|
package/spec/manifest.md
CHANGED
|
@@ -65,6 +65,10 @@ A platform **MAY** declare formatting rules that control how structured name obj
|
|
|
65
65
|
|
|
66
66
|
**OPTIONAL:** Workflows **MAY** open upgrade PRs when `foundationVersion` lags the latest release; details are out of scope for this document (see [#715](https://github.com/adobe/spectrum-design-data/discussions/715)).
|
|
67
67
|
|
|
68
|
+
## Relationship to product context
|
|
69
|
+
|
|
70
|
+
The platform manifest is the Layer 2 context document. For Layer 3 (product-layer) context — rationale, overrides, and extensions specific to a product team's working copy — see [Product context](product-context.md).
|
|
71
|
+
|
|
68
72
|
## References
|
|
69
73
|
|
|
70
74
|
* [#715 — Distributed Design Data Architecture](https://github.com/adobe/spectrum-design-data/discussions/715)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Product context
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This document defines the **product context document**: a machine-readable record that a product-layer working copy keeps alongside its token and component files. It preserves the rationale behind the working copy's existence and records the intent of each override and extension it introduces.
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
The cascade model defines three layers (Foundation → Platform → Product; see [Cascade](cascade.md)). The Platform layer has a context document — the [manifest](manifest.md) — that declares its relationship to the foundation. The Product layer has no equivalent until this document.
|
|
10
|
+
|
|
11
|
+
When a designer or engineer overrides a token or adds a component at the product layer, the intent behind those changes is currently lost. The product context document preserves that context as a machine-readable, human-editable file that travels with the product-layer dataset and can be consumed by agent tools.
|
|
12
|
+
|
|
13
|
+
## Document
|
|
14
|
+
|
|
15
|
+
A product context document **MUST** conform to [`product-context.schema.json`](../schemas/product-context.schema.json) (canonical `$id`: `https://opensource.adobe.com/spectrum-design-data/schemas/v0/product-context.schema.json`).
|
|
16
|
+
|
|
17
|
+
**RECOMMENDED:** A product-layer working copy **SHOULD** include a `product-context.json` file whenever it contains overrides or extensions.
|
|
18
|
+
|
|
19
|
+
## Required fields
|
|
20
|
+
|
|
21
|
+
| Field | Type | Description |
|
|
22
|
+
| ------------- | ------ | ------------------------------------------------------------- |
|
|
23
|
+
| `specVersion` | string | **MUST** be `1.0.0-draft` for documents targeting this draft. |
|
|
24
|
+
| `layer` | string | **MUST** be `"product"`. |
|
|
25
|
+
|
|
26
|
+
## Optional fields
|
|
27
|
+
|
|
28
|
+
| Field | Type | Description |
|
|
29
|
+
| ------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `rationale` | string | Why this product-layer working copy exists (e.g. feature name, project, team). |
|
|
31
|
+
| `createdBy` | object | Tool or agent attribution (see [createdBy shape](#createdby-shape)). |
|
|
32
|
+
| `createdAt` | string | ISO 8601 datetime when the document was **first** created. Implementations SHOULD NOT overwrite this field on subsequent updates. |
|
|
33
|
+
| `overrides` | array | Overrides of foundation or platform tokens (see [overrides](#overrides)). |
|
|
34
|
+
| `extensions` | object | Net-new tokens and components added at this layer (see [extensions](#extensions)). |
|
|
35
|
+
|
|
36
|
+
### `createdBy` shape
|
|
37
|
+
|
|
38
|
+
| Field | Type | Description |
|
|
39
|
+
| ------- | ------ | ----------------------------------------------------------------------- |
|
|
40
|
+
| `type` | string | `"agent"` or `"human"`. |
|
|
41
|
+
| `tool` | string | Tool name (e.g. `"design-data"`, `"figma-plugin"`, `"manual"`). |
|
|
42
|
+
| `model` | string | Model identifier when `type` is `"agent"` (e.g. `"claude-sonnet-4-6"`). |
|
|
43
|
+
|
|
44
|
+
### `overrides`
|
|
45
|
+
|
|
46
|
+
Each entry in `overrides` is an object that records a product-layer value override of an existing token:
|
|
47
|
+
|
|
48
|
+
| Field | Required | Type | Description |
|
|
49
|
+
| ----------- | -------- | ------ | ------------------------------------------------------------------------------------- |
|
|
50
|
+
| `uuid` | yes | string | UUID of the token being overridden. **MUST** match a token in the merged cascade. |
|
|
51
|
+
| `value` | yes | any | The overriding value. **MUST** be type-compatible with the original token value type. |
|
|
52
|
+
| `rationale` | no | string | Why this specific value was chosen. |
|
|
53
|
+
|
|
54
|
+
### `extensions`
|
|
55
|
+
|
|
56
|
+
The `extensions` object contains net-new tokens and components that do not exist in the foundation or platform layers:
|
|
57
|
+
|
|
58
|
+
| Field | Type | Description |
|
|
59
|
+
| ------------ | ----- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `tokens` | array | Token objects conforming to [`token.schema.json`](../schemas/token.schema.json). Each token **MAY** include a `rationale` field. |
|
|
61
|
+
| `components` | array | Component objects conforming to [`component.schema.json`](../schemas/component.schema.json). |
|
|
62
|
+
|
|
63
|
+
## Example
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"specVersion": "1.0.0-draft",
|
|
68
|
+
"layer": "product",
|
|
69
|
+
"rationale": "Checkout flow redesign — Q3 2026.",
|
|
70
|
+
"createdBy": {
|
|
71
|
+
"type": "agent",
|
|
72
|
+
"tool": "design-data",
|
|
73
|
+
"model": "claude-sonnet-4-6"
|
|
74
|
+
},
|
|
75
|
+
"createdAt": "2026-05-13T14:30:00Z",
|
|
76
|
+
"overrides": [
|
|
77
|
+
{
|
|
78
|
+
"uuid": "aaaaaaaa-0001-4000-8000-000000000001",
|
|
79
|
+
"value": "#f8f8f8",
|
|
80
|
+
"rationale": "Off-white card background to distinguish from pure-white page without elevation shadow."
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"extensions": {
|
|
84
|
+
"tokens": [
|
|
85
|
+
{
|
|
86
|
+
"name": { "component": "checkout-summary", "property": "background-color" },
|
|
87
|
+
"value": "#f0f0f0",
|
|
88
|
+
"rationale": "Nested surface; lighter to create hierarchy without adding a border.",
|
|
89
|
+
"uuid": "bbbbbbbb-0002-4000-8000-000000000002"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Agent capture behavior
|
|
97
|
+
|
|
98
|
+
**RECOMMENDED:** Agent tools that create or modify product-layer tokens (`write_token`, `write_component`) **SHOULD** capture a `rationale` from session context and record it in:
|
|
99
|
+
|
|
100
|
+
1. The token's inline `rationale` field (see [Token format — rationale](token-format.md#lifecycle-and-metadata)).
|
|
101
|
+
2. The product context document's `overrides[].rationale` (for overrides) or `extensions.tokens[].rationale` (for new tokens).
|
|
102
|
+
|
|
103
|
+
This makes the product context document self-maintaining during agent-assisted authoring sessions.
|
|
104
|
+
|
|
105
|
+
## Relationship to platform manifest
|
|
106
|
+
|
|
107
|
+
The platform manifest (Layer 2) declares which foundation tokens a platform includes, excludes, or overrides at a structural level. The product context document (Layer 3) records the *intent* behind a product team's specific value choices. The two documents are complementary and independent.
|
|
108
|
+
|
|
109
|
+
| Document | Layer | Primary audience | Records |
|
|
110
|
+
| ---------------------- | ----- | ----------------------------------- | -------------------------------------- |
|
|
111
|
+
| `manifest.json` | 2 | Platform engineers | Version pins, filters, typed overrides |
|
|
112
|
+
| `product-context.json` | 3 | Product designers/engineers, agents | Rationale for overrides and extensions |
|
|
113
|
+
|
|
114
|
+
## References
|
|
115
|
+
|
|
116
|
+
* [Cascade — Layers](cascade.md#layers)
|
|
117
|
+
* [Platform manifest](manifest.md)
|
|
118
|
+
* [Token format — rationale field](token-format.md#lifecycle-and-metadata)
|
|
119
|
+
* [Agent-readable surface — write operations](agent-surface.md#tool-catalog)
|
|
120
|
+
* [#847 — Phase 8.x: Product context document](https://github.com/adobe/spectrum-design-data/issues/847)
|
package/spec/token-format.md
CHANGED
|
@@ -92,15 +92,16 @@ When **`value`** is present, it **MUST** conform to the declared value type for
|
|
|
92
92
|
|
|
93
93
|
The following OPTIONAL fields implement the token lifecycle model described in [#623](https://github.com/adobe/spectrum-design-data/discussions/623) and the evolution policy in [Evolution](evolution.md). Inspired by Swift's `@available` attribute, Kotlin's `@Deprecated`, and OpenAPI 3.3's deprecation model.
|
|
94
94
|
|
|
95
|
-
| Field | Type | Description
|
|
96
|
-
| -------------------- | --------------------------------------- |
|
|
97
|
-
| `uuid` | string (UUID) | Stable unique id for rename tracking and diffs.
|
|
98
|
-
| `introduced` | string (version) | Spec version when the token was first added (e.g. `"1.0.0"`).
|
|
99
|
-
| `deprecated` | string (version) | Spec version when the token was deprecated (e.g. `"3.2.0"`). Truthy = deprecated.
|
|
100
|
-
| `deprecated_comment` | string | Human-readable deprecation explanation and migration guidance.
|
|
101
|
-
| `replaced_by` | string (UUID) or array of string (UUID) | UUID(s) of the replacement token(s). Single string for 1:1 replacement; array for one-to-many splits.
|
|
102
|
-
| `plannedRemoval` | string (version) | Spec version when the token will be removed. If omitted, defaults to the next major version after `deprecated`.
|
|
103
|
-
| `private` | boolean | Not part of public API surface.
|
|
95
|
+
| Field | Type | Description |
|
|
96
|
+
| -------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
97
|
+
| `uuid` | string (UUID) | Stable unique id for rename tracking and diffs. |
|
|
98
|
+
| `introduced` | string (version) | Spec version when the token was first added (e.g. `"1.0.0"`). |
|
|
99
|
+
| `deprecated` | string (version) | Spec version when the token was deprecated (e.g. `"3.2.0"`). Truthy = deprecated. |
|
|
100
|
+
| `deprecated_comment` | string | Human-readable deprecation explanation and migration guidance. |
|
|
101
|
+
| `replaced_by` | string (UUID) or array of string (UUID) | UUID(s) of the replacement token(s). Single string for 1:1 replacement; array for one-to-many splits. |
|
|
102
|
+
| `plannedRemoval` | string (version) | Spec version when the token will be removed. If omitted, defaults to the next major version after `deprecated`. |
|
|
103
|
+
| `private` | boolean | Not part of public API surface. |
|
|
104
|
+
| `rationale` | string | Why this token has its current value. Intended for product-layer authoring context; see [Product context](product-context.md). |
|
|
104
105
|
|
|
105
106
|
#### Lifecycle example
|
|
106
107
|
|