@ai-matrx/content-ir 0.9.0 → 0.10.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/CHANGELOG.md +63 -0
- package/README.md +24 -5
- package/dist/convert.cjs +1680 -0
- package/dist/convert.cjs.map +1 -0
- package/dist/convert.d.cts +230 -0
- package/dist/convert.d.ts +230 -0
- package/dist/convert.js +1666 -0
- package/dist/convert.js.map +1 -0
- package/dist/core.cjs +2493 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +370 -0
- package/dist/core.d.ts +370 -0
- package/dist/core.js +2452 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2030
- package/dist/index.d.ts +9 -2030
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ir-tree-DbLVxbf1.d.cts +441 -0
- package/dist/ir-tree-Dsc_66ek.d.ts +441 -0
- package/dist/ir-types-95bA2cXH.d.cts +119 -0
- package/dist/ir-types-95bA2cXH.d.ts +119 -0
- package/dist/kind-schema.types-CwncWj9U.d.cts +139 -0
- package/dist/kind-schema.types-CwncWj9U.d.ts +139 -0
- package/dist/registry.cjs +468 -0
- package/dist/registry.cjs.map +1 -0
- package/dist/registry.d.cts +357 -0
- package/dist/registry.d.ts +357 -0
- package/dist/registry.js +456 -0
- package/dist/registry.js.map +1 -0
- package/dist/session.cjs +2052 -0
- package/dist/session.cjs.map +1 -0
- package/dist/session.d.cts +75 -0
- package/dist/session.d.ts +75 -0
- package/dist/session.js +2047 -0
- package/dist/session.js.map +1 -0
- package/dist/wire.cjs +310 -0
- package/dist/wire.cjs.map +1 -0
- package/dist/wire.d.cts +326 -0
- package/dist/wire.d.ts +326 -0
- package/dist/wire.js +291 -0
- package/dist/wire.js.map +1 -0
- package/package.json +73 -1
package/dist/wire.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// core/ir-types.ts
|
|
2
|
+
var IR_VERSION = 1;
|
|
3
|
+
|
|
4
|
+
// wire/partial-kind.ts
|
|
5
|
+
var IR_PARTIAL_KEY = "__ir_partial";
|
|
6
|
+
var PARTIAL_STATES = [
|
|
7
|
+
"partial",
|
|
8
|
+
"superseded",
|
|
9
|
+
"retracted"
|
|
10
|
+
];
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function readPath(value) {
|
|
15
|
+
if (!Array.isArray(value)) return null;
|
|
16
|
+
return value.every(
|
|
17
|
+
(segment) => typeof segment === "string" || typeof segment === "number"
|
|
18
|
+
) ? value : null;
|
|
19
|
+
}
|
|
20
|
+
function readDiscriminator(value) {
|
|
21
|
+
if (!isRecord(value)) return null;
|
|
22
|
+
if (value.format === "json" && value.key === "__kind") {
|
|
23
|
+
return { format: "json", key: "__kind" };
|
|
24
|
+
}
|
|
25
|
+
if (value.format === "xml" && typeof value.tag === "string") {
|
|
26
|
+
return { format: "xml", tag: value.tag };
|
|
27
|
+
}
|
|
28
|
+
if (value.format === "fence" && typeof value.language === "string") {
|
|
29
|
+
return { format: "fence", language: value.language };
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function readResidue(value) {
|
|
34
|
+
if (value === null) return null;
|
|
35
|
+
if (!isRecord(value)) return void 0;
|
|
36
|
+
const extra = value.extra;
|
|
37
|
+
const optionalMissing = value.optionalMissing;
|
|
38
|
+
const notices = value.notices;
|
|
39
|
+
if (extra !== null && !isRecord(extra)) return void 0;
|
|
40
|
+
if (optionalMissing !== null && (!Array.isArray(optionalMissing) || !optionalMissing.every((item) => typeof item === "string"))) {
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
if (notices !== null && (!Array.isArray(notices) || !notices.every(
|
|
44
|
+
(notice) => isRecord(notice) && typeof notice.code === "string" && typeof notice.message === "string" && (notice.at === void 0 || typeof notice.at === "number")
|
|
45
|
+
))) {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
return { extra, optionalMissing, notices };
|
|
49
|
+
}
|
|
50
|
+
function readPartialKindEvent(metadata) {
|
|
51
|
+
if (!isRecord(metadata)) return null;
|
|
52
|
+
const candidate = metadata[IR_PARTIAL_KEY];
|
|
53
|
+
if (!isRecord(candidate)) return null;
|
|
54
|
+
if (candidate.v !== IR_VERSION) return null;
|
|
55
|
+
if (typeof candidate.engine !== "string") return null;
|
|
56
|
+
if (typeof candidate.seq !== "number" || !Number.isFinite(candidate.seq)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const state = candidate.state;
|
|
60
|
+
if (typeof state !== "string") return null;
|
|
61
|
+
if (!PARTIAL_STATES.includes(state)) return null;
|
|
62
|
+
if (state === "partial") {
|
|
63
|
+
const root = candidate.root;
|
|
64
|
+
if (!isRecord(root)) return null;
|
|
65
|
+
if (root.role !== "structured") return null;
|
|
66
|
+
if (root.status !== "streaming") return null;
|
|
67
|
+
if (root.kindState !== "speculative") return null;
|
|
68
|
+
if (typeof root.kind !== "string" || !root.kind) return null;
|
|
69
|
+
if (!isRecord(root.value)) return null;
|
|
70
|
+
const discriminator = readDiscriminator(root.discriminator);
|
|
71
|
+
const path = readPath(root.path);
|
|
72
|
+
const residue = readResidue(root.residue);
|
|
73
|
+
if (discriminator === null || path === null || residue === void 0) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
v: IR_VERSION,
|
|
78
|
+
engine: candidate.engine,
|
|
79
|
+
state: "partial",
|
|
80
|
+
seq: candidate.seq,
|
|
81
|
+
fingerprint: typeof candidate.fingerprint === "string" ? candidate.fingerprint : "",
|
|
82
|
+
root: {
|
|
83
|
+
role: "structured",
|
|
84
|
+
kind: root.kind,
|
|
85
|
+
kindState: "speculative",
|
|
86
|
+
discriminator,
|
|
87
|
+
path,
|
|
88
|
+
status: "streaming",
|
|
89
|
+
value: root.value,
|
|
90
|
+
residue
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (typeof candidate.kind !== "string" || !candidate.kind) return null;
|
|
95
|
+
if (state === "superseded") {
|
|
96
|
+
return {
|
|
97
|
+
v: IR_VERSION,
|
|
98
|
+
engine: candidate.engine,
|
|
99
|
+
state: "superseded",
|
|
100
|
+
seq: candidate.seq,
|
|
101
|
+
kind: candidate.kind
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (typeof candidate.reason !== "string" || !candidate.reason) return null;
|
|
105
|
+
if (candidate.becameKind !== null && typeof candidate.becameKind !== "string") {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
if (candidate.becameBlockType !== null && typeof candidate.becameBlockType !== "string") {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
v: IR_VERSION,
|
|
113
|
+
engine: candidate.engine,
|
|
114
|
+
state: "retracted",
|
|
115
|
+
seq: candidate.seq,
|
|
116
|
+
kind: candidate.kind,
|
|
117
|
+
reason: candidate.reason,
|
|
118
|
+
becameKind: candidate.becameKind,
|
|
119
|
+
becameBlockType: candidate.becameBlockType
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function sanitizeInboundPartialKindMetadata(metadata, context, hooks = {}) {
|
|
123
|
+
if (!isRecord(metadata) || !(IR_PARTIAL_KEY in metadata)) {
|
|
124
|
+
return metadata ?? void 0;
|
|
125
|
+
}
|
|
126
|
+
if (readPartialKindEvent(metadata) !== null) return metadata;
|
|
127
|
+
const { [IR_PARTIAL_KEY]: raw, ...rest } = metadata;
|
|
128
|
+
hooks.reportMalformed?.({ blockId: context.blockId, raw });
|
|
129
|
+
return rest;
|
|
130
|
+
}
|
|
131
|
+
function isProvisionalKind(event) {
|
|
132
|
+
return event !== null && event.state === "partial";
|
|
133
|
+
}
|
|
134
|
+
function isTerminalKindEvent(event) {
|
|
135
|
+
return event !== null && (event.state === "superseded" || event.state === "retracted");
|
|
136
|
+
}
|
|
137
|
+
function advancePartialKind(seen, blockId, event) {
|
|
138
|
+
if (event === null) return null;
|
|
139
|
+
const last = seen[blockId];
|
|
140
|
+
if (last !== void 0 && event.seq <= last) return null;
|
|
141
|
+
return event;
|
|
142
|
+
}
|
|
143
|
+
function makePartialKindStalenessGate() {
|
|
144
|
+
const seen = {};
|
|
145
|
+
const lastAccepted = {};
|
|
146
|
+
const terminated = {};
|
|
147
|
+
return (blockId, metadata) => {
|
|
148
|
+
if (!isRecord(metadata)) return metadata;
|
|
149
|
+
if (!(IR_PARTIAL_KEY in metadata)) {
|
|
150
|
+
const open = lastAccepted[blockId];
|
|
151
|
+
if (terminated[blockId] || open === void 0) return metadata;
|
|
152
|
+
return { ...metadata, [IR_PARTIAL_KEY]: open };
|
|
153
|
+
}
|
|
154
|
+
const parsed = readPartialKindEvent(metadata);
|
|
155
|
+
if (parsed === null) return metadata;
|
|
156
|
+
if (advancePartialKind(seen, blockId, parsed) !== null) {
|
|
157
|
+
seen[blockId] = parsed.seq;
|
|
158
|
+
lastAccepted[blockId] = metadata[IR_PARTIAL_KEY];
|
|
159
|
+
if (isTerminalKindEvent(parsed)) terminated[blockId] = true;
|
|
160
|
+
return metadata;
|
|
161
|
+
}
|
|
162
|
+
const carried = lastAccepted[blockId];
|
|
163
|
+
if (carried === void 0 || carried === metadata[IR_PARTIAL_KEY]) {
|
|
164
|
+
return metadata;
|
|
165
|
+
}
|
|
166
|
+
return { ...metadata, [IR_PARTIAL_KEY]: carried };
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// core/kind-schema.types.ts
|
|
171
|
+
var KIND_KEY = "__kind";
|
|
172
|
+
|
|
173
|
+
// wire/runtime-wrapper.ts
|
|
174
|
+
var NODE_OUTCOME_KIND = "node_outcome";
|
|
175
|
+
var RUN_RESULT_KIND = "run_result";
|
|
176
|
+
function isRecord2(value) {
|
|
177
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
178
|
+
}
|
|
179
|
+
function str(source, key) {
|
|
180
|
+
const value = source[key];
|
|
181
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
182
|
+
}
|
|
183
|
+
function num(source, key) {
|
|
184
|
+
const value = source[key];
|
|
185
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
186
|
+
}
|
|
187
|
+
function bool(source, key) {
|
|
188
|
+
const value = source[key];
|
|
189
|
+
return typeof value === "boolean" ? value : null;
|
|
190
|
+
}
|
|
191
|
+
function strings(source, key) {
|
|
192
|
+
const value = source[key];
|
|
193
|
+
if (!Array.isArray(value)) return null;
|
|
194
|
+
const out = value.filter((item) => typeof item === "string");
|
|
195
|
+
return out.length > 0 ? out : null;
|
|
196
|
+
}
|
|
197
|
+
function readOutputRef(frame, ref) {
|
|
198
|
+
let cursor = frame;
|
|
199
|
+
for (const segment of ref.split(".")) {
|
|
200
|
+
if (!isRecord2(cursor)) return void 0;
|
|
201
|
+
if (!(segment in cursor)) return void 0;
|
|
202
|
+
cursor = cursor[segment];
|
|
203
|
+
}
|
|
204
|
+
return cursor;
|
|
205
|
+
}
|
|
206
|
+
function rehydrateNodeOutcome(raw, frame) {
|
|
207
|
+
if (!isRecord2(raw)) return null;
|
|
208
|
+
if (raw[KIND_KEY] !== NODE_OUTCOME_KIND) return null;
|
|
209
|
+
const ref = str(raw, "output_ref");
|
|
210
|
+
const resolved = ref === null ? void 0 : readOutputRef(frame, ref);
|
|
211
|
+
return readNodeOutcomeValue(
|
|
212
|
+
resolved === void 0 ? raw : { ...raw, output: resolved }
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
function readNodeOutcomeValue(raw) {
|
|
216
|
+
if (!isRecord2(raw)) return null;
|
|
217
|
+
const runId = str(raw, "run_id");
|
|
218
|
+
const nodeId = str(raw, "node_id");
|
|
219
|
+
if (!runId || !nodeId) return null;
|
|
220
|
+
const output = raw.output ?? null;
|
|
221
|
+
return {
|
|
222
|
+
__kind: NODE_OUTCOME_KIND,
|
|
223
|
+
run_id: runId,
|
|
224
|
+
node_id: nodeId,
|
|
225
|
+
workflow_id: str(raw, "workflow_id"),
|
|
226
|
+
step: num(raw, "step"),
|
|
227
|
+
attempt: num(raw, "attempt") ?? 1,
|
|
228
|
+
status: str(raw, "status") ?? "completed",
|
|
229
|
+
started_at: str(raw, "started_at"),
|
|
230
|
+
ended_at: str(raw, "ended_at"),
|
|
231
|
+
duration_ms: num(raw, "duration_ms"),
|
|
232
|
+
output_kind: str(raw, "output_kind"),
|
|
233
|
+
output_kind_ok: bool(raw, "output_kind_ok"),
|
|
234
|
+
output_kind_errors: strings(raw, "output_kind_errors"),
|
|
235
|
+
output
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function rehydrateRunResult(raw, frame) {
|
|
239
|
+
if (!isRecord2(raw)) return null;
|
|
240
|
+
if (raw[KIND_KEY] !== RUN_RESULT_KIND) return null;
|
|
241
|
+
const ref = str(raw, "output_ref");
|
|
242
|
+
const resolved = ref === null ? void 0 : readOutputRef(frame, ref);
|
|
243
|
+
const outputs = Array.isArray(raw.outputs) ? raw.outputs.map((child) => rehydrateNodeOutcome(child, frame)).filter((child) => child !== null) : [];
|
|
244
|
+
return readRunResultValue({
|
|
245
|
+
...raw,
|
|
246
|
+
...resolved === void 0 ? {} : { output: resolved },
|
|
247
|
+
outputs
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
function readRunResultValue(raw) {
|
|
251
|
+
if (!isRecord2(raw)) return null;
|
|
252
|
+
const runId = str(raw, "run_id");
|
|
253
|
+
if (!runId) return null;
|
|
254
|
+
const output = raw.output ?? null;
|
|
255
|
+
const outputs = Array.isArray(raw.outputs) ? raw.outputs.map((child) => readNodeOutcomeValue(child)).filter((child) => child !== null) : [];
|
|
256
|
+
return {
|
|
257
|
+
__kind: RUN_RESULT_KIND,
|
|
258
|
+
run_id: runId,
|
|
259
|
+
workflow_id: str(raw, "workflow_id"),
|
|
260
|
+
status: str(raw, "status") ?? "completed",
|
|
261
|
+
started_at: str(raw, "started_at"),
|
|
262
|
+
ended_at: str(raw, "ended_at"),
|
|
263
|
+
duration_ms: num(raw, "duration_ms"),
|
|
264
|
+
output_kind: str(raw, "output_kind"),
|
|
265
|
+
output,
|
|
266
|
+
outputs
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function kindVerdictOf(wrapper) {
|
|
270
|
+
if (wrapper.output_kind_ok === true) return "passed";
|
|
271
|
+
if (wrapper.output_kind_ok === false) return "failed";
|
|
272
|
+
return "unchecked";
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// wire/emit-payload.ts
|
|
276
|
+
function withRootKind(kind, value) {
|
|
277
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
278
|
+
return { [KIND_KEY]: kind, ...value };
|
|
279
|
+
}
|
|
280
|
+
return value;
|
|
281
|
+
}
|
|
282
|
+
function emitPayloadJson(kind, value) {
|
|
283
|
+
return JSON.stringify(withRootKind(kind, value), null, 2);
|
|
284
|
+
}
|
|
285
|
+
function emitPayloadFence(kind, value) {
|
|
286
|
+
return "```json\n" + emitPayloadJson(kind, value) + "\n```";
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export { IR_PARTIAL_KEY, NODE_OUTCOME_KIND, RUN_RESULT_KIND, advancePartialKind, emitPayloadFence, emitPayloadJson, isProvisionalKind, isTerminalKindEvent, kindVerdictOf, makePartialKindStalenessGate, readNodeOutcomeValue, readOutputRef, readPartialKindEvent, readRunResultValue, rehydrateNodeOutcome, rehydrateRunResult, sanitizeInboundPartialKindMetadata, withRootKind };
|
|
290
|
+
//# sourceMappingURL=wire.js.map
|
|
291
|
+
//# sourceMappingURL=wire.js.map
|
package/dist/wire.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../core/ir-types.ts","../wire/partial-kind.ts","../core/kind-schema.types.ts","../wire/runtime-wrapper.ts","../wire/emit-payload.ts"],"names":["isRecord"],"mappings":"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","file":"wire.js","sourcesContent":["/**\n * The canonical IR contract for structured content.\n *\n * Every source (live agent stream, DB reload, Python-preprocessed results,\n * notes, any future surface) is normalized into these shapes exactly once.\n * Anything already carrying this IR passes through downstream layers by\n * reference — see `core/normalize.ts` for the idempotence law.\n *\n * This file is pure types + path helpers. No React, no Redux, no IO.\n */\n\n/** Path of a value inside a parsed region (object keys + array indices). */\nexport type IrPath = Array<string | number>;\n\n/**\n * How a node's kind was (or wasn't) established.\n *\n * 🚨 `unverified` IS NOT `raw`, AND THE DIFFERENCE IS LOAD-BEARING (Arman's\n * ruling, 2026-08-29). \"We checked it and it is wrong\" and \"we had nothing to\n * check it with\" are opposite facts about a payload, and collapsing them cost\n * ~221 live kinds their component overnight: a kind whose schema never loaded\n * degraded to `raw`, the render route read `raw` as \"broken instance\", and\n * perfectly valid payloads were dumped as key/value lists instead of reaching\n * the component the user built. A consumer that treats `unverified` as a\n * failure is reintroducing that outage — the data is intact and MAY be\n * entirely valid; all that is missing is the schema that would prove it.\n */\nexport type IrKindState =\n | \"resolved\" // __kind seen + schema validated\n | \"speculative\" // committed from parent itemKinds before __kind arrived\n | \"pending_kind\" // object open, no __kind yet, no speculation possible\n | \"pending_schema\" // kind known, registry cold-fetch in flight\n | \"unverified\" // kind known, NO schema was ever available — never checked\n | \"raw\"; // checked and FAILED, or structurally broken\n\n/**\n * System-level zero-data-loss channel. Unknown keys are NEVER merged into a\n * node's `value` (they'd be indistinguishable from schema fields); they are\n * carried here verbatim — Protobuf unknown-fields discipline. Distinct from\n * any domain-level `additionalDetails` field, which is an ordinary schema\n * field inside `value`.\n */\nexport interface IrResidue {\n /** Keys present in the source object but absent from the kind schema. */\n extra: Record<string, unknown> | null;\n /** Optional schema fields the source never provided. */\n optionalMissing: string[] | null;\n /** Structured warnings attached during parsing (speculation backtracks, truncation, …). */\n notices: Array<{ code: string; message: string; at?: number }> | null;\n}\n\n/** Which wire syntax carried the kind discriminator for a node. */\nexport type IrDiscriminator =\n | { format: \"json\"; key: \"__kind\" }\n | { format: \"xml\"; tag: string }\n | { format: \"fence\"; language: string };\n\n/** A schema-shaped structured node. Children live inside `value` (and carry their own metadata via `nodeIndex`). */\nexport interface IrStructuredNode {\n role: \"structured\";\n /** Canonical kind slug. Empty string while pending. */\n kind: string;\n kindState: IrKindState;\n discriminator: IrDiscriminator;\n /** Region-relative path ([] = region root). */\n path: IrPath;\n status: \"streaming\" | \"complete\" | \"error\";\n /** Compliant snapshot: schema fields + __kind ONLY. Unknown keys → residue. */\n value: Record<string, unknown>;\n residue: IrResidue | null;\n}\n\n/** Envelope version. Bump = migration point for persisted envelopes. */\nexport const IR_VERSION = 1 as const;\n\n/** Reserved key carrying the envelope inside RenderBlockPayload.data. */\nexport const IR_ENVELOPE_KEY = \"__ir\" as const;\n\n/**\n * One parsed region's canonical form. Serializable (plain JSON), carried on\n * render blocks (`data.__ir`), persisted on artifacts and message metadata,\n * and — with `engine: \"py-block-detector\"` — accepted pre-built from Python.\n */\nexport interface CanonicalBlockIR {\n v: typeof IR_VERSION;\n /** Provenance: which implementation produced this envelope. */\n engine: \"fe-kind-parser\" | \"py-block-detector\";\n /** Stable hash of the region source text — the idempotence / cache key. */\n fingerprint: string;\n root: IrStructuredNode;\n /**\n * pathKey → node metadata for per-path readers (child kinds under root).\n * Carries each child node's residue — child snapshot values inside\n * `root.value` hold schema fields only, so WITHOUT this the envelope would\n * silently drop nested unknown keys (zero-data-loss violation).\n */\n nodeIndex?: Record<\n string,\n Pick<IrStructuredNode, \"kind\" | \"kindState\" | \"status\"> & {\n residue?: IrResidue | null;\n }\n >;\n}\n\n/** Normalizer output segment: prose stays raw text; structured regions carry IR. */\nexport type CanonicalSegment =\n | { role: \"text\"; content: string }\n | {\n role: \"block\";\n blockType: string;\n content: string;\n ir: CanonicalBlockIR | null;\n };\n\nexport interface CanonicalContent {\n v: typeof IR_VERSION;\n segments: CanonicalSegment[];\n}\n\n// ---------------------------------------------------------------------------\n// Path helpers — the ONE implementation. Consumers must not roll their own.\n// ---------------------------------------------------------------------------\n\nexport function irPathKey(path: IrPath): string {\n return path.map((segment) => String(segment)).join(\".\");\n}\n\nexport function irPathsEqual(left: IrPath, right: IrPath): boolean {\n if (left.length !== right.length) return false;\n for (let i = 0; i < left.length; i++) {\n if (left[i] !== right[i]) return false;\n }\n return true;\n}\n\nexport function irPathIsUnderOrEqual(path: IrPath, prefix: IrPath): boolean {\n if (path.length < prefix.length) return false;\n for (let i = 0; i < prefix.length; i++) {\n if (path[i] !== prefix[i]) return false;\n }\n return true;\n}\n\n/** Human label for a path (\"root\", \"cards[2].front\"). */\nexport function irPathLabel(path: IrPath): string {\n if (path.length === 0) return \"root\";\n\n const parts: string[] = [];\n for (const segment of path) {\n if (typeof segment === \"number\") {\n parts[parts.length - 1] += `[${segment}]`;\n } else {\n parts.push(String(segment));\n }\n }\n return parts.join(\".\");\n}\n\n/** True when every residue channel is empty — normalize to null instead. */\nexport function isEmptyResidue(residue: IrResidue): boolean {\n return (\n (residue.extra === null || Object.keys(residue.extra).length === 0) &&\n (residue.optionalMissing === null ||\n residue.optionalMissing.length === 0) &&\n (residue.notices === null || residue.notices.length === 0)\n );\n}\n","/**\n * Streaming partial kinds — the TS twin of the Python producer's contract.\n *\n * Cross-repo system-of-record (read it before changing anything here):\n * `common-docs/systems/content-ir-system/STREAMING_PARTIAL_KINDS.md`.\n * Python twin: `aidream/packages/matrx-graph/matrx_graph/content_ir/partial.py`.\n *\n * WHAT THIS IS\n * ------------\n * While a structured region streams, the server announces what it thinks the\n * region IS and what has arrived so far, so the UI fills in progressively\n * instead of showing a spinner until the closing brace. Three events, a CLOSED\n * union on `state`, all riding `metadata.__ir_partial` on the `render_block`\n * events this app already receives:\n *\n * partial — repeatable. A provisional instance whose `root.value` is\n * VALID, CLOSED JSON (the server truncates and closes it, so\n * this side never repairs or guesses). `kindState` is\n * \"speculative\": it MAY still turn out to be something else.\n * superseded — TERMINAL. The region completed as the announced kind; drop\n * the provisional render, the block's own content/`__ir` is the\n * truth.\n * retracted — TERMINAL escape hatch. Detection was wrong; `becameKind` /\n * `becameBlockType` name what it actually is. Never a silent\n * swap.\n *\n * WHY IT IS NOT ON `__ir`\n * -----------------------\n * `__ir` means \"validated against the registered schema\", and a valid `__ir`\n * is SEEDED into the fingerprint-keyed envelope memo. A provisional value\n * there would poison every later read of that region. The two channels never\n * touch: `classifyInboundEnvelopeMetadata` sees `absent` for a partial and\n * passes the metadata through by reference.\n *\n * Pure kernel module: types + validators only. No React, no Redux, no IO.\n * Lives in @ai-matrx/content-ir `wire/` so EVERY UI (Matrix, Workflow Studio,\n * the dashboard, the Chrome extension, the desktop app) reads the channel\n * through the same reader.\n */\n\nimport { IR_VERSION } from \"../core/ir-types\";\nimport type { IrDiscriminator, IrPath, IrResidue } from \"../core/ir-types\";\n\n/** The reserved metadata key carrying every event of this contract. */\nexport const IR_PARTIAL_KEY = \"__ir_partial\" as const;\n\nexport type PartialKindState = \"partial\" | \"superseded\" | \"retracted\";\n\nconst PARTIAL_STATES: readonly PartialKindState[] = [\n \"partial\",\n \"superseded\",\n \"retracted\",\n];\n\n/** The provisional node. Deliberately `IrStructuredNode`-shaped so existing IR readers work. */\nexport interface PartialKindNode {\n role: \"structured\";\n /** The server's DETECTION GUESS for this region. */\n kind: string;\n /** Always \"speculative\" on a partial — pre-recognition, not a resolved kind. */\n kindState: \"speculative\";\n discriminator: IrDiscriminator;\n path: IrPath;\n status: \"streaming\";\n /**\n * Valid, closed JSON carrying its own `__kind`. MAY be missing required\n * schema fields — that is what `partial_unvalidated` in `residue.notices`\n * says. A renderer that throws on an absent field is not partial-ready and\n * must not be routed a provisional value.\n */\n value: Record<string, unknown>;\n residue: IrResidue | null;\n}\n\nexport interface PartialKindEvent {\n v: typeof IR_VERSION;\n engine: string;\n state: \"partial\";\n /** Monotonic PER BLOCK — the ordering / staleness key. Keep the highest. */\n seq: number;\n fingerprint: string;\n root: PartialKindNode;\n}\n\nexport interface SupersededKindEvent {\n v: typeof IR_VERSION;\n engine: string;\n state: \"superseded\";\n seq: number;\n kind: string;\n}\n\nexport interface RetractedKindEvent {\n v: typeof IR_VERSION;\n engine: string;\n state: \"retracted\";\n seq: number;\n /** The kind that was WRONGLY announced. */\n kind: string;\n reason: string;\n /** What it actually is — null when it resolved to no registered kind. */\n becameKind: string | null;\n /** The detector's final block type, so a consumer re-routes without guessing. */\n becameBlockType: string | null;\n}\n\nexport type AnyPartialKindEvent =\n | PartialKindEvent\n | SupersededKindEvent\n | RetractedKindEvent;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction readPath(value: unknown): IrPath | null {\n if (!Array.isArray(value)) return null;\n return value.every(\n (segment) => typeof segment === \"string\" || typeof segment === \"number\",\n )\n ? value\n : null;\n}\n\nfunction readDiscriminator(value: unknown): IrDiscriminator | null {\n if (!isRecord(value)) return null;\n if (value.format === \"json\" && value.key === \"__kind\") {\n return { format: \"json\", key: \"__kind\" };\n }\n if (value.format === \"xml\" && typeof value.tag === \"string\") {\n return { format: \"xml\", tag: value.tag };\n }\n if (value.format === \"fence\" && typeof value.language === \"string\") {\n return { format: \"fence\", language: value.language };\n }\n return null;\n}\n\nfunction readResidue(value: unknown): IrResidue | null | undefined {\n if (value === null) return null;\n if (!isRecord(value)) return undefined;\n const extra = value.extra;\n const optionalMissing = value.optionalMissing;\n const notices = value.notices;\n if (extra !== null && !isRecord(extra)) return undefined;\n if (\n optionalMissing !== null &&\n (!Array.isArray(optionalMissing) ||\n !optionalMissing.every((item) => typeof item === \"string\"))\n ) {\n return undefined;\n }\n if (\n notices !== null &&\n (!Array.isArray(notices) ||\n !notices.every(\n (notice) =>\n isRecord(notice) &&\n typeof notice.code === \"string\" &&\n typeof notice.message === \"string\" &&\n (notice.at === undefined || typeof notice.at === \"number\"),\n ))\n ) {\n return undefined;\n }\n return { extra, optionalMissing, notices };\n}\n\n/**\n * Read + validate a partial-channel event off a block's metadata.\n *\n * Returns null for anything malformed, foreign, or of an unknown `state`. A\n * malformed partial degrades to \"no live rendering\" — never to a wrong render,\n * and never to a thrown error inside a stream handler.\n */\nexport function readPartialKindEvent(\n metadata: Record<string, unknown> | null | undefined,\n): AnyPartialKindEvent | null {\n if (!isRecord(metadata)) return null;\n const candidate = metadata[IR_PARTIAL_KEY];\n if (!isRecord(candidate)) return null;\n if (candidate.v !== IR_VERSION) return null;\n if (typeof candidate.engine !== \"string\") return null;\n if (typeof candidate.seq !== \"number\" || !Number.isFinite(candidate.seq)) {\n return null;\n }\n\n const state = candidate.state;\n if (typeof state !== \"string\") return null;\n if (!PARTIAL_STATES.includes(state as PartialKindState)) return null;\n\n if (state === \"partial\") {\n const root = candidate.root;\n if (!isRecord(root)) return null;\n if (root.role !== \"structured\") return null;\n if (root.status !== \"streaming\") return null;\n if (root.kindState !== \"speculative\") return null;\n if (typeof root.kind !== \"string\" || !root.kind) return null;\n if (!isRecord(root.value)) return null;\n const discriminator = readDiscriminator(root.discriminator);\n const path = readPath(root.path);\n const residue = readResidue(root.residue);\n if (discriminator === null || path === null || residue === undefined) {\n return null;\n }\n return {\n v: IR_VERSION,\n engine: candidate.engine,\n state: \"partial\",\n seq: candidate.seq,\n fingerprint:\n typeof candidate.fingerprint === \"string\" ? candidate.fingerprint : \"\",\n root: {\n role: \"structured\",\n kind: root.kind,\n kindState: \"speculative\",\n discriminator,\n path,\n status: \"streaming\",\n value: root.value,\n residue,\n },\n };\n }\n\n if (typeof candidate.kind !== \"string\" || !candidate.kind) return null;\n\n if (state === \"superseded\") {\n return {\n v: IR_VERSION,\n engine: candidate.engine,\n state: \"superseded\",\n seq: candidate.seq,\n kind: candidate.kind,\n };\n }\n\n if (typeof candidate.reason !== \"string\" || !candidate.reason) return null;\n if (\n candidate.becameKind !== null &&\n typeof candidate.becameKind !== \"string\"\n ) {\n return null;\n }\n if (\n candidate.becameBlockType !== null &&\n typeof candidate.becameBlockType !== \"string\"\n ) {\n return null;\n }\n return {\n v: IR_VERSION,\n engine: candidate.engine,\n state: \"retracted\",\n seq: candidate.seq,\n kind: candidate.kind,\n reason: candidate.reason,\n becameKind: candidate.becameKind,\n becameBlockType: candidate.becameBlockType,\n };\n}\n\n/**\n * Ingest guard for the partial channel on a `render_block` event — the twin of\n * `sanitizeInboundEnvelopeMetadata` for `__ir`, and it exists for the same\n * reason: a malformed server event must be stripped at the wire boundary, not\n * carried into Redux where every later reader has to re-decide whether to\n * trust it.\n *\n * - no `__ir_partial` key → the SAME metadata reference back (zero-touch).\n * - valid event → the SAME metadata reference back (idempotence law).\n * - malformed → a COPY with the key stripped, plus a loud `reportMalformed`.\n * Dropping it degrades that block to \"no live rendering\" and nothing more.\n *\n * Pure: the host injects the reporter, exactly like the envelope gate, so\n * aidream's Workflow Studio can bind its own.\n */\nexport function sanitizeInboundPartialKindMetadata(\n metadata: Record<string, unknown> | null | undefined,\n context: { blockId: string },\n hooks: {\n reportMalformed?: (info: { blockId: string; raw: unknown }) => void;\n } = {},\n): Record<string, unknown> | undefined {\n if (!isRecord(metadata) || !(IR_PARTIAL_KEY in metadata)) {\n return metadata ?? undefined;\n }\n if (readPartialKindEvent(metadata) !== null) return metadata;\n\n const { [IR_PARTIAL_KEY]: raw, ...rest } = metadata;\n hooks.reportMalformed?.({ blockId: context.blockId, raw });\n return rest;\n}\n\n/** Narrowing helper: is this the repeatable provisional event? */\nexport function isProvisionalKind(\n event: AnyPartialKindEvent | null,\n): event is PartialKindEvent {\n return event !== null && event.state === \"partial\";\n}\n\n/**\n * Narrowing helper: is this a TERMINAL event? Every partial ends in exactly\n * one of these — that law is what makes a stuck skeleton impossible, so a\n * consumer clears its provisional render here and nowhere else.\n */\nexport function isTerminalKindEvent(\n event: AnyPartialKindEvent | null,\n): event is SupersededKindEvent | RetractedKindEvent {\n return (\n event !== null && (event.state === \"superseded\" || event.state === \"retracted\")\n );\n}\n\n/**\n * Per-block staleness gate. Events can be re-dispatched, replayed on reconnect,\n * or arrive out of order; only a strictly higher `seq` advances a block.\n * Returns null when the event should be ignored.\n *\n * Pure: the caller owns the `seen` map, so this composes into a reducer\n * without hiding module state.\n */\nexport function advancePartialKind(\n seen: Record<string, number>,\n blockId: string,\n event: AnyPartialKindEvent | null,\n): AnyPartialKindEvent | null {\n if (event === null) return null;\n const last = seen[blockId];\n if (last !== undefined && event.seq <= last) return null;\n return event;\n}\n\n/**\n * The per-block staleness GATE, as a stateful closure over `advancePartialKind`\n * — one per stream.\n *\n * `upsertRenderBlock` REPLACES the stored block, so an event landing on a block\n * would regress what the user is looking at (a filled-in quiz snapping back to\n * two questions, or a terminal being undone by a late `partial`). The highest\n * accepted event is CARRIED FORWARD rather than dropped, so it is a no-op on\n * screen instead of a flicker back to the skeleton.\n *\n * 🚨 TWO arrivals must be carried, and the second one is the common case:\n *\n * 1. A STALE key — a replay or an out-of-order event (`seq <= last`).\n * 2. **NO key at all.** The producer clears `__ir_partial` at the top of every\n * stamp and re-adds it only when the value genuinely advanced\n * (`stream_processor.py::_stamp_partial` → `_partials.advanced(...)`), so\n * it is CORRECT for it to omit the key — re-shipping an identical payload\n * every token is pure wire cost. But the block still ships whole, and\n * replacing the stored block with one that has no partial metadata is what\n * made the provisional render vanish between advances: every non-advancing\n * token dropped the user back to the pending skeleton.\n *\n * Carrying stops at the TERMINAL, and only there. After `superseded` /\n * `retracted` the region's truth is its own content or `__ir`, so resurrecting\n * a provisional value would be a lie that outlives its own contract.\n *\n * Returns the metadata to store: the same reference when nothing changed, a\n * copy with the carried-forward event otherwise.\n */\nexport function makePartialKindStalenessGate(): (\n blockId: string,\n metadata: Record<string, unknown> | undefined,\n) => Record<string, unknown> | undefined {\n const seen: Record<string, number> = {};\n const lastAccepted: Record<string, unknown> = {};\n const terminated: Record<string, true> = {};\n\n return (blockId, metadata) => {\n if (!isRecord(metadata)) return metadata;\n\n if (!(IR_PARTIAL_KEY in metadata)) {\n // The producer omitted the key because nothing advanced. Keep showing the\n // last provisional value — unless this block already terminated, in which\n // case its own content/`__ir` is the truth and the partial must stay gone.\n const open = lastAccepted[blockId];\n if (terminated[blockId] || open === undefined) return metadata;\n return { ...metadata, [IR_PARTIAL_KEY]: open };\n }\n // Anything malformed was stripped by `sanitizeInboundPartialKindMetadata`\n // at the same boundary, so a key still present here reads as valid.\n const parsed = readPartialKindEvent(metadata);\n if (parsed === null) return metadata;\n\n if (advancePartialKind(seen, blockId, parsed) !== null) {\n seen[blockId] = parsed.seq;\n // The highest accepted event is always retained — including a TERMINAL,\n // so a replayed `partial` arriving after it is suppressed by the terminal\n // rather than re-opening a closed region.\n lastAccepted[blockId] = metadata[IR_PARTIAL_KEY];\n if (isTerminalKindEvent(parsed)) terminated[blockId] = true;\n return metadata;\n }\n\n const carried = lastAccepted[blockId];\n if (carried === undefined || carried === metadata[IR_PARTIAL_KEY]) {\n return metadata;\n }\n return { ...metadata, [IR_PARTIAL_KEY]: carried };\n };\n}\n","/**\n * KindSchema — the data-defined field model for a registered kind.\n *\n * `__kind` (KIND_KEY) is the carried discriminator: it is NOT part of a\n * kind's field map; the parser enforces it via `KindSchema.kind` and stamps\n * it onto every compliant snapshot.\n *\n * Moved from app/(dev)/demos/json-block-detector/kind-schemas.ts.\n *\n * 2026-07-15 expressivity extension (A2) — four constructs the Python-owned\n * pydantic schemas need that the v1 vocabulary could not express:\n * - `{type:\"json\"}` / `{type:\"json[]\"}` — any JSON value / array of any\n * JSON values (pydantic bare `Any` fields, `items: {}` arrays, `{}`\n * schemas). A `json` value is implicitly nullable — `null` IS a JSON\n * value — so `nullable` is meaningless (and ignored) on it.\n * - `record` values widened to `\"json\"` (pydantic `dict[str, Any]` /\n * `additionalProperties: true`).\n * - `union` may now carry `kinds` (object unions — anyOf over kind refs,\n * optionally mixed with scalars). Refs externalize to `kind_edge` rows\n * exactly like `array.itemKinds`.\n * - `KindSchema.root` — a NON-OBJECT root form: the kind's VALUE is the\n * root field itself (scalar / array / json / open object), not a `__kind`\n * object with fields. Root-form kinds are data-only: the streaming\n * `__kind` parser cannot type them (a scalar cannot carry a\n * discriminator) and refuses them loudly; validation goes through the\n * emitted JSON Schema (ajv / Pydantic). `root` and a non-empty `fields`\n * are mutually exclusive.\n * - `inline_object.open` — `additionalProperties: true`; fixes the\n * open-empty-object defect where an open `inline_object{fields:{}}`\n * materialized as CLOSED (schema_proposal / item_presentation class).\n *\n * 2026-07-15 input-semantics extension (W3-A, agent-input bridge) — the\n * constructs the Wave-1 sufficiency survey of all 1,529 live agent variables\n * showed FieldSchema could not carry, added so `AgentVariable` ⇄ kind\n * conversion is faithful:\n * - `FieldBase.description` — human guidance; round-trips JSON Schema\n * `description` and VariableDefinition `helpText`.\n * - `FieldBase.default` — the field's default VALUE (JSON Schema `default`,\n * VariableDefinition `defaultValue`). Annotation-level: validators never\n * apply it; emitters carry it verbatim.\n * - `enum.open` — \"one of these options OR any string\" (the FE's\n * `allowOther`). Emits as `anyOf: [{type:\"string\", enum}, {type:\"string\"}]`\n * so the option set survives instead of widening to bare `string`.\n * - `number` bounds `min`/`max`/`step` — JSON Schema\n * `minimum`/`maximum`/`multipleOf` (number/slider components).\n * - `string[].values` (+ `open`) — an items-enum: array of strings drawn\n * from an option set (checkbox components), `open` meaning the set is\n * advisory (`allowOther` on a multi-select).\n * Picklist bindings, scope bindings, and media component identity are\n * PROVENANCE, not structure — they never enter FieldSchema; the bridge\n * carries them out-of-band (see convert/kind-variable-bridge.ts sidecar).\n */\n\n/** System discriminator — hardcoded, not part of per-kind field schemas. */\nexport const KIND_KEY = \"__kind\";\n\nexport type ScalarFieldType = \"string\" | \"number\" | \"boolean\";\n\nexport type ArrayItemScalarType = \"string\" | \"number\" | \"boolean\";\n\n/** Value domain of a `record` field — typed scalars, or any JSON value. */\nexport type RecordValueType = ArrayItemScalarType | \"json\";\n\ntype FieldBase = {\n required?: boolean;\n nullable?: boolean;\n /** Human guidance — JSON Schema `description` / variable `helpText`. */\n description?: string;\n /**\n * Default VALUE (JSON Schema `default` / variable `defaultValue`).\n * Annotation-level: validators never apply it; emitters carry it verbatim.\n */\n default?: unknown;\n};\n\nexport type FieldSchema =\n | (FieldBase & { type: \"string\" | \"boolean\" })\n | (FieldBase & {\n type: \"number\";\n /** Inclusive lower bound — JSON Schema `minimum`. */\n min?: number;\n /** Inclusive upper bound — JSON Schema `maximum`. */\n max?: number;\n /** Increment — JSON Schema `multipleOf`. Annotation-level in the parser. */\n step?: number;\n })\n | (FieldBase & {\n type: \"string[]\";\n /** Items-enum: each item must be one of these values (checkbox option sets). */\n values?: string[];\n /** With `values`: the set is advisory — any string item is also legal (`allowOther`). */\n open?: boolean;\n })\n | (FieldBase & { type: \"number[]\" | \"boolean[]\" })\n | (FieldBase & { type: \"json\" })\n | (FieldBase & { type: \"json[]\" })\n | (FieldBase & { type: \"array\"; itemKinds: string[] })\n | (FieldBase & { type: \"object\"; kind: string })\n | (FieldBase & {\n type: \"inline_object\";\n fields: Record<string, FieldSchema>;\n /** additionalProperties: true — unknown keys are legal, not residue-only. */\n open?: boolean;\n })\n | (FieldBase & { type: \"record\"; values: RecordValueType })\n | (FieldBase & {\n type: \"enum\";\n values: string[];\n /** \"One of these OR any string\" — the option set is advisory (`allowOther`). */\n open?: boolean;\n })\n | (FieldBase & {\n type: \"union\";\n scalars: Array<\"string\" | \"number\" | \"boolean\">;\n /** Object union members — kind refs (anyOf of $refs), may mix with scalars. */\n kinds?: string[];\n });\n\n/**\n * Domain fields only — __kind is enforced by the parser via KindSchema.kind\n * (block slug). A kind with `root` set has NO field map (fields stays `{}`):\n * its value is the root field's type at the top level. See the module header.\n */\nexport type KindSchema = {\n kind: string;\n fields: Record<string, FieldSchema>;\n /** Non-object root form — mutually exclusive with a non-empty `fields`. */\n root?: FieldSchema;\n};\n\nexport function readObjectKind(value: Record<string, unknown>): string | null {\n const kind = value[KIND_KEY];\n return typeof kind === \"string\" ? kind : null;\n}\n\nexport function isScalarArrayType(\n type: FieldSchema[\"type\"],\n): type is \"string[]\" | \"number[]\" | \"boolean[]\" {\n return type === \"string[]\" || type === \"number[]\" || type === \"boolean[]\";\n}\n\nexport function scalarArrayItemType(\n type: \"string[]\" | \"number[]\" | \"boolean[]\",\n): ArrayItemScalarType {\n if (type === \"number[]\") return \"number\";\n if (type === \"boolean[]\") return \"boolean\";\n return \"string\";\n}\n\n/**\n * Does this field's value domain accept ANY JSON shape (object/array/scalar/\n * null alike)? True for `json` and `json[]` ITEMS — the parser treats the\n * subtree under such a field as opaque (no kind identification, no raw_object\n * degradation: unknown structure is the declared contract, not a failure).\n */\nexport function isJsonAnyField(field: FieldSchema): boolean {\n return field.type === \"json\" || field.type === \"json[]\";\n}\n","/**\n * Runtime wrapper kinds — the reader, and THE elision gate.\n *\n * Cross-repo contract (system of record):\n * `common-docs/systems/content-ir-system/RUNTIME_WRAPPER_WIRE.md`.\n *\n * A runtime wrapper is the CLOSED set of envelopes that carry instance\n * context with a data kind NESTED inside: `node_outcome` (one settled node\n * invocation) and `run_result` (one terminated run, nesting one\n * `node_outcome` per terminal node). `tool_result` is registered server-side\n * but nothing emits it yet, so nothing here reads it.\n *\n * ## THE ELISION RULE — do it ONCE, here\n *\n * The payload is NEVER sent twice. On the wire `output` is `null` and\n * `output_ref` names the FRAME field that already holds the value:\n *\n * - `\"output\"` → the frame's own `output` (`node_completed.output`,\n * the run row's `output`).\n * - `\"output.<node_id>\"` → that key of the frame's terminal output map.\n *\n * PRESENCE OF `output_ref` IS THE MARKER. A bare `output: null` with NO ref is\n * a legitimately empty payload — never an elision, never something to go\n * looking for. This is the same rule the `__ir` envelope follows with\n * `value_ref`, for the same reason: otherwise every payload is serialized\n * twice per streamed event, twice per durable row and twice per run read.\n *\n * Rehydration happens at the single INGEST GATE (each host's one ingest point —\n * Matrix's workflow-runs reducer, the Studio's inbound-envelope gate),\n * before anything reads the wrapper. No renderer, selector or component ever\n * sees an un-rehydrated wrapper, so none of them may re-implement this.\n *\n * ## Never load-bearing\n *\n * Assembly is a pure read. A malformed wrapper yields `null` and the frame's\n * own fields carry the surface exactly as they did before the wrapper\n * existed — additive on the wire, additive here.\n */\n\nimport { KIND_KEY } from \"../core/kind-schema.types\";\n\n/** The registered slugs — named once, never spelled by hand elsewhere. */\nexport const NODE_OUTCOME_KIND = \"node_outcome\";\nexport const RUN_RESULT_KIND = \"run_result\";\n\n/** One settled node invocation, with its data kind nested in `output`. */\nexport interface NodeOutcomeWrapper {\n __kind: typeof NODE_OUTCOME_KIND;\n run_id: string;\n node_id: string;\n workflow_id: string | null;\n step: number | null;\n attempt: number;\n status: string;\n started_at: string | null;\n ended_at: string | null;\n /** `0` is a REAL duration, not \"unknown\"; `null` is unknown. */\n duration_ms: number | null;\n /** null = the node declared no kind (a loud defect, never a pass). */\n output_kind: string | null;\n /** null = never checked / degraded — NEVER renderable as a pass. */\n output_kind_ok: boolean | null;\n output_kind_errors: string[] | null;\n /** Rehydrated by {@link rehydrateNodeOutcome}; null = genuinely empty. */\n output: unknown;\n}\n\n/** One terminated run. `outputs` is one wrapper per TERMINAL node. */\nexport interface RunResultWrapper {\n __kind: typeof RUN_RESULT_KIND;\n run_id: string;\n workflow_id: string | null;\n status: string;\n started_at: string | null;\n ended_at: string | null;\n duration_ms: number | null;\n output_kind: string | null;\n output: unknown;\n outputs: NodeOutcomeWrapper[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(source: Record<string, unknown>, key: string): string | null {\n const value = source[key];\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nfunction num(source: Record<string, unknown>, key: string): number | null {\n const value = source[key];\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction bool(source: Record<string, unknown>, key: string): boolean | null {\n const value = source[key];\n return typeof value === \"boolean\" ? value : null;\n}\n\nfunction strings(\n source: Record<string, unknown>,\n key: string,\n): string[] | null {\n const value = source[key];\n if (!Array.isArray(value)) return null;\n const out = value.filter((item): item is string => typeof item === \"string\");\n return out.length > 0 ? out : null;\n}\n\n/**\n * Resolve a dotted `output_ref` against the frame that carries the payload.\n * Returns `undefined` when the path does not resolve — the caller keeps\n * `output: null` rather than inventing a value.\n */\nexport function readOutputRef(frame: unknown, ref: string): unknown {\n let cursor: unknown = frame;\n for (const segment of ref.split(\".\")) {\n if (!isRecord(cursor)) return undefined;\n if (!(segment in cursor)) return undefined;\n cursor = cursor[segment];\n }\n return cursor;\n}\n\n/**\n * Read a `node_outcome` off a frame and rehydrate its elided payload.\n *\n * `frame` is the object the wrapper travelled ON — the `node_completed` event,\n * or the run read response for a `run_result`'s children. Returns null for\n * anything that is not a node_outcome (including a missing wrapper: the\n * producer fails OPEN, so an absent wrapper is a normal, non-fatal state).\n */\nexport function rehydrateNodeOutcome(\n raw: unknown,\n frame: unknown,\n): NodeOutcomeWrapper | null {\n if (!isRecord(raw)) return null;\n if (raw[KIND_KEY] !== NODE_OUTCOME_KIND) return null;\n // THE ELISION RULE. Presence of the ref is the marker; a bare null is empty.\n const ref = str(raw, \"output_ref\");\n const resolved = ref === null ? undefined : readOutputRef(frame, ref);\n return readNodeOutcomeValue(\n resolved === undefined ? raw : { ...raw, output: resolved },\n );\n}\n\n/**\n * Read an ALREADY-REHYDRATED node_outcome value into its typed form.\n *\n * Deliberately does NOT require `__kind`: the render bridge strips the root\n * discriminator before the component sees the value, and it does NOT touch\n * `output_ref` — by the time anything renders, the ingest gate has already\n * resolved the elision, and a second resolution attempt against a frame that\n * is no longer there is how a payload goes missing.\n */\nexport function readNodeOutcomeValue(\n raw: unknown,\n): NodeOutcomeWrapper | null {\n if (!isRecord(raw)) return null;\n const runId = str(raw, \"run_id\");\n const nodeId = str(raw, \"node_id\");\n if (!runId || !nodeId) return null;\n const output = raw.output ?? null;\n\n return {\n __kind: NODE_OUTCOME_KIND,\n run_id: runId,\n node_id: nodeId,\n workflow_id: str(raw, \"workflow_id\"),\n step: num(raw, \"step\"),\n attempt: num(raw, \"attempt\") ?? 1,\n status: str(raw, \"status\") ?? \"completed\",\n started_at: str(raw, \"started_at\"),\n ended_at: str(raw, \"ended_at\"),\n duration_ms: num(raw, \"duration_ms\"),\n output_kind: str(raw, \"output_kind\"),\n output_kind_ok: bool(raw, \"output_kind_ok\"),\n output_kind_errors: strings(raw, \"output_kind_errors\"),\n output,\n };\n}\n\n/**\n * Read a `run_result` off the run read response and rehydrate every elided\n * payload — its own, and each terminal node's. Both resolve against the SAME\n * frame (the run read response), which is what `\"output.<node_id>\"` addresses.\n */\nexport function rehydrateRunResult(\n raw: unknown,\n frame: unknown,\n): RunResultWrapper | null {\n if (!isRecord(raw)) return null;\n if (raw[KIND_KEY] !== RUN_RESULT_KIND) return null;\n const ref = str(raw, \"output_ref\");\n const resolved = ref === null ? undefined : readOutputRef(frame, ref);\n const outputs = Array.isArray(raw.outputs)\n ? raw.outputs\n .map((child) => rehydrateNodeOutcome(child, frame))\n .filter((child): child is NodeOutcomeWrapper => child !== null)\n : [];\n return readRunResultValue({\n ...raw,\n ...(resolved === undefined ? {} : { output: resolved }),\n outputs,\n });\n}\n\n/**\n * Read an ALREADY-REHYDRATED run_result value into its typed form. Same\n * contract as {@link readNodeOutcomeValue}: no `__kind` requirement, no\n * second elision pass.\n */\nexport function readRunResultValue(raw: unknown): RunResultWrapper | null {\n if (!isRecord(raw)) return null;\n const runId = str(raw, \"run_id\");\n if (!runId) return null;\n const output = raw.output ?? null;\n const outputs = Array.isArray(raw.outputs)\n ? raw.outputs\n .map((child) => readNodeOutcomeValue(child))\n .filter((child): child is NodeOutcomeWrapper => child !== null)\n : [];\n\n return {\n __kind: RUN_RESULT_KIND,\n run_id: runId,\n workflow_id: str(raw, \"workflow_id\"),\n status: str(raw, \"status\") ?? \"completed\",\n started_at: str(raw, \"started_at\"),\n ended_at: str(raw, \"ended_at\"),\n duration_ms: num(raw, \"duration_ms\"),\n output_kind: str(raw, \"output_kind\"),\n output,\n outputs,\n };\n}\n\n/**\n * The kind verdict, as three states the UI must keep distinct.\n *\n * `unchecked` is NEVER a pass: the engine either did not check (no declared\n * kind) or checked and could not conclude. Collapsing it into \"ok\" is how a\n * confidently-rendered document gets shown for a shape nobody verified.\n */\nexport type KindVerdict = \"passed\" | \"failed\" | \"unchecked\";\n\nexport function kindVerdictOf(wrapper: {\n output_kind: string | null;\n output_kind_ok: boolean | null;\n}): KindVerdict {\n if (wrapper.output_kind_ok === true) return \"passed\";\n if (wrapper.output_kind_ok === false) return \"failed\";\n return \"unchecked\";\n}\n","/**\n * The forward composer: given a kind's stored example, produce the EMIT/RENDER\n * payload — `{ \"__kind\": <slug>, ...data }`.\n *\n * Pure kernel module (@ai-matrx/content-ir `wire/`): no React, no Redux, no IO.\n *\n * Since 2026-08-23 stored examples and instances ALREADY carry their marker\n * (`__kind` is part of the data — KINDS_EVERYWHERE_PLAN §4.2), so for a\n * well-formed row this is an IDENTITY with a guarantee attached: the marker is\n * the FIRST key and it names the right slug. It stays because it is also the\n * repair for the legacy rows and hand-typed values that do not, and because a\n * caller wanting a copy-ready render payload should not have to know which it\n * has.\n *\n * Scalars/arrays are returned unchanged — for those kinds the identity travels\n * out of band (`root.kind`); there is no key to add.\n */\n\nimport { KIND_KEY } from \"../core/kind-schema.types\";\n\nexport function withRootKind(kind: string, value: unknown): unknown {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return { [KIND_KEY]: kind, ...(value as Record<string, unknown>) };\n }\n return value;\n}\n\n/** The copy-ready render payload: pretty JSON of `{ __kind, ...data }`. */\nexport function emitPayloadJson(kind: string, value: unknown): string {\n return JSON.stringify(withRootKind(kind, value), null, 2);\n}\n\n/**\n * The copy-ready render BLOCK — the render payload inside a ```json fence, the\n * exact form an agent emits and a user pastes into a prompt or a message to see\n * it render live.\n */\nexport function emitPayloadFence(kind: string, value: unknown): string {\n return \"```json\\n\" + emitPayloadJson(kind, value) + \"\\n```\";\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/content-ir",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "The pure AI Matrx Content IR parser, normalized envelope, session, schema conversion, and structural validation kernel.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -33,8 +33,80 @@
|
|
|
33
33
|
"default": "./dist/index.cjs"
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
+
"./core": {
|
|
37
|
+
"import": {
|
|
38
|
+
"types": "./dist/core.d.ts",
|
|
39
|
+
"default": "./dist/core.js"
|
|
40
|
+
},
|
|
41
|
+
"require": {
|
|
42
|
+
"types": "./dist/core.d.cts",
|
|
43
|
+
"default": "./dist/core.cjs"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"./session": {
|
|
47
|
+
"import": {
|
|
48
|
+
"types": "./dist/session.d.ts",
|
|
49
|
+
"default": "./dist/session.js"
|
|
50
|
+
},
|
|
51
|
+
"require": {
|
|
52
|
+
"types": "./dist/session.d.cts",
|
|
53
|
+
"default": "./dist/session.cjs"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"./registry": {
|
|
57
|
+
"import": {
|
|
58
|
+
"types": "./dist/registry.d.ts",
|
|
59
|
+
"default": "./dist/registry.js"
|
|
60
|
+
},
|
|
61
|
+
"require": {
|
|
62
|
+
"types": "./dist/registry.d.cts",
|
|
63
|
+
"default": "./dist/registry.cjs"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"./convert": {
|
|
67
|
+
"import": {
|
|
68
|
+
"types": "./dist/convert.d.ts",
|
|
69
|
+
"default": "./dist/convert.js"
|
|
70
|
+
},
|
|
71
|
+
"require": {
|
|
72
|
+
"types": "./dist/convert.d.cts",
|
|
73
|
+
"default": "./dist/convert.cjs"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"./wire": {
|
|
77
|
+
"import": {
|
|
78
|
+
"types": "./dist/wire.d.ts",
|
|
79
|
+
"default": "./dist/wire.js"
|
|
80
|
+
},
|
|
81
|
+
"require": {
|
|
82
|
+
"types": "./dist/wire.d.cts",
|
|
83
|
+
"default": "./dist/wire.cjs"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
36
86
|
"./package.json": "./package.json"
|
|
37
87
|
},
|
|
88
|
+
"typesVersions": {
|
|
89
|
+
"*": {
|
|
90
|
+
"core": [
|
|
91
|
+
"./dist/core.d.ts"
|
|
92
|
+
],
|
|
93
|
+
"session": [
|
|
94
|
+
"./dist/session.d.ts"
|
|
95
|
+
],
|
|
96
|
+
"registry": [
|
|
97
|
+
"./dist/registry.d.ts"
|
|
98
|
+
],
|
|
99
|
+
"convert": [
|
|
100
|
+
"./dist/convert.d.ts"
|
|
101
|
+
],
|
|
102
|
+
"wire": [
|
|
103
|
+
"./dist/wire.d.ts"
|
|
104
|
+
],
|
|
105
|
+
"*": [
|
|
106
|
+
"./dist/index.d.ts"
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
},
|
|
38
110
|
"dependencies": {
|
|
39
111
|
"ajv": "^8.20.0"
|
|
40
112
|
},
|