@fuaran-ui/conformance 0.18.0 → 0.19.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/corpus/cards/card-bundle.json +1 -0
- package/corpus/cards/card-full.json +1 -0
- package/corpus/cards/card-minimal.json +1 -0
- package/corpus/cards/card-reject-bad-version.json +1 -0
- package/corpus/cards/card-reject-bundle-bad-version.json +1 -0
- package/corpus/cards/card-reject-bundle-duplicate.json +1 -0
- package/corpus/cards/card-reject-empty-enum.json +1 -0
- package/corpus/cards/card-reject-hash-not-object.json +1 -0
- package/corpus/cards/card-reject-missing-hash.json +1 -0
- package/corpus/cards/card-reject-missing-module.json +1 -0
- package/corpus/cards/card-reject-payload-no-language.json +1 -0
- package/corpus/cards/card-reject-required-not-bool.json +1 -0
- package/corpus/cards/card-reject-stray-key.json +1 -0
- package/corpus/cards/card-reject-unknown-prop-type.json +1 -0
- package/corpus/lenient/lenient-1126-clipboard-literal-envelope.expected.json +1 -0
- package/corpus/lenient/lenient-1126-clipboard-literal-envelope.json +1 -0
- package/corpus/manifest.json +847 -3
- package/corpus/nodes/box-break-before-1.json +1 -0
- package/corpus/nodes/box-keep-together-1.json +1 -0
- package/corpus/nodes/btn-copy-bound.json +1 -0
- package/corpus/nodes/button-print.json +1 -0
- package/corpus/nodes/embed-1.json +1 -0
- package/corpus/nodes/embed-aspect-1.json +1 -0
- package/corpus/nodes/embed-permissions-1.json +1 -0
- package/corpus/nodes/filters-rating-colour.json +1 -0
- package/corpus/nodes/filters-tokens.json +1 -0
- package/corpus/nodes/form-color.json +1 -0
- package/corpus/nodes/form-combobox-freetext.json +1 -0
- package/corpus/nodes/form-combobox-query.json +1 -0
- package/corpus/nodes/form-combobox-static.json +1 -0
- package/corpus/nodes/form-rating-halves.json +1 -0
- package/corpus/nodes/form-rating.json +1 -0
- package/corpus/nodes/form-tokens-freetext.json +1 -0
- package/corpus/nodes/form-tokens-query.json +1 -0
- package/corpus/nodes/form-tokens-suggested.json +1 -0
- package/corpus/nodes/grid-exportable-1.json +1 -0
- package/corpus/nodes/grid-keep-rows-together-1.json +1 -0
- package/corpus/nodes/grid-repeat-header-1.json +1 -0
- package/corpus/nodes/limit-tree-item-depth-at-max.json +1 -0
- package/corpus/nodes/media-audio-transcript-1.json +1 -0
- package/corpus/nodes/media-video-captions-1.json +1 -0
- package/corpus/nodes/media-video-tracks-2.json +1 -0
- package/corpus/nodes/multiselect-chip-list-param.json +1 -0
- package/corpus/nodes/popover-anchored-1.json +1 -0
- package/corpus/nodes/popover-open-1.json +1 -0
- package/corpus/nodes/shared-source-seeded-pair.json +1 -1
- package/corpus/nodes/style-direction-isolated-1.json +1 -0
- package/corpus/nodes/style-direction-ltr-1.json +1 -0
- package/corpus/nodes/switch-carousel-1.json +1 -0
- package/corpus/nodes/tooltip-button-1.json +1 -0
- package/corpus/nodes/tooltip-icon-button-1.json +1 -0
- package/corpus/nodes/tooltip-metric-1.json +1 -0
- package/corpus/nodes/transfer-board.json +1 -0
- package/corpus/nodes/tree-1.json +1 -0
- package/corpus/nodes/tree-expanded-1.json +1 -0
- package/corpus/nodes/tree-selection-1.json +1 -0
- package/corpus/nodes/upload-capture-camera-1.json +1 -0
- package/corpus/nodes/upload-capture-microphone-1.json +1 -0
- package/corpus/nodes/upload-destination-1.json +1 -0
- package/corpus/nodes/upload-drop-1.json +1 -0
- package/corpus/nodes/upload-paste-1.json +1 -0
- package/corpus/ops/op-updatestyle (phase 1472 direction=ltr, the only style member).json +1 -0
- package/corpus/reject/reject-action-print-with-payload.json +1 -0
- package/corpus/reject/reject-color-value-not-hex.json +1 -0
- package/corpus/reject/reject-combobox-allowfreetext-nonbool.json +1 -0
- package/corpus/reject/reject-embed-missing-title.json +1 -0
- package/corpus/reject/reject-embed-permission-nonstring.json +1 -0
- package/corpus/reject/reject-embed-unknown-permission.json +1 -0
- package/corpus/reject/reject-limit-tree-item-depth.json +1 -0
- package/corpus/reject/reject-media-track-default-nonbool.json +1 -0
- package/corpus/reject/reject-media-track-missing-srclang.json +1 -0
- package/corpus/reject/reject-modal-modality-nonstring.json +1 -0
- package/corpus/reject/reject-modal-modality-unknown.json +1 -0
- package/corpus/reject/reject-op-updatestyle-direction-nonstring.json +1 -0
- package/corpus/reject/reject-op-updatestyle-direction-unknown.json +1 -0
- package/corpus/reject/reject-rating-max-zero.json +1 -0
- package/corpus/reject/reject-style-direction-nonstring.json +1 -0
- package/corpus/reject/reject-style-direction-unknown.json +1 -0
- package/corpus/reject/reject-switch-autoadvance-fractional.json +1 -0
- package/corpus/reject/reject-switch-autoadvance-negative.json +1 -0
- package/corpus/reject/reject-switch-autoadvance-zero.json +1 -0
- package/corpus/reject/reject-tokens-closed-without-suggestions.json +1 -0
- package/corpus/reject/reject-tokens-value-not-list.json +1 -0
- package/corpus/reject/reject-tooltip-nonstring.json +1 -0
- package/corpus/reject/reject-tree-item-missing-id.json +1 -0
- package/corpus/reject/reject-tree-item-missing-label.json +1 -0
- package/corpus/reject/reject-tree-nested-item-missing-id.json +1 -0
- package/corpus/reject/reject-unknown-capture-source.json +1 -0
- package/corpus/reject/reject-upload-acceptpaste-nonbool.json +1 -0
- package/corpus/reject/reject-upload-destination-empty.json +1 -0
- package/corpus/reject/reject-upload-droptarget-nonbool.json +1 -0
- package/corpus/reject/reject-wrongtype-box-break-before.json +1 -0
- package/corpus/reject/reject-wrongtype-box-keep-together.json +1 -0
- package/corpus/reject/reject-wrongtype-clipboard-payload.json +1 -0
- package/corpus/reject/reject-wrongtype-grid-exportable-number.json +1 -0
- package/corpus/reject/reject-wrongtype-grid-exportable.json +1 -0
- package/corpus/reject/reject-wrongtype-grid-keep-rows-together.json +1 -0
- package/corpus/reject/reject-wrongtype-grid-repeat-header.json +1 -0
- package/corpus/reject/reject-wrongtype-grid-transfer-in-key.json +1 -0
- package/corpus/reject/reject-wrongtype-grid-transfer-out-key.json +1 -0
- package/corpus/schema.json +333 -1
- package/dist/cli.js +94 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +94 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/corpus/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 1,
|
|
3
3
|
"schema": "schema.json",
|
|
4
4
|
"idl": "idl.json",
|
|
5
|
-
"description": "Fuaran canonical wire-format conformance corpus. node-round-trip / op-round-trip fixtures: decode inputFile, re-encode, assert byte-equal to expectedFile. reject fixtures: decode inputFile, assert DecodeError.Code = expectedErrorCode and DecodeError.Path starts with expectedPath. lenient-accept fixtures (WIRE_FORMAT 16): decode the SHORTHAND inputFile, re-encode, assert byte-equal to expectedFile (the verbose canonical form) — a conformant host MUST accept the shorthand and normalise it; rejecting it, or decoding it to different bytes, is non-conformant. envelope-round-trip / envelope-reject fixtures (WIRE_FORMAT 15): read the $profile/$payload envelope, negotiate the authored profile against the host's own core@1.0, then either re-render byte-equal to expectedFile (Current/Behind — unknown kinds preserved verbatim, must-ignore-but-preserve) or refuse a Foreign profile with expectedErrorCode FOREIGN_PROFILE at expectedPath. elicitation-round-trip / elicitation-reject fixtures (WIRE_FORMAT 18): decode with the decoder-named entry point (elicitation = the envelope codec, elicitation-outcome = the outcome codec), then either re-encode byte-equal to expectedFile or assert the structured refusal (expectedErrorCode at a path starting with expectedPath). elicitation-answer-accept / elicitation-answer-reject fixtures (WIRE_FORMAT 18.4): the inputFile pairs {answer, contract}; run the host's answer-conformance validation and assert acceptance or the expected refusal. See fuaran-dotnet/docs/WIRE_FORMAT.md.",
|
|
5
|
+
"description": "Fuaran canonical wire-format conformance corpus. node-round-trip / op-round-trip fixtures: decode inputFile, re-encode, assert byte-equal to expectedFile. reject fixtures: decode inputFile, assert DecodeError.Code = expectedErrorCode and DecodeError.Path starts with expectedPath. lenient-accept fixtures (WIRE_FORMAT 16): decode the SHORTHAND inputFile, re-encode, assert byte-equal to expectedFile (the verbose canonical form) — a conformant host MUST accept the shorthand and normalise it; rejecting it, or decoding it to different bytes, is non-conformant. envelope-round-trip / envelope-reject fixtures (WIRE_FORMAT 15): read the $profile/$payload envelope, negotiate the authored profile against the host's own core@1.0, then either re-render byte-equal to expectedFile (Current/Behind — unknown kinds preserved verbatim, must-ignore-but-preserve) or refuse a Foreign profile with expectedErrorCode FOREIGN_PROFILE at expectedPath. elicitation-round-trip / elicitation-reject fixtures (WIRE_FORMAT 18): decode with the decoder-named entry point (elicitation = the envelope codec, elicitation-outcome = the outcome codec), then either re-encode byte-equal to expectedFile or assert the structured refusal (expectedErrorCode at a path starting with expectedPath). elicitation-answer-accept / elicitation-answer-reject fixtures (WIRE_FORMAT 18.4): the inputFile pairs {answer, contract}; run the host's answer-conformance validation and assert acceptance or the expected refusal. contract-card-round-trip / contract-card-reject fixtures (WIRE_FORMAT 25): decode with the decoder-named entry point (contract-card = the single-card codec, contract-card-bundle = the bundle codec), then either re-encode byte-equal to expectedFile or assert the structured refusal (expectedErrorCode at a path starting with expectedPath). A card is NOT a node — it is the description a host reads to label and prop-validate a Custom node it has no renderer for — so it is its own family and never appears in nodes/. See fuaran-dotnet/docs/WIRE_FORMAT.md.",
|
|
6
6
|
"kinds": [
|
|
7
7
|
"Badge",
|
|
8
8
|
"Box",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"DataGrid",
|
|
15
15
|
"Disclosure",
|
|
16
16
|
"Drawing",
|
|
17
|
+
"Embed",
|
|
17
18
|
"ErrorBoundary",
|
|
18
19
|
"Fact",
|
|
19
20
|
"FileUpload",
|
|
@@ -44,22 +45,163 @@
|
|
|
44
45
|
"SummaryList",
|
|
45
46
|
"Switch",
|
|
46
47
|
"Tabs",
|
|
47
|
-
"Toast"
|
|
48
|
+
"Toast",
|
|
49
|
+
"Tree"
|
|
48
50
|
],
|
|
49
51
|
"formFieldKinds": [
|
|
50
52
|
"Checkbox",
|
|
51
53
|
"Choice",
|
|
54
|
+
"Color",
|
|
55
|
+
"Combobox",
|
|
52
56
|
"Date",
|
|
53
57
|
"DateRange",
|
|
54
58
|
"Number",
|
|
55
59
|
"Range",
|
|
56
60
|
"RangedNumber",
|
|
61
|
+
"Rating",
|
|
57
62
|
"SegmentedChoice",
|
|
58
63
|
"Text",
|
|
59
64
|
"TextArea",
|
|
60
|
-
"Toggle"
|
|
65
|
+
"Toggle",
|
|
66
|
+
"Tokens"
|
|
67
|
+
],
|
|
68
|
+
"ops": [
|
|
69
|
+
"Batch",
|
|
70
|
+
"EditNode",
|
|
71
|
+
"InsertChild",
|
|
72
|
+
"MoveNode",
|
|
73
|
+
"RemoveNode",
|
|
74
|
+
"ReorderChildren",
|
|
75
|
+
"ReplaceBinding",
|
|
76
|
+
"ReplaceRoot",
|
|
77
|
+
"UpdateProp",
|
|
78
|
+
"UpdateState",
|
|
79
|
+
"UpdateStyle"
|
|
61
80
|
],
|
|
62
81
|
"fixtures": [
|
|
82
|
+
{
|
|
83
|
+
"id": "card-reject-bad-version",
|
|
84
|
+
"kind": "contract-card-reject",
|
|
85
|
+
"decoder": "contract-card",
|
|
86
|
+
"inputFile": "cards/card-reject-bad-version.json",
|
|
87
|
+
"expectedErrorCode": "UNSUPPORTED_VERSION",
|
|
88
|
+
"expectedPath": "$.$card",
|
|
89
|
+
"description": "a card format version this decoder does not implement (WIRE_FORMAT 25.1)"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "card-reject-bundle-bad-version",
|
|
93
|
+
"kind": "contract-card-reject",
|
|
94
|
+
"decoder": "contract-card-bundle",
|
|
95
|
+
"inputFile": "cards/card-reject-bundle-bad-version.json",
|
|
96
|
+
"expectedErrorCode": "UNSUPPORTED_VERSION",
|
|
97
|
+
"expectedPath": "$.$cards",
|
|
98
|
+
"description": "a bundle format version this decoder does not implement (WIRE_FORMAT 25.2)"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "card-reject-bundle-duplicate",
|
|
102
|
+
"kind": "contract-card-reject",
|
|
103
|
+
"decoder": "contract-card-bundle",
|
|
104
|
+
"inputFile": "cards/card-reject-bundle-duplicate.json",
|
|
105
|
+
"expectedErrorCode": "DUPLICATE_CARD",
|
|
106
|
+
"expectedPath": "$.cards[1]",
|
|
107
|
+
"description": "two cards for one identity: a document with no order to appeal to, so which description a reader gets would depend on decoder implementation detail (WIRE_FORMAT 25.2)"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "card-reject-empty-enum",
|
|
111
|
+
"kind": "contract-card-reject",
|
|
112
|
+
"decoder": "contract-card",
|
|
113
|
+
"inputFile": "cards/card-reject-empty-enum.json",
|
|
114
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
115
|
+
"expectedPath": "$.props[0].type",
|
|
116
|
+
"description": "`enum()` is unrepresentable in the tag spelling — an enum admitting nothing, spelled as though it admitted one empty choice (WIRE_FORMAT 25.1)"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "card-reject-hash-not-object",
|
|
120
|
+
"kind": "contract-card-reject",
|
|
121
|
+
"decoder": "contract-card",
|
|
122
|
+
"inputFile": "cards/card-reject-hash-not-object.json",
|
|
123
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
124
|
+
"expectedPath": "$.contentHash",
|
|
125
|
+
"description": "the digest is carried WITH its algorithm; a bare string would make two digests under different algorithms comparable (WIRE_FORMAT 25.1)"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"id": "card-reject-missing-hash",
|
|
129
|
+
"kind": "contract-card-reject",
|
|
130
|
+
"decoder": "contract-card",
|
|
131
|
+
"inputFile": "cards/card-reject-missing-hash.json",
|
|
132
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
133
|
+
"expectedPath": "$.contentHash",
|
|
134
|
+
"description": "the content hash is REQUIRED — without it a card can never be more than a name match, and the three-way verdict collapses to its weakest case for every node (WIRE_FORMAT 25.4)"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "card-reject-missing-module",
|
|
138
|
+
"kind": "contract-card-reject",
|
|
139
|
+
"decoder": "contract-card",
|
|
140
|
+
"inputFile": "cards/card-reject-missing-module.json",
|
|
141
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
142
|
+
"expectedPath": "$.moduleId",
|
|
143
|
+
"description": "half an identity is not an identity (WIRE_FORMAT 25.1)"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "card-reject-payload-no-language",
|
|
147
|
+
"kind": "contract-card-reject",
|
|
148
|
+
"decoder": "contract-card",
|
|
149
|
+
"inputFile": "cards/card-reject-payload-no-language.json",
|
|
150
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
151
|
+
"expectedPath": "$.props[0].payload.language",
|
|
152
|
+
"description": "a gate with no language names a judge for nothing; the language is the declaration and the gate is the annotation on it (WIRE_FORMAT 25.1)"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "card-reject-required-not-bool",
|
|
156
|
+
"kind": "contract-card-reject",
|
|
157
|
+
"decoder": "contract-card",
|
|
158
|
+
"inputFile": "cards/card-reject-required-not-bool.json",
|
|
159
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
160
|
+
"expectedPath": "$.props[0].required",
|
|
161
|
+
"description": "requiredness is a boolean, not a spelling (WIRE_FORMAT 25.1)"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"id": "card-reject-stray-key",
|
|
165
|
+
"kind": "contract-card-reject",
|
|
166
|
+
"decoder": "contract-card",
|
|
167
|
+
"inputFile": "cards/card-reject-stray-key.json",
|
|
168
|
+
"expectedErrorCode": "UNDECLARED_FIELD",
|
|
169
|
+
"expectedPath": "$.renderer",
|
|
170
|
+
"description": "default-deny by shape: an undeclared key is refused, never ignored — a card is a protocol artefact and its evolution is the version tag (WIRE_FORMAT 25.3)"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "card-reject-unknown-prop-type",
|
|
174
|
+
"kind": "contract-card-reject",
|
|
175
|
+
"decoder": "contract-card",
|
|
176
|
+
"inputFile": "cards/card-reject-unknown-prop-type.json",
|
|
177
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
178
|
+
"expectedPath": "$.props[0].type",
|
|
179
|
+
"description": "a prop type tag this build cannot resolve is refused at the boundary rather than read as permissive — guessing would turn a check into a pass (WIRE_FORMAT 25.3)"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "card-bundle",
|
|
183
|
+
"kind": "contract-card-round-trip",
|
|
184
|
+
"decoder": "contract-card-bundle",
|
|
185
|
+
"inputFile": "cards/card-bundle.json",
|
|
186
|
+
"expectedFile": "cards/card-bundle.json",
|
|
187
|
+
"description": "a two-card bundle, emitted sorted by (moduleId, componentId) whatever order the cards were supplied in (WIRE_FORMAT 25.2)"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "card-full",
|
|
191
|
+
"kind": "contract-card-round-trip",
|
|
192
|
+
"decoder": "contract-card",
|
|
193
|
+
"inputFile": "cards/card-full.json",
|
|
194
|
+
"expectedFile": "cards/card-full.json",
|
|
195
|
+
"description": "summary, required + optional props, an enum type tag, and both payload states — gated and ungated (WIRE_FORMAT 25.1)"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"id": "card-minimal",
|
|
199
|
+
"kind": "contract-card-round-trip",
|
|
200
|
+
"decoder": "contract-card",
|
|
201
|
+
"inputFile": "cards/card-minimal.json",
|
|
202
|
+
"expectedFile": "cards/card-minimal.json",
|
|
203
|
+
"description": "identity + content hash, no props and no summary (WIRE_FORMAT 25.1)"
|
|
204
|
+
},
|
|
63
205
|
{
|
|
64
206
|
"id": "elc-ans-accept-full",
|
|
65
207
|
"kind": "elicitation-answer-accept",
|
|
@@ -404,6 +546,14 @@
|
|
|
404
546
|
"expectedFile": "lenient/lenient-022-lvr-emphasis-normal.expected.json",
|
|
405
547
|
"description": "0.2.2 — 'Normal' coerces to false, which is the omitted-when-false canonical form"
|
|
406
548
|
},
|
|
549
|
+
{
|
|
550
|
+
"id": "lenient-1126-clipboard-literal-envelope",
|
|
551
|
+
"kind": "lenient-accept",
|
|
552
|
+
"decoder": "node",
|
|
553
|
+
"inputFile": "lenient/lenient-1126-clipboard-literal-envelope.json",
|
|
554
|
+
"expectedFile": "lenient/lenient-1126-clipboard-literal-envelope.expected.json",
|
|
555
|
+
"description": "Phase 1126 — the clipboard payload is a TextSource, so §16's transparent-Literal rule reaches it: the explicit {\"$type\":\"Literal\",\"text\":…} envelope normalises to the bare string, which is also the pre-1126 spelling and still the canonical one"
|
|
556
|
+
},
|
|
407
557
|
{
|
|
408
558
|
"id": "lenient-460-alias-emphasis-muted",
|
|
409
559
|
"kind": "lenient-accept",
|
|
@@ -980,6 +1130,22 @@
|
|
|
980
1130
|
"expectedFile": "nodes/boundary-1.json",
|
|
981
1131
|
"description": "ErrorBoundary (Markdown child + Callout fallback)"
|
|
982
1132
|
},
|
|
1133
|
+
{
|
|
1134
|
+
"id": "box-break-before-1",
|
|
1135
|
+
"kind": "node-round-trip",
|
|
1136
|
+
"decoder": "node",
|
|
1137
|
+
"inputFile": "nodes/box-break-before-1.json",
|
|
1138
|
+
"expectedFile": "nodes/box-break-before-1.json",
|
|
1139
|
+
"description": "Layout/Box (Phase 1473 breakBefore, the only new member)"
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
"id": "box-keep-together-1",
|
|
1143
|
+
"kind": "node-round-trip",
|
|
1144
|
+
"decoder": "node",
|
|
1145
|
+
"inputFile": "nodes/box-keep-together-1.json",
|
|
1146
|
+
"expectedFile": "nodes/box-keep-together-1.json",
|
|
1147
|
+
"description": "Layout/Box (Phase 1473 keepTogether, the only new member)"
|
|
1148
|
+
},
|
|
983
1149
|
{
|
|
984
1150
|
"id": "btn-1",
|
|
985
1151
|
"kind": "node-round-trip",
|
|
@@ -988,6 +1154,14 @@
|
|
|
988
1154
|
"expectedFile": "nodes/btn-1.json",
|
|
989
1155
|
"description": "Input/Button"
|
|
990
1156
|
},
|
|
1157
|
+
{
|
|
1158
|
+
"id": "btn-copy-bound",
|
|
1159
|
+
"kind": "node-round-trip",
|
|
1160
|
+
"decoder": "node",
|
|
1161
|
+
"inputFile": "nodes/btn-copy-bound.json",
|
|
1162
|
+
"expectedFile": "nodes/btn-copy-bound.json",
|
|
1163
|
+
"description": "Phase 1126 — Input/Button whose Action.WriteToClipboard carries a BOUND payload (a TextSource, not a bare string), resolved at dispatch time"
|
|
1164
|
+
},
|
|
991
1165
|
{
|
|
992
1166
|
"id": "btn-copy-link",
|
|
993
1167
|
"kind": "node-round-trip",
|
|
@@ -1020,6 +1194,14 @@
|
|
|
1020
1194
|
"expectedFile": "nodes/btn-read-workbook.json",
|
|
1021
1195
|
"description": "Input/Button (Action.ReadFileBody base64)"
|
|
1022
1196
|
},
|
|
1197
|
+
{
|
|
1198
|
+
"id": "button-print",
|
|
1199
|
+
"kind": "node-round-trip",
|
|
1200
|
+
"decoder": "node",
|
|
1201
|
+
"inputFile": "nodes/button-print.json",
|
|
1202
|
+
"expectedFile": "nodes/button-print.json",
|
|
1203
|
+
"description": "Input/Button (Phase 1124 — Action.Print: the payload-free action, inside a Chain)"
|
|
1204
|
+
},
|
|
1023
1205
|
{
|
|
1024
1206
|
"id": "button-setstate-valuefrom",
|
|
1025
1207
|
"kind": "node-round-trip",
|
|
@@ -1228,6 +1410,30 @@
|
|
|
1228
1410
|
"expectedFile": "nodes/drawing-tipped-shapes.json",
|
|
1229
1411
|
"description": "Display/Drawing (Phase 883 — tipped shapes, incl. hostile text, Bound tip and explicit empty)"
|
|
1230
1412
|
},
|
|
1413
|
+
{
|
|
1414
|
+
"id": "embed-1",
|
|
1415
|
+
"kind": "node-round-trip",
|
|
1416
|
+
"decoder": "node",
|
|
1417
|
+
"inputFile": "nodes/embed-1.json",
|
|
1418
|
+
"expectedFile": "nodes/embed-1.json",
|
|
1419
|
+
"description": "Display/Embed (Phase 1111 — the minimum: no ratio, no permissions, total denial)"
|
|
1420
|
+
},
|
|
1421
|
+
{
|
|
1422
|
+
"id": "embed-aspect-1",
|
|
1423
|
+
"kind": "node-round-trip",
|
|
1424
|
+
"decoder": "node",
|
|
1425
|
+
"inputFile": "nodes/embed-aspect-1.json",
|
|
1426
|
+
"expectedFile": "nodes/embed-aspect-1.json",
|
|
1427
|
+
"description": "Display/Embed (Phase 1111 — a declared aspect ratio, sharing Image's enum)"
|
|
1428
|
+
},
|
|
1429
|
+
{
|
|
1430
|
+
"id": "embed-permissions-1",
|
|
1431
|
+
"kind": "node-round-trip",
|
|
1432
|
+
"decoder": "node",
|
|
1433
|
+
"inputFile": "nodes/embed-permissions-1.json",
|
|
1434
|
+
"expectedFile": "nodes/embed-permissions-1.json",
|
|
1435
|
+
"description": "Display/Embed (Phase 1111 — one permission, the one that rides `allow` not `sandbox`)"
|
|
1436
|
+
},
|
|
1231
1437
|
{
|
|
1232
1438
|
"id": "empty-state-card",
|
|
1233
1439
|
"kind": "node-round-trip",
|
|
@@ -1276,6 +1482,14 @@
|
|
|
1276
1482
|
"expectedFile": "nodes/filters-declarative.json",
|
|
1277
1483
|
"description": "Input/Filters (declarative — omitted onChange + typed range bounds)"
|
|
1278
1484
|
},
|
|
1485
|
+
{
|
|
1486
|
+
"id": "filters-rating-colour",
|
|
1487
|
+
"kind": "node-round-trip",
|
|
1488
|
+
"decoder": "node",
|
|
1489
|
+
"inputFile": "nodes/filters-rating-colour.json",
|
|
1490
|
+
"expectedFile": "nodes/filters-rating-colour.json",
|
|
1491
|
+
"description": "Input/Filters (Phase 1130 — Rating + Color chips, declarative and auto-bound)"
|
|
1492
|
+
},
|
|
1279
1493
|
{
|
|
1280
1494
|
"id": "filters-segmented",
|
|
1281
1495
|
"kind": "node-round-trip",
|
|
@@ -1284,6 +1498,14 @@
|
|
|
1284
1498
|
"expectedFile": "nodes/filters-segmented.json",
|
|
1285
1499
|
"description": "Input/Filters (SegmentedFilter horizontal)"
|
|
1286
1500
|
},
|
|
1501
|
+
{
|
|
1502
|
+
"id": "filters-tokens",
|
|
1503
|
+
"kind": "node-round-trip",
|
|
1504
|
+
"decoder": "node",
|
|
1505
|
+
"inputFile": "nodes/filters-tokens.json",
|
|
1506
|
+
"expectedFile": "nodes/filters-tokens.json",
|
|
1507
|
+
"description": "Input/Filters (Phase 1121 — Tokens chip, constrained and auto-bound)"
|
|
1508
|
+
},
|
|
1287
1509
|
{
|
|
1288
1510
|
"id": "form-1",
|
|
1289
1511
|
"kind": "node-round-trip",
|
|
@@ -1292,6 +1514,38 @@
|
|
|
1292
1514
|
"expectedFile": "nodes/form-1.json",
|
|
1293
1515
|
"description": "Input/Form (all fields)"
|
|
1294
1516
|
},
|
|
1517
|
+
{
|
|
1518
|
+
"id": "form-color",
|
|
1519
|
+
"kind": "node-round-trip",
|
|
1520
|
+
"decoder": "node",
|
|
1521
|
+
"inputFile": "nodes/form-color.json",
|
|
1522
|
+
"expectedFile": "nodes/form-color.json",
|
|
1523
|
+
"description": "Input/Form (Phase 1130 — Color: upper-case hex, preserved not normalised)"
|
|
1524
|
+
},
|
|
1525
|
+
{
|
|
1526
|
+
"id": "form-combobox-freetext",
|
|
1527
|
+
"kind": "node-round-trip",
|
|
1528
|
+
"decoder": "node",
|
|
1529
|
+
"inputFile": "nodes/form-combobox-freetext.json",
|
|
1530
|
+
"expectedFile": "nodes/form-combobox-freetext.json",
|
|
1531
|
+
"description": "Input/Form (Phase 1113 — Combobox: allowFreeText, value outside the option set)"
|
|
1532
|
+
},
|
|
1533
|
+
{
|
|
1534
|
+
"id": "form-combobox-query",
|
|
1535
|
+
"kind": "node-round-trip",
|
|
1536
|
+
"decoder": "node",
|
|
1537
|
+
"inputFile": "nodes/form-combobox-query.json",
|
|
1538
|
+
"expectedFile": "nodes/form-combobox-query.json",
|
|
1539
|
+
"description": "Input/Form (Phase 1113 — Combobox: Query-bound option source, declarative, auto-bound value)"
|
|
1540
|
+
},
|
|
1541
|
+
{
|
|
1542
|
+
"id": "form-combobox-static",
|
|
1543
|
+
"kind": "node-round-trip",
|
|
1544
|
+
"decoder": "node",
|
|
1545
|
+
"inputFile": "nodes/form-combobox-static.json",
|
|
1546
|
+
"expectedFile": "nodes/form-combobox-static.json",
|
|
1547
|
+
"description": "Input/Form (Phase 1113 — Combobox: static options, allowFreeText omitted)"
|
|
1548
|
+
},
|
|
1295
1549
|
{
|
|
1296
1550
|
"id": "form-date",
|
|
1297
1551
|
"kind": "node-round-trip",
|
|
@@ -1356,6 +1610,22 @@
|
|
|
1356
1610
|
"expectedFile": "nodes/form-ranged.json",
|
|
1357
1611
|
"description": "Input/Form (RangedNumber — all/min-only/no bounds)"
|
|
1358
1612
|
},
|
|
1613
|
+
{
|
|
1614
|
+
"id": "form-rating",
|
|
1615
|
+
"kind": "node-round-trip",
|
|
1616
|
+
"decoder": "node",
|
|
1617
|
+
"inputFile": "nodes/form-rating.json",
|
|
1618
|
+
"expectedFile": "nodes/form-rating.json",
|
|
1619
|
+
"description": "Input/Form (Phase 1130 — Rating: whole stars, allowHalf omitted, static value)"
|
|
1620
|
+
},
|
|
1621
|
+
{
|
|
1622
|
+
"id": "form-rating-halves",
|
|
1623
|
+
"kind": "node-round-trip",
|
|
1624
|
+
"decoder": "node",
|
|
1625
|
+
"inputFile": "nodes/form-rating-halves.json",
|
|
1626
|
+
"expectedFile": "nodes/form-rating-halves.json",
|
|
1627
|
+
"description": "Input/Form (Phase 1130 — Rating: allowHalf entry + a bound average on a ten-scale, value auto-bound)"
|
|
1628
|
+
},
|
|
1359
1629
|
{
|
|
1360
1630
|
"id": "form-segmented",
|
|
1361
1631
|
"kind": "node-round-trip",
|
|
@@ -1372,6 +1642,30 @@
|
|
|
1372
1642
|
"expectedFile": "nodes/form-toggle.json",
|
|
1373
1643
|
"description": "Input/Form (Phase 766 — the Toggle switch affordance beside a Checkbox)"
|
|
1374
1644
|
},
|
|
1645
|
+
{
|
|
1646
|
+
"id": "form-tokens-freetext",
|
|
1647
|
+
"kind": "node-round-trip",
|
|
1648
|
+
"decoder": "node",
|
|
1649
|
+
"inputFile": "nodes/form-tokens-freetext.json",
|
|
1650
|
+
"expectedFile": "nodes/form-tokens-freetext.json",
|
|
1651
|
+
"description": "Input/Form (Phase 1121 — Tokens: the shortest spelling, allowFreeText omitted (true), value auto-bound)"
|
|
1652
|
+
},
|
|
1653
|
+
{
|
|
1654
|
+
"id": "form-tokens-query",
|
|
1655
|
+
"kind": "node-round-trip",
|
|
1656
|
+
"decoder": "node",
|
|
1657
|
+
"inputFile": "nodes/form-tokens-query.json",
|
|
1658
|
+
"expectedFile": "nodes/form-tokens-query.json",
|
|
1659
|
+
"description": "Input/Form (Phase 1121 — Tokens: Query-bound suggestion source, declarative, value auto-bound)"
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
"id": "form-tokens-suggested",
|
|
1663
|
+
"kind": "node-round-trip",
|
|
1664
|
+
"decoder": "node",
|
|
1665
|
+
"inputFile": "nodes/form-tokens-suggested.json",
|
|
1666
|
+
"expectedFile": "nodes/form-tokens-suggested.json",
|
|
1667
|
+
"description": "Input/Form (Phase 1121 — Tokens: allowFreeText false over a static suggestion source, tokens in reader order)"
|
|
1668
|
+
},
|
|
1375
1669
|
{
|
|
1376
1670
|
"id": "format-bindings",
|
|
1377
1671
|
"kind": "node-round-trip",
|
|
@@ -1604,6 +1898,14 @@
|
|
|
1604
1898
|
"expectedFile": "nodes/grid-editable-state.json",
|
|
1605
1899
|
"description": "Visualisation/Grid (Phase 663/665 — editable State-sourced grid, typed rows on the wire)"
|
|
1606
1900
|
},
|
|
1901
|
+
{
|
|
1902
|
+
"id": "grid-exportable-1",
|
|
1903
|
+
"kind": "node-round-trip",
|
|
1904
|
+
"decoder": "node",
|
|
1905
|
+
"inputFile": "nodes/grid-exportable-1.json",
|
|
1906
|
+
"expectedFile": "nodes/grid-exportable-1.json",
|
|
1907
|
+
"description": "Visualisation/Grid (Phase 1125 exportable, the only new member)"
|
|
1908
|
+
},
|
|
1607
1909
|
{
|
|
1608
1910
|
"id": "grid-field-named",
|
|
1609
1911
|
"kind": "node-round-trip",
|
|
@@ -1612,6 +1914,14 @@
|
|
|
1612
1914
|
"expectedFile": "nodes/grid-field-named.json",
|
|
1613
1915
|
"description": "Visualisation/Grid (Phase 425 — field-named columns + RowKeyField, closure-free)"
|
|
1614
1916
|
},
|
|
1917
|
+
{
|
|
1918
|
+
"id": "grid-keep-rows-together-1",
|
|
1919
|
+
"kind": "node-round-trip",
|
|
1920
|
+
"decoder": "node",
|
|
1921
|
+
"inputFile": "nodes/grid-keep-rows-together-1.json",
|
|
1922
|
+
"expectedFile": "nodes/grid-keep-rows-together-1.json",
|
|
1923
|
+
"description": "Visualisation/Grid (Phase 1473 keepRowsTogether, the only new member)"
|
|
1924
|
+
},
|
|
1615
1925
|
{
|
|
1616
1926
|
"id": "grid-paged",
|
|
1617
1927
|
"kind": "node-round-trip",
|
|
@@ -1636,6 +1946,14 @@
|
|
|
1636
1946
|
"expectedFile": "nodes/grid-reorderable.json",
|
|
1637
1947
|
"description": "Visualisation/Grid (Phase 934 — declarative row reorder: omit-when-false flag; edits and reorders share one destination)"
|
|
1638
1948
|
},
|
|
1949
|
+
{
|
|
1950
|
+
"id": "grid-repeat-header-1",
|
|
1951
|
+
"kind": "node-round-trip",
|
|
1952
|
+
"decoder": "node",
|
|
1953
|
+
"inputFile": "nodes/grid-repeat-header-1.json",
|
|
1954
|
+
"expectedFile": "nodes/grid-repeat-header-1.json",
|
|
1955
|
+
"description": "Visualisation/Grid (Phase 1473 repeatHeader, the only new member)"
|
|
1956
|
+
},
|
|
1639
1957
|
{
|
|
1640
1958
|
"id": "grid-sort-state-key",
|
|
1641
1959
|
"kind": "node-round-trip",
|
|
@@ -1748,6 +2066,14 @@
|
|
|
1748
2066
|
"expectedFile": "nodes/limit-node-depth-at-max.json",
|
|
1749
2067
|
"description": "§21 max node depth — a tree at EXACTLY the limit (24 levels). Rule 1: every conformant host MUST decode this; refusing it is non-conformance, not conservatism"
|
|
1750
2068
|
},
|
|
2069
|
+
{
|
|
2070
|
+
"id": "limit-tree-item-depth-at-max",
|
|
2071
|
+
"kind": "node-round-trip",
|
|
2072
|
+
"decoder": "node",
|
|
2073
|
+
"inputFile": "nodes/limit-tree-item-depth-at-max.json",
|
|
2074
|
+
"expectedFile": "nodes/limit-tree-item-depth-at-max.json",
|
|
2075
|
+
"description": "§21.5 the tree-item axis — a tree nesting rows at EXACTLY the limit (24 levels) inside ONE node. Rule 1: every conformant host MUST decode this. Its past-the-bound twin is `reject-limit-tree-item-depth`"
|
|
2076
|
+
},
|
|
1751
2077
|
{
|
|
1752
2078
|
"id": "link-1",
|
|
1753
2079
|
"kind": "node-round-trip",
|
|
@@ -1852,6 +2178,14 @@
|
|
|
1852
2178
|
"expectedFile": "nodes/media-audio-1.json",
|
|
1853
2179
|
"description": "Display/Media (Phase 1076 — the Audio variant, whose payload is the discriminator alone)"
|
|
1854
2180
|
},
|
|
2181
|
+
{
|
|
2182
|
+
"id": "media-audio-transcript-1",
|
|
2183
|
+
"kind": "node-round-trip",
|
|
2184
|
+
"decoder": "node",
|
|
2185
|
+
"inputFile": "nodes/media-audio-transcript-1.json",
|
|
2186
|
+
"expectedFile": "nodes/media-audio-transcript-1.json",
|
|
2187
|
+
"description": "Display/Media (Phase 1110 — the audio transcript floor)"
|
|
2188
|
+
},
|
|
1855
2189
|
{
|
|
1856
2190
|
"id": "media-video-1",
|
|
1857
2191
|
"kind": "node-round-trip",
|
|
@@ -1868,6 +2202,14 @@
|
|
|
1868
2202
|
"expectedFile": "nodes/media-video-autoplay-1.json",
|
|
1869
2203
|
"description": "Display/Media (Phase 1076 — autoplay declared, both shared bools off-default)"
|
|
1870
2204
|
},
|
|
2205
|
+
{
|
|
2206
|
+
"id": "media-video-captions-1",
|
|
2207
|
+
"kind": "node-round-trip",
|
|
2208
|
+
"decoder": "node",
|
|
2209
|
+
"inputFile": "nodes/media-video-captions-1.json",
|
|
2210
|
+
"expectedFile": "nodes/media-video-captions-1.json",
|
|
2211
|
+
"description": "Display/Media (Phase 1110 — one captions track, elected default)"
|
|
2212
|
+
},
|
|
1871
2213
|
{
|
|
1872
2214
|
"id": "media-video-poster-1",
|
|
1873
2215
|
"kind": "node-round-trip",
|
|
@@ -1876,6 +2218,14 @@
|
|
|
1876
2218
|
"expectedFile": "nodes/media-video-poster-1.json",
|
|
1877
2219
|
"description": "Display/Media (Phase 1076 — video with a poster frame in the case payload)"
|
|
1878
2220
|
},
|
|
2221
|
+
{
|
|
2222
|
+
"id": "media-video-tracks-2",
|
|
2223
|
+
"kind": "node-round-trip",
|
|
2224
|
+
"decoder": "node",
|
|
2225
|
+
"inputFile": "nodes/media-video-tracks-2.json",
|
|
2226
|
+
"expectedFile": "nodes/media-video-tracks-2.json",
|
|
2227
|
+
"description": "Display/Media (Phase 1110 — three tracks, authored order, two default elections)"
|
|
2228
|
+
},
|
|
1879
2229
|
{
|
|
1880
2230
|
"id": "metric-1",
|
|
1881
2231
|
"kind": "node-round-trip",
|
|
@@ -1980,6 +2330,14 @@
|
|
|
1980
2330
|
"expectedFile": "nodes/multiselect-1.json",
|
|
1981
2331
|
"description": "Input/Select (multi-select — list value)"
|
|
1982
2332
|
},
|
|
2333
|
+
{
|
|
2334
|
+
"id": "multiselect-chip-list-param",
|
|
2335
|
+
"kind": "node-round-trip",
|
|
2336
|
+
"decoder": "node",
|
|
2337
|
+
"inputFile": "nodes/multiselect-chip-list-param.json",
|
|
2338
|
+
"expectedFile": "nodes/multiselect-chip-list-param.json",
|
|
2339
|
+
"description": "Layout/Box (Phase 610 — multi-select chip + DataGrid scoped by a list-valued in/param)"
|
|
2340
|
+
},
|
|
1983
2341
|
{
|
|
1984
2342
|
"id": "now-environment-binding",
|
|
1985
2343
|
"kind": "node-round-trip",
|
|
@@ -1988,6 +2346,22 @@
|
|
|
1988
2346
|
"expectedFile": "nodes/now-environment-binding.json",
|
|
1989
2347
|
"description": "Binding/Now (Phase 765 — the host-furnished instant: a text slot + a Transform param feeding dateDiffDays)"
|
|
1990
2348
|
},
|
|
2349
|
+
{
|
|
2350
|
+
"id": "popover-anchored-1",
|
|
2351
|
+
"kind": "node-round-trip",
|
|
2352
|
+
"decoder": "node",
|
|
2353
|
+
"inputFile": "nodes/popover-anchored-1.json",
|
|
2354
|
+
"expectedFile": "nodes/popover-anchored-1.json",
|
|
2355
|
+
"description": "Layout/Modal (Phase 1119 — Popover modality, anchored, state-bound open)"
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2358
|
+
"id": "popover-open-1",
|
|
2359
|
+
"kind": "node-round-trip",
|
|
2360
|
+
"decoder": "node",
|
|
2361
|
+
"inputFile": "nodes/popover-open-1.json",
|
|
2362
|
+
"expectedFile": "nodes/popover-open-1.json",
|
|
2363
|
+
"description": "Layout/Modal (Phase 1119 — Popover, statically open: the SSR floor)"
|
|
2364
|
+
},
|
|
1991
2365
|
{
|
|
1992
2366
|
"id": "progress-1",
|
|
1993
2367
|
"kind": "node-round-trip",
|
|
@@ -2084,6 +2458,22 @@
|
|
|
2084
2458
|
"expectedFile": "nodes/step-1.json",
|
|
2085
2459
|
"description": "Layout/Stepper"
|
|
2086
2460
|
},
|
|
2461
|
+
{
|
|
2462
|
+
"id": "style-direction-isolated-1",
|
|
2463
|
+
"kind": "node-round-trip",
|
|
2464
|
+
"decoder": "node",
|
|
2465
|
+
"inputFile": "nodes/style-direction-isolated-1.json",
|
|
2466
|
+
"expectedFile": "nodes/style-direction-isolated-1.json",
|
|
2467
|
+
"description": "Layout/Box (Phase 1472 an Ltr value isolated inside Rtl prose)"
|
|
2468
|
+
},
|
|
2469
|
+
{
|
|
2470
|
+
"id": "style-direction-ltr-1",
|
|
2471
|
+
"kind": "node-round-trip",
|
|
2472
|
+
"decoder": "node",
|
|
2473
|
+
"inputFile": "nodes/style-direction-ltr-1.json",
|
|
2474
|
+
"expectedFile": "nodes/style-direction-ltr-1.json",
|
|
2475
|
+
"description": "Display/Markdown (Phase 1472 Direction=Ltr, the only style member)"
|
|
2476
|
+
},
|
|
2087
2477
|
{
|
|
2088
2478
|
"id": "style-role-voice-1",
|
|
2089
2479
|
"kind": "node-round-trip",
|
|
@@ -2108,6 +2498,14 @@
|
|
|
2108
2498
|
"expectedFile": "nodes/switch-1.json",
|
|
2109
2499
|
"description": "Switch (view state → details/summary cases + info default)"
|
|
2110
2500
|
},
|
|
2501
|
+
{
|
|
2502
|
+
"id": "switch-carousel-1",
|
|
2503
|
+
"kind": "node-round-trip",
|
|
2504
|
+
"decoder": "node",
|
|
2505
|
+
"inputFile": "nodes/switch-carousel-1.json",
|
|
2506
|
+
"expectedFile": "nodes/switch-carousel-1.json",
|
|
2507
|
+
"description": "Meta/Switch (Phase 1122 — an auto-advancing carousel: `autoAdvanceMs` over an index key)"
|
|
2508
|
+
},
|
|
2111
2509
|
{
|
|
2112
2510
|
"id": "switch-on-selection",
|
|
2113
2511
|
"kind": "node-round-trip",
|
|
@@ -2156,6 +2554,62 @@
|
|
|
2156
2554
|
"expectedFile": "nodes/toast-1.json",
|
|
2157
2555
|
"description": "Display/Toast (Success tone, open)"
|
|
2158
2556
|
},
|
|
2557
|
+
{
|
|
2558
|
+
"id": "tooltip-button-1",
|
|
2559
|
+
"kind": "node-round-trip",
|
|
2560
|
+
"decoder": "node",
|
|
2561
|
+
"inputFile": "nodes/tooltip-button-1.json",
|
|
2562
|
+
"expectedFile": "nodes/tooltip-button-1.json",
|
|
2563
|
+
"description": "Tooltip (Phase 1112 — the trait on a forwarding interactive kind; the description rides the button)"
|
|
2564
|
+
},
|
|
2565
|
+
{
|
|
2566
|
+
"id": "tooltip-icon-button-1",
|
|
2567
|
+
"kind": "node-round-trip",
|
|
2568
|
+
"decoder": "node",
|
|
2569
|
+
"inputFile": "nodes/tooltip-icon-button-1.json",
|
|
2570
|
+
"expectedFile": "nodes/tooltip-icon-button-1.json",
|
|
2571
|
+
"description": "Tooltip (Phase 1112 — the icon-only button: accessibility.label NAMES, tooltip DESCRIBES, describedBy merges)"
|
|
2572
|
+
},
|
|
2573
|
+
{
|
|
2574
|
+
"id": "tooltip-metric-1",
|
|
2575
|
+
"kind": "node-round-trip",
|
|
2576
|
+
"decoder": "node",
|
|
2577
|
+
"inputFile": "nodes/tooltip-metric-1.json",
|
|
2578
|
+
"expectedFile": "nodes/tooltip-metric-1.json",
|
|
2579
|
+
"description": "Tooltip (Phase 1112 — the trait on a display kind, I18n hint; description and focus stop on the wrapper)"
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
"id": "transfer-board",
|
|
2583
|
+
"kind": "node-round-trip",
|
|
2584
|
+
"decoder": "node",
|
|
2585
|
+
"inputFile": "nodes/transfer-board.json",
|
|
2586
|
+
"expectedFile": "nodes/transfer-board.json",
|
|
2587
|
+
"description": "Layout/Box (Phase 1123 — cross-container transfer: two two-way columns and a one-way archive on one shared key)"
|
|
2588
|
+
},
|
|
2589
|
+
{
|
|
2590
|
+
"id": "tree-1",
|
|
2591
|
+
"kind": "node-round-trip",
|
|
2592
|
+
"decoder": "node",
|
|
2593
|
+
"inputFile": "nodes/tree-1.json",
|
|
2594
|
+
"expectedFile": "nodes/tree-1.json",
|
|
2595
|
+
"description": "Display/Tree (Phase 1120 — two levels, no State key: static and fully expanded)"
|
|
2596
|
+
},
|
|
2597
|
+
{
|
|
2598
|
+
"id": "tree-expanded-1",
|
|
2599
|
+
"kind": "node-round-trip",
|
|
2600
|
+
"decoder": "node",
|
|
2601
|
+
"inputFile": "nodes/tree-expanded-1.json",
|
|
2602
|
+
"expectedFile": "nodes/tree-expanded-1.json",
|
|
2603
|
+
"description": "Display/Tree (Phase 1120 — three levels, the expansion key named; the key IS the affordance)"
|
|
2604
|
+
},
|
|
2605
|
+
{
|
|
2606
|
+
"id": "tree-selection-1",
|
|
2607
|
+
"kind": "node-round-trip",
|
|
2608
|
+
"decoder": "node",
|
|
2609
|
+
"inputFile": "nodes/tree-selection-1.json",
|
|
2610
|
+
"expectedFile": "nodes/tree-selection-1.json",
|
|
2611
|
+
"description": "Display/Tree (Phase 1120 — the selection key AND the handler, both declared)"
|
|
2612
|
+
},
|
|
2159
2613
|
{
|
|
2160
2614
|
"id": "upload-1",
|
|
2161
2615
|
"kind": "node-round-trip",
|
|
@@ -2164,6 +2618,46 @@
|
|
|
2164
2618
|
"expectedFile": "nodes/upload-1.json",
|
|
2165
2619
|
"description": "Input/FileUpload"
|
|
2166
2620
|
},
|
|
2621
|
+
{
|
|
2622
|
+
"id": "upload-capture-camera-1",
|
|
2623
|
+
"kind": "node-round-trip",
|
|
2624
|
+
"decoder": "node",
|
|
2625
|
+
"inputFile": "nodes/upload-capture-camera-1.json",
|
|
2626
|
+
"expectedFile": "nodes/upload-capture-camera-1.json",
|
|
2627
|
+
"description": "Input/FileUpload (Phase 1116 — camera capture, image/* filtered)"
|
|
2628
|
+
},
|
|
2629
|
+
{
|
|
2630
|
+
"id": "upload-capture-microphone-1",
|
|
2631
|
+
"kind": "node-round-trip",
|
|
2632
|
+
"decoder": "node",
|
|
2633
|
+
"inputFile": "nodes/upload-capture-microphone-1.json",
|
|
2634
|
+
"expectedFile": "nodes/upload-capture-microphone-1.json",
|
|
2635
|
+
"description": "Input/FileUpload (Phase 1116 — microphone capture, audio/* filtered)"
|
|
2636
|
+
},
|
|
2637
|
+
{
|
|
2638
|
+
"id": "upload-destination-1",
|
|
2639
|
+
"kind": "node-round-trip",
|
|
2640
|
+
"decoder": "node",
|
|
2641
|
+
"inputFile": "nodes/upload-destination-1.json",
|
|
2642
|
+
"expectedFile": "nodes/upload-destination-1.json",
|
|
2643
|
+
"description": "Input/FileUpload (Phase 1117 — streamed to a registered destination)"
|
|
2644
|
+
},
|
|
2645
|
+
{
|
|
2646
|
+
"id": "upload-drop-1",
|
|
2647
|
+
"kind": "node-round-trip",
|
|
2648
|
+
"decoder": "node",
|
|
2649
|
+
"inputFile": "nodes/upload-drop-1.json",
|
|
2650
|
+
"expectedFile": "nodes/upload-drop-1.json",
|
|
2651
|
+
"description": "Input/FileUpload (Phase 1115 — drop target; acceptPaste OMITTED)"
|
|
2652
|
+
},
|
|
2653
|
+
{
|
|
2654
|
+
"id": "upload-paste-1",
|
|
2655
|
+
"kind": "node-round-trip",
|
|
2656
|
+
"decoder": "node",
|
|
2657
|
+
"inputFile": "nodes/upload-paste-1.json",
|
|
2658
|
+
"expectedFile": "nodes/upload-paste-1.json",
|
|
2659
|
+
"description": "Input/FileUpload (Phase 1115 — paste ingestion, image/* filtered; dropTarget OMITTED)"
|
|
2660
|
+
},
|
|
2167
2661
|
{
|
|
2168
2662
|
"id": "op-batch",
|
|
2169
2663
|
"kind": "op-round-trip",
|
|
@@ -2340,6 +2834,14 @@
|
|
|
2340
2834
|
"expectedFile": "ops/op-updatestyle (phase 147 role=eyebrow + voice=structural).json",
|
|
2341
2835
|
"description": "UpdateStyle (Phase 147 Role=Eyebrow + Voice=Structural)"
|
|
2342
2836
|
},
|
|
2837
|
+
{
|
|
2838
|
+
"id": "op-updatestyle (phase 1472 direction=ltr, the only style member)",
|
|
2839
|
+
"kind": "op-round-trip",
|
|
2840
|
+
"decoder": "op",
|
|
2841
|
+
"inputFile": "ops/op-updatestyle (phase 1472 direction=ltr, the only style member).json",
|
|
2842
|
+
"expectedFile": "ops/op-updatestyle (phase 1472 direction=ltr, the only style member).json",
|
|
2843
|
+
"description": "UpdateStyle (Phase 1472 Direction=Ltr, the only style member)"
|
|
2844
|
+
},
|
|
2343
2845
|
{
|
|
2344
2846
|
"id": "reject-a11y-hidden-nonbool",
|
|
2345
2847
|
"kind": "reject",
|
|
@@ -2394,6 +2896,15 @@
|
|
|
2394
2896
|
"expectedPath": "$.accessibility.role",
|
|
2395
2897
|
"description": "accessibility.role not a JSON string — the slot is open to any role NAME, not to any value (Phase 955)"
|
|
2396
2898
|
},
|
|
2899
|
+
{
|
|
2900
|
+
"id": "reject-action-print-with-payload",
|
|
2901
|
+
"kind": "reject",
|
|
2902
|
+
"decoder": "node",
|
|
2903
|
+
"inputFile": "reject/reject-action-print-with-payload.json",
|
|
2904
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
2905
|
+
"expectedPath": "$.kind.onClick.pageRange",
|
|
2906
|
+
"description": "Print carrying a member — the payload-free action takes none; page range, size, margins and copies are the host's page setup and the reader's dialogue, so a member here is refused rather than dropped (Phase 1124)"
|
|
2907
|
+
},
|
|
2397
2908
|
{
|
|
2398
2909
|
"id": "reject-binding-float-bool",
|
|
2399
2910
|
"kind": "reject",
|
|
@@ -2448,6 +2959,24 @@
|
|
|
2448
2959
|
"expectedPath": "$.kind.layout.cols",
|
|
2449
2960
|
"description": "Masonry cols 0 — refused: a column count names how many columns the children fill, so a non-positive one describes a layout no renderer can realise. Refused rather than canonicalised to `Auto`, unlike a column-less `Grid`: that leniency works because `Auto` already means the browser's own choice, and masonry has no such case for the rewrite to land on"
|
|
2450
2961
|
},
|
|
2962
|
+
{
|
|
2963
|
+
"id": "reject-color-value-not-hex",
|
|
2964
|
+
"kind": "reject",
|
|
2965
|
+
"decoder": "node",
|
|
2966
|
+
"inputFile": "reject/reject-color-value-not-hex.json",
|
|
2967
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
2968
|
+
"expectedPath": "$.kind.fields[0].kind.value",
|
|
2969
|
+
"description": "a Color `value` of `\"rebeccapurple\"` — refused rather than coerced. `#rrggbb` is the one shape a native colour input can hold, so a literal outside it names a colour this control could never carry, and a host that narrowed it would show a colour the document did not choose. Only the STATIC case is judged, because it is the only text a decoder has: a bound value is re-checked by the pre-emit validator for an author and by the server-side submission floor for a client, which is one rule checked wherever the value becomes visible"
|
|
2970
|
+
},
|
|
2971
|
+
{
|
|
2972
|
+
"id": "reject-combobox-allowfreetext-nonbool",
|
|
2973
|
+
"kind": "reject",
|
|
2974
|
+
"decoder": "node",
|
|
2975
|
+
"inputFile": "reject/reject-combobox-allowfreetext-nonbool.json",
|
|
2976
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
2977
|
+
"expectedPath": "$.kind.fields[0].kind.allowFreeText",
|
|
2978
|
+
"description": "a Combobox `allowFreeText` of `\"yes\"` — refused rather than coerced. The slot decides whether values OUTSIDE the option set are admitted, so a lenient truthiness read is a constraint silently relaxed by a string: `\"yes\"`, `\"no\"` and `\"false\"` are all non-empty, and a host that coerced them would widen the field on two of the three. It also omits at `false`, so absence already spells the safe answer and a wrong-typed present value can only mean the emitter meant something it did not say"
|
|
2979
|
+
},
|
|
2451
2980
|
{
|
|
2452
2981
|
"id": "reject-daterange-unordered",
|
|
2453
2982
|
"kind": "reject",
|
|
@@ -2457,6 +2986,33 @@
|
|
|
2457
2986
|
"expectedPath": "$.kind.fields[0].kind.value",
|
|
2458
2987
|
"description": "DateRange literal pair with start after end — the ordered-pair rule (Phase 725)"
|
|
2459
2988
|
},
|
|
2989
|
+
{
|
|
2990
|
+
"id": "reject-embed-missing-title",
|
|
2991
|
+
"kind": "reject",
|
|
2992
|
+
"decoder": "node",
|
|
2993
|
+
"inputFile": "reject/reject-embed-missing-title.json",
|
|
2994
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
2995
|
+
"expectedPath": "$.kind.title",
|
|
2996
|
+
"description": "Embed with no `title` — refused. The accessible name is mandatory because a browsing context has no decorative case, and there is no value to default to that would not be a fabricated description of someone else's page"
|
|
2997
|
+
},
|
|
2998
|
+
{
|
|
2999
|
+
"id": "reject-embed-permission-nonstring",
|
|
3000
|
+
"kind": "reject",
|
|
3001
|
+
"decoder": "node",
|
|
3002
|
+
"inputFile": "reject/reject-embed-permission-nonstring.json",
|
|
3003
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3004
|
+
"expectedPath": "$.kind.permissions[0]",
|
|
3005
|
+
"description": "an Embed permission of `true` — refused rather than coerced. A host that read a bare boolean as a granted permission would have to invent which one it names, and every answer is a relaxation the document never spelled"
|
|
3006
|
+
},
|
|
3007
|
+
{
|
|
3008
|
+
"id": "reject-embed-unknown-permission",
|
|
3009
|
+
"kind": "reject",
|
|
3010
|
+
"decoder": "node",
|
|
3011
|
+
"inputFile": "reject/reject-embed-unknown-permission.json",
|
|
3012
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
3013
|
+
"expectedPath": "$.kind.permissions[0]",
|
|
3014
|
+
"description": "EmbedPermission 'allow-top-navigation' — refused. The set is closed at four, and top-level navigation is excluded by design rather than reserved; the path carries the array index and no `.$type`, because the slot holds bare enum strings"
|
|
3015
|
+
},
|
|
2460
3016
|
{
|
|
2461
3017
|
"id": "reject-emptynodeid",
|
|
2462
3018
|
"kind": "reject",
|
|
@@ -2583,6 +3139,15 @@
|
|
|
2583
3139
|
"expectedPath": "$",
|
|
2584
3140
|
"description": "§21.5 the op axis — 25 nested TreeOp.Batch. Counted separately from the node axis; the syntactic bound only LOOKS like cover for it"
|
|
2585
3141
|
},
|
|
3142
|
+
{
|
|
3143
|
+
"id": "reject-limit-tree-item-depth",
|
|
3144
|
+
"kind": "reject",
|
|
3145
|
+
"decoder": "node",
|
|
3146
|
+
"inputFile": "reject/reject-limit-tree-item-depth.json",
|
|
3147
|
+
"expectedErrorCode": "LIMIT_EXCEEDED",
|
|
3148
|
+
"expectedPath": "$.kind.items[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0].children[0]",
|
|
3149
|
+
"description": "§21.5 the tree-item axis — 25 nested TreeItem rows inside ONE node. Counted separately from the node axis, which cannot see it at all (the whole hierarchy is one node) and from the syntactic bound, which at ~50 levels is nowhere near reached. The `TreeOp.Batch` lesson on a third axis"
|
|
3150
|
+
},
|
|
2586
3151
|
{
|
|
2587
3152
|
"id": "reject-media-autoplay-nonbool",
|
|
2588
3153
|
"kind": "reject",
|
|
@@ -2601,6 +3166,24 @@
|
|
|
2601
3166
|
"expectedPath": "$.kind.label",
|
|
2602
3167
|
"description": "Media with no `label` — refused. The accessible name is mandatory because a transport has no decorative case, and there is no value to default to that would not be a fabricated name for someone else's recording"
|
|
2603
3168
|
},
|
|
3169
|
+
{
|
|
3170
|
+
"id": "reject-media-track-default-nonbool",
|
|
3171
|
+
"kind": "reject",
|
|
3172
|
+
"decoder": "node",
|
|
3173
|
+
"inputFile": "reject/reject-media-track-default-nonbool.json",
|
|
3174
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3175
|
+
"expectedPath": "$.kind.tracks[0].default",
|
|
3176
|
+
"description": "a track `default` of `\"true\"` — the stringified boolean, refused rather than coerced. Two hosts ruling differently on truthiness would disagree about which caption track opens, which is a difference the reader meets on the first frame"
|
|
3177
|
+
},
|
|
3178
|
+
{
|
|
3179
|
+
"id": "reject-media-track-missing-srclang",
|
|
3180
|
+
"kind": "reject",
|
|
3181
|
+
"decoder": "node",
|
|
3182
|
+
"inputFile": "reject/reject-media-track-missing-srclang.json",
|
|
3183
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
3184
|
+
"expectedPath": "$.kind.tracks[0].srcLang",
|
|
3185
|
+
"description": "a text track with no `srcLang` — refused. The language tag is what orders a track menu, drives pronunciation and tells two same-labelled tracks apart; there is no value to default to that would not be an invented claim about someone else's recording. The path carries the ARRAY INDEX, so a document with four tracks names the one at fault"
|
|
3186
|
+
},
|
|
2604
3187
|
{
|
|
2605
3188
|
"id": "reject-missing-binding-type",
|
|
2606
3189
|
"kind": "reject",
|
|
@@ -2691,6 +3274,24 @@
|
|
|
2691
3274
|
"expectedPath": "$.kind.stateKey",
|
|
2692
3275
|
"description": "Switch missing stateKey"
|
|
2693
3276
|
},
|
|
3277
|
+
{
|
|
3278
|
+
"id": "reject-modal-modality-nonstring",
|
|
3279
|
+
"kind": "reject",
|
|
3280
|
+
"decoder": "node",
|
|
3281
|
+
"inputFile": "reject/reject-modal-modality-nonstring.json",
|
|
3282
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3283
|
+
"expectedPath": "$.kind.modality",
|
|
3284
|
+
"description": "a Modal `modality` of `3` — a separate decoder arm from the unknown-string vector above, and vectored separately for that reason. An ordinal is the shape a host generating from an enum's index is likeliest to emit, and reading one would make the wire's meaning depend on a declaration order the wire never carries"
|
|
3285
|
+
},
|
|
3286
|
+
{
|
|
3287
|
+
"id": "reject-modal-modality-unknown",
|
|
3288
|
+
"kind": "reject",
|
|
3289
|
+
"decoder": "node",
|
|
3290
|
+
"inputFile": "reject/reject-modal-modality-unknown.json",
|
|
3291
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
3292
|
+
"expectedPath": "$.kind.modality",
|
|
3293
|
+
"description": "a Modal `modality` of `\"Sheet\"` — outside the closed pair `Modal | Popover`. A sheet, a drawer and a menu are all PRESENTATIONS of one of the two modalities rather than a third one, so the answer to this document is not to widen the enum but to say which of the two it meant. The path is the bare slot, per §6 and the Phase 1073 ruling: a bare enum carries no discriminator on the wire, so there is no `.$type` to name"
|
|
3294
|
+
},
|
|
2694
3295
|
{
|
|
2695
3296
|
"id": "reject-nearmiss-a11y-aria-hidden",
|
|
2696
3297
|
"kind": "reject",
|
|
@@ -2889,6 +3490,33 @@
|
|
|
2889
3490
|
"expectedPath": "$.path",
|
|
2890
3491
|
"description": "UpdateProp missing path"
|
|
2891
3492
|
},
|
|
3493
|
+
{
|
|
3494
|
+
"id": "reject-op-updatestyle-direction-nonstring",
|
|
3495
|
+
"kind": "reject",
|
|
3496
|
+
"decoder": "op",
|
|
3497
|
+
"inputFile": "reject/reject-op-updatestyle-direction-nonstring.json",
|
|
3498
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3499
|
+
"expectedPath": "$.style.direction",
|
|
3500
|
+
"description": "UpdateStyle style.direction not a JSON string (Phase 1472)"
|
|
3501
|
+
},
|
|
3502
|
+
{
|
|
3503
|
+
"id": "reject-op-updatestyle-direction-unknown",
|
|
3504
|
+
"kind": "reject",
|
|
3505
|
+
"decoder": "op",
|
|
3506
|
+
"inputFile": "reject/reject-op-updatestyle-direction-unknown.json",
|
|
3507
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
3508
|
+
"expectedPath": "$.style.direction",
|
|
3509
|
+
"description": "UpdateStyle style.direction outside the closed set — the op arm's twin of the node vector above (Phase 1472)"
|
|
3510
|
+
},
|
|
3511
|
+
{
|
|
3512
|
+
"id": "reject-rating-max-zero",
|
|
3513
|
+
"kind": "reject",
|
|
3514
|
+
"decoder": "node",
|
|
3515
|
+
"inputFile": "reject/reject-rating-max-zero.json",
|
|
3516
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3517
|
+
"expectedPath": "$.kind.fields[0].kind.max",
|
|
3518
|
+
"description": "a Rating `max` of `0` — refused rather than clamped. This is not a control with a bad number in it: a scale with no positions has nothing to draw, no `aria-valuemax` to announce and no keystroke that could change anything, so the document names a control that cannot exist. Note the asymmetry this vector pins: the SCALE is refused here and the VALUE is not, because a bound value is invisible to a decoder and a rule enforced only on literals would be two rules wearing one name"
|
|
3519
|
+
},
|
|
2892
3520
|
{
|
|
2893
3521
|
"id": "reject-setstate-value-and-valuefrom",
|
|
2894
3522
|
"kind": "reject",
|
|
@@ -2898,6 +3526,69 @@
|
|
|
2898
3526
|
"expectedPath": "$.kind.onClick.valueFrom",
|
|
2899
3527
|
"description": "SetState carrying BOTH 'value' and 'valueFrom' — exactly one is allowed; the didactic names both fields and how each is used (Phase 818)"
|
|
2900
3528
|
},
|
|
3529
|
+
{
|
|
3530
|
+
"id": "reject-style-direction-nonstring",
|
|
3531
|
+
"kind": "reject",
|
|
3532
|
+
"decoder": "node",
|
|
3533
|
+
"inputFile": "reject/reject-style-direction-nonstring.json",
|
|
3534
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3535
|
+
"expectedPath": "$.style.direction",
|
|
3536
|
+
"description": "style.direction not a JSON string (Phase 1472)"
|
|
3537
|
+
},
|
|
3538
|
+
{
|
|
3539
|
+
"id": "reject-style-direction-unknown",
|
|
3540
|
+
"kind": "reject",
|
|
3541
|
+
"decoder": "node",
|
|
3542
|
+
"inputFile": "reject/reject-style-direction-unknown.json",
|
|
3543
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
3544
|
+
"expectedPath": "$.style.direction",
|
|
3545
|
+
"description": "style.direction outside the closed set — the message names auto | ltr | rtl, and the near miss is the upper-case spelling (Phase 1472)"
|
|
3546
|
+
},
|
|
3547
|
+
{
|
|
3548
|
+
"id": "reject-switch-autoadvance-fractional",
|
|
3549
|
+
"kind": "reject",
|
|
3550
|
+
"decoder": "node",
|
|
3551
|
+
"inputFile": "reject/reject-switch-autoadvance-fractional.json",
|
|
3552
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3553
|
+
"expectedPath": "$.kind.autoAdvanceMs",
|
|
3554
|
+
"description": "Switch autoAdvanceMs is fractional — the slot is an integer count of milliseconds, and a decoder truncating where another rounded would leave two hosts disagreeing about a document neither refused (Phase 1122)"
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
"id": "reject-switch-autoadvance-negative",
|
|
3558
|
+
"kind": "reject",
|
|
3559
|
+
"decoder": "node",
|
|
3560
|
+
"inputFile": "reject/reject-switch-autoadvance-negative.json",
|
|
3561
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3562
|
+
"expectedPath": "$.kind.autoAdvanceMs",
|
|
3563
|
+
"description": "Switch autoAdvanceMs is negative — an interval names how long to wait, so a negative one describes a schedule no renderer can realise (Phase 1122)"
|
|
3564
|
+
},
|
|
3565
|
+
{
|
|
3566
|
+
"id": "reject-switch-autoadvance-zero",
|
|
3567
|
+
"kind": "reject",
|
|
3568
|
+
"decoder": "node",
|
|
3569
|
+
"inputFile": "reject/reject-switch-autoadvance-zero.json",
|
|
3570
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3571
|
+
"expectedPath": "$.kind.autoAdvanceMs",
|
|
3572
|
+
"description": "Switch autoAdvanceMs is 0 — refused, never canonicalised to absence. An absent key is already the only spelling of \"does not advance\", so accepting a zero would make two shapes mean one thing and hide the emitter's misreading of the slot (Phase 1122)"
|
|
3573
|
+
},
|
|
3574
|
+
{
|
|
3575
|
+
"id": "reject-tokens-closed-without-suggestions",
|
|
3576
|
+
"kind": "reject",
|
|
3577
|
+
"decoder": "node",
|
|
3578
|
+
"inputFile": "reject/reject-tokens-closed-without-suggestions.json",
|
|
3579
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3580
|
+
"expectedPath": "$.kind.fields[0].kind.allowFreeText",
|
|
3581
|
+
"description": "a Tokens field admitting no free text and declaring NO suggestion source — refused. No gesture could ever put a token into it: this is not a control with a bad value in it but a document naming a control that cannot exist, the same line `Rating`'s `max` of zero is refused on. Note the polarity that makes the refusal fair rather than hostile: `allowFreeText` omits at TRUE on this case (unlike `Combobox`, whose option source is required), so the shortest document `{\"$type\":\"Tokens\"}` is the plain open token box and passes — only an emitter that wrote `false` and then omitted the suggestions lands here. Note also what is NOT refused anywhere: duplicate tokens and membership of a token in the suggestion set are properties of the VALUE, invisible to a decoder whenever the slot is bound, and are held by the pre-emit validator and the server-side submission floor instead"
|
|
3582
|
+
},
|
|
3583
|
+
{
|
|
3584
|
+
"id": "reject-tokens-value-not-list",
|
|
3585
|
+
"kind": "reject",
|
|
3586
|
+
"decoder": "node",
|
|
3587
|
+
"inputFile": "reject/reject-tokens-value-not-list.json",
|
|
3588
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3589
|
+
"expectedPath": "$.kind.fields[0].kind.value",
|
|
3590
|
+
"description": "a Tokens `value` carrying a bare STRING where the slot is a `Binding<string list>` — refused rather than lifted into a one-element list. The lift is the tempting coercion and it is exactly wrong: a document saying `\"urgent\"` where the wire says a list has a misunderstanding of the slot, and silently agreeing with it would let an emitter ship a token field that can only ever hold one token while every host round-tripped it perfectly"
|
|
3591
|
+
},
|
|
2901
3592
|
{
|
|
2902
3593
|
"id": "reject-tonedpill-unknown-tone",
|
|
2903
3594
|
"kind": "reject",
|
|
@@ -2907,6 +3598,42 @@
|
|
|
2907
3598
|
"expectedPath": "$.kind.columns[0].kind.map.Delayed",
|
|
2908
3599
|
"description": "TonedPill tone-map value outside ToneVariant — the message names the seven legal tones (Phase 750)"
|
|
2909
3600
|
},
|
|
3601
|
+
{
|
|
3602
|
+
"id": "reject-tooltip-nonstring",
|
|
3603
|
+
"kind": "reject",
|
|
3604
|
+
"decoder": "node",
|
|
3605
|
+
"inputFile": "reject/reject-tooltip-nonstring.json",
|
|
3606
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3607
|
+
"expectedPath": "$.tooltip",
|
|
3608
|
+
"description": "a node `tooltip` of `42` — refused rather than stringified. A bare STRING at this slot is the canonical encoding of a literal hint (TextSource's transparent case), so a number is one lenient `toString` away from minting hint text out of a JSON type — which no downstream check could ever catch"
|
|
3609
|
+
},
|
|
3610
|
+
{
|
|
3611
|
+
"id": "reject-tree-item-missing-id",
|
|
3612
|
+
"kind": "reject",
|
|
3613
|
+
"decoder": "node",
|
|
3614
|
+
"inputFile": "reject/reject-tree-item-missing-id.json",
|
|
3615
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
3616
|
+
"expectedPath": "$.kind.items[0].id",
|
|
3617
|
+
"description": "a Tree row with no `id` — refused. Both State keys address rows BY id, so an id-less row can never be expanded, selected or restored; a synthesised positional id would move the reader's open branches the moment a sibling was inserted"
|
|
3618
|
+
},
|
|
3619
|
+
{
|
|
3620
|
+
"id": "reject-tree-item-missing-label",
|
|
3621
|
+
"kind": "reject",
|
|
3622
|
+
"decoder": "node",
|
|
3623
|
+
"inputFile": "reject/reject-tree-item-missing-label.json",
|
|
3624
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
3625
|
+
"expectedPath": "$.kind.items[0].label",
|
|
3626
|
+
"description": "a Tree row with no `label` — refused. A row's label is the only thing a reader walking the hierarchy has, and there is no value to default to that would not be an invented description of somebody's content"
|
|
3627
|
+
},
|
|
3628
|
+
{
|
|
3629
|
+
"id": "reject-tree-nested-item-missing-id",
|
|
3630
|
+
"kind": "reject",
|
|
3631
|
+
"decoder": "node",
|
|
3632
|
+
"inputFile": "reject/reject-tree-nested-item-missing-id.json",
|
|
3633
|
+
"expectedErrorCode": "MISSING_FIELD",
|
|
3634
|
+
"expectedPath": "$.kind.items[0].children[0].id",
|
|
3635
|
+
"description": "a NESTED Tree row with no `id` — refused, and the path names the row inside the hierarchy. A host whose child walker is looser than its root walker accepts this while passing every top-level case"
|
|
3636
|
+
},
|
|
2910
3637
|
{
|
|
2911
3638
|
"id": "reject-unknown-binding",
|
|
2912
3639
|
"kind": "reject",
|
|
@@ -2916,6 +3643,15 @@
|
|
|
2916
3643
|
"expectedPath": "$.kind.value.$type",
|
|
2917
3644
|
"description": "Binding $type 'Bogus'"
|
|
2918
3645
|
},
|
|
3646
|
+
{
|
|
3647
|
+
"id": "reject-unknown-capture-source",
|
|
3648
|
+
"kind": "reject",
|
|
3649
|
+
"decoder": "node",
|
|
3650
|
+
"inputFile": "reject/reject-unknown-capture-source.json",
|
|
3651
|
+
"expectedErrorCode": "UNKNOWN_DU_CASE",
|
|
3652
|
+
"expectedPath": "$.kind.capture",
|
|
3653
|
+
"description": "a FileUpload `capture` of `\"Screen\"` — outside the closed pair `Camera | Microphone`. The HTML capture attribute cannot ask for a display at all, and a screen capture is a standing grant reaching every window the reader has open rather than a third device behind the same picker permission, so it is refused exactly like a name nobody has proposed: a later admission would be an ADDITION, never a re-meaning of shipped bytes"
|
|
3654
|
+
},
|
|
2919
3655
|
{
|
|
2920
3656
|
"id": "reject-unknown-drawing-curve-command",
|
|
2921
3657
|
"kind": "reject",
|
|
@@ -3006,6 +3742,33 @@
|
|
|
3006
3742
|
"expectedPath": "$.kind.trendPolarity",
|
|
3007
3743
|
"description": "TrendPolarity value 'Neutral' — RESERVED, not admitted (§3.6.1 clause 5); refused exactly like a name nobody has proposed, so a later admission is an ADDITION rather than a re-meaning of shipped bytes"
|
|
3008
3744
|
},
|
|
3745
|
+
{
|
|
3746
|
+
"id": "reject-upload-acceptpaste-nonbool",
|
|
3747
|
+
"kind": "reject",
|
|
3748
|
+
"decoder": "node",
|
|
3749
|
+
"inputFile": "reject/reject-upload-acceptpaste-nonbool.json",
|
|
3750
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3751
|
+
"expectedPath": "$.kind.acceptPaste",
|
|
3752
|
+
"description": "a FileUpload `acceptPaste` of `1` — the second gesture slot, refused on the same reasoning and vectored separately because it is a separate decoder arm. A number is the shape a truthiness coercion is likeliest to admit, which is why this vector carries one where its `dropTarget` twin carries a string"
|
|
3753
|
+
},
|
|
3754
|
+
{
|
|
3755
|
+
"id": "reject-upload-destination-empty",
|
|
3756
|
+
"kind": "reject",
|
|
3757
|
+
"decoder": "node",
|
|
3758
|
+
"inputFile": "reject/reject-upload-destination-empty.json",
|
|
3759
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3760
|
+
"expectedPath": "$.kind.destination",
|
|
3761
|
+
"description": "a FileUpload `destination` of `\"\"` — refused rather than read as absence. The member names a host-registered destination and the empty string names none, so the document describes an upload that can never stream; reading it as \"no destination\" would silently turn a streaming upload into a client-only one, which is the one failure mode with no visible symptom"
|
|
3762
|
+
},
|
|
3763
|
+
{
|
|
3764
|
+
"id": "reject-upload-droptarget-nonbool",
|
|
3765
|
+
"kind": "reject",
|
|
3766
|
+
"decoder": "node",
|
|
3767
|
+
"inputFile": "reject/reject-upload-droptarget-nonbool.json",
|
|
3768
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3769
|
+
"expectedPath": "$.kind.dropTarget",
|
|
3770
|
+
"description": "a FileUpload `dropTarget` of `\"true\"` — refused rather than coerced. The slot decides whether a whole INGRESS ROUTE exists, and it omits at `false`, so absence already spells the plain picker: a present wrong-typed value can only mean the emitter meant something it did not say. A lenient truthiness read would open a drop target on `\"no\"` and `\"false\"` alike, and the reader would find out by dropping a file into a control that never listened for it"
|
|
3771
|
+
},
|
|
3009
3772
|
{
|
|
3010
3773
|
"id": "reject-wrongnodekind-sparkler",
|
|
3011
3774
|
"kind": "reject",
|
|
@@ -3024,6 +3787,15 @@
|
|
|
3024
3787
|
"expectedPath": "$.kind.$type",
|
|
3025
3788
|
"description": "Top-level kind 'Widget' is not a recognised node kind"
|
|
3026
3789
|
},
|
|
3790
|
+
{
|
|
3791
|
+
"id": "reject-wrongtype-box-break-before",
|
|
3792
|
+
"kind": "reject",
|
|
3793
|
+
"decoder": "node",
|
|
3794
|
+
"inputFile": "reject/reject-wrongtype-box-break-before.json",
|
|
3795
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3796
|
+
"expectedPath": "$.kind.breakBefore",
|
|
3797
|
+
"description": "Box breakBefore is the NUMBER 1, not a boolean — the truthy-integer spelling a JSON emitter reaches for, refused for the same reason as its sibling (Phase 1473)"
|
|
3798
|
+
},
|
|
3027
3799
|
{
|
|
3028
3800
|
"id": "reject-wrongtype-box-children",
|
|
3029
3801
|
"kind": "reject",
|
|
@@ -3033,6 +3805,24 @@
|
|
|
3033
3805
|
"expectedPath": "$.kind.children",
|
|
3034
3806
|
"description": "Box children is object not array"
|
|
3035
3807
|
},
|
|
3808
|
+
{
|
|
3809
|
+
"id": "reject-wrongtype-box-keep-together",
|
|
3810
|
+
"kind": "reject",
|
|
3811
|
+
"decoder": "node",
|
|
3812
|
+
"inputFile": "reject/reject-wrongtype-box-keep-together.json",
|
|
3813
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3814
|
+
"expectedPath": "$.kind.keepTogether",
|
|
3815
|
+
"description": "Box keepTogether is the STRING \"true\", not a boolean — the container arm of the print-break pair. Refused, never coerced: absence is the only spelling of \"not declared\" (Phase 1473)"
|
|
3816
|
+
},
|
|
3817
|
+
{
|
|
3818
|
+
"id": "reject-wrongtype-clipboard-payload",
|
|
3819
|
+
"kind": "reject",
|
|
3820
|
+
"decoder": "node",
|
|
3821
|
+
"inputFile": "reject/reject-wrongtype-clipboard-payload.json",
|
|
3822
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3823
|
+
"expectedPath": "$.kind.onClick.text",
|
|
3824
|
+
"description": "Action.WriteToClipboard's payload is a TextSource, so it is a string (the Literal shorthand) or a $type-tagged object — never a number. The refusal matters more here than at an ordinary text slot: the slot WIDENED in 1126 from a bare string, and a host that read the widening as \"anything goes\" would put a JSON literal on the reader's clipboard rather than refusing the document (Phase 1126)"
|
|
3825
|
+
},
|
|
3036
3826
|
{
|
|
3037
3827
|
"id": "reject-wrongtype-discriminator",
|
|
3038
3828
|
"kind": "reject",
|
|
@@ -3051,6 +3841,33 @@
|
|
|
3051
3841
|
"expectedPath": "$.kind.defaultSort.column",
|
|
3052
3842
|
"description": "bound-grid defaultSort column -1 — the same non-negative bound the staticRows spelling carries, same record, same message (Phase 861)"
|
|
3053
3843
|
},
|
|
3844
|
+
{
|
|
3845
|
+
"id": "reject-wrongtype-grid-exportable",
|
|
3846
|
+
"kind": "reject",
|
|
3847
|
+
"decoder": "node",
|
|
3848
|
+
"inputFile": "reject/reject-wrongtype-grid-exportable.json",
|
|
3849
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3850
|
+
"expectedPath": "$.kind.exportable",
|
|
3851
|
+
"description": "DataGrid exportable is the STRING \"true\", not a boolean — the shape a stringly-typed emitter produces. Refused, never coerced: coerced to false it would silently withdraw a declared affordance, coerced to true it would grow one the document never asked for (Phase 1125)"
|
|
3852
|
+
},
|
|
3853
|
+
{
|
|
3854
|
+
"id": "reject-wrongtype-grid-exportable-number",
|
|
3855
|
+
"kind": "reject",
|
|
3856
|
+
"decoder": "node",
|
|
3857
|
+
"inputFile": "reject/reject-wrongtype-grid-exportable-number.json",
|
|
3858
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3859
|
+
"expectedPath": "$.kind.exportable",
|
|
3860
|
+
"description": "DataGrid exportable is the NUMBER 1 — the truthy-integer spelling, pinned separately because a decoder can reject one non-boolean shape and accept another (Phase 1125)"
|
|
3861
|
+
},
|
|
3862
|
+
{
|
|
3863
|
+
"id": "reject-wrongtype-grid-keep-rows-together",
|
|
3864
|
+
"kind": "reject",
|
|
3865
|
+
"decoder": "node",
|
|
3866
|
+
"inputFile": "reject/reject-wrongtype-grid-keep-rows-together.json",
|
|
3867
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3868
|
+
"expectedPath": "$.kind.keepRowsTogether",
|
|
3869
|
+
"description": "DataGrid keepRowsTogether is a string — the GRID arm of the print-break pair, a decoder branch of its own that a container-arm vector says nothing about (Phase 1473)"
|
|
3870
|
+
},
|
|
3054
3871
|
{
|
|
3055
3872
|
"id": "reject-wrongtype-grid-page-size-zero",
|
|
3056
3873
|
"kind": "reject",
|
|
@@ -3060,6 +3877,33 @@
|
|
|
3060
3877
|
"expectedPath": "$.kind.pageSize",
|
|
3061
3878
|
"description": "grid pageSize 0 — a page of no rows names no page; the schema says the same with minimum:1 (Phase 862)"
|
|
3062
3879
|
},
|
|
3880
|
+
{
|
|
3881
|
+
"id": "reject-wrongtype-grid-repeat-header",
|
|
3882
|
+
"kind": "reject",
|
|
3883
|
+
"decoder": "node",
|
|
3884
|
+
"inputFile": "reject/reject-wrongtype-grid-repeat-header.json",
|
|
3885
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3886
|
+
"expectedPath": "$.kind.repeatHeader",
|
|
3887
|
+
"description": "DataGrid repeatHeader is an object, not a boolean — the fourth flag, read by its own call and so pinned on its own (Phase 1473)"
|
|
3888
|
+
},
|
|
3889
|
+
{
|
|
3890
|
+
"id": "reject-wrongtype-grid-transfer-in-key",
|
|
3891
|
+
"kind": "reject",
|
|
3892
|
+
"decoder": "node",
|
|
3893
|
+
"inputFile": "reject/reject-wrongtype-grid-transfer-in-key.json",
|
|
3894
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3895
|
+
"expectedPath": "$.kind.transferInKey",
|
|
3896
|
+
"description": "DataGrid transferInKey is a number — the slot names the shared State key a transfer travels on, so it is a key name and never an ordinal; a grid identified by position could not be paired with by any other grid (Phase 1123)"
|
|
3897
|
+
},
|
|
3898
|
+
{
|
|
3899
|
+
"id": "reject-wrongtype-grid-transfer-out-key",
|
|
3900
|
+
"kind": "reject",
|
|
3901
|
+
"decoder": "node",
|
|
3902
|
+
"inputFile": "reject/reject-wrongtype-grid-transfer-out-key.json",
|
|
3903
|
+
"expectedErrorCode": "WRONG_TYPE",
|
|
3904
|
+
"expectedPath": "$.kind.transferOutKey",
|
|
3905
|
+
"description": "DataGrid transferOutKey is a boolean — the releasing side names a KEY, never declares a flag; there is deliberately no boolean spelling of \"this grid may release rows\", because a release with no key names no counterpart and would be an affordance with nowhere to go (Phase 1123)"
|
|
3906
|
+
},
|
|
3063
3907
|
{
|
|
3064
3908
|
"id": "reject-wrongtype-heading-level",
|
|
3065
3909
|
"kind": "reject",
|