@ai-matrx/content-ir-react 0.7.0 → 0.8.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/component-resolution.types-BS1ySIg-.d.cts +104 -0
  3. package/dist/component-resolution.types-BS1ySIg-.d.ts +104 -0
  4. package/dist/component-resolution.types-fvR92hW7.d.cts +142 -0
  5. package/dist/component-resolution.types-fvR92hW7.d.ts +142 -0
  6. package/dist/db-component.cjs +226 -0
  7. package/dist/db-component.cjs.map +1 -0
  8. package/dist/db-component.d.cts +267 -0
  9. package/dist/db-component.d.ts +267 -0
  10. package/dist/db-component.js +194 -0
  11. package/dist/db-component.js.map +1 -0
  12. package/dist/host-types-CZ_Bkp4R.d.ts +131 -0
  13. package/dist/host-types-DvGv8s9L.d.cts +131 -0
  14. package/dist/host.cjs +74 -0
  15. package/dist/host.cjs.map +1 -0
  16. package/dist/host.d.cts +24 -0
  17. package/dist/host.d.ts +24 -0
  18. package/dist/host.js +52 -0
  19. package/dist/host.js.map +1 -0
  20. package/dist/index.cjs +356 -90
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +280 -672
  23. package/dist/index.d.ts +280 -672
  24. package/dist/index.js +316 -31
  25. package/dist/index.js.map +1 -1
  26. package/dist/react.cjs +361 -0
  27. package/dist/react.cjs.map +1 -0
  28. package/dist/react.d.cts +195 -0
  29. package/dist/react.d.ts +195 -0
  30. package/dist/react.js +344 -0
  31. package/dist/react.js.map +1 -0
  32. package/dist/resolver.cjs +327 -0
  33. package/dist/resolver.cjs.map +1 -0
  34. package/dist/resolver.d.cts +133 -0
  35. package/dist/resolver.d.ts +133 -0
  36. package/dist/resolver.js +304 -0
  37. package/dist/resolver.js.map +1 -0
  38. package/dist/route-C1XNcubB.d.ts +433 -0
  39. package/dist/route-C55jsF4B.d.cts +433 -0
  40. package/dist/route.cjs +259 -0
  41. package/dist/route.cjs.map +1 -0
  42. package/dist/route.d.cts +4 -0
  43. package/dist/route.d.ts +4 -0
  44. package/dist/route.js +247 -0
  45. package/dist/route.js.map +1 -0
  46. package/package.json +79 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0 — 2026-08-30
4
+
5
+ The CONTENT-IR-REACT row of the C23 all-inclusive retrofit register: the
6
+ DB-component compile cache moves IN, the default error boundary ships, and the
7
+ five areas become subpath entries.
8
+
9
+ - **`/db-component` — the DB-component compile cache is package policy.**
10
+ matrx-frontend's 316-line `dbKindComponentCache.ts` (session compile cache
11
+ keyed per winning row VERSION, the scream-once console latch, loud-but-never-
12
+ fatal `props_transform` recovery, config narrowing, allowed-imports
13
+ resolution, key-family invalidation) was pure C22 violation living in one
14
+ host. `createDbKindComponentCache(ports)` now owns all of it; the host
15
+ injects only what is host-shaped: the sandbox COMPILER (security-shaped —
16
+ the package never bundles Babel), the default allowlist, the error reporter,
17
+ the durable incident sink, and the invalidation TRIGGER via the
18
+ `registerInvalidation` port (the host wires its invalidation-registry keys;
19
+ the cache owns what invalidation means). Also ships the kind prop contract
20
+ (`DbKindComponentRenderProps`, `KindComponentUiOptions`, `ResolveKindValue`,
21
+ `RunDbKindAction`) and `isDbKindComponentBodyPending`.
22
+ - **`DbKindComponentErrorBoundary` — the default error boundary the register
23
+ named.** Catch → fallback (never a blank hole) → scream through the
24
+ `onCaught` seam (host binds structured capture + incident filing; the
25
+ default is an honest console scream). `resetSignal` (the row's `updated_at`)
26
+ un-latches the boundary when a NEW component version arrives, so a fixed
27
+ component renders without a full unmount.
28
+ - **Subpath entries for the five areas:** `/host`, `/resolver`, `/route`,
29
+ `/react`, `/db-component` — dual ESM/CJS with matching declarations, per the
30
+ fleet banner rule: `/host`, `/react`, `/db-component` are stamped
31
+ `"use client"`; `/resolver` and `/route` are pure and deliberately
32
+ unstamped; the root `.` keeps the full surface, unstamped (it mixes pure
33
+ route logic that server modules import with client components — parity with
34
+ every existing consumer). tsup moved to the two-config kit shape
35
+ (`treeshake: false` so the banner survives to dist).
36
+ - **`createKindRouteBinding(env, options)`** — the per-host partial
37
+ application every host was hand-writing as wrapper modules
38
+ (`applyIrKindRoute` / `kindServerDataFromStoredValue` /
39
+ `isPartialReadyKind` / `resolveProvisionalKindRender` with env + ownedTypes
40
+ threaded). Host route wrappers collapse to injection + re-export.
41
+ - **Session latches moved to `globalThis` slots**
42
+ (`Symbol.for("ai-matrx.content-ir-react.partial-unsafe-kinds")`, same for
43
+ the sourceless-db-row report latch): with `splitting: false` dual-format
44
+ subpath builds, a module-level Set would silently split the
45
+ `markKindPartialUnsafe` writer (in `/react`'s graph) from the
46
+ `isPartialReadyKind` reader (in `/route`'s) — the kit confirm-opener
47
+ precedent. The tarball canary now proves the slot across loader graphs and
48
+ the `"use client"` stamp per chunk.
49
+ - 20 new tests (cache policy, boundary latch/un-latch, route binding).
50
+
51
+ ### Consumer action
52
+
53
+ - Hosts that carry their own DB-component compile cache (matrx-frontend:
54
+ `features/content-ir/react/db-component/dbKindComponentCache.ts`) must
55
+ collapse it to `createDbKindComponentCache` port wiring and delete the
56
+ mechanics; a host error boundary around compiled DB components becomes a
57
+ binding of `DbKindComponentErrorBoundary` with `onCaught`.
58
+ - Host route wrapper modules should re-export from `createKindRouteBinding`
59
+ instead of hand-forwarding env/ownedTypes (signatures unchanged for their
60
+ own call sites).
61
+ - No import-path changes are REQUIRED — the root export keeps the full
62
+ surface. New code (and any RSC-adjacent graph) should prefer the subpaths.
63
+
64
+ ## 0.7.1 — 2026-08-30
65
+
66
+ - `@ai-matrx/content-ir` is now a REAL dependency (`^0.9.0`) instead of a peer
67
+ (register row X3 / law C23: sibling `@ai-matrx/*` packages are ordinary
68
+ dependencies — only react/react-dom/react-native stay peers). The kernel
69
+ resolves itself on install. `react` is the only remaining peer. No code
70
+ changes.
71
+
3
72
  ## 0.7.0 — 2026-08-29
4
73
 
5
74
  - **`kindIsRoutable` no longer counts the generic fallback as a render path.**
@@ -0,0 +1,104 @@
1
+ /**
2
+ * THE SCREAM SEAM.
3
+ *
4
+ * Every recovery path in this package is loud: a defective component row, a
5
+ * failed resolver load, a kind whose component throws on a provisional value.
6
+ * The package refuses to own where those screams land — matrx-frontend routes
7
+ * them to the Error Inspector, the dashboard to its own log, the extension to
8
+ * its background page. Each host binds one function.
9
+ *
10
+ * A host that binds a no-op has chosen silence, which is a defect in itself;
11
+ * {@link consoleErrorReporter} is the honest default.
12
+ */
13
+ interface ContentIrErrorReport {
14
+ /** Always `"content-ir"` — hosts key their capture stores on it. */
15
+ source: "content-ir";
16
+ message: string;
17
+ name?: string;
18
+ stack?: string;
19
+ /** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
20
+ relation?: string;
21
+ raw?: unknown;
22
+ }
23
+ type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
24
+ /** The default when a host binds nothing: never silent. */
25
+ declare const consoleErrorReporter: ContentIrErrorReporter;
26
+
27
+ /**
28
+ * The (kind, platform, role) → component vocabulary — the Shape System's
29
+ * resolver contract (rulings R1 + R6), stated once for every UI.
30
+ *
31
+ * Cross-repo system-of-record:
32
+ * `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
33
+ * `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
34
+ *
35
+ * Nothing here knows where a row comes from. A host supplies rows from
36
+ * `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
37
+ * only knows the shape.
38
+ */
39
+ /** JSON object, restated locally so this package depends on no host type. */
40
+ type JsonObject = Record<string, unknown>;
41
+ /**
42
+ * Which face of the shape a component draws.
43
+ *
44
+ * - `output` — the shape's finished value, the component a reader sees.
45
+ * - `input` — the authoring form for a value of this shape.
46
+ * - `loading` — the shape's LOADING face: what renders from the instant the
47
+ * kind is identified until its output component has a renderable frame.
48
+ * Authored per kind like any other component and fed the region's partial
49
+ * value each frame, so it can PERFORM the arrival (surface real text as it
50
+ * lands) instead of drawing a shapeless skeleton. Optional: a kind with no
51
+ * `loading` component falls back to the host's loading library.
52
+ */
53
+ type ComponentRole = "output" | "input" | "loading";
54
+ /** The resolver's answer for one (kind, platform, role). */
55
+ interface ComponentResolution {
56
+ /** The component key the renderer routes on (e.g. "flashcards"). */
57
+ componentKey: string;
58
+ source: string;
59
+ config: JsonObject;
60
+ /**
61
+ * Render-trust verdict (R6). Compiled entries are always active (trusted at
62
+ * bootstrap); DB rows carry their own `is_active`.
63
+ */
64
+ isActive: boolean;
65
+ /** Which tier produced this answer — the verification hook's `by`. */
66
+ resolvedBy: "compiled" | "db";
67
+ componentSource: string | null;
68
+ propsTransform: string | null;
69
+ /**
70
+ * TRUE when the row owns a real component body — even if `componentSource`
71
+ * is null because the host's warm list is body-less and the cold fetch has
72
+ * not landed it yet. THE routing gate: `routeToDbComponent` re-types on
73
+ * this flag, never on body presence, so a body-less row still routes and
74
+ * the renderer fetches/compiles the body lazily.
75
+ */
76
+ hasComponentSource: boolean;
77
+ pinnedKindVersion: number | null;
78
+ /** The db row's `updated_at` — the compile-cache staleness key. */
79
+ updatedAt: string | null;
80
+ createdBy: string | null;
81
+ }
82
+ /**
83
+ * The read side of a component resolver, as the render layer consumes it.
84
+ * The package ships {@link ComponentResolver}; a host with its own resolver
85
+ * only has to satisfy this.
86
+ */
87
+ interface ComponentResolutionSource {
88
+ /** Synchronous — the render seam's per-block call. */
89
+ resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
90
+ /** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
91
+ requestComponent(kind: string, platform: string, role: ComponentRole): void;
92
+ /** One list fetch per session. */
93
+ ensureWarm(): Promise<void>;
94
+ /** Refresh-on-view; rate-limited and deduped by the implementation. */
95
+ refresh(maxAgeMs?: number): Promise<void>;
96
+ /** Monotonic tier version — has anything at all changed? */
97
+ getVersion(): number;
98
+ /** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
99
+ getKindVersion(kind: string): number;
100
+ subscribe(listener: () => void): () => void;
101
+ subscribeKind(kind: string, listener: () => void): () => void;
102
+ }
103
+
104
+ export { type ComponentResolution as C, type ContentIrErrorReporter as a, type ContentIrErrorReport as b, consoleErrorReporter as c, type ComponentResolutionSource as d };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * THE SCREAM SEAM.
3
+ *
4
+ * Every recovery path in this package is loud: a defective component row, a
5
+ * failed resolver load, a kind whose component throws on a provisional value.
6
+ * The package refuses to own where those screams land — matrx-frontend routes
7
+ * them to the Error Inspector, the dashboard to its own log, the extension to
8
+ * its background page. Each host binds one function.
9
+ *
10
+ * A host that binds a no-op has chosen silence, which is a defect in itself;
11
+ * {@link consoleErrorReporter} is the honest default.
12
+ */
13
+ interface ContentIrErrorReport {
14
+ /** Always `"content-ir"` — hosts key their capture stores on it. */
15
+ source: "content-ir";
16
+ message: string;
17
+ name?: string;
18
+ stack?: string;
19
+ /** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
20
+ relation?: string;
21
+ raw?: unknown;
22
+ }
23
+ type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
24
+ /** The default when a host binds nothing: never silent. */
25
+ declare const consoleErrorReporter: ContentIrErrorReporter;
26
+
27
+ /**
28
+ * The (kind, platform, role) → component vocabulary — the Shape System's
29
+ * resolver contract (rulings R1 + R6), stated once for every UI.
30
+ *
31
+ * Cross-repo system-of-record:
32
+ * `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
33
+ * `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
34
+ *
35
+ * Nothing here knows where a row comes from. A host supplies rows from
36
+ * `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
37
+ * only knows the shape.
38
+ */
39
+ /** JSON object, restated locally so this package depends on no host type. */
40
+ type JsonObject = Record<string, unknown>;
41
+ /**
42
+ * Which face of the shape a component draws.
43
+ *
44
+ * - `output` — the shape's finished value, the component a reader sees.
45
+ * - `input` — the authoring form for a value of this shape.
46
+ * - `loading` — the shape's LOADING face: what renders from the instant the
47
+ * kind is identified until its output component has a renderable frame.
48
+ * Authored per kind like any other component and fed the region's partial
49
+ * value each frame, so it can PERFORM the arrival (surface real text as it
50
+ * lands) instead of drawing a shapeless skeleton. Optional: a kind with no
51
+ * `loading` component falls back to the host's loading library.
52
+ */
53
+ type ComponentRole = "output" | "input" | "loading";
54
+ /** The resolver's answer for one (kind, platform, role). */
55
+ interface ComponentResolution {
56
+ /** The component key the renderer routes on (e.g. "flashcards"). */
57
+ componentKey: string;
58
+ source: string;
59
+ config: JsonObject;
60
+ /**
61
+ * Render-trust verdict (R6). Compiled entries are always active (trusted at
62
+ * bootstrap); DB rows carry their own `is_active`.
63
+ */
64
+ isActive: boolean;
65
+ /** Which tier produced this answer — the verification hook's `by`. */
66
+ resolvedBy: "compiled" | "db";
67
+ componentSource: string | null;
68
+ propsTransform: string | null;
69
+ /**
70
+ * TRUE when the row owns a real component body — even if `componentSource`
71
+ * is null because the host's warm list is body-less and the cold fetch has
72
+ * not landed it yet. THE routing gate: `routeToDbComponent` re-types on
73
+ * this flag, never on body presence, so a body-less row still routes and
74
+ * the renderer fetches/compiles the body lazily.
75
+ */
76
+ hasComponentSource: boolean;
77
+ pinnedKindVersion: number | null;
78
+ /** The db row's `updated_at` — the compile-cache staleness key. */
79
+ updatedAt: string | null;
80
+ createdBy: string | null;
81
+ }
82
+ /**
83
+ * The read side of a component resolver, as the render layer consumes it.
84
+ * The package ships {@link ComponentResolver}; a host with its own resolver
85
+ * only has to satisfy this.
86
+ */
87
+ interface ComponentResolutionSource {
88
+ /** Synchronous — the render seam's per-block call. */
89
+ resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
90
+ /** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
91
+ requestComponent(kind: string, platform: string, role: ComponentRole): void;
92
+ /** One list fetch per session. */
93
+ ensureWarm(): Promise<void>;
94
+ /** Refresh-on-view; rate-limited and deduped by the implementation. */
95
+ refresh(maxAgeMs?: number): Promise<void>;
96
+ /** Monotonic tier version — has anything at all changed? */
97
+ getVersion(): number;
98
+ /** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
99
+ getKindVersion(kind: string): number;
100
+ subscribe(listener: () => void): () => void;
101
+ subscribeKind(kind: string, listener: () => void): () => void;
102
+ }
103
+
104
+ export { type ComponentResolution as C, type ContentIrErrorReporter as a, type ContentIrErrorReport as b, consoleErrorReporter as c, type ComponentResolutionSource as d };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * THE SCREAM SEAM.
3
+ *
4
+ * Every recovery path in this package is loud: a defective component row, a
5
+ * failed resolver load, a kind whose component throws on a provisional value.
6
+ * The package refuses to own where those screams land — matrx-frontend routes
7
+ * them to the Error Inspector, the dashboard to its own log, the extension to
8
+ * its background page. Each host binds one function.
9
+ *
10
+ * A host that binds a no-op has chosen silence, which is a defect in itself;
11
+ * {@link consoleErrorReporter} is the honest default.
12
+ */
13
+ interface ContentIrErrorReport {
14
+ /** Always `"content-ir"` — hosts key their capture stores on it. */
15
+ source: "content-ir";
16
+ message: string;
17
+ name?: string;
18
+ stack?: string;
19
+ /** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
20
+ relation?: string;
21
+ raw?: unknown;
22
+ }
23
+ type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
24
+ /** The default when a host binds nothing: never silent. */
25
+ declare const consoleErrorReporter: ContentIrErrorReporter;
26
+
27
+ /**
28
+ * The (kind, platform, role) → component vocabulary — the Shape System's
29
+ * resolver contract (rulings R1 + R6), stated once for every UI.
30
+ *
31
+ * Cross-repo system-of-record:
32
+ * `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
33
+ * `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
34
+ *
35
+ * Nothing here knows where a row comes from. A host supplies rows from
36
+ * `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
37
+ * only knows the shape.
38
+ */
39
+ /** JSON object, restated locally so this package depends on no host type. */
40
+ type JsonObject = Record<string, unknown>;
41
+ /**
42
+ * Which face of the shape a component draws.
43
+ *
44
+ * - `output` — the shape's finished value, the component a reader sees.
45
+ * - `input` — the authoring form for a value of this shape.
46
+ * - `loading` — the shape's LOADING face: what renders from the instant the
47
+ * kind is identified until its output component has a renderable frame.
48
+ * Authored per kind like any other component and fed the region's partial
49
+ * value each frame, so it can PERFORM the arrival (surface real text as it
50
+ * lands) instead of drawing a shapeless skeleton. Optional: a kind with no
51
+ * `loading` component falls back to the host's loading library.
52
+ */
53
+ type ComponentRole = "output" | "input" | "loading";
54
+ /**
55
+ * One `content_ir.kind_component` row, projected to exactly what rendering
56
+ * needs. Hosts map their own query result onto this.
57
+ */
58
+ interface KindComponentRow {
59
+ kind: string;
60
+ platform: string;
61
+ role: ComponentRole;
62
+ componentKey: string;
63
+ /** `source` column vocabulary: "bundled" | "db" (db = web sandbox only). */
64
+ source: string;
65
+ config: JsonObject;
66
+ isActive: boolean;
67
+ componentSource: string | null;
68
+ propsTransform: string | null;
69
+ /**
70
+ * Whether the row carries a real `component_source` body — supplied by the
71
+ * host when its warm list is BODY-LESS (the lazy design: metadata travels
72
+ * on the list, the body arrives per kind via the cold fetch). Omitted →
73
+ * derived from `componentSource` itself, so eager hosts change nothing.
74
+ */
75
+ hasComponentSource?: boolean;
76
+ pinnedKindVersion: number | null;
77
+ updatedAt: string | null;
78
+ createdBy: string | null;
79
+ }
80
+ /**
81
+ * One COMPILED bootstrap entry — the trusted-at-boot floor a host ships in its
82
+ * bundle, available synchronously from the first streamed byte.
83
+ */
84
+ interface SystemComponentEntry {
85
+ kind: string;
86
+ platform: string;
87
+ role: ComponentRole;
88
+ componentKey: string;
89
+ source: string;
90
+ config: JsonObject;
91
+ }
92
+ /** The resolver's answer for one (kind, platform, role). */
93
+ interface ComponentResolution {
94
+ /** The component key the renderer routes on (e.g. "flashcards"). */
95
+ componentKey: string;
96
+ source: string;
97
+ config: JsonObject;
98
+ /**
99
+ * Render-trust verdict (R6). Compiled entries are always active (trusted at
100
+ * bootstrap); DB rows carry their own `is_active`.
101
+ */
102
+ isActive: boolean;
103
+ /** Which tier produced this answer — the verification hook's `by`. */
104
+ resolvedBy: "compiled" | "db";
105
+ componentSource: string | null;
106
+ propsTransform: string | null;
107
+ /**
108
+ * TRUE when the row owns a real component body — even if `componentSource`
109
+ * is null because the host's warm list is body-less and the cold fetch has
110
+ * not landed it yet. THE routing gate: `routeToDbComponent` re-types on
111
+ * this flag, never on body presence, so a body-less row still routes and
112
+ * the renderer fetches/compiles the body lazily.
113
+ */
114
+ hasComponentSource: boolean;
115
+ pinnedKindVersion: number | null;
116
+ /** The db row's `updated_at` — the compile-cache staleness key. */
117
+ updatedAt: string | null;
118
+ createdBy: string | null;
119
+ }
120
+ /**
121
+ * The read side of a component resolver, as the render layer consumes it.
122
+ * The package ships {@link ComponentResolver}; a host with its own resolver
123
+ * only has to satisfy this.
124
+ */
125
+ interface ComponentResolutionSource {
126
+ /** Synchronous — the render seam's per-block call. */
127
+ resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
128
+ /** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
129
+ requestComponent(kind: string, platform: string, role: ComponentRole): void;
130
+ /** One list fetch per session. */
131
+ ensureWarm(): Promise<void>;
132
+ /** Refresh-on-view; rate-limited and deduped by the implementation. */
133
+ refresh(maxAgeMs?: number): Promise<void>;
134
+ /** Monotonic tier version — has anything at all changed? */
135
+ getVersion(): number;
136
+ /** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
137
+ getKindVersion(kind: string): number;
138
+ subscribe(listener: () => void): () => void;
139
+ subscribeKind(kind: string, listener: () => void): () => void;
140
+ }
141
+
142
+ export { type ComponentResolutionSource as C, type JsonObject as J, type KindComponentRow as K, type SystemComponentEntry as S, type ComponentResolution as a, type ContentIrErrorReporter as b, type ComponentRole as c, type ContentIrErrorReport as d, consoleErrorReporter as e };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * THE SCREAM SEAM.
3
+ *
4
+ * Every recovery path in this package is loud: a defective component row, a
5
+ * failed resolver load, a kind whose component throws on a provisional value.
6
+ * The package refuses to own where those screams land — matrx-frontend routes
7
+ * them to the Error Inspector, the dashboard to its own log, the extension to
8
+ * its background page. Each host binds one function.
9
+ *
10
+ * A host that binds a no-op has chosen silence, which is a defect in itself;
11
+ * {@link consoleErrorReporter} is the honest default.
12
+ */
13
+ interface ContentIrErrorReport {
14
+ /** Always `"content-ir"` — hosts key their capture stores on it. */
15
+ source: "content-ir";
16
+ message: string;
17
+ name?: string;
18
+ stack?: string;
19
+ /** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
20
+ relation?: string;
21
+ raw?: unknown;
22
+ }
23
+ type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
24
+ /** The default when a host binds nothing: never silent. */
25
+ declare const consoleErrorReporter: ContentIrErrorReporter;
26
+
27
+ /**
28
+ * The (kind, platform, role) → component vocabulary — the Shape System's
29
+ * resolver contract (rulings R1 + R6), stated once for every UI.
30
+ *
31
+ * Cross-repo system-of-record:
32
+ * `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
33
+ * `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
34
+ *
35
+ * Nothing here knows where a row comes from. A host supplies rows from
36
+ * `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
37
+ * only knows the shape.
38
+ */
39
+ /** JSON object, restated locally so this package depends on no host type. */
40
+ type JsonObject = Record<string, unknown>;
41
+ /**
42
+ * Which face of the shape a component draws.
43
+ *
44
+ * - `output` — the shape's finished value, the component a reader sees.
45
+ * - `input` — the authoring form for a value of this shape.
46
+ * - `loading` — the shape's LOADING face: what renders from the instant the
47
+ * kind is identified until its output component has a renderable frame.
48
+ * Authored per kind like any other component and fed the region's partial
49
+ * value each frame, so it can PERFORM the arrival (surface real text as it
50
+ * lands) instead of drawing a shapeless skeleton. Optional: a kind with no
51
+ * `loading` component falls back to the host's loading library.
52
+ */
53
+ type ComponentRole = "output" | "input" | "loading";
54
+ /**
55
+ * One `content_ir.kind_component` row, projected to exactly what rendering
56
+ * needs. Hosts map their own query result onto this.
57
+ */
58
+ interface KindComponentRow {
59
+ kind: string;
60
+ platform: string;
61
+ role: ComponentRole;
62
+ componentKey: string;
63
+ /** `source` column vocabulary: "bundled" | "db" (db = web sandbox only). */
64
+ source: string;
65
+ config: JsonObject;
66
+ isActive: boolean;
67
+ componentSource: string | null;
68
+ propsTransform: string | null;
69
+ /**
70
+ * Whether the row carries a real `component_source` body — supplied by the
71
+ * host when its warm list is BODY-LESS (the lazy design: metadata travels
72
+ * on the list, the body arrives per kind via the cold fetch). Omitted →
73
+ * derived from `componentSource` itself, so eager hosts change nothing.
74
+ */
75
+ hasComponentSource?: boolean;
76
+ pinnedKindVersion: number | null;
77
+ updatedAt: string | null;
78
+ createdBy: string | null;
79
+ }
80
+ /**
81
+ * One COMPILED bootstrap entry — the trusted-at-boot floor a host ships in its
82
+ * bundle, available synchronously from the first streamed byte.
83
+ */
84
+ interface SystemComponentEntry {
85
+ kind: string;
86
+ platform: string;
87
+ role: ComponentRole;
88
+ componentKey: string;
89
+ source: string;
90
+ config: JsonObject;
91
+ }
92
+ /** The resolver's answer for one (kind, platform, role). */
93
+ interface ComponentResolution {
94
+ /** The component key the renderer routes on (e.g. "flashcards"). */
95
+ componentKey: string;
96
+ source: string;
97
+ config: JsonObject;
98
+ /**
99
+ * Render-trust verdict (R6). Compiled entries are always active (trusted at
100
+ * bootstrap); DB rows carry their own `is_active`.
101
+ */
102
+ isActive: boolean;
103
+ /** Which tier produced this answer — the verification hook's `by`. */
104
+ resolvedBy: "compiled" | "db";
105
+ componentSource: string | null;
106
+ propsTransform: string | null;
107
+ /**
108
+ * TRUE when the row owns a real component body — even if `componentSource`
109
+ * is null because the host's warm list is body-less and the cold fetch has
110
+ * not landed it yet. THE routing gate: `routeToDbComponent` re-types on
111
+ * this flag, never on body presence, so a body-less row still routes and
112
+ * the renderer fetches/compiles the body lazily.
113
+ */
114
+ hasComponentSource: boolean;
115
+ pinnedKindVersion: number | null;
116
+ /** The db row's `updated_at` — the compile-cache staleness key. */
117
+ updatedAt: string | null;
118
+ createdBy: string | null;
119
+ }
120
+ /**
121
+ * The read side of a component resolver, as the render layer consumes it.
122
+ * The package ships {@link ComponentResolver}; a host with its own resolver
123
+ * only has to satisfy this.
124
+ */
125
+ interface ComponentResolutionSource {
126
+ /** Synchronous — the render seam's per-block call. */
127
+ resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
128
+ /** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
129
+ requestComponent(kind: string, platform: string, role: ComponentRole): void;
130
+ /** One list fetch per session. */
131
+ ensureWarm(): Promise<void>;
132
+ /** Refresh-on-view; rate-limited and deduped by the implementation. */
133
+ refresh(maxAgeMs?: number): Promise<void>;
134
+ /** Monotonic tier version — has anything at all changed? */
135
+ getVersion(): number;
136
+ /** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
137
+ getKindVersion(kind: string): number;
138
+ subscribe(listener: () => void): () => void;
139
+ subscribeKind(kind: string, listener: () => void): () => void;
140
+ }
141
+
142
+ export { type ComponentResolutionSource as C, type JsonObject as J, type KindComponentRow as K, type SystemComponentEntry as S, type ComponentResolution as a, type ContentIrErrorReporter as b, type ComponentRole as c, type ContentIrErrorReport as d, consoleErrorReporter as e };