@ai-matrx/content-ir 0.10.1 → 0.10.3

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,57 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.3 — 2026-08-31
4
+
5
+ **Bug fix — inline objects nest to any depth, on the streaming path too.**
6
+ `validateObjectAgainstFields` always recursed without limit, but
7
+ `resolveParentFieldSchema` looked a field up only through KIND-typed parents.
8
+ A second-level `inline_object` was therefore invisible mid-stream: it
9
+ registered no inline context and closed as an untyped object
10
+ (`Object is missing "__kind"`), degrading the whole instance to
11
+ `kindState: "raw"` — for a shape the kind's own schema declares. Found
12
+ declaring the true `lulu_print_job` shape after 0.10.2
13
+ (`costs.shipping_cost`); the same seam also gates `json`-any opacity and
14
+ `record` members nested inside an inline object.
15
+
16
+ Field lookup now resolves through an inline-object parent's field map first.
17
+ Guard: `__tests__/kind-parser.test.ts` § "inline objects nest to any depth"
18
+ (three-deep nesting resolves; chunking-invariant so the streaming path is
19
+ covered; a wrong type deep inside still degrades), proven failing on the
20
+ unfixed parser with three `Object is missing "__kind"` raws.
21
+
22
+ ### Consumer action
23
+
24
+ None required — this only widens what validates. A mirror schema that flattened
25
+ a nested shape to `json` to survive can now declare the real `inline_object`.
26
+
27
+ ## 0.10.2 — 2026-08-30
28
+
29
+ **Bug fix — `nullable` is a FIELD law, not a scalar law.** `validateFinalFieldValue`
30
+ consulted `nullable` only on scalar-shaped fields and `json[]`. Every other branch
31
+ (`object`, `inline_object`, `record`, `array`, `string[]`/`number[]`/`boolean[]`)
32
+ opened with a shape check that reads `null` as a type violation and returned an error
33
+ before `nullable` was ever looked at — so a field a kind legitimately declares
34
+ nullable, whose value is genuinely `null`, failed validation and degraded the WHOLE
35
+ instance to `kindState: "raw"`, rendering through the `generic_structured` fallback.
36
+ Reproduced live on `lulu_print_job` (`costs: null`, `estimated_shipping_dates: null`).
37
+
38
+ `nullable` now short-circuits at the top of `validateFinalFieldValue` for every field
39
+ type, and the same law was applied to the streaming placement path
40
+ (`validateValueAgainstField`), where a `null` arrives as a scalar token and every
41
+ shape check would equally have rejected it — the sibling of the same defect. Messages
42
+ for non-nullable nulls are unchanged. Guard: three cases in
43
+ `__tests__/kind-parser.test.ts` (all five shapes null on a nullable field stays typed;
44
+ chunking-invariant so the streaming path is covered; a null on a NON-nullable field
45
+ still degrades), proven failing on the unfixed parser before the fix landed.
46
+
47
+ ### Consumer action
48
+
49
+ None required — this only widens what validates. Kinds that were declared `json` with
50
+ a comment to work around this bug (matrx-frontend `features/content-ir/kinds/print-kinds.ts`)
51
+ can go back to their true `object` / `inline_object` / `record` type with
52
+ `nullable: true`, and the ~23 existing sites already declaring `nullable: true` on an
53
+ object-shaped field stop being latent bugs.
54
+
3
55
  ## 0.10.0 — 2026-08-30
4
56
 
5
57
  **Non-breaking.** Every existing `@ai-matrx/content-ir` import keeps working
package/dist/core.cjs CHANGED
@@ -1654,9 +1654,10 @@ var KindStreamParser = class {
1654
1654
  }
1655
1655
  validateFinalFieldValue(fieldSchema, value, fieldName, objectKind) {
1656
1656
  if (fieldSchema.type === "json") return null;
1657
+ if (value === null && fieldSchema.nullable === true) return null;
1657
1658
  if (fieldSchema.type === "json[]") {
1658
1659
  if (value === null) {
1659
- return fieldSchema.nullable ? null : `Field "${fieldName}" on kind "${objectKind}" cannot be null.`;
1660
+ return `Field "${fieldName}" on kind "${objectKind}" cannot be null.`;
1660
1661
  }
1661
1662
  if (!Array.isArray(value)) {
1662
1663
  return `Field "${fieldName}" on kind "${objectKind}" must be an array.`;
@@ -1753,6 +1754,7 @@ var KindStreamParser = class {
1753
1754
  if (fieldSchema.type === "json") {
1754
1755
  return null;
1755
1756
  }
1757
+ if (value === null && fieldSchema.nullable === true) return null;
1756
1758
  if (fieldSchema.type === "array" || fieldSchema.type === "json[]") {
1757
1759
  return valueKind === "array" ? null : `Field "${fieldName}" must be an array.`;
1758
1760
  }
@@ -1881,6 +1883,8 @@ var KindStreamParser = class {
1881
1883
  const fieldKey = this.fieldKeyFromPath(path);
1882
1884
  if (!fieldKey) return void 0;
1883
1885
  const parentPath = path.slice(0, -1);
1886
+ const inlineFields = this.inlineSchemas.get(this.pathKey(parentPath));
1887
+ if (inlineFields) return inlineFields[fieldKey];
1884
1888
  const parentKind = this.getObjectKindForPath(parentPath);
1885
1889
  if (!parentKind) return void 0;
1886
1890
  return this.lookupSchema(parentKind)?.fields[fieldKey];