@ai-matrx/content-ir 0.19.20 → 0.19.21

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.21
4
+ ### Unreleased
5
+
6
+ - `/core` **A MISSING FIELD NEVER DEGRADES A BLOCK** (Arman, 2026-09-28). `validateObjectAgainstSchema` / `validateObjectAgainstFields` no longer turn an absent `required` field into a `raw_fallback`: the block resolves, the snapshot fills the field blank (`emptyValueForFieldSchema`), and the gap rides the residue. Only a PRESENT value of the wrong type is still a contract violation. A pure prediction (`expectedRootKind` / parent-schema speculation, no `__kind`, no surface) claims an object only when it carries at least one of the kind's fields, so unrelated data is never hidden behind an empty component. Effect: legacy `json_root_key` payloads (`quiz_title`, `comparison`, `decision_tree`, `diagram`, `presentation`, `math_problem`) now resolve to their kind while STREAMING and in client-only parses, instead of showing "missing required field" until the server's saved copy arrived. Consumer action: kind bridges must read their legacy wrapped/renamed shape (matrx-frontend `unwrapLegacyRoot` in `features/content-ir/kinds/legacy-bridge-utils.ts`).
7
+
3
8
  ## 0.19.20
4
9
  ### Unreleased
5
10
 
package/dist/core.cjs CHANGED
@@ -1268,7 +1268,7 @@ var KindStreamParser = class {
1268
1268
  }
1269
1269
  if (!declaredKind && committedKind && this.speculativeKinds.has(pathKey)) {
1270
1270
  this.speculativeKinds.delete(pathKey);
1271
- this.finalizeSpeculatedObject(path, objectValue, committedKind, at);
1271
+ this.finalizeSpeculatedObject(path, objectValue, committedKind, at, true);
1272
1272
  return;
1273
1273
  }
1274
1274
  if (path.length === 0 && !declaredKind && !committedKind && this.rootSurfaceKind) {
@@ -1346,7 +1346,7 @@ var KindStreamParser = class {
1346
1346
  });
1347
1347
  }
1348
1348
  /** Validate + complete an object typed purely by parent prediction. */
1349
- finalizeSpeculatedObject(path, objectValue, kind, at) {
1349
+ finalizeSpeculatedObject(path, objectValue, kind, at, requireSharedField = false) {
1350
1350
  const schema = this.lookupSchema(kind);
1351
1351
  if (!schema) {
1352
1352
  this.emitRawObject(
@@ -1359,6 +1359,15 @@ var KindStreamParser = class {
1359
1359
  );
1360
1360
  return;
1361
1361
  }
1362
+ if (requireSharedField && !Object.keys(objectValue).some((key) => key in schema.fields)) {
1363
+ this.emitRawObject(
1364
+ path,
1365
+ objectValue,
1366
+ `Object carries none of "${kind}"'s fields.`,
1367
+ at
1368
+ );
1369
+ return;
1370
+ }
1362
1371
  const outcome = this.validateObjectAgainstSchema(
1363
1372
  { ...objectValue, [KIND_KEY]: kind },
1364
1373
  schema
@@ -1619,16 +1628,7 @@ var KindStreamParser = class {
1619
1628
  ...emptyOutcome
1620
1629
  };
1621
1630
  }
1622
- for (const [fieldName, fieldSchema] of Object.entries(schema.fields)) {
1623
- if (fieldSchema.required) {
1624
- if (!(fieldName in objectValue)) {
1625
- return {
1626
- error: `Kind "${schema.kind}" is missing required field "${fieldName}".`,
1627
- ...emptyOutcome
1628
- };
1629
- }
1630
- continue;
1631
- }
1631
+ for (const fieldName of Object.keys(schema.fields)) {
1632
1632
  if (!(fieldName in objectValue)) {
1633
1633
  optionalMissing.push(fieldName);
1634
1634
  }
@@ -1835,17 +1835,7 @@ var KindStreamParser = class {
1835
1835
  validateObjectAgainstFields(objectValue, fields) {
1836
1836
  const optionalMissing = [];
1837
1837
  const extraFields = [];
1838
- const emptyOutcome = { optionalMissing, extraFields };
1839
- for (const [fieldName, fieldSchema] of Object.entries(fields)) {
1840
- if (fieldSchema.required) {
1841
- if (!(fieldName in objectValue)) {
1842
- return {
1843
- error: `Inline object is missing required field "${fieldName}".`,
1844
- ...emptyOutcome
1845
- };
1846
- }
1847
- continue;
1848
- }
1838
+ for (const fieldName of Object.keys(fields)) {
1849
1839
  if (!(fieldName in objectValue)) {
1850
1840
  optionalMissing.push(fieldName);
1851
1841
  }