@techspokes/typescript-wsdl-client 0.34.0 → 0.36.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/README.md +1 -1
- package/dist/client/generateTypes.d.ts.map +1 -1
- package/dist/client/generateTypes.js +20 -0
- package/dist/compiler/schemaCompiler.d.ts +2 -0
- package/dist/compiler/schemaCompiler.d.ts.map +1 -1
- package/dist/compiler/schemaCompiler.js +31 -6
- package/dist/compiler/shapeResolver.js +4 -0
- package/dist/openapi/generateSchemas.d.ts.map +1 -1
- package/dist/openapi/generateSchemas.js +10 -2
- package/dist/test/generators.d.ts.map +1 -1
- package/dist/test/generators.js +19 -12
- package/dist/test/mockData.d.ts +5 -0
- package/dist/test/mockData.d.ts.map +1 -1
- package/dist/test/mockData.js +12 -2
- package/dist/util/attributeWildcards.d.ts +16 -0
- package/dist/util/attributeWildcards.d.ts.map +1 -0
- package/dist/util/attributeWildcards.js +14 -0
- package/docs/migration.md +1 -0
- package/docs/releases/README.md +1 -0
- package/docs/releases/v0.35.0.md +33 -0
- package/docs/releases/v0.36.0.md +32 -0
- package/docs/roadmap/README.md +14 -8
- package/docs/roadmap/v1.0-capability-conformance-framework.md +2 -2
- package/docs/roadmap/v1.0-contract-audit.md +2 -2
- package/docs/roadmap/v1.0-release-candidate-gates.md +4 -2
- package/docs/roadmap/v1.0-wsdl-coverage-matrix.md +21 -12
- package/docs/roadmap/v1.0-xs-anyattribute-wildcard-bag.md +930 -0
- package/docs/supported-patterns.md +17 -6
- package/docs/testing.md +18 -0
- package/package.json +11 -8
- package/src/runtime/clientStreamMethods.tpl.txt +1 -1
|
@@ -0,0 +1,930 @@
|
|
|
1
|
+
# xs:anyAttribute Wildcard Bag Implementation Plan
|
|
2
|
+
|
|
3
|
+
## Agentic Worker Requirement
|
|
4
|
+
|
|
5
|
+
REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
6
|
+
|
|
7
|
+
## Goal
|
|
8
|
+
|
|
9
|
+
Emit `xs:anyAttribute` wildcard attributes as a typed attribute-bag property so the capability can move from partial to supported before `1.0.0`.
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
Keep known XML attributes flattened as peer DTO properties. Emit wildcard attributes as one optional bag property named by `compiled.options.attributesKey`, defaulting to `$attributes`, because unknown attribute names can collide with child elements or known attributes. Reuse the generated client's existing input attribute-bag serialization path, and add TypeScript, OpenAPI, mock-data, conformance, and documentation evidence around that shape.
|
|
14
|
+
|
|
15
|
+
## Tech Stack
|
|
16
|
+
|
|
17
|
+
TypeScript strict mode, ESM, Node.js 24+, Vitest, OpenAPI 3.1 JSON Schema, Fastify generated gateway tests, existing conformance registry under `test/conformance/`.
|
|
18
|
+
|
|
19
|
+
## Current Evidence
|
|
20
|
+
|
|
21
|
+
Known attributes are emitted as peer TypeScript properties in `src/client/generateTypes.ts` and peer OpenAPI object properties in `src/openapi/generateSchemas.ts`. The generated client already serializes an input attribute bag from `attributesKeyIn`, default `$attributes`, into node-soap attributes in `src/client/generateClient.ts`.
|
|
22
|
+
|
|
23
|
+
The compiler already retains `attributeWildcards` on compiled types in `src/compiler/schemaCompiler.ts`. The conformance row `xs-anyattribute` currently proves only metadata retention and asserts that generated TypeScript, OpenAPI, and gateway schemas do not expose a wildcard bag.
|
|
24
|
+
|
|
25
|
+
## Target Contract
|
|
26
|
+
|
|
27
|
+
For a compiled type with `attributeWildcards`, generated TypeScript must include this property, using the configured attribute key:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
/** @xsd {"kind":"attributeWildcard","type":"xs:anyAttribute"} */
|
|
31
|
+
"$attributes"?: Record<string, string>;
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
OpenAPI must include the same property as an object of string values:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"type": "object",
|
|
39
|
+
"additionalProperties": {
|
|
40
|
+
"type": "string"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Generated mock data should include a minimal deterministic sample bag so generated tests exercise the path:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
{
|
|
49
|
+
"$attributes": {
|
|
50
|
+
"extra:trace": "sample"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Do not flatten wildcard attributes as peer properties. Do not loosen the entire schema with `additionalProperties: true`. Do not add a new CLI flag.
|
|
56
|
+
|
|
57
|
+
## Files
|
|
58
|
+
|
|
59
|
+
Modify `src/compiler/schemaCompiler.ts` to add `localAttributeWildcards` for complex-content extensions.
|
|
60
|
+
|
|
61
|
+
Modify `src/compiler/shapeResolver.ts` to preserve `localAttributeWildcards` during canonicalization.
|
|
62
|
+
|
|
63
|
+
Create `src/util/attributeWildcards.ts` to centralize the default bag name and schema helper.
|
|
64
|
+
|
|
65
|
+
Modify `src/client/generateTypes.ts` to emit the wildcard bag in generated interfaces.
|
|
66
|
+
|
|
67
|
+
Modify `src/openapi/generateSchemas.ts` to emit the wildcard bag in component schemas.
|
|
68
|
+
|
|
69
|
+
Modify `src/test/mockData.ts` to generate deterministic wildcard-bag sample data.
|
|
70
|
+
|
|
71
|
+
Modify `test/unit/mock-data.test.ts` to cover generated mock data for `attributeWildcards`.
|
|
72
|
+
|
|
73
|
+
Modify `test/unit/compiler-wildcards.test.ts` to cover `localAttributeWildcards` on extension types.
|
|
74
|
+
|
|
75
|
+
Modify `test/conformance/registry.ts` to promote `xs-anyattribute` to supported and assert the new downstream contract.
|
|
76
|
+
|
|
77
|
+
Modify generated support docs through `npm run docs:support-matrix`, then manually update `docs/supported-patterns.md`, `docs/roadmap/v1.0-wsdl-coverage-matrix.md`, `docs/roadmap/v1.0-capability-conformance-framework.md`, and `CHANGELOG.md`.
|
|
78
|
+
|
|
79
|
+
## Task 1: Add Failing Unit Tests For Compiler And Mock Data
|
|
80
|
+
|
|
81
|
+
### Files
|
|
82
|
+
|
|
83
|
+
- Modify: `test/unit/compiler-wildcards.test.ts`
|
|
84
|
+
- Modify: `test/unit/mock-data.test.ts`
|
|
85
|
+
|
|
86
|
+
- [ ] Step 1: Add a compiler test for local extension wildcard metadata
|
|
87
|
+
|
|
88
|
+
Append this test inside the existing `describe("compiler: wildcard retention", () => { ... })` block in `test/unit/compiler-wildcards.test.ts`:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
it("retains local xs:anyAttribute metadata separately on complexContent extensions", async () => {
|
|
92
|
+
const schema = `
|
|
93
|
+
<xs:complexType name="BaseWithWildcard">
|
|
94
|
+
<xs:sequence>
|
|
95
|
+
<xs:element name="baseValue" type="xs:string"/>
|
|
96
|
+
</xs:sequence>
|
|
97
|
+
<xs:anyAttribute namespace="##other" processContents="lax"/>
|
|
98
|
+
</xs:complexType>
|
|
99
|
+
<xs:complexType name="ExtendedWithWildcard">
|
|
100
|
+
<xs:complexContent>
|
|
101
|
+
<xs:extension base="tns:BaseWithWildcard">
|
|
102
|
+
<xs:sequence>
|
|
103
|
+
<xs:element name="childValue" type="xs:string"/>
|
|
104
|
+
</xs:sequence>
|
|
105
|
+
<xs:anyAttribute namespace="##any" processContents="skip"/>
|
|
106
|
+
</xs:extension>
|
|
107
|
+
</xs:complexContent>
|
|
108
|
+
</xs:complexType>
|
|
109
|
+
<xs:element name="StreamRequest" type="tns:ExtendedWithWildcard"/>
|
|
110
|
+
<xs:element name="StreamResponse" type="xs:string"/>`;
|
|
111
|
+
const compiled = await compileFromFixture(buildWsdl(schema), "extension-anyattribute");
|
|
112
|
+
const base = compiled.types.find((t) => t.name === "BaseWithWildcard");
|
|
113
|
+
const child = compiled.types.find((t) => t.name === "ExtendedWithWildcard");
|
|
114
|
+
|
|
115
|
+
expect(base?.attributeWildcards).toEqual([
|
|
116
|
+
{namespace: "##other", processContents: "lax"},
|
|
117
|
+
]);
|
|
118
|
+
expect((base as any).localAttributeWildcards).toBeUndefined();
|
|
119
|
+
expect(child?.attributeWildcards).toEqual([
|
|
120
|
+
{namespace: "##other", processContents: "lax"},
|
|
121
|
+
{namespace: "##any", processContents: "skip"},
|
|
122
|
+
]);
|
|
123
|
+
expect((child as any).localAttributeWildcards).toEqual([
|
|
124
|
+
{namespace: "##any", processContents: "skip"},
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- [ ] Step 2: Add mock-data tests for wildcard bags
|
|
130
|
+
|
|
131
|
+
Add these tests after `it("generates attribute-only types (no elements)", ... )` in `test/unit/mock-data.test.ts`:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
it("includes the default wildcard attribute bag for types with xs:anyAttribute", () => {
|
|
135
|
+
const catalog: CatalogForMocks = {
|
|
136
|
+
options: {
|
|
137
|
+
attributesKey: "$attributes",
|
|
138
|
+
},
|
|
139
|
+
meta: {
|
|
140
|
+
childType: {
|
|
141
|
+
AnyAttributeRequest: {value: "string"},
|
|
142
|
+
},
|
|
143
|
+
propMeta: {},
|
|
144
|
+
},
|
|
145
|
+
types: [
|
|
146
|
+
{
|
|
147
|
+
name: "AnyAttributeRequest",
|
|
148
|
+
attrs: [],
|
|
149
|
+
elems: [{name: "value", max: 1}],
|
|
150
|
+
attributeWildcards: [{namespace: "##other", processContents: "lax"}],
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
const result = generateMockData("AnyAttributeRequest", catalog);
|
|
155
|
+
expect(result).toMatchObject({
|
|
156
|
+
value: "sample",
|
|
157
|
+
$attributes: {
|
|
158
|
+
"extra:trace": "sample",
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("uses the configured attributesKey for wildcard attribute bags", () => {
|
|
164
|
+
const catalog: CatalogForMocks = {
|
|
165
|
+
options: {
|
|
166
|
+
attributesKey: "@@attrs",
|
|
167
|
+
},
|
|
168
|
+
meta: {
|
|
169
|
+
childType: {
|
|
170
|
+
AnyAttributeRequest: {value: "string"},
|
|
171
|
+
},
|
|
172
|
+
propMeta: {},
|
|
173
|
+
},
|
|
174
|
+
types: [
|
|
175
|
+
{
|
|
176
|
+
name: "AnyAttributeRequest",
|
|
177
|
+
attrs: [],
|
|
178
|
+
elems: [{name: "value", max: 1}],
|
|
179
|
+
attributeWildcards: [{namespace: "##any"}],
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
const result = generateMockData("AnyAttributeRequest", catalog);
|
|
184
|
+
expect(result).toMatchObject({
|
|
185
|
+
value: "sample",
|
|
186
|
+
"@@attrs": {
|
|
187
|
+
"extra:trace": "sample",
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
- [ ] Step 3: Run the focused tests and verify they fail
|
|
194
|
+
|
|
195
|
+
Run:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
npx vitest run test/unit/compiler-wildcards.test.ts test/unit/mock-data.test.ts
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Expected result: the new compiler test fails because `localAttributeWildcards` is missing, and the new mock-data tests fail at TypeScript compile time or runtime because `CatalogForMocks` does not expose `options.attributesKey` or `types[].attributeWildcards`.
|
|
202
|
+
|
|
203
|
+
## Task 2: Add Shared Wildcard Attribute Helpers
|
|
204
|
+
|
|
205
|
+
### Files
|
|
206
|
+
|
|
207
|
+
- Create: `src/util/attributeWildcards.ts`
|
|
208
|
+
|
|
209
|
+
- [ ] Step 1: Create the helper module
|
|
210
|
+
|
|
211
|
+
Create `src/util/attributeWildcards.ts`:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
export const DEFAULT_ATTRIBUTE_BAG_KEY = "$attributes";
|
|
215
|
+
|
|
216
|
+
export interface AttributeWildcardCarrier {
|
|
217
|
+
attributeWildcards?: readonly unknown[];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface AttributeWildcardOptions {
|
|
221
|
+
attributesKey?: string;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function hasAttributeWildcards(value: AttributeWildcardCarrier | undefined): boolean {
|
|
225
|
+
return Array.isArray(value?.attributeWildcards) && value.attributeWildcards.length > 0;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function wildcardAttributeBagName(options: AttributeWildcardOptions | undefined): string {
|
|
229
|
+
const configured = options?.attributesKey?.trim();
|
|
230
|
+
return configured && configured.length > 0 ? configured : DEFAULT_ATTRIBUTE_BAG_KEY;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function wildcardAttributeBagSchema(): {type: "object"; additionalProperties: {type: "string"}} {
|
|
234
|
+
return {
|
|
235
|
+
type: "object",
|
|
236
|
+
additionalProperties: {type: "string"},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
- [ ] Step 2: Run typecheck and verify the helper compiles
|
|
242
|
+
|
|
243
|
+
Run:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npm run typecheck
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Expected result: the command still fails because Task 1 intentionally introduced failing tests, or passes if tests are not part of the production TypeScript project. There must be no syntax error reported for `src/util/attributeWildcards.ts`.
|
|
250
|
+
|
|
251
|
+
## Task 3: Preserve Local Attribute Wildcards In Compiler Metadata
|
|
252
|
+
|
|
253
|
+
### Files
|
|
254
|
+
|
|
255
|
+
- Modify: `src/compiler/schemaCompiler.ts`
|
|
256
|
+
- Modify: `src/compiler/shapeResolver.ts`
|
|
257
|
+
|
|
258
|
+
- [ ] Step 1: Extend `CompiledType` with local wildcard metadata
|
|
259
|
+
|
|
260
|
+
In `src/compiler/schemaCompiler.ts`, add this documentation line after the `localElems` JSDoc line:
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
* @property {Array<Object>} [localAttributeWildcards] - Attribute wildcards added in extension
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Add this property to the `CompiledType` type after `attributeWildcards?: CompiledAttributeWildcard[];`:
|
|
267
|
+
|
|
268
|
+
```text
|
|
269
|
+
localAttributeWildcards?: CompiledAttributeWildcard[];
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
- [ ] Step 2: Store local wildcard metadata on complex-content extensions
|
|
273
|
+
|
|
274
|
+
In the complex-content extension result object in `getOrCompileComplex`, replace:
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
...(attributeWildcards.length > 0 ? {attributeWildcards} : {}),
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
with:
|
|
281
|
+
|
|
282
|
+
```text
|
|
283
|
+
...(attributeWildcards.length > 0 ? {attributeWildcards} : {}),
|
|
284
|
+
...(localAttributeWildcards.length > 0 ? {localAttributeWildcards} : {}),
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
- [ ] Step 3: Preserve local wildcard metadata in shape canonicalization
|
|
288
|
+
|
|
289
|
+
In `src/compiler/shapeResolver.ts`, find the canonicalized type object that already maps `attributeWildcards`. Add this property immediately after it:
|
|
290
|
+
|
|
291
|
+
```text
|
|
292
|
+
localAttributeWildcards: (t.localAttributeWildcards ?? []).map((w) => ({
|
|
293
|
+
...(w.namespace ? {namespace: w.namespace} : {}),
|
|
294
|
+
...(w.processContents ? {processContents: w.processContents} : {}),
|
|
295
|
+
})),
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
If the surrounding function omits empty optional arrays for `wildcards` and `attributeWildcards`, use the same conditional style already present in that function. The final emitted catalog must not add `localAttributeWildcards` to types that do not have local wildcard declarations.
|
|
299
|
+
|
|
300
|
+
- [ ] Step 4: Run the compiler wildcard test
|
|
301
|
+
|
|
302
|
+
Run:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
npx vitest run test/unit/compiler-wildcards.test.ts
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Expected result: the new `localAttributeWildcards` test passes. Existing wildcard tests still pass.
|
|
309
|
+
|
|
310
|
+
## Task 4: Emit Wildcard Attribute Bags In Generated TypeScript
|
|
311
|
+
|
|
312
|
+
### Files
|
|
313
|
+
|
|
314
|
+
- Modify: `src/client/generateTypes.ts`
|
|
315
|
+
|
|
316
|
+
- [ ] Step 1: Import the shared helpers
|
|
317
|
+
|
|
318
|
+
Add this import near the existing imports in `src/client/generateTypes.ts`:
|
|
319
|
+
|
|
320
|
+
```text
|
|
321
|
+
import {hasAttributeWildcards, wildcardAttributeBagName} from "../util/attributeWildcards.js";
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
- [ ] Step 2: Add a bag-name constant inside `generateTypes`
|
|
325
|
+
|
|
326
|
+
After `const isChoiceUnionMode = compiled.options.choice === "union";`, add:
|
|
327
|
+
|
|
328
|
+
```text
|
|
329
|
+
const wildcardBagName = wildcardAttributeBagName(compiled.options);
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
- [ ] Step 3: Add an emitter for wildcard bags
|
|
333
|
+
|
|
334
|
+
After `emitAttributeProperty`, add:
|
|
335
|
+
|
|
336
|
+
```text
|
|
337
|
+
const emitWildcardAttributeBagProperty = (indent: string) => {
|
|
338
|
+
const annObj = {
|
|
339
|
+
kind: "attributeWildcard" as const,
|
|
340
|
+
type: "xs:anyAttribute",
|
|
341
|
+
};
|
|
342
|
+
lines.push("");
|
|
343
|
+
lines.push(`${indent}/** @xsd ${JSON.stringify(annObj)} */`);
|
|
344
|
+
lines.push(`${indent}${emitPropName(wildcardBagName)}?: Record<string, string>;`);
|
|
345
|
+
};
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
- [ ] Step 4: Compute local wildcard bags for normal and choice-mode interfaces
|
|
349
|
+
|
|
350
|
+
After the `attrsToEmit` line, add:
|
|
351
|
+
|
|
352
|
+
```text
|
|
353
|
+
const wildcardCarrier = complexBase
|
|
354
|
+
? {attributeWildcards: t.localAttributeWildcards}
|
|
355
|
+
: {attributeWildcards: t.attributeWildcards};
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
- [ ] Step 5: Emit the bag in choice union base interfaces
|
|
359
|
+
|
|
360
|
+
In the choice-union branch, after the loop that emits attributes:
|
|
361
|
+
|
|
362
|
+
```text
|
|
363
|
+
for (const a of attrsToEmit) {
|
|
364
|
+
emitAttributeProperty(" ", a);
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
add:
|
|
369
|
+
|
|
370
|
+
```text
|
|
371
|
+
if (hasAttributeWildcards(wildcardCarrier)) {
|
|
372
|
+
emitWildcardAttributeBagProperty(" ");
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
- [ ] Step 6: Emit the bag in normal interfaces
|
|
377
|
+
|
|
378
|
+
In the normal interface branch, after the loop that emits attributes:
|
|
379
|
+
|
|
380
|
+
```text
|
|
381
|
+
for (const a of attrsToEmit) {
|
|
382
|
+
emitAttributeProperty(" ", a);
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
add:
|
|
387
|
+
|
|
388
|
+
```text
|
|
389
|
+
if (hasAttributeWildcards(wildcardCarrier)) {
|
|
390
|
+
emitWildcardAttributeBagProperty(" ");
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
- [ ] Step 7: Run snapshot tests to see the intentional diff
|
|
395
|
+
|
|
396
|
+
Run:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
npx vitest run test/snapshot
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Expected result: snapshots may fail only if the weather fixture contains `xs:anyAttribute`. If snapshots fail, inspect the diff and update only intentional generated type output later in Task 9.
|
|
403
|
+
|
|
404
|
+
## Task 5: Emit Wildcard Attribute Bags In OpenAPI Schemas
|
|
405
|
+
|
|
406
|
+
### Files
|
|
407
|
+
|
|
408
|
+
- Modify: `src/openapi/generateSchemas.ts`
|
|
409
|
+
|
|
410
|
+
- [ ] Step 1: Import the shared helpers
|
|
411
|
+
|
|
412
|
+
Add this import near the existing imports:
|
|
413
|
+
|
|
414
|
+
```text
|
|
415
|
+
import {hasAttributeWildcards, wildcardAttributeBagName, wildcardAttributeBagSchema} from "../util/attributeWildcards.js";
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
- [ ] Step 2: Add an `attributesKey` parameter to `buildComplexSchema`
|
|
419
|
+
|
|
420
|
+
Change the `buildComplexSchema` signature from:
|
|
421
|
+
|
|
422
|
+
```text
|
|
423
|
+
function buildComplexSchema(
|
|
424
|
+
t: CompiledType,
|
|
425
|
+
closed: boolean,
|
|
426
|
+
knownTypeNames: Set<string>,
|
|
427
|
+
aliasNames: Set<string>,
|
|
428
|
+
flattenWrappers: boolean,
|
|
429
|
+
choiceUnionMode: boolean,
|
|
430
|
+
): any {
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
to:
|
|
434
|
+
|
|
435
|
+
```text
|
|
436
|
+
function buildComplexSchema(
|
|
437
|
+
t: CompiledType,
|
|
438
|
+
closed: boolean,
|
|
439
|
+
knownTypeNames: Set<string>,
|
|
440
|
+
aliasNames: Set<string>,
|
|
441
|
+
flattenWrappers: boolean,
|
|
442
|
+
choiceUnionMode: boolean,
|
|
443
|
+
attributesKey: string,
|
|
444
|
+
): any {
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
- [ ] Step 3: Add the bag property after known attributes
|
|
448
|
+
|
|
449
|
+
After the `for (const a of t.attrs) { ... }` loop, add:
|
|
450
|
+
|
|
451
|
+
```text
|
|
452
|
+
if (hasAttributeWildcards(t)) {
|
|
453
|
+
properties[attributesKey] = wildcardAttributeBagSchema();
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
- [ ] Step 4: Pass the configured key from `generateSchemas`
|
|
458
|
+
|
|
459
|
+
In `generateSchemas`, add this constant after `const choiceUnionMode = ...` or near the other derived options:
|
|
460
|
+
|
|
461
|
+
```text
|
|
462
|
+
const attributesKey = wildcardAttributeBagName(compiled.options);
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Update the call to `buildComplexSchema` so the final argument list includes `attributesKey`:
|
|
466
|
+
|
|
467
|
+
```text
|
|
468
|
+
compiled.options.choice === "union",
|
|
469
|
+
attributesKey,
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
- [ ] Step 5: Run OpenAPI unit and conformance tests enough to observe failure movement
|
|
473
|
+
|
|
474
|
+
Run:
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
npx vitest run test/unit/openapi-choice-union.test.ts test/conformance/conformance.test.ts --runInBand
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Expected result: conformance still fails until Task 7 updates the registry assertions. OpenAPI generation must not throw for supported rows.
|
|
481
|
+
|
|
482
|
+
## Task 6: Generate Wildcard Attribute Bags In Mock Data
|
|
483
|
+
|
|
484
|
+
### Files
|
|
485
|
+
|
|
486
|
+
- Modify: `src/test/mockData.ts`
|
|
487
|
+
- Modify: `test/unit/mock-data.test.ts`
|
|
488
|
+
|
|
489
|
+
- [ ] Step 1: Import helpers
|
|
490
|
+
|
|
491
|
+
Add this import to `src/test/mockData.ts`:
|
|
492
|
+
|
|
493
|
+
```text
|
|
494
|
+
import {hasAttributeWildcards, wildcardAttributeBagName} from "../util/attributeWildcards.js";
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
- [ ] Step 2: Extend mock catalog types
|
|
498
|
+
|
|
499
|
+
Change the `CatalogForMocks` `options` type from:
|
|
500
|
+
|
|
501
|
+
```text
|
|
502
|
+
options?: {
|
|
503
|
+
choice?: "all-optional" | "union";
|
|
504
|
+
};
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
to:
|
|
508
|
+
|
|
509
|
+
```text
|
|
510
|
+
options?: {
|
|
511
|
+
attributesKey?: string;
|
|
512
|
+
choice?: "all-optional" | "union";
|
|
513
|
+
};
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Change the `types` entry type from:
|
|
517
|
+
|
|
518
|
+
```text
|
|
519
|
+
elems: Array<{ name: string; max: number | "unbounded" }>;
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
to:
|
|
523
|
+
|
|
524
|
+
```text
|
|
525
|
+
elems: Array<{ name: string; max: number | "unbounded" }>;
|
|
526
|
+
attributeWildcards?: Array<{namespace?: string; processContents?: "lax" | "strict" | "skip"}>;
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
- [ ] Step 3: Keep wildcard-only types from returning early
|
|
530
|
+
|
|
531
|
+
After `const typeMeta = catalog.types?.find((t) => t.name === typeName);`, add:
|
|
532
|
+
|
|
533
|
+
```text
|
|
534
|
+
const hasWildcardAttributes = hasAttributeWildcards(typeMeta);
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Move the existing early return below that line and change it to:
|
|
538
|
+
|
|
539
|
+
```text
|
|
540
|
+
if ((!childTypes || Object.keys(childTypes).length === 0) && !attrTypes && !hasWildcardAttributes) {
|
|
541
|
+
return {};
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
- [ ] Step 4: Add deterministic wildcard bag data
|
|
546
|
+
|
|
547
|
+
Before `return result;`, add:
|
|
548
|
+
|
|
549
|
+
```text
|
|
550
|
+
if (hasWildcardAttributes) {
|
|
551
|
+
const attributesKey = wildcardAttributeBagName(catalog.options);
|
|
552
|
+
if (!(attributesKey in result)) {
|
|
553
|
+
result[attributesKey] = {
|
|
554
|
+
"extra:trace": "sample",
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
- [ ] Step 5: Run mock-data tests
|
|
561
|
+
|
|
562
|
+
Run:
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
npx vitest run test/unit/mock-data.test.ts
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Expected result: all mock-data tests pass, including the new wildcard attribute bag tests.
|
|
569
|
+
|
|
570
|
+
## Task 7: Promote The Conformance Row To Supported
|
|
571
|
+
|
|
572
|
+
### Files
|
|
573
|
+
|
|
574
|
+
- Modify: `test/conformance/registry.ts`
|
|
575
|
+
|
|
576
|
+
- [ ] Step 1: Change row status and contract
|
|
577
|
+
|
|
578
|
+
In the `xs-anyattribute` row, replace:
|
|
579
|
+
|
|
580
|
+
```text
|
|
581
|
+
status: "partial",
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
with:
|
|
585
|
+
|
|
586
|
+
```text
|
|
587
|
+
status: "supported",
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Replace the current `publicContract` and `decisionReason` with:
|
|
591
|
+
|
|
592
|
+
```text
|
|
593
|
+
publicContract: "`xs:anyAttribute` is retained as catalog metadata and emitted as an optional wildcard attribute bag named by the configured attributes key.",
|
|
594
|
+
decision: "support",
|
|
595
|
+
decisionReason: "The compiler retains attribute wildcard metadata, and generated TypeScript, OpenAPI, gateway, generated-test, and app artifacts can represent wildcard attributes through the existing attribute-bag runtime path.",
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
- [ ] Step 2: Strengthen client expectations
|
|
599
|
+
|
|
600
|
+
Replace the `client` block for `xs-anyattribute` with:
|
|
601
|
+
|
|
602
|
+
```text
|
|
603
|
+
client: {
|
|
604
|
+
outcome: "success",
|
|
605
|
+
sourceIncludes: [
|
|
606
|
+
{file: "types", text: "\"$attributes\"?: Record<string, string>;"},
|
|
607
|
+
],
|
|
608
|
+
},
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
- [ ] Step 3: Strengthen OpenAPI expectations
|
|
612
|
+
|
|
613
|
+
Replace the existing `openapi.assert` body with:
|
|
614
|
+
|
|
615
|
+
```text
|
|
616
|
+
assert: ({doc}) => {
|
|
617
|
+
const schema = requireSchema(doc, "AnyAttributeRequest");
|
|
618
|
+
assertJsonEqual(
|
|
619
|
+
schema.properties?.$attributes,
|
|
620
|
+
{type: "object", additionalProperties: {type: "string"}},
|
|
621
|
+
"xs:anyAttribute should emit the configured wildcard attribute bag schema.",
|
|
622
|
+
);
|
|
623
|
+
if (schema.additionalProperties === true) {
|
|
624
|
+
throw new Error("xs:anyAttribute should not loosen the whole object schema.");
|
|
625
|
+
}
|
|
626
|
+
},
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
- [ ] Step 4: Exercise the bag through the generated gateway
|
|
630
|
+
|
|
631
|
+
Change the gateway request payload from:
|
|
632
|
+
|
|
633
|
+
```text
|
|
634
|
+
payload: {value: "known-only"},
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
to:
|
|
638
|
+
|
|
639
|
+
```text
|
|
640
|
+
payload: {value: "known-only", $attributes: {"extra:trace": "sample"}},
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Change the `assertClientArgs` expectation to:
|
|
644
|
+
|
|
645
|
+
```text
|
|
646
|
+
assertClientArgs: args => assertJsonEqual(
|
|
647
|
+
args,
|
|
648
|
+
{value: "known-only", $attributes: {"extra:trace": "sample"}},
|
|
649
|
+
"Gateway should pass the modeled xs:anyAttribute bag to the client.",
|
|
650
|
+
),
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
Change the gateway schema assertion from rejecting `$attributes` to requiring it:
|
|
654
|
+
|
|
655
|
+
```text
|
|
656
|
+
assert: ({readGatewayFile}) => {
|
|
657
|
+
const schemaSource = readGatewayFile("schemas/models/anyattributerequest.json");
|
|
658
|
+
if (!schemaSource.includes("\"$attributes\"")) {
|
|
659
|
+
throw new Error("xs:anyAttribute gateway schema should emit a wildcard attribute bag.");
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
- [ ] Step 5: Strengthen generated-test expectations
|
|
665
|
+
|
|
666
|
+
Replace the `generatedTests` block with:
|
|
667
|
+
|
|
668
|
+
```text
|
|
669
|
+
generatedTests: {
|
|
670
|
+
outcome: "success",
|
|
671
|
+
sourceIncludes: [
|
|
672
|
+
{file: "helpers/mock-client.ts", text: "\"$attributes\""},
|
|
673
|
+
{file: "helpers/mock-client.ts", text: "\"extra:trace\""},
|
|
674
|
+
],
|
|
675
|
+
},
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
- [ ] Step 6: Run conformance and verify failure points
|
|
679
|
+
|
|
680
|
+
Run:
|
|
681
|
+
|
|
682
|
+
```bash
|
|
683
|
+
npm run test:conformance
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
Expected result before Tasks 3 through 6 are complete: this fails on missing generated type, schema, gateway, or generated-test evidence. Expected result after Tasks 3 through 6 are complete: all conformance tests pass.
|
|
687
|
+
|
|
688
|
+
## Task 8: Update Human-Authored Documentation
|
|
689
|
+
|
|
690
|
+
### Files
|
|
691
|
+
|
|
692
|
+
- Modify: `docs/supported-patterns.md`
|
|
693
|
+
- Modify: `docs/roadmap/v1.0-wsdl-coverage-matrix.md`
|
|
694
|
+
- Modify: `docs/roadmap/v1.0-capability-conformance-framework.md`
|
|
695
|
+
- Modify: `CHANGELOG.md`
|
|
696
|
+
|
|
697
|
+
- [ ] Step 1: Regenerate the support matrix
|
|
698
|
+
|
|
699
|
+
Run:
|
|
700
|
+
|
|
701
|
+
```bash
|
|
702
|
+
npm run docs:support-matrix
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
Expected result: the generated matrix in `docs/supported-patterns.md` changes the `xs-anyattribute` status from `partial` to `supported` and uses the updated public contract.
|
|
706
|
+
|
|
707
|
+
- [ ] Step 2: Update the explanatory `xs:anyAttribute` section
|
|
708
|
+
|
|
709
|
+
In `docs/supported-patterns.md`, replace the `### xs:anyAttribute` paragraph with:
|
|
710
|
+
|
|
711
|
+
```markdown
|
|
712
|
+
### xs:anyAttribute
|
|
713
|
+
|
|
714
|
+
Attribute wildcards are retained as catalog metadata and emitted as an optional wildcard attribute bag on the enclosing generated type. The bag property uses the configured client attributes key, defaulting to `$attributes`, and maps arbitrary wildcard attribute names to string values.
|
|
715
|
+
|
|
716
|
+
Known XML attributes remain flattened as peer properties. Wildcard attributes stay inside the bag so unknown names do not collide with child elements or known attributes.
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
- [ ] Step 3: Move `xs:anyAttribute` from partial to supported in the full support list
|
|
720
|
+
|
|
721
|
+
In `docs/supported-patterns.md`, add this bullet under `## Fully Supported`:
|
|
722
|
+
|
|
723
|
+
```markdown
|
|
724
|
+
- `xs:anyAttribute` wildcard attributes emitted as an optional configured attribute bag, defaulting to `$attributes`
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
Remove this bullet from `## Not Yet Supported` if present:
|
|
728
|
+
|
|
729
|
+
```markdown
|
|
730
|
+
- Full `xs:any` serialization: arbitrary wildcard content is not emitted as a typed contract
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
Do not remove `xs:any` particle limitations unless a separate `xs:any` content implementation is done. If the existing bullet is about element wildcards, rewrite it to:
|
|
734
|
+
|
|
735
|
+
```markdown
|
|
736
|
+
- Full `xs:any` element serialization: arbitrary wildcard element content is not emitted as a typed contract
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
- [ ] Step 4: Update roadmap wording
|
|
740
|
+
|
|
741
|
+
In `docs/roadmap/v1.0-wsdl-coverage-matrix.md`, change the priority row for `xs:anyAttribute` from:
|
|
742
|
+
|
|
743
|
+
```markdown
|
|
744
|
+
| `xs:anyAttribute` | partial | Metadata retained; generated wildcard attributes deferred |
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
to:
|
|
748
|
+
|
|
749
|
+
```markdown
|
|
750
|
+
| `xs:anyAttribute` | supported | Metadata retained; wildcard attribute bag emitted |
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
In the same file, remove `xs:anyAttribute` from any list of partial-row caveats.
|
|
754
|
+
|
|
755
|
+
In `docs/roadmap/v1.0-capability-conformance-framework.md`, replace this sentence:
|
|
756
|
+
|
|
757
|
+
```markdown
|
|
758
|
+
For partial rows, prove the documented subset and avoid implying full support. For `xs-anyattribute`, gateway evidence should prove generation and runtime do not emit or require wildcard attribute bags. For external `PolicyReference`, gateway evidence should prove no generated inbound security requirement appears unless configured elsewhere.
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
with:
|
|
762
|
+
|
|
763
|
+
```markdown
|
|
764
|
+
For partial rows, prove the documented subset and avoid implying full support. External `PolicyReference` should not imply fetched or enforced external policy. The `xs-anyattribute` row is supported once generated TypeScript, OpenAPI, gateway, generated-test, and app evidence prove the configured wildcard attribute bag.
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
- [ ] Step 5: Update changelog
|
|
768
|
+
|
|
769
|
+
If the existing Unreleased roadmap bullet is still present, add this bullet under `## [Unreleased]` in `CHANGELOG.md`:
|
|
770
|
+
|
|
771
|
+
```markdown
|
|
772
|
+
- feat(xsd): emit `xs:anyAttribute` wildcard bags in generated contracts
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
Do not remove the existing `docs(roadmap): align 1.0 readiness docs with the 0.35.0 baseline` bullet unless the user explicitly asks to split changes into separate commits.
|
|
776
|
+
|
|
777
|
+
## Task 9: Run Focused Verification And Update Snapshots If Needed
|
|
778
|
+
|
|
779
|
+
### Files
|
|
780
|
+
|
|
781
|
+
- Test: `test/unit/compiler-wildcards.test.ts`
|
|
782
|
+
- Test: `test/unit/mock-data.test.ts`
|
|
783
|
+
- Test: `test/conformance/`
|
|
784
|
+
- Test: `test/snapshot/`
|
|
785
|
+
|
|
786
|
+
- [ ] Step 1: Run unit tests for changed internals
|
|
787
|
+
|
|
788
|
+
Run:
|
|
789
|
+
|
|
790
|
+
```bash
|
|
791
|
+
npx vitest run test/unit/compiler-wildcards.test.ts test/unit/mock-data.test.ts
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
Expected result: all tests pass.
|
|
795
|
+
|
|
796
|
+
- [ ] Step 2: Run conformance
|
|
797
|
+
|
|
798
|
+
Run:
|
|
799
|
+
|
|
800
|
+
```bash
|
|
801
|
+
npm run test:conformance
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
Expected result: all conformance tests pass, and `xs-anyattribute` is now a supported row.
|
|
805
|
+
|
|
806
|
+
- [ ] Step 3: Run snapshot tests
|
|
807
|
+
|
|
808
|
+
Run:
|
|
809
|
+
|
|
810
|
+
```bash
|
|
811
|
+
npm run test:snap
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
Expected result: snapshots pass if the weather fixture has no `xs:anyAttribute`. If snapshots fail because generated output intentionally changed, update snapshots with:
|
|
815
|
+
|
|
816
|
+
```bash
|
|
817
|
+
npx vitest run test/snapshot -u
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
After updating snapshots, run:
|
|
821
|
+
|
|
822
|
+
```bash
|
|
823
|
+
npm run test:snap
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
Expected result: snapshot tests pass after reviewing the diff.
|
|
827
|
+
|
|
828
|
+
- [ ] Step 4: Run docs validation
|
|
829
|
+
|
|
830
|
+
Run:
|
|
831
|
+
|
|
832
|
+
```bash
|
|
833
|
+
npm run docs:validate
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
Expected result: Markdown links, TypeScript fenced snippets, and support matrix checks pass.
|
|
837
|
+
|
|
838
|
+
## Task 10: Run End-To-End Verification
|
|
839
|
+
|
|
840
|
+
### Files
|
|
841
|
+
|
|
842
|
+
- No source edits expected.
|
|
843
|
+
|
|
844
|
+
- [ ] Step 1: Run typecheck
|
|
845
|
+
|
|
846
|
+
Run:
|
|
847
|
+
|
|
848
|
+
```bash
|
|
849
|
+
npm run typecheck
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
Expected result: TypeScript reports no errors.
|
|
853
|
+
|
|
854
|
+
- [ ] Step 2: Run the required smoke pipeline
|
|
855
|
+
|
|
856
|
+
Run:
|
|
857
|
+
|
|
858
|
+
```bash
|
|
859
|
+
npm run smoke:pipeline
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
Expected result: the command regenerates disposable output under `tmp/smoke/`, generates client, OpenAPI, gateway, and app artifacts, and `tsc -p tsconfig.smoke.json` passes.
|
|
863
|
+
|
|
864
|
+
- [ ] Step 3: Run the full test suite
|
|
865
|
+
|
|
866
|
+
Run:
|
|
867
|
+
|
|
868
|
+
```bash
|
|
869
|
+
npm test
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
Expected result: all Vitest tests pass.
|
|
873
|
+
|
|
874
|
+
- [ ] Step 4: Run full CI before release-candidate work
|
|
875
|
+
|
|
876
|
+
Run:
|
|
877
|
+
|
|
878
|
+
```bash
|
|
879
|
+
npm run ci
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
Expected result: build, typecheck, skill validation, package validation, docs validation, Vitest, and smoke pipeline pass.
|
|
883
|
+
|
|
884
|
+
## Task 11: Review Diff And Commit
|
|
885
|
+
|
|
886
|
+
### Files
|
|
887
|
+
|
|
888
|
+
- Review: all modified files from Tasks 1 through 10.
|
|
889
|
+
|
|
890
|
+
- [ ] Step 1: Inspect changed files
|
|
891
|
+
|
|
892
|
+
Run:
|
|
893
|
+
|
|
894
|
+
```bash
|
|
895
|
+
git status --short
|
|
896
|
+
git diff --stat
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
Expected result: only implementation, test, docs, changelog, and possible snapshot files are modified.
|
|
900
|
+
|
|
901
|
+
- [ ] Step 2: Review semantic diff
|
|
902
|
+
|
|
903
|
+
Run:
|
|
904
|
+
|
|
905
|
+
```bash
|
|
906
|
+
git diff
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
Expected result: the diff shows `xs:anyAttribute` moving from metadata-only partial support to supported wildcard-bag output. It must not include unrelated formatting churn or generated output under `tmp/`.
|
|
910
|
+
|
|
911
|
+
- [ ] Step 3: Commit the implementation if requested by the maintainer
|
|
912
|
+
|
|
913
|
+
Run:
|
|
914
|
+
|
|
915
|
+
```bash
|
|
916
|
+
git add src/compiler/schemaCompiler.ts src/compiler/shapeResolver.ts src/util/attributeWildcards.ts src/client/generateTypes.ts src/openapi/generateSchemas.ts src/test/mockData.ts test/unit/compiler-wildcards.test.ts test/unit/mock-data.test.ts test/conformance/registry.ts docs/supported-patterns.md docs/roadmap/v1.0-wsdl-coverage-matrix.md docs/roadmap/v1.0-capability-conformance-framework.md CHANGELOG.md
|
|
917
|
+
git commit -m "Version: 0.35.1 feat(xsd): emit anyAttribute wildcard bags"
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
Expected result: git creates a focused commit. If snapshot files changed intentionally, include those snapshot files in the `git add` command before committing.
|
|
921
|
+
|
|
922
|
+
## Self-Review
|
|
923
|
+
|
|
924
|
+
Spec coverage: The plan covers naming, TypeScript shape, OpenAPI shape, runtime reuse, mock generation, conformance promotion, docs, and verification.
|
|
925
|
+
|
|
926
|
+
Placeholder scan: The plan contains no deferred-work markers or unspecified implementation steps.
|
|
927
|
+
|
|
928
|
+
Type consistency: The plan uses `attributeWildcards`, `localAttributeWildcards`, `attributesKey`, `$attributes`, `Record<string, string>`, and `extra:trace` consistently across compiler, emitters, mocks, and tests.
|
|
929
|
+
|
|
930
|
+
Risk check: The plan intentionally does not implement explicit binding selection, external `PolicyReference` resolution, or full `xs:any` element wildcard serialization.
|