cabloy 5.1.210 → 5.1.211

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.
Files changed (42) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +7 -0
  3. package/package.json +2 -1
  4. package/repo-agent-governance/managed-assets.json +6 -6
  5. package/repo-agent-governance/skills/cabloy-contract-loop/SKILL.md +14 -8
  6. package/repo-agent-governance/skills/cabloy-contract-loop/references/verification-checklist.md +4 -1
  7. package/repo-agent-governance/tests/governance.test.mjs +65 -0
  8. package/repo-docs/ai/playbook-contract-regeneration.md +2 -0
  9. package/repo-docs/frontend/openapi-sdk-guide.md +23 -4
  10. package/repo-docs/fullstack/contract-loop-playbook.md +8 -0
  11. package/repo-docs/fullstack/openapi-to-sdk.md +12 -6
  12. package/repo-docs/reference/repo-scripts.md +3 -0
  13. package/scripts/bootstrapAgentGovernance.mjs +18 -0
  14. package/scripts/generateOpenapiIsolated.test.ts +207 -0
  15. package/scripts/generateOpenapiIsolated.ts +91 -0
  16. package/scripts/runIsolatedTest.test.ts +90 -0
  17. package/scripts/runIsolatedTest.ts +157 -82
  18. package/scripts/upgrade.test.ts +113 -0
  19. package/scripts/upgrade.ts +32 -0
  20. package/vona/packages-cli/cli/package.json +1 -1
  21. package/vona/packages-cli/cli-set-api/package.json +1 -1
  22. package/vona/packages-vona/vona/package.json +1 -1
  23. package/vona/packages-vona/vona-core/package.json +1 -1
  24. package/vona/packages-vona/vona-core/src/lib/core/testClaim.test.ts +8 -1
  25. package/vona/packages-vona/vona-core/src/lib/core/testClaim.ts +2 -2
  26. package/vona/packages-vona/vona-mock/package.json +1 -1
  27. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  28. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  29. package/zova/openapi.config.test.ts +29 -0
  30. package/zova/openapi.config.ts +13 -4
  31. package/zova/packages-cli/cli/package.json +2 -2
  32. package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/project/openapi.config.ts +13 -4
  33. package/zova/packages-cli/cli-set-front/package.json +1 -1
  34. package/zova/packages-zova/zova/package.json +2 -2
  35. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +7 -7
  36. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +12 -0
  37. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +173 -72
  38. package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +8 -1
  39. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
  40. package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/schemaRefresh.ts +21 -12
  41. package/zova/src/suite-vendor/a-zova/modules/a-form/test/lib/schemaRefreshLifecycle.test.ts +112 -0
  42. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -82,6 +82,7 @@ export type ApiApiTrainingStudentdeleteForceResponseBody =
82
82
 
83
83
  @Api()
84
84
  export class ApiTrainingStudent extends BeanApiBase {
85
+ /** List Students */
85
86
  select(
86
87
  options?: {
87
88
  query?: ApiApiTrainingStudentselectRequestQuery;
@@ -93,6 +94,7 @@ export class ApiTrainingStudent extends BeanApiBase {
93
94
  );
94
95
  }
95
96
 
97
+ /** Create Student */
96
98
  create(body: ApiApiTrainingStudentcreateRequestBody, options?: IApiActionOptions) {
97
99
  return this.$fetch.post<any, ApiApiTrainingStudentcreateResponseBody>(
98
100
  ApiApiTrainingStudentcreatePath,
@@ -101,6 +103,7 @@ export class ApiTrainingStudent extends BeanApiBase {
101
103
  );
102
104
  }
103
105
 
106
+ /** View Student */
104
107
  view(
105
108
  options: {
106
109
  params: ApiApiTrainingStudentviewRequestParams;
@@ -112,6 +115,7 @@ export class ApiTrainingStudent extends BeanApiBase {
112
115
  );
113
116
  }
114
117
 
118
+ /** Delete Student */
115
119
  delete(
116
120
  options: {
117
121
  params: ApiApiTrainingStudentdeleteRequestParams;
@@ -123,6 +127,7 @@ export class ApiTrainingStudent extends BeanApiBase {
123
127
  );
124
128
  }
125
129
 
130
+ /** Update Student */
126
131
  update(
127
132
  body: ApiApiTrainingStudentupdateRequestBody,
128
133
  options: {
@@ -136,6 +141,7 @@ export class ApiTrainingStudent extends BeanApiBase {
136
141
  );
137
142
  }
138
143
 
144
+ /** View Student Summary */
139
145
  summary(
140
146
  options: {
141
147
  params: ApiApiTrainingStudentsummaryRequestParams;
@@ -147,7 +153,7 @@ export class ApiTrainingStudent extends BeanApiBase {
147
153
  );
148
154
  }
149
155
 
150
- /** Bulk Delete */
156
+ /** Bulk Delete Students */
151
157
  deleteBulk(body: ApiApiTrainingStudentdeleteBulkRequestBody, options?: IApiActionOptions) {
152
158
  return this.$fetch.post<any, ApiApiTrainingStudentdeleteBulkResponseBody>(
153
159
  ApiApiTrainingStudentdeleteBulkPath,
@@ -156,6 +162,7 @@ export class ApiTrainingStudent extends BeanApiBase {
156
162
  );
157
163
  }
158
164
 
165
+ /** Permanently Delete Student */
159
166
  deleteForce(
160
167
  options: {
161
168
  params: ApiApiTrainingStudentdeleteForceRequestParams;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-module-a-form",
3
- "version": "5.1.53",
3
+ "version": "5.1.54",
4
4
  "gitHead": "09d901d17140a80ee0764211b441cda72fd94663",
5
5
  "description": "",
6
6
  "keywords": [
@@ -238,18 +238,16 @@ function opaqueBehavior(value: unknown): boolean {
238
238
  );
239
239
  }
240
240
 
241
+ const pageEntryBlockOptions = ['blocks', 'resource', 'id', 'formScene', 'pageTitleKey', 'draft'];
241
242
  const blockOptions: Record<string, string[]> = {
242
- 'basic-pageentry:blockPageEntry': [
243
- 'blocks',
244
- 'resource',
245
- 'id',
246
- 'formScene',
247
- 'pageTitleKey',
248
- 'draft',
249
- ],
243
+ 'basic-pageentry:blockPageEntry': pageEntryBlockOptions,
244
+ 'start-pageentry:blockPageEntry': pageEntryBlockOptions,
250
245
  'basic-pageentry:blockForm': ['blocks'],
246
+ 'start-pageentry:blockForm': ['blocks'],
251
247
  'basic-form:blockFormLayout': ['formLayout'],
248
+ 'start-form:blockFormLayout': ['formLayout'],
252
249
  'basic-pageentry:blockToolbarRow': ['actions'],
250
+ 'start-pageentry:blockToolbarRow': ['actions'],
253
251
  };
254
252
 
255
253
  function safeLayoutNode(value: unknown): boolean {
@@ -317,7 +315,7 @@ function safeBlocks(value: unknown): boolean {
317
315
  );
318
316
  }
319
317
 
320
- // Only Basic's declared layout grammar owns these title strings. Rest data/options,
318
+ // Only Basic's and Start's declared layout grammar owns these title strings. Rest data/options,
321
319
  // action metadata, descriptions, field names, and unknown structures stay strict.
322
320
  function normalizeLayoutNode(value: unknown): unknown {
323
321
  if (!isRecord(value)) return value;
@@ -334,7 +332,12 @@ function normalizeBlocks(value: unknown): unknown {
334
332
  if (!isRecord(block) || !isRecord(block.options)) return block;
335
333
  const options = { ...block.options };
336
334
  if (Object.hasOwn(options, 'blocks')) options.blocks = normalizeBlocks(options.blocks);
337
- if (block.render === 'basic-form:blockFormLayout' && safeLayout(options.formLayout)) {
335
+ if (
336
+ ['basic-form:blockFormLayout', 'start-form:blockFormLayout'].includes(
337
+ block.render as string,
338
+ ) &&
339
+ safeLayout(options.formLayout)
340
+ ) {
338
341
  const layout = options.formLayout as Record<string, unknown>;
339
342
  options.formLayout = { children: (layout.children as unknown[]).map(normalizeLayoutNode) };
340
343
  }
@@ -425,7 +428,13 @@ export function createSchemaRefreshContract(
425
428
  const form = isRecord(rest.form) ? rest.form : undefined;
426
429
  const render = rest.render ?? form?.render;
427
430
  const renderType = isRecord(render) ? render.type : render;
428
- if (renderType !== 'basic-details:formFieldDetails') continue;
431
+ if (
432
+ !['basic-details:formFieldDetails', 'start-details:formFieldDetails'].includes(
433
+ String(renderType),
434
+ )
435
+ ) {
436
+ continue;
437
+ }
429
438
  for (const name of [
430
439
  property.key,
431
440
  property.schemaKey,
@@ -434,7 +443,7 @@ export function createSchemaRefreshContract(
434
443
  if (typeof name === 'string') detailNames.add(name);
435
444
  }
436
445
  }
437
- // Basic Details resolves its row schema through the exact hidden `_name` auxiliary.
446
+ // Basic and Start Details resolve row schemas through the exact hidden `_name` auxiliary.
438
447
  // It belongs to that nested form, not to an unrelated parent field's behavior scope.
439
448
  const auxiliaryDetails = new Set<string>();
440
449
  for (const property of effective) {
@@ -424,6 +424,118 @@ test(
424
424
  },
425
425
  );
426
426
 
427
+ test(
428
+ 'Start edit layout locale refresh preserves recovered input while localized custom options reset',
429
+ { concurrency: false },
430
+ async () => {
431
+ const nestedEffect = () => {};
432
+ const studentSchema = (locale: string) => {
433
+ const title = locale === 'en-us' ? 'Training Records' : '培训记录';
434
+ const result: any = schema(
435
+ locale,
436
+ {},
437
+ {
438
+ rest: {
439
+ blocks: [
440
+ {
441
+ render: 'start-pageentry:blockPageEntry',
442
+ options: {
443
+ blocks: [
444
+ {
445
+ render: 'start-pageentry:blockForm',
446
+ options: {
447
+ blocks: [
448
+ {
449
+ render: 'start-form:blockFormLayout',
450
+ options: {
451
+ formLayout: {
452
+ children: [
453
+ {
454
+ type: 'tabs',
455
+ children: [
456
+ {
457
+ type: 'tab',
458
+ title,
459
+ children: [{ type: 'field', name: 'name' }],
460
+ },
461
+ ],
462
+ },
463
+ ],
464
+ },
465
+ },
466
+ },
467
+ ],
468
+ },
469
+ },
470
+ {
471
+ render: 'start-pageentry:blockToolbarRow',
472
+ options: {
473
+ actions: [
474
+ {
475
+ render: 'start-form:actionSubmit',
476
+ options: { permission: { actionInherit: 'update' } },
477
+ },
478
+ ],
479
+ },
480
+ },
481
+ ],
482
+ },
483
+ },
484
+ ],
485
+ },
486
+ },
487
+ );
488
+ result.properties.level = {
489
+ type: 'number',
490
+ rest: {
491
+ form: {
492
+ render: 'training-student:formFieldLevel',
493
+ options: { items: [{ value: 1, title }] },
494
+ },
495
+ },
496
+ };
497
+ result.properties.trainingRecords = {
498
+ type: 'array',
499
+ rest: { form: { render: 'start-details:formFieldDetails' } },
500
+ items: {
501
+ type: 'object',
502
+ properties: {
503
+ subject: { type: 'string', rest: { onEffect: nestedEffect } },
504
+ },
505
+ },
506
+ };
507
+ return result;
508
+ };
509
+ await withRuntime(
510
+ { data: { name: 'baseline', level: 1 }, schema: studentSchema('en-us') },
511
+ async runtime => {
512
+ const name = await initializedField(runtime, inputBindingProps());
513
+ const level = await initializedField(runtime, {
514
+ name: 'level',
515
+ slotDefault: () => 'custom level options',
516
+ });
517
+ runtime.form.reset(
518
+ { name: 'recovered unsaved name', level: 2 },
519
+ { keepDefaultValues: true },
520
+ );
521
+ // Establish the post-recovery epoch before switching locales, like mounted fields do.
522
+ name.refresh();
523
+ level.refresh();
524
+ for (const locale of ['zh-cn', 'en-us']) {
525
+ runtime.form.form.setFieldValue('level', 2, { dontValidate: true });
526
+ runtime.events.length = 0;
527
+ runtime.select(locale, studentSchema(locale));
528
+ name.refresh();
529
+ level.refresh();
530
+ assert.equal(runtime.form.form.getFieldValue('name'), 'recovered unsaved name');
531
+ assert.equal(runtime.form.form.getFieldValue('level'), 1);
532
+ assert.deepEqual(runtime.changed, []);
533
+ }
534
+ },
535
+ );
536
+ },
537
+ );
538
+
427
539
  test(
428
540
  'locale replay preserves exact raw empty and falsy values',
429
541
  { concurrency: false },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-suite-a-zova",
3
- "version": "5.1.168",
3
+ "version": "5.1.169",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "zova",
6
6
  "license": "MIT",
@@ -15,7 +15,7 @@
15
15
  "zova-module-a-behaviors": "^5.1.22",
16
16
  "zova-module-a-command": "^5.1.35",
17
17
  "zova-module-a-fetch": "^5.1.25",
18
- "zova-module-a-form": "^5.1.53",
18
+ "zova-module-a-form": "^5.1.54",
19
19
  "zova-module-a-icon": "^5.1.27",
20
20
  "zova-module-a-interceptor": "^5.1.31",
21
21
  "zova-module-a-logger": "^5.1.28",