@ai-matrx/content-ir 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +24 -5
  3. package/dist/convert.cjs +1680 -0
  4. package/dist/convert.cjs.map +1 -0
  5. package/dist/convert.d.cts +230 -0
  6. package/dist/convert.d.ts +230 -0
  7. package/dist/convert.js +1666 -0
  8. package/dist/convert.js.map +1 -0
  9. package/dist/core.cjs +2493 -0
  10. package/dist/core.cjs.map +1 -0
  11. package/dist/core.d.cts +370 -0
  12. package/dist/core.d.ts +370 -0
  13. package/dist/core.js +2452 -0
  14. package/dist/core.js.map +1 -0
  15. package/dist/index.cjs +3 -1
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +9 -2030
  18. package/dist/index.d.ts +9 -2030
  19. package/dist/index.js +3 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/ir-tree-DbLVxbf1.d.cts +441 -0
  22. package/dist/ir-tree-Dsc_66ek.d.ts +441 -0
  23. package/dist/ir-types-95bA2cXH.d.cts +119 -0
  24. package/dist/ir-types-95bA2cXH.d.ts +119 -0
  25. package/dist/kind-schema.types-CwncWj9U.d.cts +139 -0
  26. package/dist/kind-schema.types-CwncWj9U.d.ts +139 -0
  27. package/dist/registry.cjs +468 -0
  28. package/dist/registry.cjs.map +1 -0
  29. package/dist/registry.d.cts +357 -0
  30. package/dist/registry.d.ts +357 -0
  31. package/dist/registry.js +456 -0
  32. package/dist/registry.js.map +1 -0
  33. package/dist/session.cjs +2052 -0
  34. package/dist/session.cjs.map +1 -0
  35. package/dist/session.d.cts +75 -0
  36. package/dist/session.d.ts +75 -0
  37. package/dist/session.js +2047 -0
  38. package/dist/session.js.map +1 -0
  39. package/dist/wire.cjs +310 -0
  40. package/dist/wire.cjs.map +1 -0
  41. package/dist/wire.d.cts +326 -0
  42. package/dist/wire.d.ts +326 -0
  43. package/dist/wire.js +291 -0
  44. package/dist/wire.js.map +1 -0
  45. package/package.json +73 -1
@@ -0,0 +1,326 @@
1
+ import { c as IR_VERSION, d as IrDiscriminator, f as IrPath, g as IrResidue } from './ir-types-95bA2cXH.cjs';
2
+
3
+ /**
4
+ * Streaming partial kinds — the TS twin of the Python producer's contract.
5
+ *
6
+ * Cross-repo system-of-record (read it before changing anything here):
7
+ * `common-docs/systems/content-ir-system/STREAMING_PARTIAL_KINDS.md`.
8
+ * Python twin: `aidream/packages/matrx-graph/matrx_graph/content_ir/partial.py`.
9
+ *
10
+ * WHAT THIS IS
11
+ * ------------
12
+ * While a structured region streams, the server announces what it thinks the
13
+ * region IS and what has arrived so far, so the UI fills in progressively
14
+ * instead of showing a spinner until the closing brace. Three events, a CLOSED
15
+ * union on `state`, all riding `metadata.__ir_partial` on the `render_block`
16
+ * events this app already receives:
17
+ *
18
+ * partial — repeatable. A provisional instance whose `root.value` is
19
+ * VALID, CLOSED JSON (the server truncates and closes it, so
20
+ * this side never repairs or guesses). `kindState` is
21
+ * "speculative": it MAY still turn out to be something else.
22
+ * superseded — TERMINAL. The region completed as the announced kind; drop
23
+ * the provisional render, the block's own content/`__ir` is the
24
+ * truth.
25
+ * retracted — TERMINAL escape hatch. Detection was wrong; `becameKind` /
26
+ * `becameBlockType` name what it actually is. Never a silent
27
+ * swap.
28
+ *
29
+ * WHY IT IS NOT ON `__ir`
30
+ * -----------------------
31
+ * `__ir` means "validated against the registered schema", and a valid `__ir`
32
+ * is SEEDED into the fingerprint-keyed envelope memo. A provisional value
33
+ * there would poison every later read of that region. The two channels never
34
+ * touch: `classifyInboundEnvelopeMetadata` sees `absent` for a partial and
35
+ * passes the metadata through by reference.
36
+ *
37
+ * Pure kernel module: types + validators only. No React, no Redux, no IO.
38
+ * Lives in @ai-matrx/content-ir `wire/` so EVERY UI (Matrix, Workflow Studio,
39
+ * the dashboard, the Chrome extension, the desktop app) reads the channel
40
+ * through the same reader.
41
+ */
42
+
43
+ /** The reserved metadata key carrying every event of this contract. */
44
+ declare const IR_PARTIAL_KEY: "__ir_partial";
45
+ type PartialKindState = "partial" | "superseded" | "retracted";
46
+ /** The provisional node. Deliberately `IrStructuredNode`-shaped so existing IR readers work. */
47
+ interface PartialKindNode {
48
+ role: "structured";
49
+ /** The server's DETECTION GUESS for this region. */
50
+ kind: string;
51
+ /** Always "speculative" on a partial — pre-recognition, not a resolved kind. */
52
+ kindState: "speculative";
53
+ discriminator: IrDiscriminator;
54
+ path: IrPath;
55
+ status: "streaming";
56
+ /**
57
+ * Valid, closed JSON carrying its own `__kind`. MAY be missing required
58
+ * schema fields — that is what `partial_unvalidated` in `residue.notices`
59
+ * says. A renderer that throws on an absent field is not partial-ready and
60
+ * must not be routed a provisional value.
61
+ */
62
+ value: Record<string, unknown>;
63
+ residue: IrResidue | null;
64
+ }
65
+ interface PartialKindEvent {
66
+ v: typeof IR_VERSION;
67
+ engine: string;
68
+ state: "partial";
69
+ /** Monotonic PER BLOCK — the ordering / staleness key. Keep the highest. */
70
+ seq: number;
71
+ fingerprint: string;
72
+ root: PartialKindNode;
73
+ }
74
+ interface SupersededKindEvent {
75
+ v: typeof IR_VERSION;
76
+ engine: string;
77
+ state: "superseded";
78
+ seq: number;
79
+ kind: string;
80
+ }
81
+ interface RetractedKindEvent {
82
+ v: typeof IR_VERSION;
83
+ engine: string;
84
+ state: "retracted";
85
+ seq: number;
86
+ /** The kind that was WRONGLY announced. */
87
+ kind: string;
88
+ reason: string;
89
+ /** What it actually is — null when it resolved to no registered kind. */
90
+ becameKind: string | null;
91
+ /** The detector's final block type, so a consumer re-routes without guessing. */
92
+ becameBlockType: string | null;
93
+ }
94
+ type AnyPartialKindEvent = PartialKindEvent | SupersededKindEvent | RetractedKindEvent;
95
+ /**
96
+ * Read + validate a partial-channel event off a block's metadata.
97
+ *
98
+ * Returns null for anything malformed, foreign, or of an unknown `state`. A
99
+ * malformed partial degrades to "no live rendering" — never to a wrong render,
100
+ * and never to a thrown error inside a stream handler.
101
+ */
102
+ declare function readPartialKindEvent(metadata: Record<string, unknown> | null | undefined): AnyPartialKindEvent | null;
103
+ /**
104
+ * Ingest guard for the partial channel on a `render_block` event — the twin of
105
+ * `sanitizeInboundEnvelopeMetadata` for `__ir`, and it exists for the same
106
+ * reason: a malformed server event must be stripped at the wire boundary, not
107
+ * carried into Redux where every later reader has to re-decide whether to
108
+ * trust it.
109
+ *
110
+ * - no `__ir_partial` key → the SAME metadata reference back (zero-touch).
111
+ * - valid event → the SAME metadata reference back (idempotence law).
112
+ * - malformed → a COPY with the key stripped, plus a loud `reportMalformed`.
113
+ * Dropping it degrades that block to "no live rendering" and nothing more.
114
+ *
115
+ * Pure: the host injects the reporter, exactly like the envelope gate, so
116
+ * aidream's Workflow Studio can bind its own.
117
+ */
118
+ declare function sanitizeInboundPartialKindMetadata(metadata: Record<string, unknown> | null | undefined, context: {
119
+ blockId: string;
120
+ }, hooks?: {
121
+ reportMalformed?: (info: {
122
+ blockId: string;
123
+ raw: unknown;
124
+ }) => void;
125
+ }): Record<string, unknown> | undefined;
126
+ /** Narrowing helper: is this the repeatable provisional event? */
127
+ declare function isProvisionalKind(event: AnyPartialKindEvent | null): event is PartialKindEvent;
128
+ /**
129
+ * Narrowing helper: is this a TERMINAL event? Every partial ends in exactly
130
+ * one of these — that law is what makes a stuck skeleton impossible, so a
131
+ * consumer clears its provisional render here and nowhere else.
132
+ */
133
+ declare function isTerminalKindEvent(event: AnyPartialKindEvent | null): event is SupersededKindEvent | RetractedKindEvent;
134
+ /**
135
+ * Per-block staleness gate. Events can be re-dispatched, replayed on reconnect,
136
+ * or arrive out of order; only a strictly higher `seq` advances a block.
137
+ * Returns null when the event should be ignored.
138
+ *
139
+ * Pure: the caller owns the `seen` map, so this composes into a reducer
140
+ * without hiding module state.
141
+ */
142
+ declare function advancePartialKind(seen: Record<string, number>, blockId: string, event: AnyPartialKindEvent | null): AnyPartialKindEvent | null;
143
+ /**
144
+ * The per-block staleness GATE, as a stateful closure over `advancePartialKind`
145
+ * — one per stream.
146
+ *
147
+ * `upsertRenderBlock` REPLACES the stored block, so an event landing on a block
148
+ * would regress what the user is looking at (a filled-in quiz snapping back to
149
+ * two questions, or a terminal being undone by a late `partial`). The highest
150
+ * accepted event is CARRIED FORWARD rather than dropped, so it is a no-op on
151
+ * screen instead of a flicker back to the skeleton.
152
+ *
153
+ * 🚨 TWO arrivals must be carried, and the second one is the common case:
154
+ *
155
+ * 1. A STALE key — a replay or an out-of-order event (`seq <= last`).
156
+ * 2. **NO key at all.** The producer clears `__ir_partial` at the top of every
157
+ * stamp and re-adds it only when the value genuinely advanced
158
+ * (`stream_processor.py::_stamp_partial` → `_partials.advanced(...)`), so
159
+ * it is CORRECT for it to omit the key — re-shipping an identical payload
160
+ * every token is pure wire cost. But the block still ships whole, and
161
+ * replacing the stored block with one that has no partial metadata is what
162
+ * made the provisional render vanish between advances: every non-advancing
163
+ * token dropped the user back to the pending skeleton.
164
+ *
165
+ * Carrying stops at the TERMINAL, and only there. After `superseded` /
166
+ * `retracted` the region's truth is its own content or `__ir`, so resurrecting
167
+ * a provisional value would be a lie that outlives its own contract.
168
+ *
169
+ * Returns the metadata to store: the same reference when nothing changed, a
170
+ * copy with the carried-forward event otherwise.
171
+ */
172
+ declare function makePartialKindStalenessGate(): (blockId: string, metadata: Record<string, unknown> | undefined) => Record<string, unknown> | undefined;
173
+
174
+ /**
175
+ * Runtime wrapper kinds — the reader, and THE elision gate.
176
+ *
177
+ * Cross-repo contract (system of record):
178
+ * `common-docs/systems/content-ir-system/RUNTIME_WRAPPER_WIRE.md`.
179
+ *
180
+ * A runtime wrapper is the CLOSED set of envelopes that carry instance
181
+ * context with a data kind NESTED inside: `node_outcome` (one settled node
182
+ * invocation) and `run_result` (one terminated run, nesting one
183
+ * `node_outcome` per terminal node). `tool_result` is registered server-side
184
+ * but nothing emits it yet, so nothing here reads it.
185
+ *
186
+ * ## THE ELISION RULE — do it ONCE, here
187
+ *
188
+ * The payload is NEVER sent twice. On the wire `output` is `null` and
189
+ * `output_ref` names the FRAME field that already holds the value:
190
+ *
191
+ * - `"output"` → the frame's own `output` (`node_completed.output`,
192
+ * the run row's `output`).
193
+ * - `"output.<node_id>"` → that key of the frame's terminal output map.
194
+ *
195
+ * PRESENCE OF `output_ref` IS THE MARKER. A bare `output: null` with NO ref is
196
+ * a legitimately empty payload — never an elision, never something to go
197
+ * looking for. This is the same rule the `__ir` envelope follows with
198
+ * `value_ref`, for the same reason: otherwise every payload is serialized
199
+ * twice per streamed event, twice per durable row and twice per run read.
200
+ *
201
+ * Rehydration happens at the single INGEST GATE (each host's one ingest point —
202
+ * Matrix's workflow-runs reducer, the Studio's inbound-envelope gate),
203
+ * before anything reads the wrapper. No renderer, selector or component ever
204
+ * sees an un-rehydrated wrapper, so none of them may re-implement this.
205
+ *
206
+ * ## Never load-bearing
207
+ *
208
+ * Assembly is a pure read. A malformed wrapper yields `null` and the frame's
209
+ * own fields carry the surface exactly as they did before the wrapper
210
+ * existed — additive on the wire, additive here.
211
+ */
212
+ /** The registered slugs — named once, never spelled by hand elsewhere. */
213
+ declare const NODE_OUTCOME_KIND = "node_outcome";
214
+ declare const RUN_RESULT_KIND = "run_result";
215
+ /** One settled node invocation, with its data kind nested in `output`. */
216
+ interface NodeOutcomeWrapper {
217
+ __kind: typeof NODE_OUTCOME_KIND;
218
+ run_id: string;
219
+ node_id: string;
220
+ workflow_id: string | null;
221
+ step: number | null;
222
+ attempt: number;
223
+ status: string;
224
+ started_at: string | null;
225
+ ended_at: string | null;
226
+ /** `0` is a REAL duration, not "unknown"; `null` is unknown. */
227
+ duration_ms: number | null;
228
+ /** null = the node declared no kind (a loud defect, never a pass). */
229
+ output_kind: string | null;
230
+ /** null = never checked / degraded — NEVER renderable as a pass. */
231
+ output_kind_ok: boolean | null;
232
+ output_kind_errors: string[] | null;
233
+ /** Rehydrated by {@link rehydrateNodeOutcome}; null = genuinely empty. */
234
+ output: unknown;
235
+ }
236
+ /** One terminated run. `outputs` is one wrapper per TERMINAL node. */
237
+ interface RunResultWrapper {
238
+ __kind: typeof RUN_RESULT_KIND;
239
+ run_id: string;
240
+ workflow_id: string | null;
241
+ status: string;
242
+ started_at: string | null;
243
+ ended_at: string | null;
244
+ duration_ms: number | null;
245
+ output_kind: string | null;
246
+ output: unknown;
247
+ outputs: NodeOutcomeWrapper[];
248
+ }
249
+ /**
250
+ * Resolve a dotted `output_ref` against the frame that carries the payload.
251
+ * Returns `undefined` when the path does not resolve — the caller keeps
252
+ * `output: null` rather than inventing a value.
253
+ */
254
+ declare function readOutputRef(frame: unknown, ref: string): unknown;
255
+ /**
256
+ * Read a `node_outcome` off a frame and rehydrate its elided payload.
257
+ *
258
+ * `frame` is the object the wrapper travelled ON — the `node_completed` event,
259
+ * or the run read response for a `run_result`'s children. Returns null for
260
+ * anything that is not a node_outcome (including a missing wrapper: the
261
+ * producer fails OPEN, so an absent wrapper is a normal, non-fatal state).
262
+ */
263
+ declare function rehydrateNodeOutcome(raw: unknown, frame: unknown): NodeOutcomeWrapper | null;
264
+ /**
265
+ * Read an ALREADY-REHYDRATED node_outcome value into its typed form.
266
+ *
267
+ * Deliberately does NOT require `__kind`: the render bridge strips the root
268
+ * discriminator before the component sees the value, and it does NOT touch
269
+ * `output_ref` — by the time anything renders, the ingest gate has already
270
+ * resolved the elision, and a second resolution attempt against a frame that
271
+ * is no longer there is how a payload goes missing.
272
+ */
273
+ declare function readNodeOutcomeValue(raw: unknown): NodeOutcomeWrapper | null;
274
+ /**
275
+ * Read a `run_result` off the run read response and rehydrate every elided
276
+ * payload — its own, and each terminal node's. Both resolve against the SAME
277
+ * frame (the run read response), which is what `"output.<node_id>"` addresses.
278
+ */
279
+ declare function rehydrateRunResult(raw: unknown, frame: unknown): RunResultWrapper | null;
280
+ /**
281
+ * Read an ALREADY-REHYDRATED run_result value into its typed form. Same
282
+ * contract as {@link readNodeOutcomeValue}: no `__kind` requirement, no
283
+ * second elision pass.
284
+ */
285
+ declare function readRunResultValue(raw: unknown): RunResultWrapper | null;
286
+ /**
287
+ * The kind verdict, as three states the UI must keep distinct.
288
+ *
289
+ * `unchecked` is NEVER a pass: the engine either did not check (no declared
290
+ * kind) or checked and could not conclude. Collapsing it into "ok" is how a
291
+ * confidently-rendered document gets shown for a shape nobody verified.
292
+ */
293
+ type KindVerdict = "passed" | "failed" | "unchecked";
294
+ declare function kindVerdictOf(wrapper: {
295
+ output_kind: string | null;
296
+ output_kind_ok: boolean | null;
297
+ }): KindVerdict;
298
+
299
+ /**
300
+ * The forward composer: given a kind's stored example, produce the EMIT/RENDER
301
+ * payload — `{ "__kind": <slug>, ...data }`.
302
+ *
303
+ * Pure kernel module (@ai-matrx/content-ir `wire/`): no React, no Redux, no IO.
304
+ *
305
+ * Since 2026-08-23 stored examples and instances ALREADY carry their marker
306
+ * (`__kind` is part of the data — KINDS_EVERYWHERE_PLAN §4.2), so for a
307
+ * well-formed row this is an IDENTITY with a guarantee attached: the marker is
308
+ * the FIRST key and it names the right slug. It stays because it is also the
309
+ * repair for the legacy rows and hand-typed values that do not, and because a
310
+ * caller wanting a copy-ready render payload should not have to know which it
311
+ * has.
312
+ *
313
+ * Scalars/arrays are returned unchanged — for those kinds the identity travels
314
+ * out of band (`root.kind`); there is no key to add.
315
+ */
316
+ declare function withRootKind(kind: string, value: unknown): unknown;
317
+ /** The copy-ready render payload: pretty JSON of `{ __kind, ...data }`. */
318
+ declare function emitPayloadJson(kind: string, value: unknown): string;
319
+ /**
320
+ * The copy-ready render BLOCK — the render payload inside a ```json fence, the
321
+ * exact form an agent emits and a user pastes into a prompt or a message to see
322
+ * it render live.
323
+ */
324
+ declare function emitPayloadFence(kind: string, value: unknown): string;
325
+
326
+ export { type AnyPartialKindEvent, IR_PARTIAL_KEY, type KindVerdict, NODE_OUTCOME_KIND, type NodeOutcomeWrapper, type PartialKindEvent, type PartialKindNode, type PartialKindState, RUN_RESULT_KIND, type RetractedKindEvent, type RunResultWrapper, type SupersededKindEvent, advancePartialKind, emitPayloadFence, emitPayloadJson, isProvisionalKind, isTerminalKindEvent, kindVerdictOf, makePartialKindStalenessGate, readNodeOutcomeValue, readOutputRef, readPartialKindEvent, readRunResultValue, rehydrateNodeOutcome, rehydrateRunResult, sanitizeInboundPartialKindMetadata, withRootKind };
package/dist/wire.d.ts ADDED
@@ -0,0 +1,326 @@
1
+ import { c as IR_VERSION, d as IrDiscriminator, f as IrPath, g as IrResidue } from './ir-types-95bA2cXH.js';
2
+
3
+ /**
4
+ * Streaming partial kinds — the TS twin of the Python producer's contract.
5
+ *
6
+ * Cross-repo system-of-record (read it before changing anything here):
7
+ * `common-docs/systems/content-ir-system/STREAMING_PARTIAL_KINDS.md`.
8
+ * Python twin: `aidream/packages/matrx-graph/matrx_graph/content_ir/partial.py`.
9
+ *
10
+ * WHAT THIS IS
11
+ * ------------
12
+ * While a structured region streams, the server announces what it thinks the
13
+ * region IS and what has arrived so far, so the UI fills in progressively
14
+ * instead of showing a spinner until the closing brace. Three events, a CLOSED
15
+ * union on `state`, all riding `metadata.__ir_partial` on the `render_block`
16
+ * events this app already receives:
17
+ *
18
+ * partial — repeatable. A provisional instance whose `root.value` is
19
+ * VALID, CLOSED JSON (the server truncates and closes it, so
20
+ * this side never repairs or guesses). `kindState` is
21
+ * "speculative": it MAY still turn out to be something else.
22
+ * superseded — TERMINAL. The region completed as the announced kind; drop
23
+ * the provisional render, the block's own content/`__ir` is the
24
+ * truth.
25
+ * retracted — TERMINAL escape hatch. Detection was wrong; `becameKind` /
26
+ * `becameBlockType` name what it actually is. Never a silent
27
+ * swap.
28
+ *
29
+ * WHY IT IS NOT ON `__ir`
30
+ * -----------------------
31
+ * `__ir` means "validated against the registered schema", and a valid `__ir`
32
+ * is SEEDED into the fingerprint-keyed envelope memo. A provisional value
33
+ * there would poison every later read of that region. The two channels never
34
+ * touch: `classifyInboundEnvelopeMetadata` sees `absent` for a partial and
35
+ * passes the metadata through by reference.
36
+ *
37
+ * Pure kernel module: types + validators only. No React, no Redux, no IO.
38
+ * Lives in @ai-matrx/content-ir `wire/` so EVERY UI (Matrix, Workflow Studio,
39
+ * the dashboard, the Chrome extension, the desktop app) reads the channel
40
+ * through the same reader.
41
+ */
42
+
43
+ /** The reserved metadata key carrying every event of this contract. */
44
+ declare const IR_PARTIAL_KEY: "__ir_partial";
45
+ type PartialKindState = "partial" | "superseded" | "retracted";
46
+ /** The provisional node. Deliberately `IrStructuredNode`-shaped so existing IR readers work. */
47
+ interface PartialKindNode {
48
+ role: "structured";
49
+ /** The server's DETECTION GUESS for this region. */
50
+ kind: string;
51
+ /** Always "speculative" on a partial — pre-recognition, not a resolved kind. */
52
+ kindState: "speculative";
53
+ discriminator: IrDiscriminator;
54
+ path: IrPath;
55
+ status: "streaming";
56
+ /**
57
+ * Valid, closed JSON carrying its own `__kind`. MAY be missing required
58
+ * schema fields — that is what `partial_unvalidated` in `residue.notices`
59
+ * says. A renderer that throws on an absent field is not partial-ready and
60
+ * must not be routed a provisional value.
61
+ */
62
+ value: Record<string, unknown>;
63
+ residue: IrResidue | null;
64
+ }
65
+ interface PartialKindEvent {
66
+ v: typeof IR_VERSION;
67
+ engine: string;
68
+ state: "partial";
69
+ /** Monotonic PER BLOCK — the ordering / staleness key. Keep the highest. */
70
+ seq: number;
71
+ fingerprint: string;
72
+ root: PartialKindNode;
73
+ }
74
+ interface SupersededKindEvent {
75
+ v: typeof IR_VERSION;
76
+ engine: string;
77
+ state: "superseded";
78
+ seq: number;
79
+ kind: string;
80
+ }
81
+ interface RetractedKindEvent {
82
+ v: typeof IR_VERSION;
83
+ engine: string;
84
+ state: "retracted";
85
+ seq: number;
86
+ /** The kind that was WRONGLY announced. */
87
+ kind: string;
88
+ reason: string;
89
+ /** What it actually is — null when it resolved to no registered kind. */
90
+ becameKind: string | null;
91
+ /** The detector's final block type, so a consumer re-routes without guessing. */
92
+ becameBlockType: string | null;
93
+ }
94
+ type AnyPartialKindEvent = PartialKindEvent | SupersededKindEvent | RetractedKindEvent;
95
+ /**
96
+ * Read + validate a partial-channel event off a block's metadata.
97
+ *
98
+ * Returns null for anything malformed, foreign, or of an unknown `state`. A
99
+ * malformed partial degrades to "no live rendering" — never to a wrong render,
100
+ * and never to a thrown error inside a stream handler.
101
+ */
102
+ declare function readPartialKindEvent(metadata: Record<string, unknown> | null | undefined): AnyPartialKindEvent | null;
103
+ /**
104
+ * Ingest guard for the partial channel on a `render_block` event — the twin of
105
+ * `sanitizeInboundEnvelopeMetadata` for `__ir`, and it exists for the same
106
+ * reason: a malformed server event must be stripped at the wire boundary, not
107
+ * carried into Redux where every later reader has to re-decide whether to
108
+ * trust it.
109
+ *
110
+ * - no `__ir_partial` key → the SAME metadata reference back (zero-touch).
111
+ * - valid event → the SAME metadata reference back (idempotence law).
112
+ * - malformed → a COPY with the key stripped, plus a loud `reportMalformed`.
113
+ * Dropping it degrades that block to "no live rendering" and nothing more.
114
+ *
115
+ * Pure: the host injects the reporter, exactly like the envelope gate, so
116
+ * aidream's Workflow Studio can bind its own.
117
+ */
118
+ declare function sanitizeInboundPartialKindMetadata(metadata: Record<string, unknown> | null | undefined, context: {
119
+ blockId: string;
120
+ }, hooks?: {
121
+ reportMalformed?: (info: {
122
+ blockId: string;
123
+ raw: unknown;
124
+ }) => void;
125
+ }): Record<string, unknown> | undefined;
126
+ /** Narrowing helper: is this the repeatable provisional event? */
127
+ declare function isProvisionalKind(event: AnyPartialKindEvent | null): event is PartialKindEvent;
128
+ /**
129
+ * Narrowing helper: is this a TERMINAL event? Every partial ends in exactly
130
+ * one of these — that law is what makes a stuck skeleton impossible, so a
131
+ * consumer clears its provisional render here and nowhere else.
132
+ */
133
+ declare function isTerminalKindEvent(event: AnyPartialKindEvent | null): event is SupersededKindEvent | RetractedKindEvent;
134
+ /**
135
+ * Per-block staleness gate. Events can be re-dispatched, replayed on reconnect,
136
+ * or arrive out of order; only a strictly higher `seq` advances a block.
137
+ * Returns null when the event should be ignored.
138
+ *
139
+ * Pure: the caller owns the `seen` map, so this composes into a reducer
140
+ * without hiding module state.
141
+ */
142
+ declare function advancePartialKind(seen: Record<string, number>, blockId: string, event: AnyPartialKindEvent | null): AnyPartialKindEvent | null;
143
+ /**
144
+ * The per-block staleness GATE, as a stateful closure over `advancePartialKind`
145
+ * — one per stream.
146
+ *
147
+ * `upsertRenderBlock` REPLACES the stored block, so an event landing on a block
148
+ * would regress what the user is looking at (a filled-in quiz snapping back to
149
+ * two questions, or a terminal being undone by a late `partial`). The highest
150
+ * accepted event is CARRIED FORWARD rather than dropped, so it is a no-op on
151
+ * screen instead of a flicker back to the skeleton.
152
+ *
153
+ * 🚨 TWO arrivals must be carried, and the second one is the common case:
154
+ *
155
+ * 1. A STALE key — a replay or an out-of-order event (`seq <= last`).
156
+ * 2. **NO key at all.** The producer clears `__ir_partial` at the top of every
157
+ * stamp and re-adds it only when the value genuinely advanced
158
+ * (`stream_processor.py::_stamp_partial` → `_partials.advanced(...)`), so
159
+ * it is CORRECT for it to omit the key — re-shipping an identical payload
160
+ * every token is pure wire cost. But the block still ships whole, and
161
+ * replacing the stored block with one that has no partial metadata is what
162
+ * made the provisional render vanish between advances: every non-advancing
163
+ * token dropped the user back to the pending skeleton.
164
+ *
165
+ * Carrying stops at the TERMINAL, and only there. After `superseded` /
166
+ * `retracted` the region's truth is its own content or `__ir`, so resurrecting
167
+ * a provisional value would be a lie that outlives its own contract.
168
+ *
169
+ * Returns the metadata to store: the same reference when nothing changed, a
170
+ * copy with the carried-forward event otherwise.
171
+ */
172
+ declare function makePartialKindStalenessGate(): (blockId: string, metadata: Record<string, unknown> | undefined) => Record<string, unknown> | undefined;
173
+
174
+ /**
175
+ * Runtime wrapper kinds — the reader, and THE elision gate.
176
+ *
177
+ * Cross-repo contract (system of record):
178
+ * `common-docs/systems/content-ir-system/RUNTIME_WRAPPER_WIRE.md`.
179
+ *
180
+ * A runtime wrapper is the CLOSED set of envelopes that carry instance
181
+ * context with a data kind NESTED inside: `node_outcome` (one settled node
182
+ * invocation) and `run_result` (one terminated run, nesting one
183
+ * `node_outcome` per terminal node). `tool_result` is registered server-side
184
+ * but nothing emits it yet, so nothing here reads it.
185
+ *
186
+ * ## THE ELISION RULE — do it ONCE, here
187
+ *
188
+ * The payload is NEVER sent twice. On the wire `output` is `null` and
189
+ * `output_ref` names the FRAME field that already holds the value:
190
+ *
191
+ * - `"output"` → the frame's own `output` (`node_completed.output`,
192
+ * the run row's `output`).
193
+ * - `"output.<node_id>"` → that key of the frame's terminal output map.
194
+ *
195
+ * PRESENCE OF `output_ref` IS THE MARKER. A bare `output: null` with NO ref is
196
+ * a legitimately empty payload — never an elision, never something to go
197
+ * looking for. This is the same rule the `__ir` envelope follows with
198
+ * `value_ref`, for the same reason: otherwise every payload is serialized
199
+ * twice per streamed event, twice per durable row and twice per run read.
200
+ *
201
+ * Rehydration happens at the single INGEST GATE (each host's one ingest point —
202
+ * Matrix's workflow-runs reducer, the Studio's inbound-envelope gate),
203
+ * before anything reads the wrapper. No renderer, selector or component ever
204
+ * sees an un-rehydrated wrapper, so none of them may re-implement this.
205
+ *
206
+ * ## Never load-bearing
207
+ *
208
+ * Assembly is a pure read. A malformed wrapper yields `null` and the frame's
209
+ * own fields carry the surface exactly as they did before the wrapper
210
+ * existed — additive on the wire, additive here.
211
+ */
212
+ /** The registered slugs — named once, never spelled by hand elsewhere. */
213
+ declare const NODE_OUTCOME_KIND = "node_outcome";
214
+ declare const RUN_RESULT_KIND = "run_result";
215
+ /** One settled node invocation, with its data kind nested in `output`. */
216
+ interface NodeOutcomeWrapper {
217
+ __kind: typeof NODE_OUTCOME_KIND;
218
+ run_id: string;
219
+ node_id: string;
220
+ workflow_id: string | null;
221
+ step: number | null;
222
+ attempt: number;
223
+ status: string;
224
+ started_at: string | null;
225
+ ended_at: string | null;
226
+ /** `0` is a REAL duration, not "unknown"; `null` is unknown. */
227
+ duration_ms: number | null;
228
+ /** null = the node declared no kind (a loud defect, never a pass). */
229
+ output_kind: string | null;
230
+ /** null = never checked / degraded — NEVER renderable as a pass. */
231
+ output_kind_ok: boolean | null;
232
+ output_kind_errors: string[] | null;
233
+ /** Rehydrated by {@link rehydrateNodeOutcome}; null = genuinely empty. */
234
+ output: unknown;
235
+ }
236
+ /** One terminated run. `outputs` is one wrapper per TERMINAL node. */
237
+ interface RunResultWrapper {
238
+ __kind: typeof RUN_RESULT_KIND;
239
+ run_id: string;
240
+ workflow_id: string | null;
241
+ status: string;
242
+ started_at: string | null;
243
+ ended_at: string | null;
244
+ duration_ms: number | null;
245
+ output_kind: string | null;
246
+ output: unknown;
247
+ outputs: NodeOutcomeWrapper[];
248
+ }
249
+ /**
250
+ * Resolve a dotted `output_ref` against the frame that carries the payload.
251
+ * Returns `undefined` when the path does not resolve — the caller keeps
252
+ * `output: null` rather than inventing a value.
253
+ */
254
+ declare function readOutputRef(frame: unknown, ref: string): unknown;
255
+ /**
256
+ * Read a `node_outcome` off a frame and rehydrate its elided payload.
257
+ *
258
+ * `frame` is the object the wrapper travelled ON — the `node_completed` event,
259
+ * or the run read response for a `run_result`'s children. Returns null for
260
+ * anything that is not a node_outcome (including a missing wrapper: the
261
+ * producer fails OPEN, so an absent wrapper is a normal, non-fatal state).
262
+ */
263
+ declare function rehydrateNodeOutcome(raw: unknown, frame: unknown): NodeOutcomeWrapper | null;
264
+ /**
265
+ * Read an ALREADY-REHYDRATED node_outcome value into its typed form.
266
+ *
267
+ * Deliberately does NOT require `__kind`: the render bridge strips the root
268
+ * discriminator before the component sees the value, and it does NOT touch
269
+ * `output_ref` — by the time anything renders, the ingest gate has already
270
+ * resolved the elision, and a second resolution attempt against a frame that
271
+ * is no longer there is how a payload goes missing.
272
+ */
273
+ declare function readNodeOutcomeValue(raw: unknown): NodeOutcomeWrapper | null;
274
+ /**
275
+ * Read a `run_result` off the run read response and rehydrate every elided
276
+ * payload — its own, and each terminal node's. Both resolve against the SAME
277
+ * frame (the run read response), which is what `"output.<node_id>"` addresses.
278
+ */
279
+ declare function rehydrateRunResult(raw: unknown, frame: unknown): RunResultWrapper | null;
280
+ /**
281
+ * Read an ALREADY-REHYDRATED run_result value into its typed form. Same
282
+ * contract as {@link readNodeOutcomeValue}: no `__kind` requirement, no
283
+ * second elision pass.
284
+ */
285
+ declare function readRunResultValue(raw: unknown): RunResultWrapper | null;
286
+ /**
287
+ * The kind verdict, as three states the UI must keep distinct.
288
+ *
289
+ * `unchecked` is NEVER a pass: the engine either did not check (no declared
290
+ * kind) or checked and could not conclude. Collapsing it into "ok" is how a
291
+ * confidently-rendered document gets shown for a shape nobody verified.
292
+ */
293
+ type KindVerdict = "passed" | "failed" | "unchecked";
294
+ declare function kindVerdictOf(wrapper: {
295
+ output_kind: string | null;
296
+ output_kind_ok: boolean | null;
297
+ }): KindVerdict;
298
+
299
+ /**
300
+ * The forward composer: given a kind's stored example, produce the EMIT/RENDER
301
+ * payload — `{ "__kind": <slug>, ...data }`.
302
+ *
303
+ * Pure kernel module (@ai-matrx/content-ir `wire/`): no React, no Redux, no IO.
304
+ *
305
+ * Since 2026-08-23 stored examples and instances ALREADY carry their marker
306
+ * (`__kind` is part of the data — KINDS_EVERYWHERE_PLAN §4.2), so for a
307
+ * well-formed row this is an IDENTITY with a guarantee attached: the marker is
308
+ * the FIRST key and it names the right slug. It stays because it is also the
309
+ * repair for the legacy rows and hand-typed values that do not, and because a
310
+ * caller wanting a copy-ready render payload should not have to know which it
311
+ * has.
312
+ *
313
+ * Scalars/arrays are returned unchanged — for those kinds the identity travels
314
+ * out of band (`root.kind`); there is no key to add.
315
+ */
316
+ declare function withRootKind(kind: string, value: unknown): unknown;
317
+ /** The copy-ready render payload: pretty JSON of `{ __kind, ...data }`. */
318
+ declare function emitPayloadJson(kind: string, value: unknown): string;
319
+ /**
320
+ * The copy-ready render BLOCK — the render payload inside a ```json fence, the
321
+ * exact form an agent emits and a user pastes into a prompt or a message to see
322
+ * it render live.
323
+ */
324
+ declare function emitPayloadFence(kind: string, value: unknown): string;
325
+
326
+ export { type AnyPartialKindEvent, IR_PARTIAL_KEY, type KindVerdict, NODE_OUTCOME_KIND, type NodeOutcomeWrapper, type PartialKindEvent, type PartialKindNode, type PartialKindState, RUN_RESULT_KIND, type RetractedKindEvent, type RunResultWrapper, type SupersededKindEvent, advancePartialKind, emitPayloadFence, emitPayloadJson, isProvisionalKind, isTerminalKindEvent, kindVerdictOf, makePartialKindStalenessGate, readNodeOutcomeValue, readOutputRef, readPartialKindEvent, readRunResultValue, rehydrateNodeOutcome, rehydrateRunResult, sanitizeInboundPartialKindMetadata, withRootKind };