@ai-matrx/content-ir 0.2.2 → 0.5.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/dist/index.d.cts CHANGED
@@ -12,8 +12,20 @@ import { ComponentType } from 'react';
12
12
  */
13
13
  /** Path of a value inside a parsed region (object keys + array indices). */
14
14
  type IrPath = Array<string | number>;
15
- /** How a node's kind was (or wasn't) established. */
16
- type IrKindState = "resolved" | "speculative" | "pending_kind" | "pending_schema" | "raw";
15
+ /**
16
+ * How a node's kind was (or wasn't) established.
17
+ *
18
+ * 🚨 `unverified` IS NOT `raw`, AND THE DIFFERENCE IS LOAD-BEARING (Arman's
19
+ * ruling, 2026-08-29). "We checked it and it is wrong" and "we had nothing to
20
+ * check it with" are opposite facts about a payload, and collapsing them cost
21
+ * ~221 live kinds their component overnight: a kind whose schema never loaded
22
+ * degraded to `raw`, the render route read `raw` as "broken instance", and
23
+ * perfectly valid payloads were dumped as key/value lists instead of reaching
24
+ * the component the user built. A consumer that treats `unverified` as a
25
+ * failure is reintroducing that outage — the data is intact and MAY be
26
+ * entirely valid; all that is missing is the schema that would prove it.
27
+ */
28
+ type IrKindState = "resolved" | "speculative" | "pending_kind" | "pending_schema" | "unverified" | "raw";
17
29
  /**
18
30
  * System-level zero-data-loss channel. Unknown keys are NEVER merged into a
19
31
  * node's `value` (they'd be indistinguishable from schema fields); they are
@@ -290,6 +302,16 @@ interface SchemaResolver {
290
302
  kindForJsonRootKey?(key: string): string | null;
291
303
  }
292
304
  declare function setJsonRootKeyLookup(lookup: ((key: string) => string | null) | null): void;
305
+ /**
306
+ * Why a node degraded off the `resolved` path.
307
+ *
308
+ * `"unverified"` is reserved for ONE situation: no schema was registered for
309
+ * an identified kind, so no check ever ran. Every other degrade — a schema
310
+ * violation, an array-item kind mismatch, a duplicate key, a bad field
311
+ * placement, a contradicted speculation — is `"invalid"`: something checked
312
+ * the node and it failed.
313
+ */
314
+ type RawObjectCause = "unverified" | "invalid";
293
315
  type KindStreamEvent = {
294
316
  type: "kind_identified";
295
317
  kind: string;
@@ -336,15 +358,23 @@ type KindStreamEvent = {
336
358
  value: unknown;
337
359
  reason: string;
338
360
  /**
339
- * The kind that WAS identified for this node before it degraded raw
340
- * present ONLY for schema-availability failures ("no schema registered"
341
- * for an identified/declared kind), never for structural failures
342
- * (missing __kind, duplicate keys, schema violations). Consumers use it
343
- * to preserve a known-but-unrenderable kind on the envelope so the
344
- * render seam can route to the generic viewer (or upgrade when the
345
- * schema arrives late) instead of dumping raw JSON.
361
+ * The kind that WAS identified for this node before it degraded set
362
+ * for schema-availability degrades AND (since 2026-08-29) structural
363
+ * ones, so a payload that said what it is stays acknowledged as an
364
+ * instance of that kind. Absent only when nothing ever identified it
365
+ * (an object with no `__kind` at all).
346
366
  */
347
367
  kind?: string;
368
+ /**
369
+ * WHY this node is not `resolved` — the discriminator the render route
370
+ * reads. See `IrKindState` for why collapsing these two is an outage.
371
+ *
372
+ * - `"unverified"`: no schema was available, so nothing was checked.
373
+ * The value is intact and may be perfectly valid.
374
+ * - `"invalid"` (default): a check RAN and the node failed it, or the
375
+ * node is structurally broken (duplicate key, bad placement).
376
+ */
377
+ cause?: RawObjectCause;
348
378
  at: number;
349
379
  } | {
350
380
  type: "optional_field_missing";
@@ -462,7 +492,7 @@ declare class KindStreamParser {
462
492
  * Recorded at the first root key; ADOPTED only when the root object closes
463
493
  * (`completeTypedObject`). That is the surface registry's complete-only
464
494
  * convergence law, and every json_root_key row is `streaming:false` — these
465
- * legacy shapes are recognised by their whole payload, so speculating
495
+ * legacy shapes are recognized by their whole payload, so speculating
466
496
  * mid-stream would flash a kind component over an object that may never
467
497
  * satisfy the schema. An explicit `expectedRootKind` (an agent's declared
468
498
  * output schema) is stronger context and always wins; an actual `__kind`
@@ -508,6 +538,14 @@ declare class KindStreamParser {
508
538
  private completeRoot;
509
539
  /** Mark a node raw (node-scoped failure) without killing the stream. */
510
540
  private markNodeRaw;
541
+ /**
542
+ * Degrade ONE node off the resolved path.
543
+ *
544
+ * `cause` defaults to `"invalid"` deliberately: every call site that omits
545
+ * it is a real failure (validation, duplicate key, placement, contradicted
546
+ * speculation). ONLY the "no schema registered" sites pass `"unverified"`,
547
+ * and they are the reason the parameter exists — see `IrKindState`.
548
+ */
511
549
  private emitRawObject;
512
550
  private clearKindWait;
513
551
  private emitFieldIfReady;
@@ -596,11 +634,20 @@ declare class IrTree {
596
634
  */
597
635
  private readonly earlyFields;
598
636
  /**
599
- * pathKey → identified kind preserved through a SCHEMA-AVAILABILITY raw
600
- * fallback (parser stamped `kind` on the raw_object event). Structural raws
601
- * (missing __kind, duplicate key, validation failure) never land here.
637
+ * pathKey → identified kind preserved through a raw fallback (parser stamped
638
+ * `kind` on the raw_object event) schema-availability degrades and, since
639
+ * 2026-08-29, structural ones too. Only a node nothing ever identified (no
640
+ * `__kind` at all) is absent here.
602
641
  */
603
642
  private readonly rawKinds;
643
+ /**
644
+ * pathKey → WHY the node degraded. `"unverified"` means no schema was
645
+ * available and nothing was ever checked; `"invalid"` means a check ran and
646
+ * failed. THE RENDER ROUTE BRANCHES ON THIS — see `IrKindState`. Absent =
647
+ * `"invalid"`, so a parser that predates the `cause` field (or any consumer
648
+ * hand-building events) keeps the strict, safe reading.
649
+ */
650
+ private readonly rawCauses;
604
651
  private regionStatus;
605
652
  private errorReason;
606
653
  private rootRawValue;
@@ -877,7 +924,7 @@ declare function envelopeCacheFromEnvelopes(envelopes: readonly CanonicalBlockIR
877
924
  *
878
925
  * The frontend host shell is `redux/render-block-envelope.ts` (binds the
879
926
  * hooks to `seedEnvelope` + `captureError`); aidream's Workflow Studio binds
880
- * its own. Contract: features/content-ir/docs/PYTHON_ENVELOPE_CONTRACT.md.
927
+ * its own. Contract: /Users/armanisadeghi/code/common-docs/systems/content-ir-system/PYTHON_ENVELOPE_CONTRACT.md.
881
928
  */
882
929
 
883
930
  /** Read a CanonicalBlockIR envelope off a block's metadata (or anything). */
@@ -1194,7 +1241,7 @@ interface KindDefinition {
1194
1241
  * edges → the same `KindSchema` the parser/emitter consume, re-attaching
1195
1242
  * `object.kind` / `array.itemKinds` from the edges by path.
1196
1243
  *
1197
- * Design invariants (KIND_REGISTRY_STORAGE.md §4):
1244
+ * Design invariants (from the 2026-07-05 kind-registry storage design, since deleted):
1198
1245
  * - The `data` element is `FieldSchema` + `name`, MINUS ref targets. Order is
1199
1246
  * intrinsic to the array (fixes the jsonb key-reorder bug).
1200
1247
  * - `kind_edge` is the SINGLE source of truth for kind→kind refs: `object`
@@ -1334,7 +1381,7 @@ declare function storageToKindSchema(kind: string, shape: KindStorageShape): Kin
1334
1381
  * row out of production. This module is PURE (deps injected) so it runs in the
1335
1382
  * harness, in CI, and in a browser author-save alike.
1336
1383
  *
1337
- * Ownership split (KIND_REGISTRY_STORAGE.md §2): the caller writes the outcome
1384
+ * Ownership split (the 2026-07-05 kind-registry storage design, since deleted; the live contract is the code below): the caller writes the outcome
1338
1385
  * to the LIVE `content_ir.kind_definition` row's `is_active`; the canonical
1339
1386
  * `_version_capture` trigger snapshots that state into `history.row_versions`
1340
1387
  * (never a post-hoc history mutation).
@@ -1932,4 +1979,4 @@ declare function emitPayloadJson(kind: string, value: unknown): string;
1932
1979
  */
1933
1980
  declare function emitPayloadFence(kind: string, value: unknown): string;
1934
1981
 
1935
- export { type AnyPartialKindEvent, type ArrayItemKindBinding, type ArrayItemScalarType, type BlockSchemaDraft, type CanonicalBlockIR, type CanonicalContent, type CanonicalSegment, type CompleteValueEnvelopeOptions, type CompliantKindSnapshot, type ContentRegionInit, type ConversionProblem, type DroppedMetadata, type DualGateDefinition, type DualGateInput, type DualGateResolvedComponent, type DualGateResult, type FieldComparison, type FieldSchema, type Fingerprinter, IR_ENVELOPE_CACHE_VERSION, IR_ENVELOPE_KEY, IR_PARTIAL_KEY, IR_VERSION, type InboundEnvelopeHooks, type InboundEnvelopeVerdict, type IrDiscriminator, type IrEnvelopeCache, type IrKindState, type IrPath, type IrResidue, type IrStructuredNode, IrTree, type IrTreeNode, type ItemKindRefCheck, JSON_DISCRIMINATOR, type JsonPath, type JsonSchemaNode, JsonStreamTokenizer, type JsonToken, KIND_KEY, type KindBlockProps, type KindDefinition, type KindEdgeSpec, type KindJsonSchemaExport, type KindJsonSchemaOptions, type KindResolution, type KindSchema, KindStorageError, type KindStorageShape, type KindStreamEvent, KindStreamParser, type KindStreamParserOptions, type KindTier, type KindVerdict, type LegResult, NODE_OUTCOME_KIND, type NodeOutcomeWrapper, type NormalizeJsonRegionOptions, ParseSession, type ParseSessionOptions, type PartialKindEvent, type PartialKindNode, type PartialKindState, type Punct, ROOT_STORAGE_NAME, RUN_RESULT_KIND, type RecordValueType, type RegionEndReason, type RegionFormat, type RegionSourceKind, type RetractedKindEvent, type RunResultWrapper, type SavePlanEntry, type SavePlanValidation, type ScalarFieldType, type SchemaConversionResult, type SchemaLayoutMode, type SchemaResolver, type StoredFieldElement, type SupersededKindEvent, advancePartialKind, buildAgentSchemaWithRenderBlockSupport, buildCompliantKindSnapshot, classifyInboundEnvelopeMetadata, collectReferencedKinds, collectSchemaReferencedKinds, compareWithExistingKindSchema, convertAiSchemaToBlockFields, createFingerprinter, createKindStreamParser, describeDualGateFailure, disposeParseSession, emitPayloadFence, emitPayloadJson, emptyValueForFieldSchema, envelopeCacheFromEnvelopes, envelopeFromCompleteValue, fenceDiscriminator, fieldsToDbPayload, fingerprintText, formatBlockLabel, getParseSession, injectKindIntoObjectSchema, irPathIsUnderOrEqual, irPathKey, irPathLabel, irPathsEqual, isCanonicalBlockIR, isDuplicateBlockSlug, isEmptyResidue, isIrEnvelopeCache, isJsonAnyField, isProvisionalKind, isScalarArrayType, isTerminalKindEvent, kindSchemaToJsonSchema, kindSchemaToStorage, kindVerdictOf, makePartialKindStalenessGate, mergeResidueIntoValue, normalizeAiSchemaInput, normalizeJsonRegion, openParseSession, readEnvelope, readNodeOutcomeValue, readObjectKind, readOutputRef, readPartialKindEvent, readRunResultValue, reconstructRegionValue, rehydrateNodeOutcome, rehydrateRunResult, reuseEnvelopeIfCurrent, runKindDualGate, runSchemaConversion, sanitizeInboundEnvelopeMetadata, sanitizeInboundPartialKindMetadata, scalarArrayItemType, schemaLayoutMode, schemaStructureDepth, setJsonRootKeyLookup, storageToKindSchema, stripKindDeep, validateBlockSchemaSavePlan, validateStructuralLeg, withRootKind, xmlDiscriminator };
1982
+ export { type AnyPartialKindEvent, type ArrayItemKindBinding, type ArrayItemScalarType, type BlockSchemaDraft, type CanonicalBlockIR, type CanonicalContent, type CanonicalSegment, type CompleteValueEnvelopeOptions, type CompliantKindSnapshot, type ContentRegionInit, type ConversionProblem, type DroppedMetadata, type DualGateDefinition, type DualGateInput, type DualGateResolvedComponent, type DualGateResult, type FieldComparison, type FieldSchema, type Fingerprinter, IR_ENVELOPE_CACHE_VERSION, IR_ENVELOPE_KEY, IR_PARTIAL_KEY, IR_VERSION, type InboundEnvelopeHooks, type InboundEnvelopeVerdict, type IrDiscriminator, type IrEnvelopeCache, type IrKindState, type IrPath, type IrResidue, type IrStructuredNode, IrTree, type IrTreeNode, type ItemKindRefCheck, JSON_DISCRIMINATOR, type JsonPath, type JsonSchemaNode, JsonStreamTokenizer, type JsonToken, KIND_KEY, type KindBlockProps, type KindDefinition, type KindEdgeSpec, type KindJsonSchemaExport, type KindJsonSchemaOptions, type KindResolution, type KindSchema, KindStorageError, type KindStorageShape, type KindStreamEvent, KindStreamParser, type KindStreamParserOptions, type KindTier, type KindVerdict, type LegResult, NODE_OUTCOME_KIND, type NodeOutcomeWrapper, type NormalizeJsonRegionOptions, ParseSession, type ParseSessionOptions, type PartialKindEvent, type PartialKindNode, type PartialKindState, type Punct, ROOT_STORAGE_NAME, RUN_RESULT_KIND, type RawObjectCause, type RecordValueType, type RegionEndReason, type RegionFormat, type RegionSourceKind, type RetractedKindEvent, type RunResultWrapper, type SavePlanEntry, type SavePlanValidation, type ScalarFieldType, type SchemaConversionResult, type SchemaLayoutMode, type SchemaResolver, type StoredFieldElement, type SupersededKindEvent, advancePartialKind, buildAgentSchemaWithRenderBlockSupport, buildCompliantKindSnapshot, classifyInboundEnvelopeMetadata, collectReferencedKinds, collectSchemaReferencedKinds, compareWithExistingKindSchema, convertAiSchemaToBlockFields, createFingerprinter, createKindStreamParser, describeDualGateFailure, disposeParseSession, emitPayloadFence, emitPayloadJson, emptyValueForFieldSchema, envelopeCacheFromEnvelopes, envelopeFromCompleteValue, fenceDiscriminator, fieldsToDbPayload, fingerprintText, formatBlockLabel, getParseSession, injectKindIntoObjectSchema, irPathIsUnderOrEqual, irPathKey, irPathLabel, irPathsEqual, isCanonicalBlockIR, isDuplicateBlockSlug, isEmptyResidue, isIrEnvelopeCache, isJsonAnyField, isProvisionalKind, isScalarArrayType, isTerminalKindEvent, kindSchemaToJsonSchema, kindSchemaToStorage, kindVerdictOf, makePartialKindStalenessGate, mergeResidueIntoValue, normalizeAiSchemaInput, normalizeJsonRegion, openParseSession, readEnvelope, readNodeOutcomeValue, readObjectKind, readOutputRef, readPartialKindEvent, readRunResultValue, reconstructRegionValue, rehydrateNodeOutcome, rehydrateRunResult, reuseEnvelopeIfCurrent, runKindDualGate, runSchemaConversion, sanitizeInboundEnvelopeMetadata, sanitizeInboundPartialKindMetadata, scalarArrayItemType, schemaLayoutMode, schemaStructureDepth, setJsonRootKeyLookup, storageToKindSchema, stripKindDeep, validateBlockSchemaSavePlan, validateStructuralLeg, withRootKind, xmlDiscriminator };
package/dist/index.d.ts CHANGED
@@ -12,8 +12,20 @@ import { ComponentType } from 'react';
12
12
  */
13
13
  /** Path of a value inside a parsed region (object keys + array indices). */
14
14
  type IrPath = Array<string | number>;
15
- /** How a node's kind was (or wasn't) established. */
16
- type IrKindState = "resolved" | "speculative" | "pending_kind" | "pending_schema" | "raw";
15
+ /**
16
+ * How a node's kind was (or wasn't) established.
17
+ *
18
+ * 🚨 `unverified` IS NOT `raw`, AND THE DIFFERENCE IS LOAD-BEARING (Arman's
19
+ * ruling, 2026-08-29). "We checked it and it is wrong" and "we had nothing to
20
+ * check it with" are opposite facts about a payload, and collapsing them cost
21
+ * ~221 live kinds their component overnight: a kind whose schema never loaded
22
+ * degraded to `raw`, the render route read `raw` as "broken instance", and
23
+ * perfectly valid payloads were dumped as key/value lists instead of reaching
24
+ * the component the user built. A consumer that treats `unverified` as a
25
+ * failure is reintroducing that outage — the data is intact and MAY be
26
+ * entirely valid; all that is missing is the schema that would prove it.
27
+ */
28
+ type IrKindState = "resolved" | "speculative" | "pending_kind" | "pending_schema" | "unverified" | "raw";
17
29
  /**
18
30
  * System-level zero-data-loss channel. Unknown keys are NEVER merged into a
19
31
  * node's `value` (they'd be indistinguishable from schema fields); they are
@@ -290,6 +302,16 @@ interface SchemaResolver {
290
302
  kindForJsonRootKey?(key: string): string | null;
291
303
  }
292
304
  declare function setJsonRootKeyLookup(lookup: ((key: string) => string | null) | null): void;
305
+ /**
306
+ * Why a node degraded off the `resolved` path.
307
+ *
308
+ * `"unverified"` is reserved for ONE situation: no schema was registered for
309
+ * an identified kind, so no check ever ran. Every other degrade — a schema
310
+ * violation, an array-item kind mismatch, a duplicate key, a bad field
311
+ * placement, a contradicted speculation — is `"invalid"`: something checked
312
+ * the node and it failed.
313
+ */
314
+ type RawObjectCause = "unverified" | "invalid";
293
315
  type KindStreamEvent = {
294
316
  type: "kind_identified";
295
317
  kind: string;
@@ -336,15 +358,23 @@ type KindStreamEvent = {
336
358
  value: unknown;
337
359
  reason: string;
338
360
  /**
339
- * The kind that WAS identified for this node before it degraded raw
340
- * present ONLY for schema-availability failures ("no schema registered"
341
- * for an identified/declared kind), never for structural failures
342
- * (missing __kind, duplicate keys, schema violations). Consumers use it
343
- * to preserve a known-but-unrenderable kind on the envelope so the
344
- * render seam can route to the generic viewer (or upgrade when the
345
- * schema arrives late) instead of dumping raw JSON.
361
+ * The kind that WAS identified for this node before it degraded set
362
+ * for schema-availability degrades AND (since 2026-08-29) structural
363
+ * ones, so a payload that said what it is stays acknowledged as an
364
+ * instance of that kind. Absent only when nothing ever identified it
365
+ * (an object with no `__kind` at all).
346
366
  */
347
367
  kind?: string;
368
+ /**
369
+ * WHY this node is not `resolved` — the discriminator the render route
370
+ * reads. See `IrKindState` for why collapsing these two is an outage.
371
+ *
372
+ * - `"unverified"`: no schema was available, so nothing was checked.
373
+ * The value is intact and may be perfectly valid.
374
+ * - `"invalid"` (default): a check RAN and the node failed it, or the
375
+ * node is structurally broken (duplicate key, bad placement).
376
+ */
377
+ cause?: RawObjectCause;
348
378
  at: number;
349
379
  } | {
350
380
  type: "optional_field_missing";
@@ -462,7 +492,7 @@ declare class KindStreamParser {
462
492
  * Recorded at the first root key; ADOPTED only when the root object closes
463
493
  * (`completeTypedObject`). That is the surface registry's complete-only
464
494
  * convergence law, and every json_root_key row is `streaming:false` — these
465
- * legacy shapes are recognised by their whole payload, so speculating
495
+ * legacy shapes are recognized by their whole payload, so speculating
466
496
  * mid-stream would flash a kind component over an object that may never
467
497
  * satisfy the schema. An explicit `expectedRootKind` (an agent's declared
468
498
  * output schema) is stronger context and always wins; an actual `__kind`
@@ -508,6 +538,14 @@ declare class KindStreamParser {
508
538
  private completeRoot;
509
539
  /** Mark a node raw (node-scoped failure) without killing the stream. */
510
540
  private markNodeRaw;
541
+ /**
542
+ * Degrade ONE node off the resolved path.
543
+ *
544
+ * `cause` defaults to `"invalid"` deliberately: every call site that omits
545
+ * it is a real failure (validation, duplicate key, placement, contradicted
546
+ * speculation). ONLY the "no schema registered" sites pass `"unverified"`,
547
+ * and they are the reason the parameter exists — see `IrKindState`.
548
+ */
511
549
  private emitRawObject;
512
550
  private clearKindWait;
513
551
  private emitFieldIfReady;
@@ -596,11 +634,20 @@ declare class IrTree {
596
634
  */
597
635
  private readonly earlyFields;
598
636
  /**
599
- * pathKey → identified kind preserved through a SCHEMA-AVAILABILITY raw
600
- * fallback (parser stamped `kind` on the raw_object event). Structural raws
601
- * (missing __kind, duplicate key, validation failure) never land here.
637
+ * pathKey → identified kind preserved through a raw fallback (parser stamped
638
+ * `kind` on the raw_object event) schema-availability degrades and, since
639
+ * 2026-08-29, structural ones too. Only a node nothing ever identified (no
640
+ * `__kind` at all) is absent here.
602
641
  */
603
642
  private readonly rawKinds;
643
+ /**
644
+ * pathKey → WHY the node degraded. `"unverified"` means no schema was
645
+ * available and nothing was ever checked; `"invalid"` means a check ran and
646
+ * failed. THE RENDER ROUTE BRANCHES ON THIS — see `IrKindState`. Absent =
647
+ * `"invalid"`, so a parser that predates the `cause` field (or any consumer
648
+ * hand-building events) keeps the strict, safe reading.
649
+ */
650
+ private readonly rawCauses;
604
651
  private regionStatus;
605
652
  private errorReason;
606
653
  private rootRawValue;
@@ -877,7 +924,7 @@ declare function envelopeCacheFromEnvelopes(envelopes: readonly CanonicalBlockIR
877
924
  *
878
925
  * The frontend host shell is `redux/render-block-envelope.ts` (binds the
879
926
  * hooks to `seedEnvelope` + `captureError`); aidream's Workflow Studio binds
880
- * its own. Contract: features/content-ir/docs/PYTHON_ENVELOPE_CONTRACT.md.
927
+ * its own. Contract: /Users/armanisadeghi/code/common-docs/systems/content-ir-system/PYTHON_ENVELOPE_CONTRACT.md.
881
928
  */
882
929
 
883
930
  /** Read a CanonicalBlockIR envelope off a block's metadata (or anything). */
@@ -1194,7 +1241,7 @@ interface KindDefinition {
1194
1241
  * edges → the same `KindSchema` the parser/emitter consume, re-attaching
1195
1242
  * `object.kind` / `array.itemKinds` from the edges by path.
1196
1243
  *
1197
- * Design invariants (KIND_REGISTRY_STORAGE.md §4):
1244
+ * Design invariants (from the 2026-07-05 kind-registry storage design, since deleted):
1198
1245
  * - The `data` element is `FieldSchema` + `name`, MINUS ref targets. Order is
1199
1246
  * intrinsic to the array (fixes the jsonb key-reorder bug).
1200
1247
  * - `kind_edge` is the SINGLE source of truth for kind→kind refs: `object`
@@ -1334,7 +1381,7 @@ declare function storageToKindSchema(kind: string, shape: KindStorageShape): Kin
1334
1381
  * row out of production. This module is PURE (deps injected) so it runs in the
1335
1382
  * harness, in CI, and in a browser author-save alike.
1336
1383
  *
1337
- * Ownership split (KIND_REGISTRY_STORAGE.md §2): the caller writes the outcome
1384
+ * Ownership split (the 2026-07-05 kind-registry storage design, since deleted; the live contract is the code below): the caller writes the outcome
1338
1385
  * to the LIVE `content_ir.kind_definition` row's `is_active`; the canonical
1339
1386
  * `_version_capture` trigger snapshots that state into `history.row_versions`
1340
1387
  * (never a post-hoc history mutation).
@@ -1932,4 +1979,4 @@ declare function emitPayloadJson(kind: string, value: unknown): string;
1932
1979
  */
1933
1980
  declare function emitPayloadFence(kind: string, value: unknown): string;
1934
1981
 
1935
- export { type AnyPartialKindEvent, type ArrayItemKindBinding, type ArrayItemScalarType, type BlockSchemaDraft, type CanonicalBlockIR, type CanonicalContent, type CanonicalSegment, type CompleteValueEnvelopeOptions, type CompliantKindSnapshot, type ContentRegionInit, type ConversionProblem, type DroppedMetadata, type DualGateDefinition, type DualGateInput, type DualGateResolvedComponent, type DualGateResult, type FieldComparison, type FieldSchema, type Fingerprinter, IR_ENVELOPE_CACHE_VERSION, IR_ENVELOPE_KEY, IR_PARTIAL_KEY, IR_VERSION, type InboundEnvelopeHooks, type InboundEnvelopeVerdict, type IrDiscriminator, type IrEnvelopeCache, type IrKindState, type IrPath, type IrResidue, type IrStructuredNode, IrTree, type IrTreeNode, type ItemKindRefCheck, JSON_DISCRIMINATOR, type JsonPath, type JsonSchemaNode, JsonStreamTokenizer, type JsonToken, KIND_KEY, type KindBlockProps, type KindDefinition, type KindEdgeSpec, type KindJsonSchemaExport, type KindJsonSchemaOptions, type KindResolution, type KindSchema, KindStorageError, type KindStorageShape, type KindStreamEvent, KindStreamParser, type KindStreamParserOptions, type KindTier, type KindVerdict, type LegResult, NODE_OUTCOME_KIND, type NodeOutcomeWrapper, type NormalizeJsonRegionOptions, ParseSession, type ParseSessionOptions, type PartialKindEvent, type PartialKindNode, type PartialKindState, type Punct, ROOT_STORAGE_NAME, RUN_RESULT_KIND, type RecordValueType, type RegionEndReason, type RegionFormat, type RegionSourceKind, type RetractedKindEvent, type RunResultWrapper, type SavePlanEntry, type SavePlanValidation, type ScalarFieldType, type SchemaConversionResult, type SchemaLayoutMode, type SchemaResolver, type StoredFieldElement, type SupersededKindEvent, advancePartialKind, buildAgentSchemaWithRenderBlockSupport, buildCompliantKindSnapshot, classifyInboundEnvelopeMetadata, collectReferencedKinds, collectSchemaReferencedKinds, compareWithExistingKindSchema, convertAiSchemaToBlockFields, createFingerprinter, createKindStreamParser, describeDualGateFailure, disposeParseSession, emitPayloadFence, emitPayloadJson, emptyValueForFieldSchema, envelopeCacheFromEnvelopes, envelopeFromCompleteValue, fenceDiscriminator, fieldsToDbPayload, fingerprintText, formatBlockLabel, getParseSession, injectKindIntoObjectSchema, irPathIsUnderOrEqual, irPathKey, irPathLabel, irPathsEqual, isCanonicalBlockIR, isDuplicateBlockSlug, isEmptyResidue, isIrEnvelopeCache, isJsonAnyField, isProvisionalKind, isScalarArrayType, isTerminalKindEvent, kindSchemaToJsonSchema, kindSchemaToStorage, kindVerdictOf, makePartialKindStalenessGate, mergeResidueIntoValue, normalizeAiSchemaInput, normalizeJsonRegion, openParseSession, readEnvelope, readNodeOutcomeValue, readObjectKind, readOutputRef, readPartialKindEvent, readRunResultValue, reconstructRegionValue, rehydrateNodeOutcome, rehydrateRunResult, reuseEnvelopeIfCurrent, runKindDualGate, runSchemaConversion, sanitizeInboundEnvelopeMetadata, sanitizeInboundPartialKindMetadata, scalarArrayItemType, schemaLayoutMode, schemaStructureDepth, setJsonRootKeyLookup, storageToKindSchema, stripKindDeep, validateBlockSchemaSavePlan, validateStructuralLeg, withRootKind, xmlDiscriminator };
1982
+ export { type AnyPartialKindEvent, type ArrayItemKindBinding, type ArrayItemScalarType, type BlockSchemaDraft, type CanonicalBlockIR, type CanonicalContent, type CanonicalSegment, type CompleteValueEnvelopeOptions, type CompliantKindSnapshot, type ContentRegionInit, type ConversionProblem, type DroppedMetadata, type DualGateDefinition, type DualGateInput, type DualGateResolvedComponent, type DualGateResult, type FieldComparison, type FieldSchema, type Fingerprinter, IR_ENVELOPE_CACHE_VERSION, IR_ENVELOPE_KEY, IR_PARTIAL_KEY, IR_VERSION, type InboundEnvelopeHooks, type InboundEnvelopeVerdict, type IrDiscriminator, type IrEnvelopeCache, type IrKindState, type IrPath, type IrResidue, type IrStructuredNode, IrTree, type IrTreeNode, type ItemKindRefCheck, JSON_DISCRIMINATOR, type JsonPath, type JsonSchemaNode, JsonStreamTokenizer, type JsonToken, KIND_KEY, type KindBlockProps, type KindDefinition, type KindEdgeSpec, type KindJsonSchemaExport, type KindJsonSchemaOptions, type KindResolution, type KindSchema, KindStorageError, type KindStorageShape, type KindStreamEvent, KindStreamParser, type KindStreamParserOptions, type KindTier, type KindVerdict, type LegResult, NODE_OUTCOME_KIND, type NodeOutcomeWrapper, type NormalizeJsonRegionOptions, ParseSession, type ParseSessionOptions, type PartialKindEvent, type PartialKindNode, type PartialKindState, type Punct, ROOT_STORAGE_NAME, RUN_RESULT_KIND, type RawObjectCause, type RecordValueType, type RegionEndReason, type RegionFormat, type RegionSourceKind, type RetractedKindEvent, type RunResultWrapper, type SavePlanEntry, type SavePlanValidation, type ScalarFieldType, type SchemaConversionResult, type SchemaLayoutMode, type SchemaResolver, type StoredFieldElement, type SupersededKindEvent, advancePartialKind, buildAgentSchemaWithRenderBlockSupport, buildCompliantKindSnapshot, classifyInboundEnvelopeMetadata, collectReferencedKinds, collectSchemaReferencedKinds, compareWithExistingKindSchema, convertAiSchemaToBlockFields, createFingerprinter, createKindStreamParser, describeDualGateFailure, disposeParseSession, emitPayloadFence, emitPayloadJson, emptyValueForFieldSchema, envelopeCacheFromEnvelopes, envelopeFromCompleteValue, fenceDiscriminator, fieldsToDbPayload, fingerprintText, formatBlockLabel, getParseSession, injectKindIntoObjectSchema, irPathIsUnderOrEqual, irPathKey, irPathLabel, irPathsEqual, isCanonicalBlockIR, isDuplicateBlockSlug, isEmptyResidue, isIrEnvelopeCache, isJsonAnyField, isProvisionalKind, isScalarArrayType, isTerminalKindEvent, kindSchemaToJsonSchema, kindSchemaToStorage, kindVerdictOf, makePartialKindStalenessGate, mergeResidueIntoValue, normalizeAiSchemaInput, normalizeJsonRegion, openParseSession, readEnvelope, readNodeOutcomeValue, readObjectKind, readOutputRef, readPartialKindEvent, readRunResultValue, reconstructRegionValue, rehydrateNodeOutcome, rehydrateRunResult, reuseEnvelopeIfCurrent, runKindDualGate, runSchemaConversion, sanitizeInboundEnvelopeMetadata, sanitizeInboundPartialKindMetadata, scalarArrayItemType, schemaLayoutMode, schemaStructureDepth, setJsonRootKeyLookup, storageToKindSchema, stripKindDeep, validateBlockSchemaSavePlan, validateStructuralLeg, withRootKind, xmlDiscriminator };
package/dist/index.js CHANGED
@@ -105,11 +105,20 @@ var IrTree = class {
105
105
  */
106
106
  earlyFields = /* @__PURE__ */ new Map();
107
107
  /**
108
- * pathKey → identified kind preserved through a SCHEMA-AVAILABILITY raw
109
- * fallback (parser stamped `kind` on the raw_object event). Structural raws
110
- * (missing __kind, duplicate key, validation failure) never land here.
108
+ * pathKey → identified kind preserved through a raw fallback (parser stamped
109
+ * `kind` on the raw_object event) schema-availability degrades and, since
110
+ * 2026-08-29, structural ones too. Only a node nothing ever identified (no
111
+ * `__kind` at all) is absent here.
111
112
  */
112
113
  rawKinds = /* @__PURE__ */ new Map();
114
+ /**
115
+ * pathKey → WHY the node degraded. `"unverified"` means no schema was
116
+ * available and nothing was ever checked; `"invalid"` means a check ran and
117
+ * failed. THE RENDER ROUTE BRANCHES ON THIS — see `IrKindState`. Absent =
118
+ * `"invalid"`, so a parser that predates the `cause` field (or any consumer
119
+ * hand-building events) keeps the strict, safe reading.
120
+ */
121
+ rawCauses = /* @__PURE__ */ new Map();
113
122
  regionStatus = "streaming";
114
123
  errorReason = null;
115
124
  rootRawValue = null;
@@ -162,6 +171,7 @@ var IrTree = class {
162
171
  this.pendingSchemaPaths.delete(pathKey);
163
172
  this.earlyFields.delete(pathKey);
164
173
  if (event.kind) this.rawKinds.set(pathKey, event.kind);
174
+ this.rawCauses.set(pathKey, event.cause ?? "invalid");
165
175
  this.markRaw(event.path, event.reason, event.value);
166
176
  return;
167
177
  }
@@ -360,10 +370,11 @@ var IrTree = class {
360
370
  const isRaw = rootRawReason !== null;
361
371
  const identifiedKind = this.identifiedKinds.get("") ?? "";
362
372
  const rootKind = isRaw ? this.rawKinds.get("") ?? "" : rootNode?.kind ?? (this.completedKind || identifiedKind);
373
+ const rootRawState = this.rawCauses.get("") === "unverified" ? "unverified" : "raw";
363
374
  const root = {
364
375
  role: "structured",
365
376
  kind: rootKind,
366
- kindState: isRaw ? "raw" : rootNode ? rootNode.kindState : this.pendingSchemaPaths.has("") ? "pending_schema" : this.regionStatus === "streaming" ? identifiedKind ? "pending_schema" : "pending_kind" : "raw",
377
+ kindState: isRaw ? rootRawState : rootNode ? rootNode.kindState : this.pendingSchemaPaths.has("") ? "pending_schema" : this.regionStatus === "streaming" ? identifiedKind ? "pending_schema" : "pending_kind" : "raw",
367
378
  discriminator: JSON_DISCRIMINATOR,
368
379
  path: [],
369
380
  status: this.regionStatus,
@@ -384,7 +395,11 @@ var IrTree = class {
384
395
  }
385
396
  for (const [pathKey] of this.rawPaths) {
386
397
  if (pathKey === "") continue;
387
- nodeIndex[pathKey] = { kind: "", kindState: "raw", status: "complete" };
398
+ nodeIndex[pathKey] = {
399
+ kind: this.rawKinds.get(pathKey) ?? "",
400
+ kindState: this.rawCauses.get(pathKey) === "unverified" ? "unverified" : "raw",
401
+ status: "complete"
402
+ };
388
403
  }
389
404
  return {
390
405
  v: IR_VERSION,
@@ -722,7 +737,8 @@ var KindStreamParser = class {
722
737
  safeCopy(value),
723
738
  `No block schema registered for "${kind}".`,
724
739
  at,
725
- kind
740
+ kind,
741
+ "unverified"
726
742
  );
727
743
  }
728
744
  }
@@ -756,7 +772,8 @@ var KindStreamParser = class {
756
772
  safeCopy(value ?? {}),
757
773
  `No block schema registered for "${kind}".`,
758
774
  at,
759
- kind
775
+ kind,
776
+ "unverified"
760
777
  );
761
778
  this.closedPendingPaths.delete(pathKey);
762
779
  continue;
@@ -899,7 +916,7 @@ var KindStreamParser = class {
899
916
  * Recorded at the first root key; ADOPTED only when the root object closes
900
917
  * (`completeTypedObject`). That is the surface registry's complete-only
901
918
  * convergence law, and every json_root_key row is `streaming:false` — these
902
- * legacy shapes are recognised by their whole payload, so speculating
919
+ * legacy shapes are recognized by their whole payload, so speculating
903
920
  * mid-stream would flash a kind component over an object that may never
904
921
  * satisfy the schema. An explicit `expectedRootKind` (an agent's declared
905
922
  * output schema) is stronger context and always wins; an actual `__kind`
@@ -1302,18 +1319,19 @@ var KindStreamParser = class {
1302
1319
  objectValue,
1303
1320
  `No block schema registered for "${kind}".`,
1304
1321
  at,
1305
- kind
1322
+ kind,
1323
+ "unverified"
1306
1324
  );
1307
1325
  return;
1308
1326
  }
1309
1327
  const arrayItemError = this.validateArrayItemKind(path, kind);
1310
1328
  if (arrayItemError) {
1311
- this.emitRawObject(path, objectValue, arrayItemError, at);
1329
+ this.emitRawObject(path, objectValue, arrayItemError, at, kind);
1312
1330
  return;
1313
1331
  }
1314
1332
  const outcome = this.validateObjectAgainstSchema(objectValue, schema);
1315
1333
  if (outcome.error) {
1316
- this.emitRawObject(path, objectValue, outcome.error, at);
1334
+ this.emitRawObject(path, objectValue, outcome.error, at, kind);
1317
1335
  return;
1318
1336
  }
1319
1337
  this.objectKinds.set(pathKey, kind);
@@ -1336,7 +1354,8 @@ var KindStreamParser = class {
1336
1354
  objectValue,
1337
1355
  `No block schema registered for "${kind}".`,
1338
1356
  at,
1339
- kind
1357
+ kind,
1358
+ "unverified"
1340
1359
  );
1341
1360
  return;
1342
1361
  }
@@ -1345,7 +1364,7 @@ var KindStreamParser = class {
1345
1364
  schema
1346
1365
  );
1347
1366
  if (outcome.error) {
1348
- this.emitRawObject(path, objectValue, outcome.error, at);
1367
+ this.emitRawObject(path, objectValue, outcome.error, at, kind);
1349
1368
  return;
1350
1369
  }
1351
1370
  this.emitSchemaNotices(path, kind, outcome, at);
@@ -1405,10 +1424,19 @@ var KindStreamParser = class {
1405
1424
  markNodeRaw(path, liveValue, reason, at) {
1406
1425
  const pathKey = this.pathKey(path);
1407
1426
  if (this.rawObjectPaths.has(pathKey)) return;
1427
+ const identifiedKind = this.objectKinds.get(pathKey) ?? (typeof liveValue === "object" && liveValue !== null && !Array.isArray(liveValue) ? readObjectKind(liveValue) ?? void 0 : void 0);
1408
1428
  this.speculativeKinds.delete(pathKey);
1409
- this.emitRawObject(path, safeCopy(liveValue), reason, at);
1429
+ this.emitRawObject(path, safeCopy(liveValue), reason, at, identifiedKind);
1410
1430
  }
1411
- emitRawObject(path, value, reason, at, identifiedKind) {
1431
+ /**
1432
+ * Degrade ONE node off the resolved path.
1433
+ *
1434
+ * `cause` defaults to `"invalid"` deliberately: every call site that omits
1435
+ * it is a real failure (validation, duplicate key, placement, contradicted
1436
+ * speculation). ONLY the "no schema registered" sites pass `"unverified"`,
1437
+ * and they are the reason the parameter exists — see `IrKindState`.
1438
+ */
1439
+ emitRawObject(path, value, reason, at, identifiedKind, cause = "invalid") {
1412
1440
  const pathKey = this.pathKey(path);
1413
1441
  if (this.rawObjectPaths.has(pathKey)) return;
1414
1442
  this.rawObjectPaths.add(pathKey);
@@ -1419,6 +1447,7 @@ var KindStreamParser = class {
1419
1447
  value,
1420
1448
  reason,
1421
1449
  ...identifiedKind !== void 0 && { kind: identifiedKind },
1450
+ cause,
1422
1451
  at
1423
1452
  });
1424
1453
  }
@@ -2988,21 +3017,26 @@ function fieldSchemaSummary(field) {
2988
3017
  function resolvePrimaryType(node) {
2989
3018
  const raw = node.type;
2990
3019
  if (typeof raw === "string") {
2991
- return { type: raw === "integer" ? "number" : raw, nullable: false };
3020
+ const t = raw === "integer" ? "number" : raw;
3021
+ return { type: t, nullable: false, members: [t] };
2992
3022
  }
2993
3023
  if (Array.isArray(raw)) {
2994
3024
  const types = raw.filter((t) => typeof t === "string");
2995
3025
  const nullable = types.includes("null");
2996
- const primary = types.find((t) => t !== "null") ?? (nullable && types.length === 1 ? "null" : null);
2997
- if (primary === "integer") {
2998
- return { type: "number", nullable };
2999
- }
3000
- return { type: primary ?? null, nullable };
3001
- }
3002
- if (node.enum) return { type: "string", nullable: false };
3003
- if (node.properties) return { type: "object", nullable: false };
3004
- if (node.items) return { type: "array", nullable: false };
3005
- return { type: null, nullable: false };
3026
+ const members = [
3027
+ ...new Set(
3028
+ types.filter((t) => t !== "null").map((t) => t === "integer" ? "number" : t)
3029
+ )
3030
+ ];
3031
+ const primary = members[0] ?? (nullable && types.length === 1 ? "null" : null);
3032
+ return { type: primary ?? null, nullable, members };
3033
+ }
3034
+ if (node.enum) return { type: "string", nullable: false, members: ["string"] };
3035
+ if (node.properties)
3036
+ return { type: "object", nullable: false, members: ["object"] };
3037
+ if (node.items)
3038
+ return { type: "array", nullable: false, members: ["array"] };
3039
+ return { type: null, nullable: false, members: [] };
3006
3040
  }
3007
3041
  function carriedMetadataKeys(field) {
3008
3042
  if (field === null) return /* @__PURE__ */ new Set();
@@ -3320,7 +3354,34 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
3320
3354
  });
3321
3355
  return { ...requiredNullableFlags(required), type: "json" };
3322
3356
  }
3323
- const { type, nullable } = resolvePrimaryType(node);
3357
+ const { type, nullable, members } = resolvePrimaryType(node);
3358
+ if (members.length > 1) {
3359
+ const objectish = members.some((m) => m === "object" || m === "array");
3360
+ if (objectish) {
3361
+ ctx.problems.push({
3362
+ severity: "info",
3363
+ path,
3364
+ message: `Union of [${members.join(", ")}] at "${path || "(root)"}" spans objects/arrays \u2014 carried as any JSON value (json).`
3365
+ });
3366
+ return { ...requiredNullableFlags(required), type: "json" };
3367
+ }
3368
+ const scalars = members.filter(
3369
+ (m) => m === "string" || m === "number" || m === "boolean"
3370
+ );
3371
+ if (scalars.length === members.length && scalars.length > 1) {
3372
+ return {
3373
+ ...requiredNullableFlags(required, nullable),
3374
+ type: "union",
3375
+ scalars
3376
+ };
3377
+ }
3378
+ ctx.problems.push({
3379
+ severity: "warning",
3380
+ path,
3381
+ message: `Union of [${members.join(", ")}] at "${path || "(root)"}" has no exact field type \u2014 carried as any JSON value (json) rather than narrowed to "${type}".`
3382
+ });
3383
+ return { ...requiredNullableFlags(required), type: "json" };
3384
+ }
3324
3385
  if (type === "string") {
3325
3386
  if (Array.isArray(node.enum)) {
3326
3387
  const values = node.enum.filter(