# Decisions on specification ambiguities

Where the 2025.10 specifications are silent, contradictory, or phrased as prose rather than requirements, this toolkit makes the following choices. Each is tied to the issue code it affects so behaviour can be traced and, if the specification is clarified, revisited.

| Topic                                      | Decision                                                                                                                                                                                                                               | Codes                                                       |
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| Unknown properties in value objects        | The spec does not say whether extra keys are allowed in a color, dimension, or composite value. They are reported as a warning, not an error.                                                                                          | `value.unknown-property`                                    |
| Unknown `$`-properties                     | Unknown `$`-prefixed properties on tokens and groups are warnings, for forward compatibility with future spec versions. Names starting with `$` are never treated as token or group names.                                             | `token.property.unknown`, `group.property.unknown`          |
| Non-`$` properties on a token              | §6.1 says an object cannot be both a token and a group. Any non-`$` key on an object with `$value` is an error.                                                                                                                        | `token.property.not-allowed`                                |
| `$ref` on a group                          | §6.4.1 presents `$ref: "#/group"` as the JSON Schema spelling of `$extends`. A group carrying `$ref` is treated exactly like `$extends`.                                                                                               | `extends.*`                                                 |
| Reference nodes                            | An object with `$ref` and no `$value` and no child members (§7.1.2, Example 32) is a token whose value is the referenced fragment.                                                                                                     | `ref.*`                                                     |
| `$extends` merge                           | Deep merge: nested groups at the same path merge, tokens at the same path are replaced wholesale, and local `$type` wins. The extending group's effective `$type` falls back to the base group's.                                      | `extends.inherited-token.invalid`                           |
| Inherited tokens under a different type    | §6.7.3 says local and inherited constraints must both hold. A token inherited into a group whose effective type differs from the token's origin type is reported at the extending group. Only top-level inherited members are checked. | `extends.inherited-token.invalid`                           |
| Alias resolution and `$extends`            | Curly aliases resolve through the merged view, so inherited tokens are reachable. `$ref` pointers resolve over the raw document only, as RFC 6901 requires.                                                                            | `alias.target.missing`, `ref.target.missing`                |
| Type of an untyped alias                   | Per §5.2.2 the alias takes the resolved type of its target. If the target has no type either, both are reported.                                                                                                                       | `token.type.missing`                                        |
| Cycles                                     | Alias cycles and `$extends` cycles are each detected once over their graph; every member of a cycle is reported, and a token aliasing into a cycle is also reported.                                                                   | `alias.cycle`, `ref.cycle`, `extends.cycle`                 |
| Hex versus components                      | The Color Module requires `hex` to be a 6-digit fallback but does not say it must agree with the components. For `srgb` with all-numeric components, disagreement beyond one 8-bit step is a warning. Other spaces are not compared.   | `color.hex.mismatch`                                        |
| Unbounded color axes                       | Lab and OKLab a/b and LCH and OKLCH chroma are "theoretically unbounded"; only finiteness is checked. Hue is `[0, 360)`.                                                                                                               | `color.component.out-of-range`                              |
| Cubic Bézier x range and typography fields | Phrased as prose rather than MUST, but treated as errors because the value is otherwise meaningless.                                                                                                                                   | `cubic-bezier.x.out-of-range`, `composite.property.missing` |
| Gradient stop positions                    | The spec says values outside `[0, 1]` must be treated as clamped, so they are a warning, not an error.                                                                                                                                 | `gradient.position.out-of-range`                            |
| Empty names                                | An empty string is a valid JSON string and the spec does not forbid it, but no alias can target it. Warning.                                                                                                                           | `name.empty`                                                |
| Case-only name collisions                  | The spec says tools MAY warn. They are warned, once per colliding set, at the parent group.                                                                                                                                            | `group.name.case-collision`                                 |
| `$schema`                                  | Tolerated at the document root only.                                                                                                                                                                                                   | `group.property.unknown` elsewhere                          |
| Failed property-level references           | When a nested `$ref` inside a value does not resolve, the rest of that value is not validated, to avoid a cascade of secondary errors.                                                                                                 | `ref.*`                                                     |
| Depth limit                                | Documents nested deeper than 256 groups are rejected. No conforming file comes close; the limit exists so hostile input cannot overflow the stack.                                                                                     | `document.too-deep`                                         |
